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