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