Path: blob/master/test/jdk/java/security/Provider/SecurityProviderModularTest.java
41149 views
/*1* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223import java.nio.file.Files;24import java.nio.file.Path;25import java.nio.file.Paths;26import java.nio.file.StandardCopyOption;27import java.security.Security;28import java.util.Collections;29import java.util.HashMap;30import java.util.LinkedList;31import java.util.List;32import java.util.Map;33import java.util.Arrays;34import java.util.stream.Stream;35import java.io.File;36import java.io.IOException;37import java.io.OutputStream;38import java.lang.module.ModuleDescriptor;39import java.lang.module.ModuleDescriptor.Builder;40import jdk.internal.module.ModuleInfoWriter;41import jdk.test.lib.process.ProcessTools;42import jdk.test.lib.util.JarUtils;434445/*46* @test47* @bug 8130360 818331048* @summary Test security provider in different combination of modular option49* defined with(out) service description.50* @library /test/lib51* @modules java.base/jdk.internal.module52* @build jdk.test.lib.util.JarUtils TestProvider TestClient53* @run main SecurityProviderModularTest CL true54* @run main SecurityProviderModularTest CL false55* @run main SecurityProviderModularTest SL true56* @run main SecurityProviderModularTest SL false57* @run main SecurityProviderModularTest SPN true58* @run main SecurityProviderModularTest SPN false59* @run main SecurityProviderModularTest SPT true60* @run main SecurityProviderModularTest SPT false61*/62public class SecurityProviderModularTest {6364private static final Path TEST_CLASSES65= Paths.get(System.getProperty("test.classes"));66private static final Path ARTIFACT_DIR = Paths.get("jars");67private static final Path SEC_FILE = Paths.get("java.extn.security");68private static final String PS = File.pathSeparator;69private static final String P_TYPE = "p.TestProvider";70private static final String C_TYPE = "c.TestClient";7172/**73* Here is the naming convention followed.74* Test runtime arguments,75* CL - Provider class loaded through ClassLoader76* SL - Provider class to be discovered by ServiceLoader77* SPN - Provider name defined through "java.extn.security" file which78* referred through system property "java.security.properties".79* SPT - Provider type defined through "java.extn.security" file which80* referred through system property "java.security.properties".81*82* For each jar file name,83* p.jar - Unnamed provider jar.84* pd.jar - Unnamed provider jar with META-INF provider descriptor.85* mp.jar - Modular provider jar.86* mpd.jar - Modular provider jar with META-INF provider descriptor.87* msp.jar - Modular provider jar provides service through module-info.java88* mspd.jar - Modular provider jar with META-INF provider descriptor and89* provides service through module-info.java.90* c.jar - Unnamed client jar.91* mc.jar - Modular client jar.92* mcs.jar - Modular client jar uses service through module-info.java.93* amc.jar - Modular client used for automatic provider jar.94* amcs.jar - Modular client used for automatic provider jar uses service95* through module-info.java.96*/97private static final Path P_JAR = artifact("p.jar");98private static final Path PD_JAR = artifact("pd.jar");99private static final Path MP_JAR = artifact("mp.jar");100private static final Path MPD_JAR = artifact("mpd.jar");101private static final Path MSP_JAR = artifact("msp.jar");102private static final Path MSPD_JAR = artifact("mspd.jar");103private static final Path C_JAR = artifact("c.jar");104private static final Path MC_JAR = artifact("mc.jar");105private static final Path MCS_JAR = artifact("mcs.jar");106private static final Path AMC_JAR = artifact("amc.jar");107private static final Path AMCS_JAR = artifact("amcs.jar");108private static final Map<String, String> MSG_MAP = new HashMap<>();109110static {111/*112* This mapping help process finding expected message based113* on the key passed as argument while executing java command.114*/115MSG_MAP.put("NoAccess", "cannot access class p.TestProvider");116MSG_MAP.put("Success", "Client: found provider TestProvider");117MSG_MAP.put("NoProvider", "Provider TestProvider not found");118}119120private final String addUNArg;121private final String addNMArg;122private final String cArg;123private final String unnP;124private final String modP;125private final String unnC;126private final String modC;127private final String autoMC;128private final String expModRes;129private final String expAModRes;130// Common set of VM arguments used in all test cases131private final List<String> commonArgs;132133public SecurityProviderModularTest(String use, boolean metaDesc) {134135List<String> argList = new LinkedList<>();136argList.add("-Duser.language=en");137argList.add("-Duser.region=US");138final boolean useSL = "SL".equals(use) || "SPN".equals(use);139final boolean useCL = "CL".equals(use);140final boolean useSPT = "SPT".equals(use);141final boolean useSP = use.startsWith("SP");142/* Use Security property file when the provider expected to143* loaded through Security property file. */144if (useSP) {145/* Create a java.security file to specify the new provider.146* java.security file extension can be provided using147* "-Djava.security.properties" VM argument at runtime.*/148createJavaSecurityFileExtn("SPN".equals(use));149argList.add("-Djava.security.properties=" + toAbsPath(SEC_FILE));150}151commonArgs = Collections.unmodifiableList(argList);152cArg = (useCL) ? P_TYPE : "TestProvider";153addUNArg = (useSL) ? "" : ("--add-modules="154+ ((metaDesc) ? "pd" : "p"));155addNMArg = (useSL) ? "" : "--add-modules=mp";156157// Based on Testcase, select unnamed/modular jar files to use.158unnP = toAbsPath((metaDesc) ? PD_JAR : P_JAR);159modP = toAbsPath(useSL ? (metaDesc ? MSPD_JAR : MSP_JAR)160: (metaDesc ? MPD_JAR : MP_JAR));161unnC = toAbsPath(C_JAR);162modC = toAbsPath(useSL ? MCS_JAR : MC_JAR);163autoMC = toAbsPath(useSL ? AMCS_JAR : AMC_JAR);164165expModRes = "Success";166expAModRes = (useSPT | useCL) ? "Success"167: (metaDesc) ? "Success" : "NoProvider";168String loadByMsg = useSP ? "SecurityPropertyFile"169: ((useCL) ? "ClassLoader" : "ServiceLoader");170System.out.printf("%n*** Providers loaded through %s and includes"171+ " META Descriptor: %s ***%n%n", loadByMsg, metaDesc);172}173174/*175* Test cases are based on the following logic,176* for (ProviderLoadedThrough : {"ServiceLoader", "ClassLoader",177* "SecurityPropertyFile"}) {178* for (definedWith : {"METAINFService", "WithoutMETAINFService"}) {179* for (clientType : {"NAMED", "AUTOMATIC", "UNNAMED"}) {180* for (providerType : {"NAMED", "AUTOMATIC", "UNNAMED"}) {181* Create and run java command for each possible case182* }183* }184* }185* }186*/187public static void main(String[] args) throws Exception {188189// Generates unnamed and modular jars.190setUp();191boolean metaDesc = Boolean.valueOf(args[1]);192SecurityProviderModularTest test193= new SecurityProviderModularTest(args[0], metaDesc);194test.process(args[0]);195}196197private void process(String use) throws Exception {198199// Case: NAMED-NAMED, NAMED-AUTOMATIC, NAMED-UNNAMED200System.out.printf("Case: Modular Client and Modular Provider");201execute(String.format("--module-path %s%s%s -m mc/%s %s %s",202modC, PS, modP, C_TYPE, use, cArg), expModRes);203System.out.printf("Case: Modular Client and automatic Provider");204execute(String.format("--module-path %s%s%s %s -m mc/%s %s %s", autoMC,205PS, unnP, addUNArg, C_TYPE, use, cArg), expAModRes);206System.out.printf("Case: Modular Client and unnamed Provider");207execute(String.format("--module-path %s -cp %s -m mc/%s %s %s", autoMC,208unnP, C_TYPE, use, cArg), expAModRes);209210// Case: AUTOMATIC-NAMED, AUTOMATIC-AUTOMATIC, AUTOMATIC-UNNAMED211System.out.printf("Case: Automatic Client and modular Provider");212execute(String.format("--module-path %s%s%s %s -m c/%s %s %s", unnC,213PS, modP, addNMArg, C_TYPE, use, cArg), expModRes);214System.out.printf("Case: Automatic Client and automatic Provider");215execute(String.format("--module-path %s%s%s %s -m c/%s %s %s", unnC,216PS, unnP, addUNArg, C_TYPE, use, cArg), expAModRes);217System.out.printf("Case: Automatic Client and unnamed Provider");218execute(String.format("--module-path %s -cp %s -m c/%s %s %s", unnC,219unnP, C_TYPE, use, cArg), expAModRes);220221// Case: UNNAMED-NAMED, UNNAMED-AUTOMATIC, UNNAMED-UNNAMED222System.out.printf("Case: Unnamed Client and modular Provider");223execute(String.format("-cp %s --module-path %s %s %s %s %s", unnC,224modP, addNMArg, C_TYPE, use, cArg), expModRes);225System.out.printf("Case: Unnamed Client and automatic Provider");226execute(String.format("-cp %s --module-path %s %s %s %s %s", unnC,227unnP, addUNArg, C_TYPE, use, cArg), expAModRes);228System.out.printf("Case: Unnamed Client and unnamed Provider");229execute(String.format("-cp %s%s%s %s %s %s", unnC, PS, unnP, C_TYPE,230use, cArg), expAModRes);231232// Case: unnamed jars in --module-path and modular jars in -cp.233System.out.printf(234"Case: Unnamed Client and Unnamed Provider in modulepath");235execute(String.format("--module-path %s%s%s %s -m c/%s %s %s", unnC,236PS, unnP, addUNArg, C_TYPE, use, cArg), expAModRes);237System.out.printf(238"Case: Modular Client and Modular Provider in classpath");239execute(String.format("-cp %s%s%s %s %s %s", modC, PS, modP, C_TYPE,240use, cArg), expAModRes);241}242243/**244* Execute with command arguments and process the result.245*/246private void execute(String args, String msgKey) throws Exception {247248String[] safeArgs = Stream.concat(commonArgs.stream(),249Stream.of(args.split("\\s+"))).filter(s -> {250if (s.contains(" ")) {251throw new RuntimeException("No spaces in args");252}253return !s.isEmpty();254}).toArray(String[]::new);255String out = ProcessTools.executeTestJvm(safeArgs).getOutput();256// Handle response.257if ((msgKey != null && out.contains(MSG_MAP.get(msgKey)))) {258System.out.printf("PASS: Expected Result: %s.%n",259MSG_MAP.get(msgKey));260} else if (out.contains("Exception") || out.contains("Error")) {261System.out.printf("OUTPUT: %s", out);262throw new RuntimeException("FAIL: Unknown Exception occured. "263+ "Expected: " + MSG_MAP.get(msgKey));264} else {265System.out.printf("OUTPUT: %s", out);266throw new RuntimeException("FAIL: Unknown Test case found");267}268}269270/**271* Creates Unnamed/modular jar files for TestClient and TestClassLoader.272*/273private static void setUp() throws Exception {274275if (ARTIFACT_DIR.toFile().exists()) {276System.out.println("Skipping setup: Artifacts already exists.");277return;278}279// Generate unnamed provider jar file.280JarUtils.createJarFile(P_JAR, TEST_CLASSES, "p/TestProvider.class");281// Generate unnamed client jar file.282JarUtils.createJarFile(C_JAR, TEST_CLASSES, "c/TestClient.class");283// Generate unnamed provider jar files with META-INF descriptor.284generateJar(P_JAR, PD_JAR, null, true);285286Builder mBuilder = ModuleDescriptor.newModule("mp").exports("p");287// Modular provider defined as META-INF service.288generateJar(P_JAR, MPD_JAR, mBuilder.build(), true);289// Modular jar exports package to let the provider type accessible.290generateJar(P_JAR, MP_JAR, mBuilder.build(), false);291292mBuilder = ModuleDescriptor.newModule("mp")293.provides("java.security.Provider", Arrays.asList(P_TYPE));294// Modular provider Service in module-info does not need to export295// its package.296generateJar(P_JAR, MSP_JAR, mBuilder.build(), false);297// Modular provider Service in module-info also have META-INF descriptor298generateJar(P_JAR, MSPD_JAR, mBuilder.build(), true);299300mBuilder = ModuleDescriptor.newModule("mc").exports("c");301// Generate modular client jar file to use automatic provider jar.302generateJar(C_JAR, AMC_JAR, mBuilder.build(), false);303// Generate modular client jar file to use modular provider jar.304generateJar(C_JAR, MC_JAR, mBuilder.requires("mp").build(), false);305306mBuilder = ModuleDescriptor.newModule("mc").exports("c")307.uses("java.security.Provider");308// Generate modular client jar file to use automatic provider service.309generateJar(C_JAR, AMCS_JAR, mBuilder.build(), false);310// Generate modular client jar file using modular provider service.311generateJar(C_JAR, MCS_JAR, mBuilder.requires("mp").build(), false);312}313314/**315* Update Unnamed jars and include descriptor files.316*/317private static void generateJar(Path sjar, Path djar,318ModuleDescriptor mDesc, boolean metaDesc) throws Exception {319320Files.copy(sjar, djar, StandardCopyOption.REPLACE_EXISTING);321Path dir = Files.createTempDirectory("tmp");322if (metaDesc) {323write(dir.resolve(Paths.get("META-INF", "services",324"java.security.Provider")), P_TYPE);325}326if (mDesc != null) {327Path mi = dir.resolve("module-info.class");328try (OutputStream out = Files.newOutputStream(mi)) {329ModuleInfoWriter.write(mDesc, out);330}331System.out.format("Added 'module-info.class' in '%s'%n", djar);332}333JarUtils.updateJarFile(djar, dir);334}335336/**337* Look for file path in generated jars.338*/339private static Path artifact(String file) {340return ARTIFACT_DIR.resolve(file);341}342343/**344* Convert to absolute file path.345*/346private static String toAbsPath(Path path) {347return path.toFile().getAbsolutePath();348}349350/**351* Create the parent directories if missing to ensure the path exist.352*/353private static Path ensurePath(Path at) throws IOException {354Path parent = at.getParent();355if (parent != null && !parent.toFile().exists()) {356ensurePath(parent);357}358return Files.createDirectories(parent);359}360361/**362* Generates service descriptor inside META-INF folder.363*/364private static void write(Path at, String content) throws IOException {365ensurePath(at);366Files.write(at, content.getBytes("UTF-8"));367}368369/**370* Create new provider entry through java.security file extension.371* New provider entry will be the last entry inside the JRE.372*/373private static void createJavaSecurityFileExtn(boolean useName) {374int insertAt = Security.getProviders().length + 1;375String provider = (useName ? "TestProvider" : P_TYPE);376try {377Files.write(SEC_FILE, String.format("security.provider.%s=%s",378insertAt, provider).getBytes("UTF-8"));379} catch (IOException e) {380throw new RuntimeException(e);381}382System.out.printf("Security property file created at: %s with value:"383+ " %s%n", SEC_FILE, provider);384}385}386387388