8233922: Service binding augments module graph with observable incubator modules
Reviewed-by: mchung
This commit is contained in:
parent
ec51784c0d
commit
745feb207c
@ -312,7 +312,7 @@ public final class Configuration {
|
||||
{
|
||||
List<Configuration> parents = List.of(empty());
|
||||
Resolver resolver = new Resolver(finder, parents, ModuleFinder.of(), traceOutput);
|
||||
resolver.resolve(roots).bind();
|
||||
resolver.resolve(roots).bind(/*bindIncubatorModules*/false);
|
||||
return new Configuration(parents, resolver);
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,6 @@ package java.lang.module;
|
||||
import java.io.PrintStream;
|
||||
import java.lang.module.ModuleDescriptor.Provides;
|
||||
import java.lang.module.ModuleDescriptor.Requires.Modifier;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@ -45,6 +44,7 @@ import java.util.stream.Collectors;
|
||||
|
||||
import jdk.internal.module.ModuleHashes;
|
||||
import jdk.internal.module.ModuleReferenceImpl;
|
||||
import jdk.internal.module.ModuleResolution;
|
||||
import jdk.internal.module.ModuleTarget;
|
||||
|
||||
/**
|
||||
@ -215,15 +215,32 @@ final class Resolver {
|
||||
* service-use relation.
|
||||
*/
|
||||
Resolver bind() {
|
||||
return bind(/*bindIncubatorModules*/true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Augments the set of resolved modules with modules induced by the
|
||||
* service-use relation.
|
||||
*
|
||||
* @param bindIncubatorModules true if incubator modules are candidates to
|
||||
* add to the module graph
|
||||
*/
|
||||
Resolver bind(boolean bindIncubatorModules) {
|
||||
// Scan the finders for all available service provider modules. As
|
||||
// java.base uses services then the module finders will be scanned
|
||||
// anyway.
|
||||
Map<String, Set<ModuleReference>> availableProviders = new HashMap<>();
|
||||
for (ModuleReference mref : findAll()) {
|
||||
ModuleDescriptor descriptor = mref.descriptor();
|
||||
if (!descriptor.provides().isEmpty()) {
|
||||
|
||||
boolean candidate;
|
||||
if (!bindIncubatorModules && (mref instanceof ModuleReferenceImpl)) {
|
||||
ModuleResolution mres = ((ModuleReferenceImpl) mref).moduleResolution();
|
||||
candidate = (mres == null) || (mres.hasIncubatingWarning() == false);
|
||||
} else {
|
||||
candidate = true;
|
||||
}
|
||||
if (candidate && !descriptor.provides().isEmpty()) {
|
||||
for (Provides provides : descriptor.provides()) {
|
||||
String sn = provides.service();
|
||||
|
||||
|
@ -352,7 +352,7 @@ public final class ModuleBootstrap {
|
||||
|
||||
Configuration cf;
|
||||
if (needResolution) {
|
||||
cf = JLMA.resolveAndBind(finder, roots, traceOutput);
|
||||
cf = Modules.newBootLayerConfiguration(finder, roots, traceOutput);
|
||||
} else {
|
||||
if (archivedModuleGraph != null) {
|
||||
cf = archivedModuleGraph.configuration();
|
||||
|
@ -34,6 +34,7 @@ import java.util.stream.Stream;
|
||||
import jdk.internal.org.objectweb.asm.ClassWriter;
|
||||
import jdk.internal.org.objectweb.asm.ModuleVisitor;
|
||||
import jdk.internal.org.objectweb.asm.Opcodes;
|
||||
import jdk.internal.org.objectweb.asm.commons.ModuleResolutionAttribute;
|
||||
import jdk.internal.org.objectweb.asm.commons.ModuleTargetAttribute;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.*;
|
||||
|
||||
@ -78,7 +79,9 @@ public final class ModuleInfoWriter {
|
||||
* Writes the given module descriptor to a module-info.class file,
|
||||
* returning it in a byte array.
|
||||
*/
|
||||
private static byte[] toModuleInfo(ModuleDescriptor md, ModuleTarget target) {
|
||||
private static byte[] toModuleInfo(ModuleDescriptor md,
|
||||
ModuleResolution mres,
|
||||
ModuleTarget target) {
|
||||
ClassWriter cw = new ClassWriter(0);
|
||||
cw.visit(Opcodes.V10, ACC_MODULE, "module-info", null, null, null);
|
||||
|
||||
@ -147,6 +150,11 @@ public final class ModuleInfoWriter {
|
||||
|
||||
mv.visitEnd();
|
||||
|
||||
// write ModuleResolution attribute if specified
|
||||
if (mres != null) {
|
||||
cw.visitAttribute(new ModuleResolutionAttribute(mres.value()));
|
||||
}
|
||||
|
||||
// write ModuleTarget attribute if there is a target platform
|
||||
if (target != null && target.targetPlatform().length() > 0) {
|
||||
cw.visitAttribute(new ModuleTargetAttribute(target.targetPlatform()));
|
||||
@ -161,14 +169,39 @@ public final class ModuleInfoWriter {
|
||||
* module-info.class.
|
||||
*/
|
||||
public static void write(ModuleDescriptor descriptor,
|
||||
ModuleResolution mres,
|
||||
ModuleTarget target,
|
||||
OutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
byte[] bytes = toModuleInfo(descriptor, target);
|
||||
byte[] bytes = toModuleInfo(descriptor, mres, target);
|
||||
out.write(bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a module descriptor to the given output stream as a
|
||||
* module-info.class.
|
||||
*/
|
||||
public static void write(ModuleDescriptor descriptor,
|
||||
ModuleResolution mres,
|
||||
OutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
write(descriptor, mres, null, out);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a module descriptor to the given output stream as a
|
||||
* module-info.class.
|
||||
*/
|
||||
public static void write(ModuleDescriptor descriptor,
|
||||
ModuleTarget target,
|
||||
OutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
write(descriptor, null, target, out);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a module descriptor to the given output stream as a
|
||||
* module-info.class.
|
||||
@ -176,7 +209,7 @@ public final class ModuleInfoWriter {
|
||||
public static void write(ModuleDescriptor descriptor, OutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
write(descriptor, null, out);
|
||||
write(descriptor, null, null, out);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -184,7 +217,7 @@ public final class ModuleInfoWriter {
|
||||
* in module-info.class format.
|
||||
*/
|
||||
public static ByteBuffer toByteBuffer(ModuleDescriptor descriptor) {
|
||||
byte[] bytes = toModuleInfo(descriptor, null);
|
||||
byte[] bytes = toModuleInfo(descriptor, null, null);
|
||||
return ByteBuffer.wrap(bytes);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2019, 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
|
||||
@ -25,6 +25,7 @@
|
||||
|
||||
package jdk.internal.module;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.lang.module.Configuration;
|
||||
import java.lang.module.ModuleDescriptor;
|
||||
import java.lang.module.ModuleFinder;
|
||||
@ -33,6 +34,7 @@ import java.lang.module.ResolvedModule;
|
||||
import java.net.URI;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
@ -40,6 +42,7 @@ import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import jdk.internal.access.JavaLangModuleAccess;
|
||||
import jdk.internal.loader.BootLoader;
|
||||
import jdk.internal.loader.BuiltinClassLoader;
|
||||
import jdk.internal.loader.ClassLoaders;
|
||||
@ -61,6 +64,7 @@ public class Modules {
|
||||
private Modules() { }
|
||||
|
||||
private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
|
||||
private static final JavaLangModuleAccess JLMA = SharedSecrets.getJavaLangModuleAccess();
|
||||
|
||||
/**
|
||||
* Creates a new Module. The module has the given ModuleDescriptor and
|
||||
@ -158,6 +162,20 @@ public class Modules {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a collection of root modules, with service binding and the empty
|
||||
* Configuration as the parent to create a Configuration for the boot layer.
|
||||
*
|
||||
* This method is intended to be used to create the Configuration for the
|
||||
* boot layer during startup or at a link-time.
|
||||
*/
|
||||
public static Configuration newBootLayerConfiguration(ModuleFinder finder,
|
||||
Collection<String> roots,
|
||||
PrintStream traceOutput)
|
||||
{
|
||||
return JLMA.resolveAndBind(finder, roots, traceOutput);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the VM when code in the given Module has been transformed by
|
||||
* an agent and so may have been instrumented to call into supporting
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2019, 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
|
||||
@ -61,6 +61,7 @@ import java.util.stream.Collectors;
|
||||
import jdk.internal.module.Checks;
|
||||
import jdk.internal.module.DefaultRoots;
|
||||
import jdk.internal.module.IllegalAccessMaps;
|
||||
import jdk.internal.module.Modules;
|
||||
import jdk.internal.module.ModuleHashes;
|
||||
import jdk.internal.module.ModuleInfo.Attributes;
|
||||
import jdk.internal.module.ModuleInfoExtender;
|
||||
@ -291,10 +292,10 @@ public final class SystemModulesPlugin implements Plugin {
|
||||
|
||||
/**
|
||||
* Resolves a collection of root modules, with service binding, to create
|
||||
* configuration.
|
||||
* a Configuration for the boot layer.
|
||||
*/
|
||||
private Configuration resolve(ModuleFinder finder, Set<String> roots) {
|
||||
return Configuration.empty().resolveAndBind(finder, ModuleFinder.of(), roots);
|
||||
return Modules.newBootLayerConfiguration(finder, roots, null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -59,8 +59,8 @@ public class DefaultModules {
|
||||
String testSrc = System.getProperty("test.src");
|
||||
|
||||
// $JDK_HOME/bin/java TestModules.java
|
||||
String source = Path.of(testSrc, "src", "TestRootModules.java").toString();
|
||||
ProcessTools.executeTestJava(source)
|
||||
String source = Path.of(testSrc, "TestRootModules.java").toString();
|
||||
ProcessTools.executeTestJava("--add-exports", "java.base/jdk.internal.module=ALL-UNNAMED", source)
|
||||
.outputTo(System.out)
|
||||
.errorTo(System.err)
|
||||
.shouldHaveExitValue(0);
|
||||
@ -89,15 +89,18 @@ public class DefaultModules {
|
||||
javaLauncher += ".exe";
|
||||
|
||||
// $CUSTOM_JDK/bin/java TestRootModules.java
|
||||
source = Path.of(testSrc, "src", "TestRootModules.java").toString();
|
||||
out.format("Command line: [%s %s]%n", javaLauncher, source);
|
||||
ProcessTools.executeProcess(new ProcessBuilder(javaLauncher, source))
|
||||
source = Path.of(testSrc, "TestRootModules.java").toString();
|
||||
ProcessBuilder pb = new ProcessBuilder(javaLauncher,
|
||||
"--add-exports", "java.base/jdk.internal.module=ALL-UNNAMED",
|
||||
source);
|
||||
out.format("Command line: [%s]%n", pb.command());
|
||||
ProcessTools.executeProcess(pb)
|
||||
.outputTo(System.out)
|
||||
.errorTo(System.err)
|
||||
.shouldHaveExitValue(0);
|
||||
|
||||
// $CUSTOM_JDK/bin/java TestJson.java
|
||||
source = Path.of(testSrc, "src", "TestJson.java").toString();
|
||||
source = Path.of(testSrc, "TestJson.java").toString();
|
||||
out.format("Command line: [%s %s]%n", javaLauncher, source);
|
||||
ProcessTools.executeProcess(new ProcessBuilder(javaLauncher, source))
|
||||
.outputTo(System.out)
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2019, 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
|
||||
@ -21,11 +21,12 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
|
||||
import java.lang.module.ModuleDescriptor;
|
||||
import java.lang.module.ModuleFinder;
|
||||
import java.lang.module.ModuleReference;
|
||||
|
||||
import jdk.internal.module.ModuleResolution;
|
||||
|
||||
/**
|
||||
* Test the set of modules in the boot layer includes all modules that export
|
||||
* an API. Also test that java.se is not resolved.
|
||||
@ -37,6 +38,7 @@ public class TestRootModules {
|
||||
// For now, this test ignores the ModuleResolution attribute
|
||||
ModuleLayer bootLayer = ModuleLayer.boot();
|
||||
ModuleFinder.ofSystem().findAll().stream()
|
||||
.filter(mref -> !ModuleResolution.doNotResolveByDefault(mref))
|
||||
.map(ModuleReference::descriptor)
|
||||
.filter(descriptor -> descriptor.exports()
|
||||
.stream()
|
226
test/jdk/jdk/modules/incubator/ServiceBinding.java
Normal file
226
test/jdk/jdk/modules/incubator/ServiceBinding.java
Normal file
@ -0,0 +1,226 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8233922
|
||||
* @modules java.base/jdk.internal.module
|
||||
* @library /test/lib
|
||||
* @build ServiceBinding TestBootLayer
|
||||
* @run testng ServiceBinding
|
||||
* @summary Test service binding with incubator modules
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.module.ModuleDescriptor;
|
||||
import java.lang.module.Configuration;
|
||||
import java.lang.module.ModuleFinder;
|
||||
import java.lang.module.ResolvedModule;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Files;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static java.lang.module.ModuleDescriptor.newModule;
|
||||
|
||||
import jdk.internal.module.ModuleInfoWriter;
|
||||
import jdk.internal.module.ModuleResolution;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
|
||||
@Test
|
||||
public class ServiceBinding {
|
||||
private static final Path HERE = Path.of(".");
|
||||
|
||||
/**
|
||||
* module m1 uses p.S
|
||||
* (incubating) module m2 requires m1 provides p.S
|
||||
*/
|
||||
public void test1() throws Exception {
|
||||
Path mlib = Files.createTempDirectory(HERE, "mlib");
|
||||
|
||||
var m1 = newModule("m1").exports("p").uses("p.S").build();
|
||||
var m2 = newModule("m2").requires("m1").provides("p.S", List.of("impl.S1")).build();
|
||||
|
||||
writeModule(mlib, m1);
|
||||
writeIncubatingModule(mlib, m2);
|
||||
|
||||
// boot layer: root=m1, incubator module m2 should not be resolved
|
||||
testBootLayer(mlib, Set.of("m1"), Set.of("m1"), Set.of("m2"))
|
||||
.shouldNotMatch("WARNING:.*m2");
|
||||
|
||||
// custom configuration: root=m1, incubator module m2 should be resolved
|
||||
testCustomConfiguration(mlib, Set.of("m1"), Set.of("m2"));
|
||||
}
|
||||
|
||||
/**
|
||||
* module m1 uses p.S
|
||||
* (incubating) module m2 requires m1 provides P.S uses q.S
|
||||
* (incubating) module m3 requires m2 provides q.S
|
||||
*/
|
||||
public void test2() throws Exception {
|
||||
Path mlib = Files.createTempDirectory("mlib");
|
||||
|
||||
var m1 = newModule("m1").exports("p").uses("p.S").build();
|
||||
var m2 = newModule("m2")
|
||||
.requires("m1")
|
||||
.provides("p.S", List.of("impl.S1"))
|
||||
.exports("q")
|
||||
.uses("q.S")
|
||||
.build();
|
||||
var m3 = newModule("m3").requires("m2").provides("q.S", List.of("impl.S1")).build();
|
||||
|
||||
writeModule(mlib, m1);
|
||||
writeIncubatingModule(mlib, m2);
|
||||
writeIncubatingModule(mlib, m3);
|
||||
|
||||
// boot layer: root=m1, incubator modules m2 and m3 should not be resolved
|
||||
testBootLayer(mlib, Set.of("m1"), Set.of("m1"), Set.of("m2", "m3"))
|
||||
.shouldNotMatch("WARNING:.*m2")
|
||||
.shouldNotMatch("WARNING:.*m3");
|
||||
|
||||
// boot layer: root=m2, incubator module m3 should not be resolved
|
||||
testBootLayer(mlib, Set.of("m2"), Set.of("m1", "m2"), Set.of("m3"))
|
||||
.shouldMatch("WARNING:.*m2")
|
||||
.shouldNotMatch("WARNING:.*m3");
|
||||
|
||||
// custom configuration: root=m1, incubator modules m2 and m3 should be resolved
|
||||
testCustomConfiguration(mlib, Set.of("m1"), Set.of("m1", "m2", "m3"));
|
||||
|
||||
// custom configuration: root=m2, incubator module m3 should be resolved
|
||||
testCustomConfiguration(mlib, Set.of("m2"), Set.of("m1", "m2", "m3"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an exploded module on the file system.
|
||||
*
|
||||
* @param mlib the top-level module directory
|
||||
* @param descriptor the module descriptor of the module to write
|
||||
*/
|
||||
void writeModule(Path mlib, ModuleDescriptor descriptor) throws Exception {
|
||||
writeModule(mlib, descriptor, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an exploded module on the file system. The module will be an
|
||||
* incubating module.
|
||||
*
|
||||
* @param mlib the top-level module directory
|
||||
* @param descriptor the module descriptor of the module to write
|
||||
*/
|
||||
void writeIncubatingModule(Path mlib, ModuleDescriptor descriptor) throws Exception {
|
||||
writeModule(mlib, descriptor, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an exploded module on the file system.
|
||||
*
|
||||
* @param mlib the top-level module directory
|
||||
* @param descriptor the module descriptor of the module to write
|
||||
* @param incubating to create an incubating module
|
||||
*/
|
||||
void writeModule(Path mlib, ModuleDescriptor descriptor, boolean incubating)
|
||||
throws Exception
|
||||
{
|
||||
// create ModuleResolution attribute if incubating module
|
||||
ModuleResolution mres = (incubating) ? ModuleResolution.empty().withIncubating() : null;
|
||||
String name = descriptor.name();
|
||||
|
||||
// create directory for module
|
||||
Path dir = Files.createDirectory(mlib.resolve(name));
|
||||
|
||||
// module-info.class
|
||||
try (OutputStream out = Files.newOutputStream(dir.resolve("module-info.class"))) {
|
||||
ModuleInfoWriter.write(descriptor, mres, out);
|
||||
}
|
||||
|
||||
// create a dummy class file for each package
|
||||
for (String pn : descriptor.packages()) {
|
||||
Path subdir = dir.resolve(pn.replace('.', File.separatorChar));
|
||||
Files.createDirectories(subdir);
|
||||
Files.createFile(subdir.resolve("C.class"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run TestBootLayer in a child VM with the given module path and the
|
||||
* --add-modules option with additional root modules. TestBootLayer checks
|
||||
* the modules in the boot layer.
|
||||
*
|
||||
* @param mlib the module path
|
||||
* @param roots the modules to specify to --add-modules
|
||||
* @param expected the names of modules that should be in the boot layer
|
||||
* @param notExpected the names of modules that should not be in boot layer
|
||||
*/
|
||||
OutputAnalyzer testBootLayer(Path mlib,
|
||||
Set<String> roots,
|
||||
Set<String> expected,
|
||||
Set<String> notExpected)
|
||||
throws Exception
|
||||
{
|
||||
var opts = Stream.of("-p", mlib.toString(),
|
||||
"--add-modules", commaSeparated(roots),
|
||||
"TestBootLayer", commaSeparated(expected), commaSeparated(notExpected));
|
||||
return ProcessTools.executeTestJava(opts.toArray(String[]::new))
|
||||
.outputTo(System.out)
|
||||
.errorTo(System.out)
|
||||
.shouldHaveExitValue(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Configuration by resolving a set of root modules, with service
|
||||
* binding, then checks that the Configuration includes the expected modules.
|
||||
*
|
||||
* @param mlib the module path
|
||||
* @param roots the names of the root modules
|
||||
* @param expected the names of modules that should be in the configuration
|
||||
*/
|
||||
void testCustomConfiguration(Path mlib, Set<String> roots, Set<String> expected) {
|
||||
ModuleFinder finder = ModuleFinder.of(mlib);
|
||||
Configuration cf = ModuleLayer.boot()
|
||||
.configuration()
|
||||
.resolveAndBind(finder, ModuleFinder.of(), roots);
|
||||
|
||||
Set<String> modules = cf.modules().stream()
|
||||
.map(ResolvedModule::name)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
expected.stream()
|
||||
.filter(mn -> !modules.contains(mn))
|
||||
.findAny()
|
||||
.ifPresent(mn -> {
|
||||
throw new RuntimeException(mn + " not in configuration!!!");
|
||||
});
|
||||
}
|
||||
|
||||
String commaSeparated(Set<String> s) {
|
||||
return s.stream().collect(Collectors.joining(","));
|
||||
}
|
||||
}
|
60
test/jdk/jdk/modules/incubator/TestBootLayer.java
Normal file
60
test/jdk/jdk/modules/incubator/TestBootLayer.java
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 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.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Launched by the test ServiceBinding to test modules in the boot layer.
|
||||
*/
|
||||
|
||||
public class TestBootLayer {
|
||||
public static void main(String[] args) throws Exception {
|
||||
Pattern splitter = Pattern.compile(",");
|
||||
|
||||
// the names of all modules in the boot layer
|
||||
Set<String> modules = ModuleLayer.boot().modules().stream()
|
||||
.map(Module::getName)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
// throw exception if an expected module is not in the boot layer
|
||||
splitter.splitAsStream(args[0])
|
||||
.filter(Predicate.not(String::isEmpty))
|
||||
.filter(mn -> !modules.contains(mn))
|
||||
.findAny()
|
||||
.ifPresent(mn -> {
|
||||
throw new RuntimeException(mn + " not in boot layer!!!");
|
||||
});
|
||||
|
||||
// throw exception if an unexpected module is in the boot layer
|
||||
splitter.splitAsStream(args[1])
|
||||
.filter(Predicate.not(String::isEmpty))
|
||||
.filter(mn -> modules.contains(mn))
|
||||
.findAny()
|
||||
.ifPresent(mn -> {
|
||||
throw new RuntimeException(mn + " in boot layer!!!!");
|
||||
});
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user