--- old/test/javax/security/auth/login/modules/JaasModularClientTest.java 2015-12-21 09:55:14.304497194 -0800 +++ new/test/javax/security/auth/login/modules/JaasModularClientTest.java 2015-12-21 09:55:14.105499552 -0800 @@ -21,7 +21,6 @@ * questions. */ -import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.LinkedHashMap; @@ -29,12 +28,11 @@ import java.util.Map; import java.util.Arrays; import java.io.IOException; -import java.io.OutputStream; -import java.io.File; import java.lang.module.ModuleDescriptor; +import java.util.ArrayList; import jdk.testlibrary.ProcessTools; import jdk.testlibrary.OutputAnalyzer; -import jdk.internal.module.ModuleInfoWriter; +import org.testng.annotations.BeforeTest; /** * @test @@ -42,397 +40,254 @@ * @library /jdk/jigsaw/lib * @library /lib/testlibrary * @library /java/security/modules + * @build CompilerUtils JarUtils * @summary Test custom JAAS module with all possible modular option. The test * includes different combination of JAAS client/login 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. - * @run main/othervm -Duser.language=en -Duser.region=US JaasModularClientTest + * interaction with or without service description. + * @run testng JaasModularClientTest */ -public class JaasModularClientTest extends JigsawSecurityUtils { +public class JaasModularClientTest extends ModularTest { - 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 = "auto"; - private static final String JAR_EXTN = ".jar"; - - private static final String SERVICE_MODULE_NAME = "jaasloginmodule"; - private static final Path SERVICE_SRC_DIR - = SRC_DIR.resolve(SERVICE_MODULE_NAME); - private static final String SERVICE_PKG = "login"; - 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 MODULAR_SERVICE_DESCRIPTOR_JAR_NAME - = MODULAR + SERVICE_PKG + DESCRIPTOR + JAR_EXTN; - - private static final String CLIENT_MODULE_NAME = "jaasclientmodule"; - 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 S_SRC = SRC.resolve("TestLoginModule.java"); + private static final String S_PKG = "login"; + private static final String S_JAR_NAME = S_PKG + JAR_EXTN; + private static final String S_DESCR_JAR_NAME = S_PKG + DESCRIPTOR + + JAR_EXTN; + private static final String MS_JAR_NAME = MODULAR + S_PKG + JAR_EXTN; + private static final String MS_DESCR_JAR_NAME = MODULAR + S_PKG + DESCRIPTOR + + JAR_EXTN; + + private static final Path C_SRC = SRC.resolve("JaasClient.java"); + private static final String C_PKG = "client"; + private static final String C_JAR_NAME = C_PKG + JAR_EXTN; + private static final String MC_DEPENDS_ON_AUTO_SERVICE_JAR_NAME = MODULAR + + C_PKG + AUTO + JAR_EXTN; + private static final String MC_JAR_NAME = MODULAR + C_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 S_BUILD_DIR = COMPILE_DIR.resolve(S_PKG); + private static final Path S_WITH_META_DESCR_BUILD_DIR = COMPILE_DIR.resolve( + S_PKG + DESCRIPTOR); + private static final Path C_BUILD_DIR = COMPILE_DIR.resolve(C_PKG); + private static final Path M_BASE_PATH = BUILD_DIR.resolve("mbase"); 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(MODULAR_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 String MAIN_CLASS = CLIENT_PKG + ".JaasClient"; - private static final String LOGIN_SERVICE_INTERFACE + private static final Path S_ARTIFACTS_DIR = ARTIFACTS_DIR.resolve(S_PKG); + private static final Path S_JAR = S_ARTIFACTS_DIR.resolve(S_JAR_NAME); + private static final Path S_WITH_DESCRIPTOR_JAR = S_ARTIFACTS_DIR.resolve( + S_DESCR_JAR_NAME); + private static final Path MS_JAR = S_ARTIFACTS_DIR.resolve(MS_JAR_NAME); + private static final Path MS_WITH_DESCR_JAR = S_ARTIFACTS_DIR.resolve( + MS_DESCR_JAR_NAME); + + private static final Path C_ARTIFACTS_DIR = ARTIFACTS_DIR.resolve(C_PKG); + private static final Path C_JAR = C_ARTIFACTS_DIR.resolve(C_JAR_NAME); + private static final Path MC_JAR = C_ARTIFACTS_DIR.resolve(MC_JAR_NAME); + private static final Path MC_DEPENDS_ON_AUTO_SERVICE_JAR = C_ARTIFACTS_DIR + .resolve(MC_DEPENDS_ON_AUTO_SERVICE_JAR_NAME); + + private static final String MAIN = C_PKG + ".JaasClient"; + private static final String S_INTERFACE = "javax.security.auth.spi.LoginModule"; - private static final String SERVICE_IMPL = SERVICE_PKG + ".TestLoginModule"; - private static final List REQUIRED_MODULES - = Arrays.asList("java.base", "jdk.security.auth"); - 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 EXPECTED_FAILURE = "No LoginModule found"; + private static final String S_IMPL = S_PKG + ".TestLoginModule"; + private static final List M_REQUIRED = Arrays.asList("java.base", + "jdk.security.auth"); + private static final Path META_DESCR_PATH = Paths.get("META-INF") + .resolve("services").resolve(S_INTERFACE); + private static final Path S_META_DESCR_FPATH = S_WITH_META_DESCR_BUILD_DIR + .resolve(META_DESCR_PATH); + + private static final boolean WITH_S_DESCR = true; + private static final boolean WITHOUT_S_DESCR = false; + private static final String LOGIN_MODULE_NOT_FOUND_MSG + = "No LoginModule found"; private static final String NO_FAILURE = null; private static final Map VM_ARGS = new LinkedHashMap<>(); - public static void main(String[] args) { - - boolean success = true; - boolean ready = createArtifacts(); - if (!ready) { - throw new RuntimeException("Unable to prepare to run this test."); - } + /** + * Generates Test specific input parameters. + */ + @Override + public Object[][] getTestInput() { + List> params = new ArrayList<>(); + String[] args = new String[]{}; //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); - success &= runTest(MODULE_TYPE.EXPLICIT, MODULE_TYPE.EXPLICIT, - WITHOUT_SERVICE_DESCRIPTOR, PASS, NO_FAILURE); - success &= runTest(MODULE_TYPE.EXPLICIT, MODULE_TYPE.AUTO, - WITH_SERVICE_DESCRIPTOR, PASS, NO_FAILURE); - success &= runTest(MODULE_TYPE.EXPLICIT, MODULE_TYPE.AUTO, - WITHOUT_SERVICE_DESCRIPTOR, PASS, EXPECTED_FAILURE); - success &= runTest(MODULE_TYPE.EXPLICIT, MODULE_TYPE.UNNAMED, - WITH_SERVICE_DESCRIPTOR, PASS, NO_FAILURE); - success &= runTest(MODULE_TYPE.EXPLICIT, MODULE_TYPE.UNNAMED, - WITHOUT_SERVICE_DESCRIPTOR, PASS, NO_FAILURE); - - success &= runTest(MODULE_TYPE.AUTO, MODULE_TYPE.EXPLICIT, - WITH_SERVICE_DESCRIPTOR, PASS, NO_FAILURE); - success &= runTest(MODULE_TYPE.AUTO, MODULE_TYPE.EXPLICIT, - WITHOUT_SERVICE_DESCRIPTOR, PASS, NO_FAILURE); - success &= runTest(MODULE_TYPE.AUTO, MODULE_TYPE.AUTO, - WITH_SERVICE_DESCRIPTOR, PASS, NO_FAILURE); - success &= runTest(MODULE_TYPE.AUTO, MODULE_TYPE.AUTO, - WITHOUT_SERVICE_DESCRIPTOR, PASS, EXPECTED_FAILURE); - success &= runTest(MODULE_TYPE.AUTO, MODULE_TYPE.UNNAMED, - WITH_SERVICE_DESCRIPTOR, PASS, NO_FAILURE); - success &= runTest(MODULE_TYPE.AUTO, MODULE_TYPE.UNNAMED, - WITHOUT_SERVICE_DESCRIPTOR, PASS, NO_FAILURE); - - success &= runTest(MODULE_TYPE.UNNAMED, MODULE_TYPE.EXPLICIT, - WITH_SERVICE_DESCRIPTOR, PASS, NO_FAILURE); - success &= runTest(MODULE_TYPE.UNNAMED, MODULE_TYPE.EXPLICIT, - WITHOUT_SERVICE_DESCRIPTOR, PASS, NO_FAILURE); - success &= runTest(MODULE_TYPE.UNNAMED, MODULE_TYPE.AUTO, - WITH_SERVICE_DESCRIPTOR, PASS, NO_FAILURE); - success &= runTest(MODULE_TYPE.UNNAMED, MODULE_TYPE.AUTO, - WITHOUT_SERVICE_DESCRIPTOR, PASS, EXPECTED_FAILURE); - success &= runTest(MODULE_TYPE.UNNAMED, MODULE_TYPE.UNNAMED, - WITH_SERVICE_DESCRIPTOR, PASS, NO_FAILURE); - success &= runTest(MODULE_TYPE.UNNAMED, MODULE_TYPE.UNNAMED, - WITHOUT_SERVICE_DESCRIPTOR, PASS, NO_FAILURE); + //Service META Descriptor Required, + //Expected Failure message, mechanism used to find the provider + params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.EXPLICIT, + WITH_S_DESCR, NO_FAILURE, args)); + params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.EXPLICIT, + WITHOUT_S_DESCR, NO_FAILURE, args)); + params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.AUTO, + WITH_S_DESCR, NO_FAILURE, args)); + params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.AUTO, + WITHOUT_S_DESCR, LOGIN_MODULE_NOT_FOUND_MSG, args)); + params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.UNNAMED, + WITH_S_DESCR, NO_FAILURE, args)); + params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.UNNAMED, + WITHOUT_S_DESCR, NO_FAILURE, args)); + + params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.EXPLICIT, + WITH_S_DESCR, NO_FAILURE, args)); + params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.EXPLICIT, + WITHOUT_S_DESCR, NO_FAILURE, args)); + params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.AUTO, + WITH_S_DESCR, NO_FAILURE, args)); + params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.AUTO, + WITHOUT_S_DESCR, LOGIN_MODULE_NOT_FOUND_MSG, args)); + params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.UNNAMED, + WITH_S_DESCR, NO_FAILURE, args)); + params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.UNNAMED, + WITHOUT_S_DESCR, NO_FAILURE, args)); + + params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.EXPLICIT, + WITH_S_DESCR, NO_FAILURE, args)); + params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.EXPLICIT, + WITHOUT_S_DESCR, NO_FAILURE, args)); + params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.AUTO, + WITH_S_DESCR, NO_FAILURE, args)); + params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.AUTO, + WITHOUT_S_DESCR, LOGIN_MODULE_NOT_FOUND_MSG, args)); + params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.UNNAMED, + WITH_S_DESCR, NO_FAILURE, args)); + params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.UNNAMED, + WITHOUT_S_DESCR, NO_FAILURE, args)); + return params.stream().map(p -> p.toArray()).toArray(Object[][]::new); + } + + /** + * Pre-compile and generate the artifacts required to run this test before + * running each test cases. + */ + @BeforeTest + public void buildArtifacts() { + + boolean done = true; + try { + VM_ARGS.put("-Duser.language=", "en"); + VM_ARGS.put("-Duser.region", "US"); + VM_ARGS.put("-Djava.security.auth.login.config=", SRC.resolve( + "jaas.conf").toFile().getCanonicalPath()); + + done = CompilerUtils.compile(S_SRC, S_BUILD_DIR); + done &= CompilerUtils.compile(S_SRC, S_WITH_META_DESCR_BUILD_DIR); + done &= createMetaInfServiceDescriptor(S_META_DESCR_FPATH, S_IMPL); + //Generate regular/modular jars with(out) META-INF + //service descriptor + generateJar(true, MODULE_TYPE.EXPLICIT, MS_JAR, S_BUILD_DIR, false); + generateJar(true, MODULE_TYPE.EXPLICIT, MS_WITH_DESCR_JAR, + S_WITH_META_DESCR_BUILD_DIR, false); + generateJar(true, MODULE_TYPE.UNNAMED, S_JAR, S_BUILD_DIR, false); + generateJar(true, MODULE_TYPE.UNNAMED, S_WITH_DESCRIPTOR_JAR, + S_WITH_META_DESCR_BUILD_DIR, false); + //Generate regular/modular(depends on explicit/auto service) + //jars for client + done &= CompilerUtils.compile(C_SRC, C_BUILD_DIR); + generateJar(false, MODULE_TYPE.EXPLICIT, MC_JAR, C_BUILD_DIR, true); + generateJar(false, MODULE_TYPE.EXPLICIT, + MC_DEPENDS_ON_AUTO_SERVICE_JAR, C_BUILD_DIR, false); + generateJar(false, MODULE_TYPE.UNNAMED, C_JAR, C_BUILD_DIR, false); + System.out.format("%nArtifacts generated successfully? %s", done); + if (!done) { + throw new RuntimeException("Artifact generation failed"); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } - if (!success) { - throw new RuntimeException("Atleast one test failed."); + /** + * Generate modular/regular jar based on module type for this test. + */ + private void generateJar(boolean isService, MODULE_TYPE moduleType, + Path jar, Path compilePath, boolean depends) throws IOException { + + ModuleDescriptor mDescriptor = null; + if (isService) { + mDescriptor = generateModuleDescriptor(isService, moduleType, S_PKG, + S_PKG, S_INTERFACE, S_IMPL, null, M_REQUIRED, depends); + } else { + mDescriptor = generateModuleDescriptor(isService, moduleType, C_PKG, + C_PKG, S_INTERFACE, null, S_PKG, M_REQUIRED, depends); } + generateJar(mDescriptor, jar, compilePath); } - public static boolean runTest(MODULE_TYPE clientModuleType, - MODULE_TYPE serviceModuletype, boolean addMetaInfDescriptor, - boolean expectedResult, String expectedFailure) { + /** + * Holds Logic for the test client. This method will get called with each + * test parameter. + */ + @Override + public OutputAnalyzer executeTestClient(MODULE_TYPE cModuleType, + Path cJarPath, MODULE_TYPE sModuletype, Path sJarPath, + String... args) throws Exception { - boolean result = true; + OutputAnalyzer output = null; 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); + if (!(cModuleType == MODULE_TYPE.UNNAMED + && sModuletype == MODULE_TYPE.UNNAMED)) { + copyJarsToModuleBase(cModuleType, cJarPath, M_BASE_PATH); + copyJarsToModuleBase(sModuletype, sJarPath, M_BASE_PATH); } - System.out.println("Started executing java client with required" + System.out.format("%nExecuting java client with required" + " custom service 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); - OutputAnalyzer output = ProcessTools.executeTestJava( - getJavaCommand(moduleBasePath, classPath, moduleName, - MAIN_CLASS, VM_ARGS)) - .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."); - System.out.println("------------------------------------"); - } else { - throw new RuntimeException("Unexpected failure occured."); - } - } - - } catch (Exception e) { - e.printStackTrace(System.out); - result = false; + String mName = getModuleName(cModuleType, cJarPath, + C_PKG); + Path cmBasePath = (cModuleType != MODULE_TYPE.UNNAMED + || sModuletype != MODULE_TYPE.UNNAMED) ? M_BASE_PATH : null; + String cPath = buildClassPath(cModuleType, cJarPath, sModuletype, + sJarPath); + output = ProcessTools.executeTestJava( + getJavaCommand(cmBasePath, cPath, mName, MAIN, VM_ARGS, + args)).outputTo(System.out).errorTo(System.out); } finally { - //clean module path so that the modulepath can only hold + //clean module path so that the modulepath can hold only //the required jars for next run. - cleanModuleBasePath(); + cleanModuleBasePath(M_BASE_PATH); + System.out.println("--------------------------------------------"); } - - return (expectedResult == result); + return output; } - //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) { + /** + * Decide the pre-generated client/service jar path for each test case + * based on client/service module type. + */ + @Override + public Path findJarPath(boolean service, MODULE_TYPE moduleType, + boolean addMetaDesc, boolean dependsOnServiceModule) { if (service) { if (moduleType == MODULE_TYPE.EXPLICIT) { - if (addMetaInfDescriptor) { - return MODULAR_SERVICE_WITH_DESCRIPTOR_JAR; + if (addMetaDesc) { + return MS_WITH_DESCR_JAR; } else { - return MODULAR_SERVICE_JAR; + return MS_JAR; } } else { - if (addMetaInfDescriptor) { - return REGULAR_SERVICE_WITH_DESCRIPTOR_JAR; + if (addMetaDesc) { + return S_WITH_DESCRIPTOR_JAR; } else { - return REGULAR_SERVICE_JAR; + return S_JAR; } } } else { if (moduleType == MODULE_TYPE.EXPLICIT) { if (dependsOnServiceModule) { - return MODULAR_CLIENT_JAR; + return MC_JAR; } else { - return MODULAR_CLIENT_AUTO_DEPEND_JAR; + return MC_DEPENDS_ON_AUTO_SERVICE_JAR; } } else { - return REGULAR_CLIENT_JAR; + return C_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 jar files required to run this test. - private static boolean createArtifacts() { - - boolean done = true; - try { - VM_ARGS.put("-Duser.language=", "en"); - VM_ARGS.put("-Duser.region", "US"); - VM_ARGS.put("-Djava.security.auth.login.config=", - (CLIENT_SRC_DIR.resolve(CLIENT_PKG).resolve("jaas.conf") - .toRealPath().toString())); - - done = CompilerUtils.compile(SERVICE_SRC_DIR, SERVICE_BUILD_DIR); - done &= CompilerUtils.compile(SERVICE_SRC_DIR, - SERVICE_META_BUILD_DIR); - done &= CompilerUtils.compile(CLIENT_SRC_DIR, CLIENT_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); - generateJar(true, MODULE_TYPE.EXPLICIT, - MODULAR_SERVICE_WITH_DESCRIPTOR_JAR, - SERVICE_META_BUILD_DIR, false); - generateJar(true, MODULE_TYPE.UNNAMED, REGULAR_SERVICE_JAR, - SERVICE_BUILD_DIR, false); - generateJar(true, MODULE_TYPE.UNNAMED, - REGULAR_SERVICE_WITH_DESCRIPTOR_JAR, - SERVICE_META_BUILD_DIR, false); - //Generate regular/modular(depends on explicit/auto service) - //jars for client - generateJar(false, MODULE_TYPE.EXPLICIT, MODULAR_CLIENT_JAR, - CLIENT_BUILD_DIR, true); - generateJar(false, MODULE_TYPE.EXPLICIT, - MODULAR_CLIENT_AUTO_DEPEND_JAR, CLIENT_BUILD_DIR, false); - generateJar(false, MODULE_TYPE.UNNAMED, - REGULAR_CLIENT_JAR, CLIENT_BUILD_DIR, false); - - 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) - 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); - } - if (moduleDescriptor != null) { - System.out.println(String.format( - "Creating Modular jar file '%s'", jarFile)); - } else { - System.out.println(String.format( - "Creating regular 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); - } - JarUtils.updateJarFile(jarFile, dir); - } - - } - - //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(); - }); - } - } --- /dev/null 2015-07-25 05:49:27.889711346 -0700 +++ new/test/java/security/Provider/SecurityProviderModularTest.java 2015-12-21 09:55:14.628493354 -0800 @@ -0,0 +1,338 @@ +/* + * 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.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Arrays; +import java.io.IOException; +import java.lang.module.ModuleDescriptor; +import jdk.testlibrary.ProcessTools; +import jdk.testlibrary.OutputAnalyzer; +import org.testng.annotations.BeforeTest; + +/** + * @test + * @bug 8130360 + * @library /jdk/jigsaw/lib + * @library /lib/testlibrary + * @library /java/security/modules + * @modules java.base/jdk.internal.module + * @build CompilerUtils JarUtils + * @summary Test custom security provider module with all possible modular + * condition. The test includes different combination of security + * client/provider modules interaction with or without service + * description. + * @run testng SecurityProviderModularTest + */ +public class SecurityProviderModularTest extends ModularTest { + + private static final Path S_SRC = SRC.resolve("TestSecurityProvider.java"); + private static final String S_PKG = "provider"; + private static final String S_JAR_NAME = S_PKG + JAR_EXTN; + private static final String S_WITH_DESCR_JAR_NAME = S_PKG + DESCRIPTOR + + JAR_EXTN; + private static final String MS_JAR_NAME = MODULAR + S_PKG + JAR_EXTN; + private static final String MS_WITH_DESCR_JAR_NAME = MODULAR + S_PKG + + DESCRIPTOR + JAR_EXTN; + + private static final Path C_SRC = SRC.resolve( + "TestSecurityProviderClient.java"); + private static final String C_PKG = "client"; + private static final String C_JAR_NAME = C_PKG + JAR_EXTN; + private static final String MC_DEPENDS_ON_AUTO_SERVICE_JAR_NAME = MODULAR + + C_PKG + AUTO + JAR_EXTN; + private static final String MC_JAR_NAME = MODULAR + C_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 S_BUILD_DIR = COMPILE_DIR.resolve(S_PKG); + private static final Path S_WITH_META_DESCR_BUILD_DIR = COMPILE_DIR.resolve( + S_PKG + DESCRIPTOR); + private static final Path C_BUILD_DIR = COMPILE_DIR.resolve(C_PKG); + private static final Path M_BASE_PATH = BUILD_DIR.resolve("mbase"); + private static final Path ARTIFACTS_DIR = BUILD_DIR.resolve("artifacts"); + + private static final Path S_ARTIFACTS_DIR = ARTIFACTS_DIR.resolve(S_PKG); + private static final Path S_JAR = S_ARTIFACTS_DIR.resolve(S_JAR_NAME); + private static final Path S_WITH_DESCRIPTOR_JAR = S_ARTIFACTS_DIR.resolve( + S_WITH_DESCR_JAR_NAME); + private static final Path MS_JAR = S_ARTIFACTS_DIR.resolve( + MS_JAR_NAME); + private static final Path MS_WITH_DESCR_JAR = S_ARTIFACTS_DIR.resolve( + MS_WITH_DESCR_JAR_NAME); + + private static final Path C_ARTIFACTS_DIR = ARTIFACTS_DIR.resolve(C_PKG); + private static final Path C_JAR = C_ARTIFACTS_DIR.resolve(C_JAR_NAME); + private static final Path MC_JAR = C_ARTIFACTS_DIR.resolve(MC_JAR_NAME); + private static final Path MC_DEPENDS_ON_AUTO_SERVICE_JAR = C_ARTIFACTS_DIR + .resolve(MC_DEPENDS_ON_AUTO_SERVICE_JAR_NAME); + + private static final String MAIN = C_PKG + ".TestSecurityProviderClient"; + private static final String S_INTERFACE = "java.security.Provider"; + private static final String S_IMPL = S_PKG + ".TestSecurityProvider"; + private static final List M_REQUIRED = Arrays.asList("java.base"); + private static final Path META_DESCR_PATH = Paths.get("META-INF") + .resolve("services").resolve(S_INTERFACE); + private static final Path S_META_DESCR_FPATH = S_WITH_META_DESCR_BUILD_DIR + .resolve(META_DESCR_PATH); + + private static final boolean WITH_S_DESCR = true; + private static final boolean WITHOUT_S_DESCR = false; + private static final String CLASS_NOT_FOUND_MSG = "NoClassDefFoundError:" + + " provider/TestSecurityProvider"; + private static final String PROVIDER_NOT_FOUND_MSG = "Unable to find Test" + + " Security Provider"; + private static final String CAN_NOT_ACCESS_MSG = "cannot access class"; + private static final String NO_FAILURE = null; + private static final String SERVICE_LOADER = "SERVICE_LOADER"; + private static final String CLASS_LOADER = "CLASS_LOADER"; + private static final String SECURITY_PROP = "SECURITY_PROP"; + private static final List MECHANISMS = Arrays.asList(SERVICE_LOADER, + CLASS_LOADER, SECURITY_PROP); + private static final Path SECURE_PROP_EXTN = Paths.get("./java.secure.ext"); + + /** + * Generates Test specific input parameters. + */ + @Override + public Object[][] getTestInput() { + + List> params = new ArrayList<>(); + MECHANISMS.stream().forEach((mechanism) -> { + boolean useCLoader = CLASS_LOADER.equals(mechanism); + boolean useSLoader = SERVICE_LOADER.equals(mechanism); + String[] args = new String[]{mechanism}; + //PARAMETER ORDERS - + //client Module Type, Service Module Type, + //Service META Descriptor Required, + //Expected Failure message, mech used to find the provider + params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.EXPLICIT, + WITH_S_DESCR, NO_FAILURE, args)); + params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.EXPLICIT, + WITHOUT_S_DESCR, NO_FAILURE, args)); + params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.AUTO, + WITH_S_DESCR, ((useCLoader) ? CAN_NOT_ACCESS_MSG + : NO_FAILURE), args)); + params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.AUTO, + WITHOUT_S_DESCR, CLASS_NOT_FOUND_MSG, args)); + params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.UNNAMED, + WITH_S_DESCR, ((useCLoader) ? CAN_NOT_ACCESS_MSG + : NO_FAILURE), args)); + params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.UNNAMED, + WITHOUT_S_DESCR, ((useCLoader) ? CAN_NOT_ACCESS_MSG + : ((useSLoader) ? PROVIDER_NOT_FOUND_MSG + : NO_FAILURE)), args)); + + params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.EXPLICIT, + WITH_S_DESCR, NO_FAILURE, args)); + params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.EXPLICIT, + WITH_S_DESCR, NO_FAILURE, args)); + params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.AUTO, + WITH_S_DESCR, NO_FAILURE, args)); + params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.AUTO, + WITHOUT_S_DESCR, CLASS_NOT_FOUND_MSG, args)); + params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.UNNAMED, + WITH_S_DESCR, NO_FAILURE, args)); + params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.UNNAMED, + WITHOUT_S_DESCR, ((useSLoader) ? PROVIDER_NOT_FOUND_MSG + : NO_FAILURE), args)); + + params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.EXPLICIT, + WITH_S_DESCR, NO_FAILURE, args)); + params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.EXPLICIT, + WITHOUT_S_DESCR, NO_FAILURE, args)); + params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.AUTO, + WITH_S_DESCR, NO_FAILURE, args)); + params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.AUTO, + WITHOUT_S_DESCR, CLASS_NOT_FOUND_MSG, args)); + params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.UNNAMED, + WITH_S_DESCR, NO_FAILURE, args)); + params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.UNNAMED, + WITHOUT_S_DESCR, ((useSLoader) ? PROVIDER_NOT_FOUND_MSG + : NO_FAILURE), args)); + }); + return params.stream().map(p -> p.toArray()).toArray(Object[][]::new); + } + + /** + * Pre-compile and generate the artifacts required to run this test before + * running each test cases. + */ + @BeforeTest + public void buildArtifacts() { + + boolean done = true; + try { + + done &= CompilerUtils.compile(S_SRC, S_BUILD_DIR); + done &= CompilerUtils.compile(S_SRC, S_WITH_META_DESCR_BUILD_DIR); + done &= createMetaInfServiceDescriptor(S_META_DESCR_FPATH, S_IMPL); + //Generate regular/modular jars with(out) META-INF + //Service descriptor + generateJar(true, MODULE_TYPE.EXPLICIT, MS_JAR, S_BUILD_DIR, false); + generateJar(true, MODULE_TYPE.EXPLICIT, MS_WITH_DESCR_JAR, + S_WITH_META_DESCR_BUILD_DIR, false); + generateJar(true, MODULE_TYPE.UNNAMED, S_JAR, S_BUILD_DIR, false); + generateJar(true, MODULE_TYPE.UNNAMED, S_WITH_DESCRIPTOR_JAR, + S_WITH_META_DESCR_BUILD_DIR, false); + //Generate regular/modular(depends on explicit/auto Service) + //jars for client + done &= CompilerUtils.compile(C_SRC, C_BUILD_DIR, "-cp", + S_JAR.toFile().getCanonicalPath()); + generateJar(false, MODULE_TYPE.EXPLICIT, MC_JAR, C_BUILD_DIR, true); + generateJar(false, MODULE_TYPE.EXPLICIT, + MC_DEPENDS_ON_AUTO_SERVICE_JAR, C_BUILD_DIR, false); + generateJar(false, MODULE_TYPE.UNNAMED, C_JAR, C_BUILD_DIR, false); + System.out.format("%nArtifacts generated successfully? %s", done); + if (!done) { + throw new RuntimeException("Artifacts generation failed"); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + /** + * Generate modular/regular jar based on module type for this test. + */ + private void generateJar(boolean isService, MODULE_TYPE moduleType, + Path jar, Path compilePath, boolean depends) throws IOException { + + ModuleDescriptor mDescriptor = null; + if (isService) { + mDescriptor = generateModuleDescriptor(isService, moduleType, S_PKG, + S_PKG, S_INTERFACE, S_IMPL, null, M_REQUIRED, depends); + } else { + mDescriptor = generateModuleDescriptor(isService, moduleType, C_PKG, + C_PKG, S_INTERFACE, null, S_PKG, M_REQUIRED, depends); + } + generateJar(mDescriptor, jar, compilePath); + } + + /** + * Holds Logic for the test. This method will get called with each test + * parameter. + */ + @Override + public OutputAnalyzer executeTestClient(MODULE_TYPE cModuleType, + Path cJarPath, MODULE_TYPE sModuletype, Path sJarPath, + String... args) throws Exception { + + OutputAnalyzer output = null; + try { + + //For automated/explicit module type copy the corresponding + //jars to module base folder, which will be considered as + //module base path during execution. + if (!(cModuleType == MODULE_TYPE.UNNAMED + && sModuletype == MODULE_TYPE.UNNAMED)) { + copyJarsToModuleBase(cModuleType, cJarPath, M_BASE_PATH); + copyJarsToModuleBase(sModuletype, sJarPath, M_BASE_PATH); + } + + System.out.format("%nExecuting java client with required" + + " custom security provider in class/module path."); + String mName = getModuleName(cModuleType, cJarPath, C_PKG); + Path cmBasePath = (cModuleType != MODULE_TYPE.UNNAMED + || sModuletype != MODULE_TYPE.UNNAMED) ? M_BASE_PATH : null; + String cPath = buildClassPath(cModuleType, cJarPath, sModuletype, + sJarPath); + + Map VM_ARGS = getVMArgs(sModuletype, args); + output = ProcessTools.executeTestJava( + getJavaCommand(cmBasePath, cPath, mName, MAIN, VM_ARGS, + args)).outputTo(System.out).errorTo(System.out); + } finally { + //clean module path so that the modulepath can hold only + //the required jars for next run. + cleanModuleBasePath(M_BASE_PATH); + System.out.println("--------------------------------------------"); + } + return output; + } + + /** + * Decide the pre-generated client/service jar path for each test case + * based on client/service module type. + */ + @Override + public Path findJarPath(boolean isService, MODULE_TYPE moduleType, + boolean addMetaDesc, boolean dependsOnServiceModule) { + if (isService) { + if (moduleType == MODULE_TYPE.EXPLICIT) { + if (addMetaDesc) { + return MS_WITH_DESCR_JAR; + } else { + return MS_JAR; + } + } else { + if (addMetaDesc) { + return S_WITH_DESCRIPTOR_JAR; + } else { + return S_JAR; + } + } + } else { + if (moduleType == MODULE_TYPE.EXPLICIT) { + if (dependsOnServiceModule) { + return MC_JAR; + } else { + return MC_DEPENDS_ON_AUTO_SERVICE_JAR; + } + } else { + return C_JAR; + } + } + } + + /** + * VM argument required for the test. + */ + private Map getVMArgs(MODULE_TYPE sModuletype, + String... args) throws IOException { + final Map VM_ARGS = new LinkedHashMap<>(); + VM_ARGS.put("-Duser.language=", "en"); + VM_ARGS.put("-Duser.region=", "US"); + //If mechanism selected to find the provider through + //Security.getProvider() then use providerName/ProviderClassName based + //on modular/regular provider jar in security configuration file. + if (args != null && args.length > 0 && SECURITY_PROP.equals(args[0])) { + if (sModuletype == MODULE_TYPE.UNNAMED) { + Files.write(SECURE_PROP_EXTN, ("security.provider.10=" + S_IMPL) + .getBytes()); + } else { + Files.write(SECURE_PROP_EXTN, "security.provider.10=TEST" + .getBytes()); + } + VM_ARGS.put("-Djava.security.properties=", SECURE_PROP_EXTN.toFile() + .getCanonicalPath()); + } + return VM_ARGS; + } + +} --- /dev/null 2015-07-25 05:49:27.889711346 -0700 +++ new/test/java/security/Provider/TestSecurityProvider.java 2015-12-21 09:55:15.102487738 -0800 @@ -0,0 +1,45 @@ +/* + * 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. + */ +package provider; + +import java.security.Provider; + +/** + * Custom Security provider for modular test. + */ +public final class TestSecurityProvider extends Provider { + + public TestSecurityProvider() { + super("TEST", 1.0d, "Test Security provider"); + System.out.println(String.format("TEST Security provider loaded" + + " successfully : %s", this.toString())); + } + + @Override + public String toString() { + return "TestSecurityProvider [getName()=" + getName() + + ", getVersion()=" + getVersion() + ", getInfo()=" + + getInfo() + ", toString()=" + super.toString() + "]"; + } + +} --- /dev/null 2015-07-25 05:49:27.889711346 -0700 +++ new/test/java/security/Provider/TestSecurityProviderClient.java 2015-12-21 09:55:15.567482229 -0800 @@ -0,0 +1,80 @@ +/* + * 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. + */ +package client; + +import java.security.Provider; +import java.security.Security; +import java.util.Iterator; +import java.util.ServiceLoader; + +/** + * Modular test for client using different mechanism to find the custom security + * provider. It uses ServiceLoader and ClassLoader to find the TEST provider + * available in classPath/modulePath. It also tries to find, if the provider is + * configured through "java.security" file. + */ +public class TestSecurityProviderClient { + + private static final String CUSTOM_PROVIDER_NAME = "TEST"; + private static final String EXCEPTION_MESSAGE + = "Unable to find Test Security Provider"; + private static final String SERVICE_LOADER = "SERVICE_LOADER"; + private static final String CLASS_LOADER = "CLASS_LOADER"; + + public static void main(String[] args) { + Provider provider = null; + //Try to find the TEST provider loaded by ServiceLoader. + if (args != null && args.length > 0 + && SERVICE_LOADER.equals(args[0])) { + System.out.println( + "Using service loader to find Security provider."); + ServiceLoader services + = ServiceLoader.load(java.security.Provider.class); + Iterator iterator = services.iterator(); + while (iterator.hasNext()) { + Provider p = iterator.next(); + if (p.getName().equals(CUSTOM_PROVIDER_NAME)) { + provider = p; + break; + } + } + } else if (args != null && args.length > 0 + && CLASS_LOADER.equals(args[0])) { + System.out.println("Using class loader to find Security provider."); + //Find the TEST provider loaded by ClassLoader. + provider = new provider.TestSecurityProvider(); + } else { + //Find the TEST provider configured through Security.getProvider(). + System.out.println("Finding Security provider through" + + " Security.getProvider()."); + provider = Security.getProvider(CUSTOM_PROVIDER_NAME); + } + + if (provider != null) { + System.out.format("%nTest Security provider named '%s' loaded " + + "successfully", CUSTOM_PROVIDER_NAME); + } else { + throw new RuntimeException(EXCEPTION_MESSAGE); + } + } +} --- old/test/java/security/modules/JigsawSecurityUtils.java 2015-12-21 09:55:16.296473592 -0800 +++ /dev/null 2015-07-25 05:49:27.889711346 -0700 @@ -1,126 +0,0 @@ -/* - * 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.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.List; -import java.util.Map; -import java.lang.module.ModuleDescriptor; -import static java.lang.module.ModuleDescriptor.Builder; - -/** - * Jigsaw utility methods are part of this class. It exposes methods to generate - * module descriptor object and create service descriptor inside META-INF folder - * etc. - */ -public class JigsawSecurityUtils { - - /** - * Enum represents all supported module types in JDK9. - */ - public enum MODULE_TYPE { - - EXPLICIT, AUTO, UNNAMED; - } - - public static final String SPACE = " "; - - /** - * Constructs a Java Command line string based on modular structure followed - * by modular client and service. - */ - public static String[] getJavaCommand(Path modulePath, - StringBuilder classPath, String clientModuleName, - String mainClass, Map vmArgs) throws IOException { - - final StringBuilder command = new StringBuilder(); - vmArgs.forEach((key, value) -> command.append(key + value + SPACE)); - if (modulePath != null) { - command.append("-mp" + SPACE + modulePath.toRealPath() + SPACE); - } - if (classPath != null && classPath.length() > 0) { - command.append("-cp" + SPACE + classPath + SPACE); - } - if (clientModuleName != null && clientModuleName.length() > 0) { - command.append("-m" + SPACE + clientModuleName + "/"); - } - command.append(mainClass); - return command.toString().trim().split("[\\s]+"); - } - - /** - * Generate ModuleDescriptor object for explicit/auto based client/service - * modules. - */ - public static ModuleDescriptor generateModuleDescriptor( - boolean service, MODULE_TYPE moduleType, String moduleName, - String pkg, String serviceInterface, - String serviceImpl, String serviceModuleName, - List requiredModules, boolean depends) { - final Builder builder; - if (moduleType == MODULE_TYPE.EXPLICIT) { - System.out.println("Generating ModuleDescriptor object"); - builder = new Builder(moduleName).exports(pkg); - if (service) { - builder.provides(serviceInterface, serviceImpl); - } else { - builder.uses(serviceInterface); - if (depends) { - builder.requires(serviceModuleName); - } - } - } else { - System.out.println("ModuleDescriptor object not required."); - return null; - } - requiredModules.stream().forEach(reqMod -> builder.requires(reqMod)); - - return builder.build(); - } - - /** - * Generates service descriptor inside META-INF folder. - */ - public static boolean createMetaInfServiceDescriptor( - Path serviceDescriptorFile, String serviceImpl) { - boolean created = true; - System.out.println(String.format("Creating META-INF service descriptor" - + " for '%s' at path '%s'", serviceImpl, - serviceDescriptorFile)); - try { - Path parent = serviceDescriptorFile.getParent(); - if (parent != null) { - Files.createDirectories(parent); - } - Files.write(serviceDescriptorFile, serviceImpl.getBytes("UTF-8")); - System.out.println(String.format( - "META-INF service descriptor generated successfully")); - } catch (IOException e) { - e.printStackTrace(System.out); - created = false; - } - return created; - } - -} --- /dev/null 2015-07-25 05:49:27.889711346 -0700 +++ new/test/java/security/modules/ModularTest.java 2015-12-21 09:55:16.059476400 -0800 @@ -0,0 +1,277 @@ +/* + * 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.io.IOException; +import java.io.OutputStream; +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import java.util.Map; +import java.util.StringJoiner; +import java.util.Arrays; +import java.util.stream.Collectors; +import java.lang.module.ModuleDescriptor; +import jdk.testlibrary.OutputAnalyzer; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; +import jdk.internal.module.ModuleInfoWriter; +import static java.lang.module.ModuleDescriptor.Builder; + +/** + * Base class need to be extended by modular test for security. + */ +public abstract class ModularTest { + + /** + * Enum represents all supported module types supported in JDK9. i.e. + * 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. + */ + public enum MODULE_TYPE { + + EXPLICIT, AUTO, UNNAMED; + } + + public static final String SPACE = " "; + public static final Path SRC = Paths.get(System.getProperty("test.src")); + public static final String DESCRIPTOR = "MetaService"; + public static final String MODULAR = "Modular"; + public static final String AUTO = "AutoServiceType"; + public static final String JAR_EXTN = ".jar"; + + /** + * Setup test data for the test. + */ + @DataProvider(name = "TestParams") + public Object[][] setUpTestData() { + return getTestInput(); + } + + /** + * Test method for TestNG. + */ + @Test(dataProvider = "TestParams") + public void runTest(MODULE_TYPE cModuleType, MODULE_TYPE sModuletype, + boolean addMetaDesc, String failureMsgExpected, String[] args) + throws Exception { + + String testName = new StringJoiner("_").add(cModuleType.toString()) + .add(sModuletype.toString()).add( + (addMetaDesc) ? "DESCRIPTOR" : "NO_DESCRIPTOR") + .toString(); + + System.out.format("%nStarting Test case: '%s'", testName); + Path cJarPath = findJarPath(false, cModuleType, false, + (sModuletype == MODULE_TYPE.EXPLICIT)); + Path sJarPath = findJarPath(true, sModuletype, addMetaDesc, false); + System.out.format("%nClient jar path : %s ", cJarPath); + System.out.format("%nService jar path : %s ", sJarPath); + OutputAnalyzer output = executeTestClient(cModuleType, cJarPath, + sModuletype, sJarPath, args); + + if (output.getExitValue() != 0) { + if (failureMsgExpected != null + && output.getOutput().contains(failureMsgExpected)) { + System.out.println("PASS: Test is expected to fail here."); + } else { + System.out.format("%nUnexpected failure occured with exit code" + + " '%s'.", output.getExitValue()); + throw new RuntimeException("Unexpected failure occured."); + } + } + } + + /** + * Abstract method need to be implemented by each Test type to provide + * test parameters. + */ + public abstract Object[][] getTestInput(); + + /** + * Execute the test client to access required service. + */ + public abstract OutputAnalyzer executeTestClient(MODULE_TYPE cModuleType, + Path cJarPath, MODULE_TYPE sModuletype, Path sJarPath, + String... args) throws Exception; + + /** + * Find the Jar for service/client based on module type and if service + * descriptor required. + */ + public abstract Path findJarPath(boolean service, MODULE_TYPE moduleType, + boolean addMetaDesc, boolean dependsOnServiceModule); + + /** + * Constructs a Java Command line string based on modular structure followed + * by modular client and service. + */ + public String[] getJavaCommand(Path modulePath, String classPath, + String clientModuleName, String mainClass, + Map vmArgs, String... options) throws IOException { + + final StringJoiner command = new StringJoiner(SPACE, SPACE, SPACE); + vmArgs.forEach((key, value) -> command.add(key + value)); + if (modulePath != null) { + command.add("-mp").add(modulePath.toFile().getCanonicalPath()); + } + if (classPath != null && classPath.length() > 0) { + command.add("-cp").add(classPath); + } + if (clientModuleName != null && clientModuleName.length() > 0) { + command.add("-m").add(clientModuleName + "/" + mainClass); + } else { + command.add(mainClass); + } + command.add(Arrays.stream(options).collect(Collectors.joining(SPACE))); + return command.toString().trim().split("[\\s]+"); + } + + /** + * Generate ModuleDescriptor object for explicit/auto based client/Service + * modules type. + */ + public ModuleDescriptor generateModuleDescriptor(boolean isService, + MODULE_TYPE moduleType, String moduleName, String pkg, + String serviceInterface, String serviceImpl, + String serviceModuleName, List requiredModules, + boolean depends) { + + final Builder builder; + if (moduleType == MODULE_TYPE.EXPLICIT) { + System.out.format(" %nGenerating ModuleDescriptor object"); + builder = new Builder(moduleName).exports(pkg); + if (isService) { + builder.provides(serviceInterface, serviceImpl); + } else { + builder.uses(serviceInterface); + if (depends) { + builder.requires(serviceModuleName); + } + } + } else { + System.out.format(" %nModuleDescriptor object not required."); + return null; + } + requiredModules.stream().forEach(reqMod -> builder.requires(reqMod)); + return builder.build(); + } + + /** + * Generates service descriptor inside META-INF folder. + */ + public boolean createMetaInfServiceDescriptor( + Path serviceDescriptorFile, String serviceImpl) { + boolean created = true; + System.out.format("%nCreating META-INF service descriptor for '%s' " + + "at path '%s'", serviceImpl, serviceDescriptorFile); + try { + Path parent = serviceDescriptorFile.getParent(); + if (parent != null) { + Files.createDirectories(parent); + } + Files.write(serviceDescriptorFile, serviceImpl.getBytes("UTF-8")); + System.out.println( + "META-INF service descriptor generated successfully"); + } catch (IOException e) { + e.printStackTrace(System.out); + created = false; + } + return created; + } + + /** + * Generate modular/regular jar file. + */ + public void generateJar(ModuleDescriptor mDescriptor, Path jar, + Path compilePath) throws IOException { + System.out.format("%nCreating jar file '%s'", jar); + JarUtils.createJarFile(jar, compilePath); + if (mDescriptor != null) { + Path dir = Files.createTempDirectory("tmp"); + Path mi = dir.resolve("module-info.class"); + try (OutputStream out = Files.newOutputStream(mi)) { + ModuleInfoWriter.write(mDescriptor, out); + } + System.out.format("%nAdding 'module-info.class' to jar '%s'", jar); + JarUtils.updateJarFile(jar, dir); + } + } + + /** + * Copy pre-generated jar files to the module base path. + */ + public void copyJarsToModuleBase(MODULE_TYPE moduleType, Path jar, + Path mBasePath) throws IOException { + if (mBasePath != null) { + Files.createDirectories(mBasePath); + } + if (moduleType != MODULE_TYPE.UNNAMED) { + Path artifactName = mBasePath.resolve(jar.getFileName()); + System.out.format("%nCopy jar path: '%s' to module base path: %s", + jar, artifactName); + Files.copy(jar, artifactName); + } + } + + /** + * Construct class path string. + */ + public String buildClassPath(MODULE_TYPE cModuleType, + Path cJarPath, MODULE_TYPE sModuletype, + Path sJarPath) throws IOException { + StringJoiner classPath = new StringJoiner(File.pathSeparator); + classPath.add((cModuleType == MODULE_TYPE.UNNAMED) + ? cJarPath.toFile().getCanonicalPath() : ""); + classPath.add((sModuletype == MODULE_TYPE.UNNAMED) + ? sJarPath.toFile().getCanonicalPath() : ""); + return classPath.toString(); + } + + /** + * Construct executable module name for java. It is fixed for explicit + * module type while it is same as jar file name for automated module type. + */ + public String getModuleName(MODULE_TYPE moduleType, + Path jarPath, String mName) { + String jarName = jarPath.toFile().getName(); + return (moduleType == MODULE_TYPE.EXPLICIT) ? mName + : ((moduleType == MODULE_TYPE.AUTO) ? jarName.substring(0, + jarName.indexOf(JAR_EXTN)) : ""); + } + + /** + * Delete all the files inside the base module path. + */ + public void cleanModuleBasePath(Path mBasePath) { + Arrays.asList(mBasePath.toFile().listFiles()).forEach(f -> { + System.out.println("delete: " + f); + f.delete(); + }); + } + +} --- old/test/javax/security/auth/login/modules/src/jaasclientmodule/client/JaasClient.java 2015-12-21 09:55:16.870466790 -0800 +++ /dev/null 2015-07-25 05:49:27.889711346 -0700 @@ -1,103 +0,0 @@ -/* - * 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. - */ -package client; - -import java.io.IOException; -import java.security.Principal; -import javax.security.auth.callback.Callback; -import javax.security.auth.callback.CallbackHandler; -import javax.security.auth.callback.NameCallback; -import javax.security.auth.callback.PasswordCallback; -import javax.security.auth.callback.UnsupportedCallbackException; -import javax.security.auth.login.LoginException; -import javax.security.auth.login.LoginContext; -import com.sun.security.auth.UnixPrincipal; - -/** - * JAAS client which will try to authenticate a user through a custom JAAS LOGIN - * Module. - */ -public class JaasClient { - - private static final String USER_NAME = "testUser"; - private static final String PASSWORD = "testPassword"; - private static final String LOGIN_CONTEXT = "ModularLoginConf"; - - public static void main(String[] args) { - try { - LoginContext lc = new LoginContext(LOGIN_CONTEXT, - new MyCallbackHandler()); - lc.login(); - checkPrincipal(lc, true); - lc.logout(); - checkPrincipal(lc, false); - } catch (LoginException le) { - throw new RuntimeException(le); - } - System.out.println("Test passed."); - - } - - /* - * Check context for principal of the test user. - */ - private static void checkPrincipal(LoginContext loginContext, - boolean principalShouldExist) { - if (!principalShouldExist) { - if (loginContext.getSubject().getPrincipals().size() != 0) { - throw new RuntimeException("Test failed. Principal was not " - + "cleared."); - } - return; - } - for (Principal p : loginContext.getSubject().getPrincipals()) { - if (p instanceof UnixPrincipal - && USER_NAME.equals(p.getName())) { - //Proper principal was found, return. - return; - } - } - throw new RuntimeException("Test failed. UnixPrincipal " - + USER_NAME + " expected."); - - } - - private static class MyCallbackHandler implements CallbackHandler { - - @Override - public void handle(Callback[] callbacks) throws IOException, - UnsupportedCallbackException { - for (Callback callback : callbacks) { - if (callback instanceof NameCallback) { - ((NameCallback) callback).setName(USER_NAME); - } else if (callback instanceof PasswordCallback) { - ((PasswordCallback) callback).setPassword( - PASSWORD.toCharArray()); - } else { - throw new UnsupportedCallbackException(callback); - } - } - } - } - -} --- /dev/null 2015-07-25 05:49:27.889711346 -0700 +++ new/test/javax/security/auth/login/modules/JaasClient.java 2015-12-21 09:55:16.628469658 -0800 @@ -0,0 +1,103 @@ +/* + * 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. + */ +package client; + +import java.io.IOException; +import java.security.Principal; +import javax.security.auth.callback.Callback; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.callback.NameCallback; +import javax.security.auth.callback.PasswordCallback; +import javax.security.auth.callback.UnsupportedCallbackException; +import javax.security.auth.login.LoginException; +import javax.security.auth.login.LoginContext; +import com.sun.security.auth.UnixPrincipal; + +/** + * JAAS client which will try to authenticate a user through a custom JAAS LOGIN + * Module. + */ +public class JaasClient { + + private static final String USER_NAME = "testUser"; + private static final String PASSWORD = "testPassword"; + private static final String LOGIN_CONTEXT = "ModularLoginConf"; + + public static void main(String[] args) { + try { + LoginContext lc = new LoginContext(LOGIN_CONTEXT, + new MyCallbackHandler()); + lc.login(); + checkPrincipal(lc, true); + lc.logout(); + checkPrincipal(lc, false); + } catch (LoginException le) { + throw new RuntimeException(le); + } + System.out.println("Test passed."); + + } + + /* + * Check context for principal of the test user. + */ + private static void checkPrincipal(LoginContext loginContext, + boolean principalShouldExist) { + if (!principalShouldExist) { + if (loginContext.getSubject().getPrincipals().size() != 0) { + throw new RuntimeException("Test failed. Principal was not " + + "cleared."); + } + return; + } + for (Principal p : loginContext.getSubject().getPrincipals()) { + if (p instanceof UnixPrincipal + && USER_NAME.equals(p.getName())) { + //Proper principal was found, return. + return; + } + } + throw new RuntimeException("Test failed. UnixPrincipal " + + USER_NAME + " expected."); + + } + + private static class MyCallbackHandler implements CallbackHandler { + + @Override + public void handle(Callback[] callbacks) throws IOException, + UnsupportedCallbackException { + for (Callback callback : callbacks) { + if (callback instanceof NameCallback) { + ((NameCallback) callback).setName(USER_NAME); + } else if (callback instanceof PasswordCallback) { + ((PasswordCallback) callback).setPassword( + PASSWORD.toCharArray()); + } else { + throw new UnsupportedCallbackException(callback); + } + } + } + } + +} --- old/test/javax/security/auth/login/modules/src/jaasloginmodule/login/TestLoginModule.java 2015-12-21 09:55:17.283461896 -0800 +++ /dev/null 2015-07-25 05:49:27.889711346 -0700 @@ -1,140 +0,0 @@ -/* - * 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. - */ -package login; - -import java.io.IOException; -import java.util.Map; -import javax.security.auth.Subject; -import javax.security.auth.callback.Callback; -import javax.security.auth.callback.CallbackHandler; -import javax.security.auth.callback.NameCallback; -import javax.security.auth.callback.PasswordCallback; -import javax.security.auth.callback.UnsupportedCallbackException; -import javax.security.auth.login.LoginException; -import javax.security.auth.spi.LoginModule; -import com.sun.security.auth.UnixPrincipal; - -/** - * Custom JAAS login module which will be loaded through Java LoginContext when - * it is bundled by Strict/Auto/Unnamed modules. - */ -public class TestLoginModule implements LoginModule { - - private static final String USER_NAME = "testUser"; - private static final String PASSWORD = "testPassword"; - private Subject subject; - private CallbackHandler callbackHandler; - private UnixPrincipal userPrincipal; - private String username; - private String password; - private boolean succeeded = false; - private boolean commitSucceeded = false; - - @Override - public void initialize(Subject subject, CallbackHandler callbackHandler, - Map sharedState, Map options) { - - this.subject = subject; - this.callbackHandler = callbackHandler; - System.out.println(String.format( - "'%s' login module initialized", this.getClass())); - } - - /* - * Authenticate the user by prompting for a username and password. - */ - @Override - public boolean login() throws LoginException { - if (callbackHandler == null) { - throw new LoginException("No CallbackHandler available"); - } - - Callback[] callbacks = new Callback[2]; - callbacks[0] = new NameCallback("Username: "); - callbacks[1] = new PasswordCallback("Password: ", false); - - try { - callbackHandler.handle(callbacks); - username = ((NameCallback) callbacks[0]).getName(); - password = new String(((PasswordCallback) callbacks[1]) - .getPassword()); - System.out.println(String.format("'%s' login module found username" - + " as '%s' and password as '%s'", this.getClass(), - username, password)); - if (username.equals(USER_NAME) - && password.equals(PASSWORD)) { - System.out.println(String.format("'%s' login module " - + "authentication done successfully", this.getClass())); - succeeded = true; - return true; - } - throw new IllegalArgumentException("Incorrect username/password!"); - } catch (IOException | UnsupportedCallbackException e) { - throw new LoginException("Login failed: " + e.getMessage()); - } - } - - @Override - public boolean commit() throws LoginException { - if (succeeded == false) { - return false; - } - userPrincipal = new UnixPrincipal(username); - if (!subject.getPrincipals().contains(userPrincipal)) { - subject.getPrincipals().add(userPrincipal); - } - System.out.println(String.format("'%s' login module authentication " - + "committed", this.getClass())); - password = null; - commitSucceeded = true; - return true; - } - - @Override - public boolean abort() throws LoginException { - if (succeeded == false) { - return false; - } - System.out.println(String.format( - "'%s' login module aborted", this.getClass())); - clearState(); - return true; - } - - @Override - public boolean logout() throws LoginException { - clearState(); - System.out.println(String.format( - "'%s' login module logout completed", this.getClass())); - return true; - } - - private void clearState() { - if (commitSucceeded) { - subject.getPrincipals().remove(userPrincipal); - } - username = null; - password = null; - userPrincipal = null; - } -} --- /dev/null 2015-07-25 05:49:27.889711346 -0700 +++ new/test/javax/security/auth/login/modules/TestLoginModule.java 2015-12-21 09:55:17.040464776 -0800 @@ -0,0 +1,140 @@ +/* + * 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. + */ +package login; + +import java.io.IOException; +import java.util.Map; +import javax.security.auth.Subject; +import javax.security.auth.callback.Callback; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.callback.NameCallback; +import javax.security.auth.callback.PasswordCallback; +import javax.security.auth.callback.UnsupportedCallbackException; +import javax.security.auth.login.LoginException; +import javax.security.auth.spi.LoginModule; +import com.sun.security.auth.UnixPrincipal; + +/** + * Custom JAAS login module which will be loaded through Java LoginContext when + * it is bundled by Strict/Auto/Unnamed modules. + */ +public class TestLoginModule implements LoginModule { + + private static final String USER_NAME = "testUser"; + private static final String PASSWORD = "testPassword"; + private Subject subject; + private CallbackHandler callbackHandler; + private UnixPrincipal userPrincipal; + private String username; + private String password; + private boolean succeeded = false; + private boolean commitSucceeded = false; + + @Override + public void initialize(Subject subject, CallbackHandler callbackHandler, + Map sharedState, Map options) { + + this.subject = subject; + this.callbackHandler = callbackHandler; + System.out.println(String.format( + "'%s' login module initialized", this.getClass())); + } + + /* + * Authenticate the user by prompting for a username and password. + */ + @Override + public boolean login() throws LoginException { + if (callbackHandler == null) { + throw new LoginException("No CallbackHandler available"); + } + + Callback[] callbacks = new Callback[2]; + callbacks[0] = new NameCallback("Username: "); + callbacks[1] = new PasswordCallback("Password: ", false); + + try { + callbackHandler.handle(callbacks); + username = ((NameCallback) callbacks[0]).getName(); + password = new String(((PasswordCallback) callbacks[1]) + .getPassword()); + System.out.println(String.format("'%s' login module found username" + + " as '%s' and password as '%s'", this.getClass(), + username, password)); + if (username.equals(USER_NAME) + && password.equals(PASSWORD)) { + System.out.println(String.format("'%s' login module " + + "authentication done successfully", this.getClass())); + succeeded = true; + return true; + } + throw new IllegalArgumentException("Incorrect username/password!"); + } catch (IOException | UnsupportedCallbackException e) { + throw new LoginException("Login failed: " + e.getMessage()); + } + } + + @Override + public boolean commit() throws LoginException { + if (succeeded == false) { + return false; + } + userPrincipal = new UnixPrincipal(username); + if (!subject.getPrincipals().contains(userPrincipal)) { + subject.getPrincipals().add(userPrincipal); + } + System.out.println(String.format("'%s' login module authentication " + + "committed", this.getClass())); + password = null; + commitSucceeded = true; + return true; + } + + @Override + public boolean abort() throws LoginException { + if (succeeded == false) { + return false; + } + System.out.println(String.format( + "'%s' login module aborted", this.getClass())); + clearState(); + return true; + } + + @Override + public boolean logout() throws LoginException { + clearState(); + System.out.println(String.format( + "'%s' login module logout completed", this.getClass())); + return true; + } + + private void clearState() { + if (commitSucceeded) { + subject.getPrincipals().remove(userPrincipal); + } + username = null; + password = null; + userPrincipal = null; + } +} --- old/test/javax/security/auth/login/modules/src/jaasclientmodule/client/jaas.conf 2015-12-21 09:55:17.699456968 -0800 +++ /dev/null 2015-07-25 05:49:27.889711346 -0700 @@ -1,3 +0,0 @@ -ModularLoginConf { - login.TestLoginModule required; -}; --- /dev/null 2015-07-25 05:49:27.889711346 -0700 +++ new/test/javax/security/auth/login/modules/jaas.conf 2015-12-21 09:55:17.452459894 -0800 @@ -0,0 +1,3 @@ +ModularLoginConf { + login.TestLoginModule required; +};