1 /*
   2  * Copyright (c) 2015, 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.security.KeyStore;
  28 import java.security.cert.Certificate;
  29 import java.security.cert.X509Certificate;
  30 import java.util.LinkedHashMap;
  31 import java.util.List;
  32 import java.util.Map;
  33 import java.util.Arrays;
  34 import java.io.FileOutputStream;
  35 import java.io.IOException;
  36 import java.io.File;
  37 import java.io.OutputStream;
  38 import java.lang.module.ModuleDescriptor;
  39 import sun.security.tools.keytool.CertAndKeyGen;
  40 import sun.security.x509.X500Name;
  41 import jdk.internal.module.ModuleInfoWriter;
  42 import jdk.testlibrary.ProcessTools;
  43 import jdk.testlibrary.OutputAnalyzer;
  44 import jdk.testlibrary.JDKToolLauncher;
  45 
  46 /**
  47  * @test
  48  * @bug 8130360
  49  * @library /jdk/jigsaw/lib
  50  * @library /lib/testlibrary
  51  * @library /java/security/modules
  52  * @summary Test custom JCE provider module with all possible modular condition.
  53  *          The test includes different combination of JCE client/provider
  54  *          modules interaction with or without service description.
  55  *          The different module types used here are,
  56  *          EXPLICIT - Modules have module descriptor(module-info.java)
  57  *          defining the module.
  58  *          AUTO - Are regular jar files but provided in MODULE_PATH
  59  *          instead of CLASS_PATH.
  60  *          UNNAMED - Are regular jar but provided through CLASS_PATH.
  61  *          This test uses a boolean argument indicating to use signed jar
  62  *          for the third party JCE provider.
  63  * @run main/othervm -Duser.language=en -Duser.region=US JCEProviderModularTest
  64  *      false
  65  * @run main/othervm -Duser.language=en -Duser.region=US JCEProviderModularTest
  66  *      true
  67  */
  68 public class JCEProviderModularTest extends JigsawSecurityUtils {
  69 
  70     private static final String TEST_SRC = System.getProperty("test.src");
  71     private static final Path SRC_DIR = Paths.get(TEST_SRC, "src");
  72     private static final String DESCRIPTOR = "metaservice";
  73     private static final String MODULAR = "modular";
  74     private static final String AUTO = "autodepend";
  75     private static final String JAR_EXTN = ".jar";
  76 
  77     private static final String SERVICE_MODULE_NAME = "jceprovidermodule";
  78     private static final Path SERVICE_SRC_DIR
  79             = SRC_DIR.resolve(SERVICE_MODULE_NAME);
  80     private static final String SERVICE_PKG = "provider";
  81     private static final String SERVICE_JAR_NAME = SERVICE_PKG + JAR_EXTN;
  82     private static final String SERVICE_DESCRIPTOR_JAR_NAME
  83             = SERVICE_PKG + DESCRIPTOR + JAR_EXTN;
  84     private static final String MODULAR_SERVICE_JAR_NAME
  85             = MODULAR + SERVICE_PKG + JAR_EXTN;
  86     private static final String MODULE_SERVICE_DESCRIPTOR_JAR_NAME
  87             = MODULAR + SERVICE_PKG + DESCRIPTOR + JAR_EXTN;
  88 
  89     private static final String CLIENT_MODULE_NAME = "jceclientmodule";
  90     private static final Path CLIENT_SRC_DIR
  91             = SRC_DIR.resolve(CLIENT_MODULE_NAME);
  92     private static final String CLIENT_PKG = "client";
  93     private static final String CLIENT_JAR_NAME = CLIENT_PKG + JAR_EXTN;
  94     private static final String MODULAR_CLIENT_AUTO_DEPEND_JAR_NAME
  95             = MODULAR + CLIENT_PKG + AUTO + JAR_EXTN;
  96     private static final String MODULAR_CLIENT_JAR_NAME
  97             = MODULAR + CLIENT_PKG + JAR_EXTN;
  98 
  99     private static final Path BUILD_DIR = Paths.get(".").resolve("build");
 100     private static final Path COMPILE_DIR = BUILD_DIR.resolve("bin");
 101     private static final Path SERVICE_BUILD_DIR
 102             = COMPILE_DIR.resolve(SERVICE_PKG);
 103     private static final Path SERVICE_META_BUILD_DIR
 104             = COMPILE_DIR.resolve(SERVICE_PKG + DESCRIPTOR);
 105     private static final Path CLIENT_BUILD_DIR
 106             = COMPILE_DIR.resolve(CLIENT_PKG);
 107 
 108     private static final String MODULE_DIR_NAME = "jarmodule";
 109     private static final Path MODULE_BASE_PATH
 110             = BUILD_DIR.resolve(MODULE_DIR_NAME);
 111 
 112     private static final Path ARTIFACTS_DIR = BUILD_DIR.resolve("artifacts");
 113     private static final Path SERVICE_ARTIFACTS_DIR
 114             = ARTIFACTS_DIR.resolve(SERVICE_PKG);
 115     private static final Path REGULAR_SERVICE_JAR
 116             = SERVICE_ARTIFACTS_DIR.resolve(SERVICE_JAR_NAME);
 117     private static final Path REGULAR_SERVICE_WITH_DESCRIPTOR_JAR
 118             = SERVICE_ARTIFACTS_DIR.resolve(SERVICE_DESCRIPTOR_JAR_NAME);
 119     private static final Path MODULAR_SERVICE_JAR
 120             = SERVICE_ARTIFACTS_DIR.resolve(MODULAR_SERVICE_JAR_NAME);
 121     private static final Path MODULAR_SERVICE_WITH_DESCRIPTOR_JAR
 122             = SERVICE_ARTIFACTS_DIR.resolve(MODULE_SERVICE_DESCRIPTOR_JAR_NAME);
 123 
 124     private static final Path CLIENT_ARTIFACTS_DIR
 125             = ARTIFACTS_DIR.resolve(CLIENT_PKG);
 126     private static final Path REGULAR_CLIENT_JAR
 127             = CLIENT_ARTIFACTS_DIR.resolve(CLIENT_JAR_NAME);
 128     private static final Path MODULAR_CLIENT_JAR
 129             = CLIENT_ARTIFACTS_DIR.resolve(MODULAR_CLIENT_JAR_NAME);
 130     private static final Path MODULAR_CLIENT_AUTO_DEPEND_JAR
 131             = CLIENT_ARTIFACTS_DIR.resolve(MODULAR_CLIENT_AUTO_DEPEND_JAR_NAME);
 132 
 133     private static final Path KEYSTORE_DIR = BUILD_DIR.resolve("store");
 134     private static final Path KEYSTORE_PATH
 135             = KEYSTORE_DIR.resolve("test.keystore");
 136     private static final String STORE_PASSWORD = "password";
 137     private static final String ALIAS = "test";
 138 
 139     private static final String MAIN_CLASS = CLIENT_PKG + ".TestJCEClient";
 140     private static final String LOGIN_SERVICE_INTERFACE
 141             = "java.security.Provider";
 142     private static final String SERVICE_IMPL = SERVICE_PKG + ".TestJCEProvider";
 143     private static final List<String> REQUIRED_MODULES
 144             = Arrays.asList("java.base");
 145     private static final Path META_DESCRIPTOR = Paths.get("META-INF")
 146             .resolve("services").resolve(LOGIN_SERVICE_INTERFACE);
 147     private static final Path META_SERVICE_DESCRIPTOR
 148             = SERVICE_META_BUILD_DIR.resolve(META_DESCRIPTOR);
 149 
 150     private static final boolean WITH_SERVICE_DESCRIPTOR = true;
 151     private static final boolean WITHOUT_SERVICE_DESCRIPTOR = false;
 152     private static final boolean PASS = true;
 153     private static final String PROVIDER_CLASS_NOT_FOUND_MSG
 154             = "NoClassDefFoundError: provider/TestJCEProvider";
 155     private static final String PROVIDER_NOT_FOUND_BY_CLIENT_MSG
 156             = "Unable to find Test JCE Provider";
 157     private static final String CAN_NOT_ACCESS_MSG = "cannot access class";
 158     private static final String NO_FAILURE = null;
 159     private static final String USE_SERVICE_LOADER = "USE_SERVICE_LOADER";
 160     private static final String USE_CLASS_LOADER = "USE_CLASS_LOADER";
 161     private static final String USE_SECURITY_PROP = "USE_SECURITY_PROP";
 162     private static final List<String> MECHANISMS = Arrays.asList(
 163             USE_SERVICE_LOADER, USE_CLASS_LOADER, USE_SECURITY_PROP);
 164     private static final Path SECURITY_PROP_EXTN
 165             = Paths.get("./java.security.extn");
 166 
 167     public static void main(String[] args) {
 168 
 169         boolean success = true;
 170         boolean useSignedJar = (args != null && args.length > 0)
 171                 ? Boolean.valueOf(args[0]) : false;
 172 
 173         boolean ready = createArtifacts(useSignedJar);
 174         if (!ready) {
 175             throw new RuntimeException("Unable to prepare to run this test.");
 176         }
 177 
 178         for (String mechanism : MECHANISMS) {
 179             boolean useClassLoader = USE_CLASS_LOADER.equals(mechanism);
 180             boolean useServiceLoader = USE_SERVICE_LOADER.equals(mechanism);
 181             //PARAMETER ORDERS -
 182             //client Module Type, Service Module Type,
 183             //Service META Descriptor Required, Expected Result, 
 184             //Expected Failure message, Signed/Unsigned?, 
 185             //mechanism used to find the provider
 186             success &= runTest(MODULE_TYPE.EXPLICIT, MODULE_TYPE.EXPLICIT,
 187                     WITH_SERVICE_DESCRIPTOR, PASS, NO_FAILURE,
 188                     useSignedJar, mechanism);
 189             success &= runTest(MODULE_TYPE.EXPLICIT, MODULE_TYPE.EXPLICIT,
 190                     WITHOUT_SERVICE_DESCRIPTOR, PASS, NO_FAILURE,
 191                     useSignedJar, mechanism);
 192             success &= runTest(MODULE_TYPE.EXPLICIT, MODULE_TYPE.AUTO,
 193                     WITH_SERVICE_DESCRIPTOR, PASS,
 194                     ((useClassLoader) ? CAN_NOT_ACCESS_MSG : NO_FAILURE),
 195                     useSignedJar, mechanism);
 196             success &= runTest(MODULE_TYPE.EXPLICIT, MODULE_TYPE.AUTO,
 197                     WITHOUT_SERVICE_DESCRIPTOR, PASS,
 198                     PROVIDER_CLASS_NOT_FOUND_MSG, useSignedJar, mechanism);
 199             success &= runTest(MODULE_TYPE.EXPLICIT, MODULE_TYPE.UNNAMED,
 200                     WITH_SERVICE_DESCRIPTOR, PASS,
 201                     ((useClassLoader) ? CAN_NOT_ACCESS_MSG : NO_FAILURE),
 202                     useSignedJar, mechanism);
 203             success &= runTest(MODULE_TYPE.EXPLICIT, MODULE_TYPE.UNNAMED,
 204                     WITHOUT_SERVICE_DESCRIPTOR, PASS, ((useClassLoader)
 205                             ? CAN_NOT_ACCESS_MSG
 206                             : ((useServiceLoader)
 207                                     ? PROVIDER_NOT_FOUND_BY_CLIENT_MSG
 208                                     : NO_FAILURE)),
 209                     useSignedJar, mechanism);
 210 
 211             success &= runTest(MODULE_TYPE.AUTO, MODULE_TYPE.EXPLICIT,
 212                     WITH_SERVICE_DESCRIPTOR, PASS, NO_FAILURE,
 213                     useSignedJar, mechanism);
 214             success &= runTest(MODULE_TYPE.AUTO, MODULE_TYPE.EXPLICIT,
 215                     WITHOUT_SERVICE_DESCRIPTOR, PASS, NO_FAILURE,
 216                     useSignedJar, mechanism);
 217             success &= runTest(MODULE_TYPE.AUTO, MODULE_TYPE.AUTO,
 218                     WITH_SERVICE_DESCRIPTOR, PASS, NO_FAILURE,
 219                     useSignedJar, mechanism);
 220             success &= runTest(MODULE_TYPE.AUTO, MODULE_TYPE.AUTO,
 221                     WITHOUT_SERVICE_DESCRIPTOR, PASS,
 222                     PROVIDER_CLASS_NOT_FOUND_MSG, useSignedJar, mechanism);
 223             success &= runTest(MODULE_TYPE.AUTO, MODULE_TYPE.UNNAMED,
 224                     WITH_SERVICE_DESCRIPTOR, PASS, NO_FAILURE,
 225                     useSignedJar, mechanism);
 226             success &= runTest(MODULE_TYPE.AUTO, MODULE_TYPE.UNNAMED,
 227                     WITHOUT_SERVICE_DESCRIPTOR, PASS,
 228                     ((useServiceLoader) ? PROVIDER_NOT_FOUND_BY_CLIENT_MSG
 229                             : NO_FAILURE),
 230                     useSignedJar, mechanism);
 231 
 232             success &= runTest(MODULE_TYPE.UNNAMED, MODULE_TYPE.EXPLICIT,
 233                     WITH_SERVICE_DESCRIPTOR, PASS, NO_FAILURE,
 234                     useSignedJar, mechanism);
 235             success &= runTest(MODULE_TYPE.UNNAMED, MODULE_TYPE.EXPLICIT,
 236                     WITHOUT_SERVICE_DESCRIPTOR, PASS, NO_FAILURE,
 237                     useSignedJar, mechanism);
 238             success &= runTest(MODULE_TYPE.UNNAMED, MODULE_TYPE.AUTO,
 239                     WITH_SERVICE_DESCRIPTOR, PASS, NO_FAILURE,
 240                     useSignedJar, mechanism);
 241             success &= runTest(MODULE_TYPE.UNNAMED, MODULE_TYPE.AUTO,
 242                     WITHOUT_SERVICE_DESCRIPTOR, PASS,
 243                     PROVIDER_CLASS_NOT_FOUND_MSG, useSignedJar, mechanism);
 244             success &= runTest(MODULE_TYPE.UNNAMED, MODULE_TYPE.UNNAMED,
 245                     WITH_SERVICE_DESCRIPTOR, PASS, NO_FAILURE,
 246                     useSignedJar, mechanism);
 247             success &= runTest(MODULE_TYPE.UNNAMED, MODULE_TYPE.UNNAMED,
 248                     WITHOUT_SERVICE_DESCRIPTOR, PASS,
 249                     ((useServiceLoader) ? PROVIDER_NOT_FOUND_BY_CLIENT_MSG
 250                             : NO_FAILURE),
 251                     useSignedJar, mechanism);
 252 
 253             if (!success) {
 254                 throw new RuntimeException("At least one test failed.");
 255             }
 256         }
 257     }
 258 
 259     public static boolean runTest(MODULE_TYPE clientModuleType,
 260             MODULE_TYPE serviceModuletype, boolean addMetaInfDescriptor,
 261             boolean expectedResult, String expectedFailure,
 262             boolean useSignedJar, String mechanism) {
 263 
 264         boolean result = true;
 265         try {
 266 
 267             String testName = (clientModuleType + "_")
 268                     + (serviceModuletype + "_")
 269                     + ((addMetaInfDescriptor) ? "DESCRIPTOR" : "NO_DESCRIPTOR");
 270 
 271             System.out.println(String.format(
 272                     "Starting Test case: '%s'", testName));
 273             Path clientJarPath = findJarPath(false, clientModuleType, false,
 274                     (serviceModuletype == MODULE_TYPE.EXPLICIT));
 275             Path serviceJarPath = findJarPath(
 276                     true, serviceModuletype, addMetaInfDescriptor, false);
 277             System.out.println(String.format(
 278                     "Client jar path : %s ", clientJarPath));
 279             System.out.println(String.format(
 280                     "Service jar path : %s ", serviceJarPath));
 281             //For automated/explicit module type copy the corresponding
 282             //jars to module base folder, which will be considered as
 283             //module base path during execution.
 284             if (!(clientModuleType == MODULE_TYPE.UNNAMED
 285                     && serviceModuletype == MODULE_TYPE.UNNAMED)) {
 286                 copyJarsToModuleBase(clientModuleType, clientJarPath,
 287                         serviceModuletype, serviceJarPath);
 288             }
 289 
 290             System.out.println("Started executing java client with required"
 291                     + " custom JCE provider in class/module path.");
 292             String moduleName
 293                     = getClientModuleName(clientModuleType, clientJarPath);
 294             Path moduleBasePath = (clientModuleType != MODULE_TYPE.UNNAMED
 295                     || serviceModuletype != MODULE_TYPE.UNNAMED)
 296                             ? MODULE_BASE_PATH : null;
 297             StringBuilder classPath
 298                     = getClassPath(clientModuleType, clientJarPath,
 299                             serviceModuletype, serviceJarPath);
 300 
 301             final Map<String, String> VM_ARGS
 302                     = getVMArgs(mechanism, serviceModuletype);
 303             OutputAnalyzer output = ProcessTools.executeTestJava(
 304                     getJavaCommand(moduleBasePath, classPath, moduleName,
 305                             MAIN_CLASS, VM_ARGS, mechanism))
 306                     .outputTo(System.out)
 307                     .errorTo(System.out);
 308 
 309             if (output.getExitValue() != 0) {
 310                 if (expectedFailure != null
 311                         && output.getOutput().contains(expectedFailure)) {
 312                     System.out.println("PASS: Test is expected to fail here.");
 313                 } else {
 314                     System.out.println(String.format(
 315                             "Unexpected failure occured during executing '%s'"
 316                             + " with exit code '%s'.",
 317                             MAIN_CLASS, output.getExitValue()));
 318                     result = false;
 319                 }
 320             }
 321         } catch (Exception e) {
 322             e.printStackTrace(System.out);
 323             result = false;
 324         } finally {
 325             //clean module path so that the modulepath can only hold
 326             //the required jars for next run.
 327             cleanModuleBasePath();
 328         }
 329 
 330         return (expectedResult == result);
 331     }
 332 
 333     //Decide the pre-generated client/service jar path for a given module type.
 334     private static Path findJarPath(boolean service, MODULE_TYPE moduleType,
 335             boolean addMetaInfDescriptor, boolean dependsOnServiceModule) {
 336         if (service) {
 337             if (moduleType == MODULE_TYPE.EXPLICIT) {
 338                 if (addMetaInfDescriptor) {
 339                     return MODULAR_SERVICE_WITH_DESCRIPTOR_JAR;
 340                 } else {
 341                     return MODULAR_SERVICE_JAR;
 342                 }
 343             } else {
 344                 if (addMetaInfDescriptor) {
 345                     return REGULAR_SERVICE_WITH_DESCRIPTOR_JAR;
 346                 } else {
 347                     return REGULAR_SERVICE_JAR;
 348                 }
 349             }
 350         } else {
 351             if (moduleType == MODULE_TYPE.EXPLICIT) {
 352                 if (dependsOnServiceModule) {
 353                     return MODULAR_CLIENT_JAR;
 354                 } else {
 355                     return MODULAR_CLIENT_AUTO_DEPEND_JAR;
 356                 }
 357             } else {
 358                 return REGULAR_CLIENT_JAR;
 359             }
 360         }
 361     }
 362 
 363     //Copy pre-generated jar files to the base module path based on module type.
 364     private static void copyJarsToModuleBase(MODULE_TYPE clientModuleType,
 365             Path modularClientJarPath, MODULE_TYPE serviceModuletype,
 366             Path modularServiceJarPath) throws IOException {
 367 
 368         if (MODULE_BASE_PATH != null) {
 369             Files.createDirectories(MODULE_BASE_PATH);
 370         }
 371         if (clientModuleType != MODULE_TYPE.UNNAMED) {
 372             Path clientArtifactName = MODULE_BASE_PATH.resolve(
 373                     modularClientJarPath.getFileName());
 374             System.out.println(String.format("Copy client jar path: '%s'"
 375                     + " to module base path: %s", modularClientJarPath,
 376                     clientArtifactName));
 377             Files.copy(modularClientJarPath, clientArtifactName);
 378         }
 379         if (serviceModuletype != MODULE_TYPE.UNNAMED) {
 380             Path serviceArtifactName = MODULE_BASE_PATH.resolve(
 381                     modularServiceJarPath.getFileName());
 382             System.out.println(String.format("Copy service jar path: '%s'"
 383                     + " to module base path: %s", modularServiceJarPath,
 384                     serviceArtifactName));
 385             Files.copy(modularServiceJarPath, serviceArtifactName);
 386         }
 387     }
 388 
 389     //Pre-compile and generate the artifacts required to run this test.
 390     private static boolean createArtifacts(boolean useSignedJar) {
 391 
 392         boolean done = true;
 393         try {
 394             //If signed jar required then prepare the keystore for first time.
 395             if (useSignedJar) {
 396                 done &= generateKeyStore(KEYSTORE_PATH.toString(),
 397                         STORE_PASSWORD, ALIAS);
 398             }
 399             done &= CompilerUtils.compile(SERVICE_SRC_DIR, SERVICE_BUILD_DIR);
 400             done &= CompilerUtils.compile(SERVICE_SRC_DIR,
 401                     SERVICE_META_BUILD_DIR);
 402             done &= createMetaInfServiceDescriptor(META_SERVICE_DESCRIPTOR,
 403                     SERVICE_IMPL);
 404             //Generate regular/modular jars with(out) META-INF
 405             //service descriptor
 406             generateJar(true, MODULE_TYPE.EXPLICIT, MODULAR_SERVICE_JAR,
 407                     SERVICE_BUILD_DIR, false, useSignedJar);
 408             generateJar(true, MODULE_TYPE.EXPLICIT,
 409                     MODULAR_SERVICE_WITH_DESCRIPTOR_JAR,
 410                     SERVICE_META_BUILD_DIR, false, useSignedJar);
 411             generateJar(true, MODULE_TYPE.UNNAMED, REGULAR_SERVICE_JAR,
 412                     SERVICE_BUILD_DIR, false, useSignedJar);
 413             generateJar(true, MODULE_TYPE.UNNAMED,
 414                     REGULAR_SERVICE_WITH_DESCRIPTOR_JAR,
 415                     SERVICE_META_BUILD_DIR, false, useSignedJar);
 416             //Generate regular/modular(depends on explicit/auto service)
 417             //jars for client
 418             done &= CompilerUtils.compile(CLIENT_SRC_DIR, CLIENT_BUILD_DIR,
 419                     "-cp", REGULAR_SERVICE_JAR.toRealPath().toString());
 420             generateJar(false, MODULE_TYPE.EXPLICIT, MODULAR_CLIENT_JAR,
 421                     CLIENT_BUILD_DIR, true, useSignedJar);
 422             generateJar(false, MODULE_TYPE.EXPLICIT,
 423                     MODULAR_CLIENT_AUTO_DEPEND_JAR, CLIENT_BUILD_DIR,
 424                     false, useSignedJar);
 425             generateJar(false, MODULE_TYPE.UNNAMED,
 426                     REGULAR_CLIENT_JAR, CLIENT_BUILD_DIR, false, useSignedJar);
 427 
 428             System.out.println(String.format(
 429                     "Artifacts generated successfully? '%s'", done));
 430         } catch (IOException e) {
 431             e.printStackTrace(System.out);
 432             done = false;
 433         }
 434         return done;
 435     }
 436 
 437     //Generate modular/regular jar based on module type.
 438     private static void generateJar(boolean service, MODULE_TYPE moduleType,
 439             Path jarFile, Path compilePath, boolean depends,
 440             boolean useSignedJar) throws IOException {
 441 
 442         ModuleDescriptor moduleDescriptor = null;
 443         if (service) {
 444             moduleDescriptor = generateModuleDescriptor(service, moduleType,
 445                     SERVICE_MODULE_NAME, SERVICE_PKG,
 446                     LOGIN_SERVICE_INTERFACE, SERVICE_IMPL, null,
 447                     REQUIRED_MODULES, depends);
 448         } else {
 449             moduleDescriptor = generateModuleDescriptor(service,
 450                     moduleType, CLIENT_MODULE_NAME, CLIENT_PKG,
 451                     LOGIN_SERVICE_INTERFACE, null, SERVICE_MODULE_NAME,
 452                     REQUIRED_MODULES, depends);
 453         }
 454         System.out.println(String.format(
 455                 "Creating jar file '%s'", jarFile));
 456         JarUtils.createJarFile(jarFile, compilePath);
 457         if (moduleDescriptor != null) {
 458             Path dir = Files.createTempDirectory("tmp");
 459             Path mi = dir.resolve("module-info.class");
 460             try (OutputStream out = Files.newOutputStream(mi)) {
 461                 ModuleInfoWriter.write(moduleDescriptor, out);
 462             }
 463             System.out.println(String.format(
 464                     "Adding 'module-info.class' to jar file '%s'", jarFile));
 465             JarUtils.updateJarFile(jarFile, dir);
 466         }
 467         //If the jar holds provider implementation then sign it.
 468         if (service && useSignedJar) {
 469             signJar(jarFile, KEYSTORE_PATH.toRealPath().toString(),
 470                     STORE_PASSWORD, ALIAS);
 471         }
 472     }
 473 
 474     //Construct class path argument value.
 475     private static StringBuilder getClassPath(MODULE_TYPE clientModuleType,
 476             Path clientJarPath, MODULE_TYPE serviceModuletype,
 477             Path serviceJarPath) throws IOException {
 478 
 479         StringBuilder classPath = new StringBuilder();
 480         classPath.append((clientModuleType == MODULE_TYPE.UNNAMED)
 481                 ? (clientJarPath.toRealPath().toString()
 482                 + File.pathSeparatorChar) : "");
 483         classPath.append((serviceModuletype == MODULE_TYPE.UNNAMED)
 484                 ? serviceJarPath.toRealPath().toString() : "");
 485         return classPath;
 486     }
 487 
 488     //Construct client modulename to run the client. It is fixed for explicit
 489     //module type while it is same as jar file name for automated module type.
 490     private static String getClientModuleName(MODULE_TYPE clientModuleType,
 491             Path clientJarPath) {
 492 
 493         String jarFileName = clientJarPath.toFile().getName();
 494         return (clientModuleType == MODULE_TYPE.EXPLICIT)
 495                 ? CLIENT_MODULE_NAME
 496                 : ((clientModuleType == MODULE_TYPE.AUTO)
 497                         ? jarFileName.substring(
 498                                 0, jarFileName.indexOf(JAR_EXTN)) : "");
 499     }
 500 
 501     //Delete all the files inside the base module path.
 502     private static void cleanModuleBasePath() {
 503 
 504         Arrays.asList(MODULE_BASE_PATH.toFile().listFiles())
 505                 .forEach(f -> {
 506                     System.out.println("delete " + f);
 507                     f.delete();
 508                 });
 509         System.out.println("------------------------------------------------");
 510     }
 511 
 512     //Generate a keystore with random keys.
 513     public static boolean generateKeyStore(String keyStoreFile,
 514             String password, String alias) throws IOException {
 515         boolean created = true;
 516         Path parent = KEYSTORE_PATH.getParent();
 517         if (parent != null) {
 518             Files.createDirectories(parent);
 519         }
 520         try (FileOutputStream keyStoreOut
 521                 = new FileOutputStream(keyStoreFile)) {
 522 
 523             KeyStore keyStore = KeyStore.getInstance("JKS");
 524             keyStore.load(null, null);
 525 
 526             CertAndKeyGen keyGen
 527                     = new CertAndKeyGen("RSA", "SHA1WithRSA", null);
 528             keyGen.generate(2048);
 529             //Generate self signed certificate
 530             Certificate[] chain = new X509Certificate[1];
 531             chain[0] = keyGen.getSelfCertificate(
 532                     new X500Name("CN=ROOT"), (long) 365 * 24 * 3600);
 533             keyStore.setKeyEntry(alias, keyGen.getPrivateKey(),
 534                     password.toCharArray(), chain);
 535 
 536             keyStore.store(keyStoreOut, password.toCharArray());
 537         } catch (Exception e) {
 538             created = false;
 539             e.printStackTrace(System.out);
 540         }
 541         return created;
 542     }
 543 
 544     //Sign a jar file by provided keystore file.
 545     public static void signJar(Path jarFile, String keyStore,
 546             String password, String alias) {
 547         try {
 548             JDKToolLauncher jarsigner = JDKToolLauncher.create("jarsigner")
 549                     .addToolArg("-keystore")
 550                     .addToolArg(keyStore)
 551                     .addToolArg("-storepass")
 552                     .addToolArg(password)
 553                     .addToolArg("-keypass")
 554                     .addToolArg(password)
 555                     .addToolArg(jarFile.toFile().getCanonicalPath())
 556                     .addToolArg(alias);
 557             ProcessBuilder processBuilder
 558                     = new ProcessBuilder(jarsigner.getCommand());
 559             OutputAnalyzer output = ProcessTools.executeProcess(processBuilder);
 560             System.out.println(
 561                     "_________________BEGIN JAR SIGN OUTPUT__________________");
 562             System.out.println(output.getOutput());
 563             System.out.println(
 564                     "_______________________END OUTPUT_______________________");
 565             output.shouldHaveExitValue(0);
 566         } catch (Exception e) {
 567             throw new RuntimeException(String.format(
 568                     "Unable to sign Jar file '%s'", jarFile));
 569         }
 570     }
 571 
 572     private static Map<String, String> getVMArgs(String mechanism,
 573             MODULE_TYPE serviceModuletype) throws IOException {
 574         final Map<String, String> VM_ARGS = new LinkedHashMap<>();
 575         VM_ARGS.put("-Duser.language=", "en");
 576         VM_ARGS.put("-Duser.region=", "US");
 577         //If mechanism to find the provider through Security.getProvider()
 578         //then use providerName/ProviderClassName based on modular/regular
 579         //provider jar in "java.security" configuration file.
 580         if (USE_SECURITY_PROP.equals(mechanism)) {
 581             if (serviceModuletype == MODULE_TYPE.UNNAMED) {
 582                 Files.write(SECURITY_PROP_EXTN,
 583                         "security.provider.10=provider.TestJCEProvider"
 584                         .getBytes());
 585             } else {
 586                 Files.write(SECURITY_PROP_EXTN,
 587                         "security.provider.10=TEST".getBytes());
 588             }
 589             VM_ARGS.put("-Djava.security.properties=",
 590                     SECURITY_PROP_EXTN.toFile().getCanonicalPath());
 591         }
 592         return VM_ARGS;
 593     }
 594 
 595 }