--- /dev/null 2015-07-25 05:49:27.889711346 -0700 +++ new/test/java/security/Provider/modules/JCEProviderModularTest.java 2015-11-30 02:16:11.827262227 -0800 @@ -0,0 +1,574 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.security.KeyStore; +import java.security.cert.Certificate; +import java.security.cert.X509Certificate; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Arrays; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.File; +import java.io.OutputStream; +import java.lang.module.ModuleDescriptor; +import sun.security.tools.keytool.CertAndKeyGen; +import sun.security.x509.X500Name; +import jdk.internal.module.ModuleInfoWriter; +import jdk.testlibrary.ProcessTools; +import jdk.testlibrary.OutputAnalyzer; +import jdk.testlibrary.JDKToolLauncher; + +/** + * @test + * @bug 8130360 + * @library /jdk/jigsaw/lib + * @library /lib/testlibrary + * @library /java/security/modules + * @summary Test custom JCE provider module with all possible modular condition. + * The test includes different combination of JCE client/provider + * modules interaction with or without service description. + * The different module types used here are, + * EXPLICIT - Modules have module descriptor(module-info.java) + * defining the module. + * AUTO - Are regular jar files but provided in MODULE_PATH + * instead of CLASS_PATH. + * UNNAMED - Are regular jar but provided through CLASS_PATH. + * This test uses a boolean argument indicating to use signed jar + * for the third party JCE provider. + * @run main/othervm -Duser.language=en -Duser.region=US JCEProviderModularTest + * false + * @run main/othervm -Duser.language=en -Duser.region=US JCEProviderModularTest + * true + */ +public class JCEProviderModularTest extends JigsawSecurityUtils { + + private static final String TEST_SRC = System.getProperty("test.src"); + private static final Path SRC_DIR = Paths.get(TEST_SRC, "src"); + private static final String DESCRIPTOR = "metaservice"; + private static final String MODULAR = "modular"; + private static final String AUTO = "autodepend"; + private static final String JAR_EXTN = ".jar"; + + private static final String SERVICE_MODULE_NAME = "jceprovidermodule"; + private static final Path SERVICE_SRC_DIR + = SRC_DIR.resolve(SERVICE_MODULE_NAME); + private static final String SERVICE_PKG = "provider"; + private static final String SERVICE_JAR_NAME = SERVICE_PKG + JAR_EXTN; + private static final String SERVICE_DESCRIPTOR_JAR_NAME + = SERVICE_PKG + DESCRIPTOR + JAR_EXTN; + private static final String MODULAR_SERVICE_JAR_NAME + = MODULAR + SERVICE_PKG + JAR_EXTN; + private static final String MODULE_SERVICE_DESCRIPTOR_JAR_NAME + = MODULAR + SERVICE_PKG + DESCRIPTOR + JAR_EXTN; + + private static final String CLIENT_MODULE_NAME = "jceclientmodule"; + private static final Path CLIENT_SRC_DIR + = SRC_DIR.resolve(CLIENT_MODULE_NAME); + private static final String CLIENT_PKG = "client"; + private static final String CLIENT_JAR_NAME = CLIENT_PKG + JAR_EXTN; + private static final String MODULAR_CLIENT_AUTO_DEPEND_JAR_NAME + = MODULAR + CLIENT_PKG + AUTO + JAR_EXTN; + private static final String MODULAR_CLIENT_JAR_NAME + = MODULAR + CLIENT_PKG + JAR_EXTN; + + private static final Path BUILD_DIR = Paths.get(".").resolve("build"); + private static final Path COMPILE_DIR = BUILD_DIR.resolve("bin"); + private static final Path SERVICE_BUILD_DIR + = COMPILE_DIR.resolve(SERVICE_PKG); + private static final Path SERVICE_META_BUILD_DIR + = COMPILE_DIR.resolve(SERVICE_PKG + DESCRIPTOR); + private static final Path CLIENT_BUILD_DIR + = COMPILE_DIR.resolve(CLIENT_PKG); + + private static final String EXPLICIT_MODULE_NAME = "jarmodule"; + private static final Path EXPLICIT_MODULE_BASE_PATH + = BUILD_DIR.resolve(EXPLICIT_MODULE_NAME); + + private static final Path ARTIFACTS_DIR = BUILD_DIR.resolve("artifacts"); + private static final Path SERVICE_ARTIFACTS_DIR + = ARTIFACTS_DIR.resolve(SERVICE_PKG); + private static final Path REGULAR_SERVICE_JAR + = SERVICE_ARTIFACTS_DIR.resolve(SERVICE_JAR_NAME); + private static final Path REGULAR_SERVICE_WITH_DESCRIPTOR_JAR + = SERVICE_ARTIFACTS_DIR.resolve(SERVICE_DESCRIPTOR_JAR_NAME); + private static final Path MODULAR_SERVICE_JAR + = SERVICE_ARTIFACTS_DIR.resolve(MODULAR_SERVICE_JAR_NAME); + private static final Path MODULAR_SERVICE_WITH_DESCRIPTOR_JAR + = SERVICE_ARTIFACTS_DIR.resolve(MODULE_SERVICE_DESCRIPTOR_JAR_NAME); + + private static final Path CLIENT_ARTIFACTS_DIR + = ARTIFACTS_DIR.resolve(CLIENT_PKG); + private static final Path REGULAR_CLIENT_JAR + = CLIENT_ARTIFACTS_DIR.resolve(CLIENT_JAR_NAME); + private static final Path MODULAR_CLIENT_JAR + = CLIENT_ARTIFACTS_DIR.resolve(MODULAR_CLIENT_JAR_NAME); + private static final Path MODULAR_CLIENT_AUTO_DEPEND_JAR + = CLIENT_ARTIFACTS_DIR.resolve(MODULAR_CLIENT_AUTO_DEPEND_JAR_NAME); + + private static final Path KEYSTORE_DIR = BUILD_DIR.resolve("store"); + private static final Path KEYSTORE_PATH + = KEYSTORE_DIR.resolve("test.keystore"); + private static final String STORE_PASSWORD = "password"; + private static final String ALIAS = "test"; + + private static final String MAIN_CLASS = CLIENT_PKG + ".TestJCEClient"; + private static final String LOGIN_SERVICE_INTERFACE + = "java.security.Provider"; + private static final String SERVICE_IMPL = SERVICE_PKG + ".TestJCEProvider"; + private static final List REQUIRED_MODULES + = Arrays.asList("java.base"); + private static final Path META_DESCRIPTOR = Paths.get("META-INF") + .resolve("services").resolve(LOGIN_SERVICE_INTERFACE); + private static final Path META_SERVICE_DESCRIPTOR + = SERVICE_META_BUILD_DIR.resolve(META_DESCRIPTOR); + + private static final boolean WITH_SERVICE_DESCRIPTOR = true; + private static final boolean WITHOUT_SERVICE_DESCRIPTOR = false; + private static final boolean PASS = true; + private static final String PROVIDER_CLASS_NOT_FOUND_MSG + = "NoClassDefFoundError: provider/TestJCEProvider"; + private static final String PROVIDER_NOT_FOUND_BY_CLIENT_MSG + = "Unable to find Test JCE Provider"; + private static final String CAN_NOT_ACCESS_MSG = "cannot access class"; + private static final String NO_FAILURE = null; + private static final String USE_SERVICE_LOADER = "USE_SERVICE_LOADER"; + private static final String USE_CLASS_LOADER = "USE_CLASS_LOADER"; + private static final String USE_SECURITY_PROP = "USE_SECURITY_PROP"; + private static final List MECHANISMS = Arrays.asList( + USE_SERVICE_LOADER, USE_CLASS_LOADER, USE_SECURITY_PROP); + private static final Path SECURITY_PROP_EXTN + = Paths.get("./java.security.extn"); + + public static void main(String[] args) { + + boolean success = true; + boolean useSignedJar = (args != null && args.length > 0) + ? Boolean.valueOf(args[0]) : false; + + boolean ready = createArtifacts(useSignedJar); + if (!ready) { + throw new RuntimeException("Unable to prepare to run this test."); + } + + for (String mechanism : MECHANISMS) { + boolean useClassLoader = USE_CLASS_LOADER.equals(mechanism); + //PARAMETER ORDERS - + //client Module Type, Service Module Type, + //Service META Descriptor Required, Expected Result + success &= runTest(MODULE_TYPE.EXPLICIT, MODULE_TYPE.EXPLICIT, + WITH_SERVICE_DESCRIPTOR, PASS, NO_FAILURE, + useSignedJar, mechanism); + success &= runTest(MODULE_TYPE.EXPLICIT, MODULE_TYPE.EXPLICIT, + WITHOUT_SERVICE_DESCRIPTOR, PASS, NO_FAILURE, + useSignedJar, mechanism); + success &= runTest(MODULE_TYPE.EXPLICIT, MODULE_TYPE.AUTO, + WITH_SERVICE_DESCRIPTOR, PASS, + ((useClassLoader) ? CAN_NOT_ACCESS_MSG : NO_FAILURE), + useSignedJar, mechanism); + success &= runTest(MODULE_TYPE.EXPLICIT, MODULE_TYPE.AUTO, + WITHOUT_SERVICE_DESCRIPTOR, PASS, + PROVIDER_CLASS_NOT_FOUND_MSG, useSignedJar, mechanism); + success &= runTest(MODULE_TYPE.EXPLICIT, MODULE_TYPE.UNNAMED, + WITH_SERVICE_DESCRIPTOR, PASS, + ((useClassLoader) ? CAN_NOT_ACCESS_MSG : NO_FAILURE), + useSignedJar, mechanism); + success &= runTest(MODULE_TYPE.EXPLICIT, MODULE_TYPE.UNNAMED, + WITHOUT_SERVICE_DESCRIPTOR, PASS, ((useClassLoader) + ? CAN_NOT_ACCESS_MSG + : PROVIDER_NOT_FOUND_BY_CLIENT_MSG), + useSignedJar, mechanism); + + success &= runTest(MODULE_TYPE.AUTO, MODULE_TYPE.EXPLICIT, + WITH_SERVICE_DESCRIPTOR, PASS, NO_FAILURE, + useSignedJar, mechanism); + success &= runTest(MODULE_TYPE.AUTO, MODULE_TYPE.EXPLICIT, + WITHOUT_SERVICE_DESCRIPTOR, PASS, NO_FAILURE, + useSignedJar, mechanism); + success &= runTest(MODULE_TYPE.AUTO, MODULE_TYPE.AUTO, + WITH_SERVICE_DESCRIPTOR, PASS, NO_FAILURE, + useSignedJar, mechanism); + success &= runTest(MODULE_TYPE.AUTO, MODULE_TYPE.AUTO, + WITHOUT_SERVICE_DESCRIPTOR, PASS, + PROVIDER_CLASS_NOT_FOUND_MSG, useSignedJar, mechanism); + success &= runTest(MODULE_TYPE.AUTO, MODULE_TYPE.UNNAMED, + WITH_SERVICE_DESCRIPTOR, PASS, NO_FAILURE, + useSignedJar, mechanism); + success &= runTest(MODULE_TYPE.AUTO, MODULE_TYPE.UNNAMED, + WITHOUT_SERVICE_DESCRIPTOR, PASS, + ((useClassLoader) ? NO_FAILURE + : PROVIDER_NOT_FOUND_BY_CLIENT_MSG), + useSignedJar, mechanism); + + success &= runTest(MODULE_TYPE.UNNAMED, MODULE_TYPE.EXPLICIT, + WITH_SERVICE_DESCRIPTOR, PASS, NO_FAILURE, + useSignedJar, mechanism); + success &= runTest(MODULE_TYPE.UNNAMED, MODULE_TYPE.EXPLICIT, + WITHOUT_SERVICE_DESCRIPTOR, PASS, NO_FAILURE, + useSignedJar, mechanism); + success &= runTest(MODULE_TYPE.UNNAMED, MODULE_TYPE.AUTO, + WITH_SERVICE_DESCRIPTOR, PASS, NO_FAILURE, + useSignedJar, mechanism); + success &= runTest(MODULE_TYPE.UNNAMED, MODULE_TYPE.AUTO, + WITHOUT_SERVICE_DESCRIPTOR, PASS, + PROVIDER_CLASS_NOT_FOUND_MSG, useSignedJar, mechanism); + success &= runTest(MODULE_TYPE.UNNAMED, MODULE_TYPE.UNNAMED, + WITH_SERVICE_DESCRIPTOR, PASS, NO_FAILURE, + useSignedJar, mechanism); + success &= runTest(MODULE_TYPE.UNNAMED, MODULE_TYPE.UNNAMED, + WITHOUT_SERVICE_DESCRIPTOR, PASS, + ((useClassLoader) ? NO_FAILURE + : PROVIDER_NOT_FOUND_BY_CLIENT_MSG), + useSignedJar, mechanism); + + if (!success) { + throw new RuntimeException("At least one test failed."); + } + } + } + + public static boolean runTest(MODULE_TYPE clientModuleType, + MODULE_TYPE serviceModuletype, boolean addMetaInfDescriptor, + boolean expectedResult, String expectedFailure, + boolean useSignedJar, String mechanism) { + + boolean result = true; + try { + + String testName = (clientModuleType + "_") + + (serviceModuletype + "_") + + ((addMetaInfDescriptor) ? "DESCRIPTOR" : "NO_DESCRIPTOR"); + + System.out.println(String.format( + "Starting Test case: '%s'", testName)); + Path clientJarPath = findJarPath(false, clientModuleType, false, + (serviceModuletype == MODULE_TYPE.EXPLICIT)); + Path serviceJarPath = findJarPath( + true, serviceModuletype, addMetaInfDescriptor, false); + System.out.println(String.format( + "Client jar path : %s ", clientJarPath)); + System.out.println(String.format( + "Service jar path : %s ", serviceJarPath)); + //For automated/explicit module type copy the corresponding + //jars to module base folder, which will be considered as + //module base path during execution. + if (!(clientModuleType == MODULE_TYPE.UNNAMED + && serviceModuletype == MODULE_TYPE.UNNAMED)) { + copyJarsToModuleBase(clientModuleType, clientJarPath, + serviceModuletype, serviceJarPath); + } + + System.out.println("Started executing java client with required" + + " custom JCE provider in class/module path."); + String moduleName + = getClientModuleName(clientModuleType, clientJarPath); + Path moduleBasePath = (clientModuleType != MODULE_TYPE.UNNAMED + || serviceModuletype != MODULE_TYPE.UNNAMED) + ? EXPLICIT_MODULE_BASE_PATH : null; + StringBuilder classPath + = getClassPath(clientModuleType, clientJarPath, + serviceModuletype, serviceJarPath); + + final Map VM_ARGS = new LinkedHashMap<>(); + VM_ARGS.put("-Duser.language=", "en"); + VM_ARGS.put("-Duser.region=", "US"); + if (USE_SECURITY_PROP.equals(mechanism)) { + VM_ARGS.put("-Djava.security.properties=", + SECURITY_PROP_EXTN.toFile().getCanonicalPath()); + } + OutputAnalyzer output = ProcessTools.executeTestJava( + getJavaCommand(moduleBasePath, classPath, moduleName, + MAIN_CLASS, VM_ARGS, mechanism)) + .outputTo(System.out) + .errorTo(System.out); + + if (output.getExitValue() != 0) { + if (expectedFailure != null + && output.getOutput().contains(expectedFailure)) { + System.out.println("PASS: Test is expected to fail here."); + } else { + System.out.println(String.format( + "Unexpected failure occured during executing '%s'" + + " with exit code '%s'.", + MAIN_CLASS, output.getExitValue())); + result = false; + } + } + } catch (Exception e) { + e.printStackTrace(System.out); + result = false; + } finally { + //clean module path so that the modulepath can only hold + //the required jars for next run. + cleanModuleBasePath(); + } + + return (expectedResult == result); + } + + //Decide the pre-generated client/service jar path for a given module type. + private static Path findJarPath(boolean service, MODULE_TYPE moduleType, + boolean addMetaInfDescriptor, boolean dependsOnServiceModule) { + if (service) { + if (moduleType == MODULE_TYPE.EXPLICIT) { + if (addMetaInfDescriptor) { + return MODULAR_SERVICE_WITH_DESCRIPTOR_JAR; + } else { + return MODULAR_SERVICE_JAR; + } + } else { + if (addMetaInfDescriptor) { + return REGULAR_SERVICE_WITH_DESCRIPTOR_JAR; + } else { + return REGULAR_SERVICE_JAR; + } + } + } else { + if (moduleType == MODULE_TYPE.EXPLICIT) { + if (dependsOnServiceModule) { + return MODULAR_CLIENT_JAR; + } else { + return MODULAR_CLIENT_AUTO_DEPEND_JAR; + } + } else { + return REGULAR_CLIENT_JAR; + } + } + } + + //Copy pre-generated jar files to the base module path based on module type. + private static void copyJarsToModuleBase(MODULE_TYPE clientModuleType, + Path modularClientJarPath, MODULE_TYPE serviceModuletype, + Path modularServiceJarPath) throws IOException { + + if (EXPLICIT_MODULE_BASE_PATH != null) { + Files.createDirectories(EXPLICIT_MODULE_BASE_PATH); + } + if (clientModuleType != MODULE_TYPE.UNNAMED) { + Path clientArtifactName = EXPLICIT_MODULE_BASE_PATH.resolve( + modularClientJarPath.getFileName()); + System.out.println(String.format("Copy client jar path: '%s'" + + " to module base path: %s", modularClientJarPath, + clientArtifactName)); + Files.copy(modularClientJarPath, clientArtifactName); + } + if (serviceModuletype != MODULE_TYPE.UNNAMED) { + Path serviceArtifactName = EXPLICIT_MODULE_BASE_PATH.resolve( + modularServiceJarPath.getFileName()); + System.out.println(String.format("Copy service jar path: '%s'" + + " to module base path: %s", modularServiceJarPath, + serviceArtifactName)); + Files.copy(modularServiceJarPath, serviceArtifactName); + } + } + + //Pre-compile and generate the artifacts required to run this test. + private static boolean createArtifacts(boolean useSignedJar) { + + boolean done = true; + try { + Files.write(SECURITY_PROP_EXTN, + "security.provider.13=TEST".getBytes()); + //If signed jar required then prepare the keystore for first time. + if (useSignedJar) { + done &= generateKeyStore(KEYSTORE_PATH.toString(), + STORE_PASSWORD, ALIAS); + } + done &= CompilerUtils.compile(SERVICE_SRC_DIR, SERVICE_BUILD_DIR); + done &= CompilerUtils.compile(SERVICE_SRC_DIR, + SERVICE_META_BUILD_DIR); + done &= createMetaInfServiceDescriptor(META_SERVICE_DESCRIPTOR, + SERVICE_IMPL); + //Generate regular/modular jars with(out) META-INF + //service descriptor + generateJar(true, MODULE_TYPE.EXPLICIT, MODULAR_SERVICE_JAR, + SERVICE_BUILD_DIR, false, useSignedJar); + generateJar(true, MODULE_TYPE.EXPLICIT, + MODULAR_SERVICE_WITH_DESCRIPTOR_JAR, + SERVICE_META_BUILD_DIR, false, useSignedJar); + generateJar(true, MODULE_TYPE.UNNAMED, REGULAR_SERVICE_JAR, + SERVICE_BUILD_DIR, false, useSignedJar); + generateJar(true, MODULE_TYPE.UNNAMED, + REGULAR_SERVICE_WITH_DESCRIPTOR_JAR, + SERVICE_META_BUILD_DIR, false, useSignedJar); + //Generate regular/modular(depends on explicit/auto service) + //jars for client + done &= CompilerUtils.compile(CLIENT_SRC_DIR, CLIENT_BUILD_DIR, + "-cp", REGULAR_SERVICE_JAR.toRealPath().toString()); + generateJar(false, MODULE_TYPE.EXPLICIT, MODULAR_CLIENT_JAR, + CLIENT_BUILD_DIR, true, useSignedJar); + generateJar(false, MODULE_TYPE.EXPLICIT, + MODULAR_CLIENT_AUTO_DEPEND_JAR, CLIENT_BUILD_DIR, + false, useSignedJar); + generateJar(false, MODULE_TYPE.UNNAMED, + REGULAR_CLIENT_JAR, CLIENT_BUILD_DIR, false, useSignedJar); + + System.out.println(String.format( + "Artifacts generated successfully? '%s'", done)); + } catch (IOException e) { + e.printStackTrace(System.out); + done = false; + } + return done; + } + + //Generate modular/regular jar based on module type. + private static void generateJar(boolean service, MODULE_TYPE moduleType, + Path jarFile, Path compilePath, boolean depends, + boolean useSignedJar) throws IOException { + + ModuleDescriptor moduleDescriptor = null; + if (service) { + moduleDescriptor = generateModuleDescriptor(service, moduleType, + SERVICE_MODULE_NAME, SERVICE_PKG, + LOGIN_SERVICE_INTERFACE, SERVICE_IMPL, null, + REQUIRED_MODULES, depends); + } else { + moduleDescriptor = generateModuleDescriptor(service, + moduleType, CLIENT_MODULE_NAME, CLIENT_PKG, + LOGIN_SERVICE_INTERFACE, null, SERVICE_MODULE_NAME, + REQUIRED_MODULES, depends); + } + System.out.println(String.format( + "Creating jar file '%s'", jarFile)); + JarUtils.createJarFile(jarFile, compilePath); + if (moduleDescriptor != null) { + Path dir = Files.createTempDirectory("tmp"); + Path mi = dir.resolve("module-info.class"); + try (OutputStream out = Files.newOutputStream(mi)) { + ModuleInfoWriter.write(moduleDescriptor, out); + } + System.out.println(String.format( + "Adding 'module-info.class' to jar file '%s'", jarFile)); + JarUtils.updateJarFile(jarFile, dir); + } + //If the jar holds provider implementation then sign it. + if (service && useSignedJar) { + signJar(jarFile, KEYSTORE_PATH.toRealPath().toString(), + STORE_PASSWORD, ALIAS); + } + } + + //Construct class path argument value. + private static StringBuilder getClassPath(MODULE_TYPE clientModuleType, + Path clientJarPath, MODULE_TYPE serviceModuletype, + Path serviceJarPath) throws IOException { + + StringBuilder classPath = new StringBuilder(); + classPath.append((clientModuleType == MODULE_TYPE.UNNAMED) + ? (clientJarPath.toRealPath().toString() + + File.pathSeparatorChar) : ""); + classPath.append((serviceModuletype == MODULE_TYPE.UNNAMED) + ? serviceJarPath.toRealPath().toString() : ""); + return classPath; + } + + //Construct client modulename to run the client. It is fixed for explicit + //module type while it is same as jar file name for automated module type. + private static String getClientModuleName(MODULE_TYPE clientModuleType, + Path clientJarPath) { + + String jarFileName = clientJarPath.toFile().getName(); + return (clientModuleType == MODULE_TYPE.EXPLICIT) + ? CLIENT_MODULE_NAME + : ((clientModuleType == MODULE_TYPE.AUTO) + ? jarFileName.substring( + 0, jarFileName.indexOf(JAR_EXTN)) : ""); + } + + //Delete all the files inside the base module path. + private static void cleanModuleBasePath() { + + Arrays.asList(EXPLICIT_MODULE_BASE_PATH.toFile().listFiles()) + .forEach(f -> { + System.out.println("delete " + f); + f.delete(); + }); + System.out.println("------------------------------------------------"); + } + + //Generate a keystore with random keys. + public static boolean generateKeyStore(String keyStoreFile, + String password, String alias) throws IOException { + boolean created = true; + Path parent = KEYSTORE_PATH.getParent(); + if (parent != null) { + Files.createDirectories(parent); + } + try (FileOutputStream keyStoreOut + = new FileOutputStream(keyStoreFile)) { + + KeyStore keyStore = KeyStore.getInstance("JKS"); + keyStore.load(null, null); + + CertAndKeyGen keyGen + = new CertAndKeyGen("RSA", "SHA1WithRSA", null); + keyGen.generate(2048); + //Generate self signed certificate + Certificate[] chain = new X509Certificate[1]; + chain[0] = keyGen.getSelfCertificate( + new X500Name("CN=ROOT"), (long) 365 * 24 * 3600); + keyStore.setKeyEntry(alias, keyGen.getPrivateKey(), + password.toCharArray(), chain); + + keyStore.store(keyStoreOut, password.toCharArray()); + } catch (Exception e) { + created = false; + e.printStackTrace(System.out); + } + return created; + } + + //Sign a jar file by provided keystore file. + public static void signJar(Path jarFile, String keyStore, + String password, String alias) { + try { + JDKToolLauncher jarsigner = JDKToolLauncher.create("jarsigner") + .addToolArg("-keystore") + .addToolArg(keyStore) + .addToolArg("-storepass") + .addToolArg(password) + .addToolArg("-keypass") + .addToolArg(password) + .addToolArg(jarFile.toFile().getCanonicalPath()) + .addToolArg(alias); + ProcessBuilder processBuilder + = new ProcessBuilder(jarsigner.getCommand()); + OutputAnalyzer output = ProcessTools.executeProcess(processBuilder); + System.out.println( + "_________________BEGIN JAR SIGN OUTPUT__________________"); + System.out.println(output.getOutput()); + System.out.println( + "_______________________END OUTPUT_______________________"); + output.shouldHaveExitValue(0); + } catch (Exception e) { + throw new RuntimeException(String.format( + "Unable to sign Jar file '%s'", jarFile)); + } + } + +}