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