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.Path;
  25 import java.nio.file.Paths;
  26 import java.util.LinkedHashMap;
  27 import java.util.List;
  28 import java.util.Map;
  29 import java.util.Arrays;
  30 import java.io.IOException;
  31 import java.lang.module.ModuleDescriptor;
  32 import java.util.ArrayList;
  33 import jdk.test.lib.compiler.CompilerUtils;
  34 import jdk.testlibrary.ProcessTools;
  35 import jdk.testlibrary.OutputAnalyzer;
  36 import org.testng.annotations.BeforeTest;
  37 
  38 /**
  39  * @test
  40  * @bug 8151654
  41  * @library /lib/testlibrary /test/lib
  42  * @library /java/security/modules
  43  * @build jdk.test.lib.compiler.CompilerUtils JarUtils
  44  * @summary Test custom JAAS callback handler with all possible modular option.
  45  * @run testng JaasModularDefaultHandlerTest
  46  */
  47 public class JaasModularDefaultHandlerTest extends ModularTest {
  48 
  49     private static final Path S_SRC = SRC.resolve("TestCallbackHandler.java");
  50     private static final String MODULAR = "M";
  51     private static final String S_PKG = "handler";
  52     private static final String S_JAR_NAME = S_PKG + JAR_EXTN;
  53     private static final String MS_JAR_NAME = MODULAR + S_PKG + JAR_EXTN;
  54     private static final String HANDLER = S_PKG + ".TestCallbackHandler";
  55 
  56     private static final Path C_SRC
  57             = SRC.resolve("JaasClientWithDefaultHandler.java");
  58     private static final Path CL_SRC = SRC.resolve("TestLoginModule.java");
  59     private static final String C_PKG = "login";
  60     private static final String C_JAR_NAME = C_PKG + JAR_EXTN;
  61     private static final String MCN_JAR_NAME
  62             = MODULAR + C_PKG + "NoMUse" + JAR_EXTN;
  63     private static final String MC_JAR_NAME = MODULAR + C_PKG + JAR_EXTN;
  64 
  65     private static final Path BUILD_DIR = Paths.get(".").resolve("build");
  66     private static final Path COMPILE_DIR = BUILD_DIR.resolve("bin");
  67     private static final Path S_BUILD_DIR = COMPILE_DIR.resolve(S_PKG);
  68     private static final Path C_BLD_DIR = COMPILE_DIR.resolve(C_PKG);
  69     private static final Path M_BASE_PATH = BUILD_DIR.resolve("mbase");
  70     private static final Path ARTIFACTS_DIR = BUILD_DIR.resolve("artifacts");
  71 
  72     private static final Path S_ARTIFACTS_DIR = ARTIFACTS_DIR.resolve(S_PKG);
  73     private static final Path S_JAR = S_ARTIFACTS_DIR.resolve(S_JAR_NAME);
  74     private static final Path MS_JAR = S_ARTIFACTS_DIR.resolve(MS_JAR_NAME);
  75 
  76     private static final Path C_ARTIFACTS_DIR = ARTIFACTS_DIR.resolve(C_PKG);
  77     private static final Path C_JAR = C_ARTIFACTS_DIR.resolve(C_JAR_NAME);
  78     private static final Path MC_JAR = C_ARTIFACTS_DIR.resolve(MC_JAR_NAME);
  79     private static final Path MCN_JAR = C_ARTIFACTS_DIR.resolve(MCN_JAR_NAME);
  80 
  81     private static final String MAIN = C_PKG + ".JaasClientWithDefaultHandler";
  82     private static final List<String> M_REQUIRED = Arrays.asList("java.base",
  83             "jdk.security.auth");
  84 
  85     private static final String CLASS_NOT_FOUND_MSG
  86             = "java.lang.ClassNotFoundException: handler.TestCallbackHandler";
  87     private static final String NO_FAILURE = null;
  88 
  89     /**
  90      * Generates Test specific input parameters.
  91      */
  92     @Override
  93     public Object[][] getTestInput() {
  94 
  95         List<List<Object>> params = new ArrayList<>();
  96         String[] args = new String[]{HANDLER};
  97         // PARAMETER ORDERS -
  98         // Client Module Type, Service Module Type,
  99         // Service META Descriptor Required,
 100         // Expected Failure message, Client arguments
 101         params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.EXPLICIT,
 102                 false, NO_FAILURE, args));
 103         params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.AUTO,
 104                 false, NO_FAILURE, args));
 105         params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.UNNAMED,
 106                 false, NO_FAILURE, args));
 107 
 108         params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.EXPLICIT,
 109                 false, NO_FAILURE, args));
 110         params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.AUTO,
 111                 false, NO_FAILURE, args));
 112         params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.UNNAMED,
 113                 false, NO_FAILURE, args));
 114 
 115         params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.EXPLICIT,
 116                 false, NO_FAILURE, args));
 117         params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.AUTO,
 118                 false, NO_FAILURE, args));
 119         params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.UNNAMED,
 120                 false, NO_FAILURE, args));
 121         return params.stream().map(p -> p.toArray()).toArray(Object[][]::new);
 122     }
 123 
 124     /**
 125      * Pre-compile and generate the artifacts required to run this test before
 126      * running each test cases.
 127      */
 128     @BeforeTest
 129     public void buildArtifacts() {
 130 
 131         boolean done = true;
 132         try {
 133             done = CompilerUtils.compile(S_SRC, S_BUILD_DIR);
 134             // Generate modular/regular handler jars.
 135             generateJar(true, MODULE_TYPE.EXPLICIT, MS_JAR, S_BUILD_DIR, false);
 136             generateJar(true, MODULE_TYPE.UNNAMED, S_JAR, S_BUILD_DIR, false);
 137             // Compile client source codes.
 138             done &= CompilerUtils.compile(C_SRC, C_BLD_DIR);
 139             done &= CompilerUtils.compile(CL_SRC, C_BLD_DIR);
 140             // Generate modular client jar with explicit dependency
 141             generateJar(false, MODULE_TYPE.EXPLICIT, MC_JAR, C_BLD_DIR, true);
 142             // Generate modular client jar without any dependency
 143             generateJar(false, MODULE_TYPE.EXPLICIT, MCN_JAR, C_BLD_DIR, false);
 144             // Generate regular client jar
 145             generateJar(false, MODULE_TYPE.UNNAMED, C_JAR, C_BLD_DIR, false);
 146             System.out.format("%nArtifacts generated successfully? %s", done);
 147             if (!done) {
 148                 throw new RuntimeException("Artifact generation failed");
 149             }
 150         } catch (IOException e) {
 151             throw new RuntimeException(e);
 152         }
 153     }
 154 
 155     /**
 156      * Generate modular/regular jar based on module type for this test.
 157      */
 158     private void generateJar(boolean isService, MODULE_TYPE moduleType,
 159             Path jar, Path compilePath, boolean depends) throws IOException {
 160 
 161         ModuleDescriptor mDescriptor = null;
 162         if (isService) {
 163             mDescriptor = generateModuleDescriptor(isService, moduleType, S_PKG,
 164                     S_PKG, null, null, null, M_REQUIRED, depends);
 165         } else {
 166             mDescriptor = generateModuleDescriptor(isService, moduleType, C_PKG,
 167                     C_PKG, null, null, S_PKG, M_REQUIRED, depends);
 168         }
 169         generateJar(mDescriptor, jar, compilePath);
 170     }
 171 
 172     /**
 173      * Holds Logic for the test client. This method will get called with each
 174      * test parameter.
 175      */
 176     @Override
 177     public OutputAnalyzer executeTestClient(MODULE_TYPE cModuleType,
 178             Path cJarPath, MODULE_TYPE sModuletype, Path sJarPath,
 179             String... args) throws Exception {
 180 
 181         OutputAnalyzer output = null;
 182         try {
 183             // For automated/explicit module types, copy the corresponding
 184             // jars to module base folder, which will be considered as
 185             // module base path during execution.
 186             if (!(cModuleType == MODULE_TYPE.UNNAMED
 187                     && sModuletype == MODULE_TYPE.UNNAMED)) {
 188                 copyJarsToModuleBase(cModuleType, cJarPath, M_BASE_PATH);
 189                 copyJarsToModuleBase(sModuletype, sJarPath, M_BASE_PATH);
 190             }
 191 
 192             System.out.format("%nExecuting java client with required"
 193                     + " custom service in class/module path.");
 194             String mName = getModuleName(cModuleType, cJarPath, C_PKG);
 195             Path cmBasePath = (cModuleType != MODULE_TYPE.UNNAMED
 196                     || sModuletype != MODULE_TYPE.UNNAMED) ? M_BASE_PATH : null;
 197             String cPath = buildClassPath(cModuleType, cJarPath, sModuletype,
 198                     sJarPath);
 199             Map<String, String> vmArgs = getVMArgs(sModuletype, cModuleType,
 200                     getModuleName(sModuletype, sJarPath, S_PKG));
 201             output = ProcessTools.executeTestJava(
 202                     getJavaCommand(cmBasePath, cPath, mName, MAIN, vmArgs,
 203                             args)).outputTo(System.out).errorTo(System.out);
 204         } finally {
 205             // Clean module path to hold required jars for next run.
 206             cleanModuleBasePath(M_BASE_PATH);
 207         }
 208         return output;
 209     }
 210 
 211     /**
 212      * Decide the pre-generated client/service jar path for each test case
 213      * based on client/service module type.
 214      */
 215     @Override
 216     public Path findJarPath(boolean depends, MODULE_TYPE moduleType,
 217             boolean addMetaDesc, boolean dependsOnServiceModule) {
 218         if (depends) {
 219             if (moduleType == MODULE_TYPE.EXPLICIT) {
 220                 return MS_JAR;
 221             } else {
 222                 return S_JAR;
 223             }
 224         } else {
 225             // Choose corresponding client jar using dependent module
 226             if (moduleType == MODULE_TYPE.EXPLICIT) {
 227                 if (dependsOnServiceModule) {
 228                     return MC_JAR;
 229                 } else {
 230                     return MCN_JAR;
 231                 }
 232             } else {
 233                 return C_JAR;
 234             }
 235         }
 236     }
 237 
 238     /**
 239      * VM argument required for the test.
 240      */
 241     private Map<String, String> getVMArgs(MODULE_TYPE sModuletype,
 242             MODULE_TYPE cModuleType, String addModName) throws IOException {
 243         final Map<String, String> vmArgs = new LinkedHashMap<>();
 244         vmArgs.put("-Duser.language=", "en");
 245         vmArgs.put("-Duser.region=", "US");
 246         vmArgs.put("-Djava.security.auth.login.config=", SRC.resolve(
 247                 "jaas.conf").toFile().getCanonicalPath());
 248         if (addModName != null
 249                 && !(cModuleType == MODULE_TYPE.EXPLICIT
 250                 && sModuletype == MODULE_TYPE.EXPLICIT)) {
 251             vmArgs.put("--add-modules=", addModName);
 252         }
 253         return vmArgs;
 254     }
 255 
 256 }