1 /* 2 * Copyright (c) 2016, 2023, 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 import java.nio.file.Files; 25 import java.nio.file.Path; 26 import java.nio.file.Paths; 27 import java.nio.file.StandardCopyOption; 28 import java.util.Collections; 29 import java.util.LinkedList; 30 import java.util.List; 31 import java.io.File; 32 import java.io.OutputStream; 33 import java.lang.module.ModuleDescriptor; 34 import java.lang.module.ModuleDescriptor.Builder; 35 import java.util.stream.Stream; 36 import jdk.test.lib.process.ProcessTools; 37 import jdk.test.lib.process.OutputAnalyzer; 38 import jdk.test.lib.util.JarUtils; 39 import jdk.test.lib.util.ModuleInfoWriter; 40 41 /* 42 * @test 43 * @bug 8151654 8183310 44 * @summary Test default callback handler with all possible modular option. 45 * @enablePreview 46 * @modules java.base/jdk.internal.module 47 * @library /test/lib 48 * @build jdk.test.lib.util.JarUtils 49 * @build TestCallbackHandler TestLoginModule JaasClientWithDefaultHandler 50 * @run main JaasModularDefaultHandlerTest 51 */ 52 public class JaasModularDefaultHandlerTest { 53 54 private static final Path SRC = Paths.get(System.getProperty("test.src")); 55 private static final Path TEST_CLASSES 56 = Paths.get(System.getProperty("test.classes")); 57 private static final Path ARTIFACT_DIR = Paths.get("jars"); 58 private static final String PS = File.pathSeparator; 59 private static final String H_TYPE = "handler.TestCallbackHandler"; 60 private static final String C_TYPE = "login.JaasClientWithDefaultHandler"; 61 62 /** 63 * Here is the naming convention followed for each jar. 64 * h.jar - Unnamed handler jar. 65 * mh.jar - Modular handler jar. 66 * c.jar - Unnamed client jar. 67 * mc.jar - Modular client jar. 68 * amc.jar - Modular client used for automatic handler jar. 69 */ 70 private static final Path H_JAR = artifact("h.jar"); 71 private static final Path MH_JAR = artifact("mh.jar"); 72 private static final Path C_JAR = artifact("c.jar"); 73 private static final Path MC_JAR = artifact("mc.jar"); 74 private static final Path AMC_JAR = artifact("amc.jar"); 75 76 private final String unnH; 77 private final String modH; 78 private final String unnC; 79 private final String modC; 80 private final String autoMC; 81 // Common set of VM arguments used in all test cases 82 private final List<String> commonArgs; 83 84 public JaasModularDefaultHandlerTest() { 85 86 List<String> argList = new LinkedList<>(); 87 argList.add("-Djava.security.auth.login.config=" 88 + toAbsPath(SRC.resolve("jaas.conf"))); 89 commonArgs = Collections.unmodifiableList(argList); 90 91 // Based on Testcase, select unnamed/modular jar files to use. 92 unnH = toAbsPath(H_JAR); 93 modH = toAbsPath(MH_JAR); 94 unnC = toAbsPath(C_JAR); 95 modC = toAbsPath(MC_JAR); 96 autoMC = toAbsPath(AMC_JAR); 97 } 98 99 /* 100 * Test cases are based on the following logic, 101 * for (clientType : {"NAMED", "AUTOMATIC", "UNNAMED"}) { 102 * for (handlerType : {"NAMED", "AUTOMATIC", "UNNAMED"}) { 103 * Create and run java command for each possible case 104 * } 105 * } 106 */ 107 public static void main(String[] args) throws Exception { 108 109 // Generates unnamed and modular jars. 110 setUp(); 111 JaasModularDefaultHandlerTest jt = new JaasModularDefaultHandlerTest(); 112 jt.process(); 113 } 114 115 private void process() throws Exception { 116 117 // Case: NAMED-NAMED, NAMED-AUTOMATIC, NAMED-UNNAMED 118 System.out.println("Case: Modular Client and Modular Handler"); 119 execute(String.format("--module-path %s%s%s -m mc/%s %s", 120 modC, PS, modH, C_TYPE, H_TYPE)); 121 System.out.println("Case: Modular Client and automatic Handler"); 122 execute(String.format("--module-path %s%s%s --add-modules=h -m mc/%s %s", 123 autoMC, PS, unnH, C_TYPE, H_TYPE)); 124 System.out.println("Case: Modular Client and unnamed Handler"); 125 execute(String.format("--module-path %s -cp %s -m mc/%s %s", autoMC, 126 unnH, C_TYPE, H_TYPE)); 127 128 // Case: AUTOMATIC-NAMED, AUTOMATIC-AUTOMATIC, AUTOMATIC-UNNAMED 129 System.out.println("Case: Automatic Client and modular Handler"); 130 execute(String.format("--module-path %s%s%s --add-modules=mh -m c/%s %s", 131 unnC, PS, modH, C_TYPE, H_TYPE)); 132 System.out.println("Case: Automatic Client and automatic Handler"); 133 execute(String.format("--module-path %s%s%s --add-modules=h -m c/%s %s", 134 unnC, PS, unnH, C_TYPE, H_TYPE)); 135 System.out.println("Case: Automatic Client and unnamed Handler"); 136 execute(String.format("--module-path %s -cp %s -m c/%s %s", unnC, 137 unnH, C_TYPE, H_TYPE)); 138 139 // Case: UNNAMED-NAMED, UNNAMED-AUTOMATIC, UNNAMED-UNNAMED 140 System.out.println("Case: Unnamed Client and modular Handler"); 141 execute(String.format("-cp %s --module-path %s --add-modules=mh %s %s", 142 unnC, modH, C_TYPE, H_TYPE)); 143 System.out.println("Case: Unnamed Client and automatic Handler"); 144 execute(String.format("-cp %s --module-path %s --add-modules=h %s %s", 145 unnC, unnH, C_TYPE, H_TYPE)); 146 System.out.println("Case: Unnamed Client and unnamed Handler"); 147 execute(String.format("-cp %s%s%s %s %s", unnC, PS, unnH, C_TYPE, 148 H_TYPE)); 149 150 // Case: unnamed jars in --module-path and modular jars in -cp. 151 System.out.println("Case: Unnamed Client and Handler in modulepath"); 152 execute(String.format("--module-path %s%s%s --add-modules=h -m c/%s %s", 153 unnC, PS, unnH, C_TYPE, H_TYPE)); 154 System.out.println("Case: Modular Client and Provider in classpath"); 155 execute(String.format("-cp %s%s%s %s %s", 156 modC, PS, modH, C_TYPE, H_TYPE)); 157 } 158 159 /** 160 * Execute with command arguments and process the result. 161 */ 162 private void execute(String args) throws Exception { 163 164 String[] safeArgs = Stream.concat(commonArgs.stream(), 165 Stream.of(args.split("\\s+"))).filter(s -> { 166 if (s.contains(" ")) { 167 throw new RuntimeException("No spaces in args"); 168 } 169 return !s.isEmpty(); 170 }).toArray(String[]::new); 171 OutputAnalyzer out = ProcessTools.executeTestJava(safeArgs); 172 // Handle response. 173 if (out.getExitValue() != 0) { 174 System.out.printf("OUTPUT: %s", out.getOutput()); 175 throw new RuntimeException("FAIL: Unknown failure occured."); 176 } else { 177 System.out.println("Passed."); 178 } 179 } 180 181 /** 182 * Creates Unnamed/modular jar files for TestClient and TestClassLoader. 183 */ 184 private static void setUp() throws Exception { 185 186 if (ARTIFACT_DIR.toFile().exists()) { 187 System.out.println("Skipping setup: Artifacts already exists."); 188 return; 189 } 190 // Generate unnamed handler jar file. 191 JarUtils.createJarFile(H_JAR, TEST_CLASSES, 192 "handler/TestCallbackHandler.class"); 193 // Generate unnamed client jar file. 194 JarUtils.createJarFile(C_JAR, TEST_CLASSES, 195 "login/TestLoginModule.class", 196 "login/JaasClientWithDefaultHandler.class"); 197 198 Builder mBuilder = ModuleDescriptor.newModule("mh"); 199 // Modular jar exports package to let the handler type accessible. 200 generateJar(H_JAR, MH_JAR, mBuilder.exports("handler").build()); 201 202 mBuilder = ModuleDescriptor.newModule("mc").exports("login") 203 .requires("jdk.security.auth"); 204 // Generate modular client jar file to use automatic handler jar. 205 generateJar(C_JAR, AMC_JAR, mBuilder.build()); 206 // Generate modular client jar file to use modular handler jar. 207 generateJar(C_JAR, MC_JAR, mBuilder.requires("mh").build()); 208 } 209 210 /** 211 * Update Unnamed jars and include module descriptor files. 212 */ 213 private static void generateJar(Path sjar, Path djar, 214 ModuleDescriptor mDesc) throws Exception { 215 216 Files.copy(sjar, djar, StandardCopyOption.REPLACE_EXISTING); 217 Path dir = Files.createTempDirectory("tmp"); 218 if (mDesc != null) { 219 Path mi = dir.resolve("module-info.class"); 220 try (OutputStream out = Files.newOutputStream(mi)) { 221 ModuleInfoWriter.write(mDesc, out); 222 } 223 System.out.format("Added 'module-info.class' in '%s'%n", djar); 224 } 225 JarUtils.updateJarFile(djar, dir); 226 } 227 228 /** 229 * Look for file path in generated jars. 230 */ 231 private static Path artifact(String file) { 232 return ARTIFACT_DIR.resolve(file); 233 } 234 235 /** 236 * Convert to absolute file path. 237 */ 238 private static String toAbsPath(Path path) { 239 return path.toFile().getAbsolutePath(); 240 } 241 }