下面列出了怎么用java.lang.module.ModuleDescriptor.Provides的API类实例代码及写法,或者点击链接到github查看源代码。
private boolean checkModuleInfo(byte[] moduleInfoBytes, Set<String> entries)
throws IOException
{
boolean ok = true;
if (moduleInfoBytes != null) { // no root module-info.class if null
try {
// ModuleDescriptor.read() checks open/exported pkgs vs packages
ModuleDescriptor md = ModuleDescriptor.read(ByteBuffer.wrap(moduleInfoBytes));
// A module must have the implementation class of the services it 'provides'.
if (md.provides().stream().map(Provides::providers).flatMap(List::stream)
.filter(p -> !entries.contains(toBinaryName(p)))
.peek(p -> fatalError(formatMsg("error.missing.provider", p)))
.count() != 0) {
ok = false;
}
} catch (InvalidModuleDescriptorException x) {
fatalError(x.getMessage());
ok = false;
}
}
return ok;
}
/**
* Returns a new {@code ModuleDescriptor} instance.
*/
ModuleDescriptor newModuleDescriptor(String name,
Version version,
Set<ModuleDescriptor.Modifier> ms,
Set<Requires> requires,
Set<Exports> exports,
Set<Opens> opens,
Set<String> uses,
Set<Provides> provides,
Set<String> packages,
String mainClass,
int hashCode);
/**
* Returns a new {@code ModuleDescriptor} instance.
*/
ModuleDescriptor newModuleDescriptor(String name,
Version version,
Set<ModuleDescriptor.Modifier> ms,
Set<Requires> requires,
Set<Exports> exports,
Set<Opens> opens,
Set<String> uses,
Set<Provides> provides,
Set<String> packages,
String mainClass,
int hashCode);
private Provides provides(String st, String pc) {
return ModuleDescriptor.newModule("foo")
.provides(st, List.of(pc))
.build()
.provides()
.iterator()
.next();
}
private Provides provides(String st, List<String> pns) {
return ModuleDescriptor.newModule("foo")
.provides(st, pns)
.build()
.provides()
.iterator()
.next();
}
public void testProvidesWithProvides() {
Provides p1 = provides("p.S", "q.S1");
ModuleDescriptor descriptor = ModuleDescriptor.newModule("m")
.provides(p1)
.build();
Provides p2 = descriptor.provides().iterator().next();
assertEquals(p1, p2);
}
public void testProvides() {
Set<Provides> set = ModuleDescriptor.newModule("foo")
.provides("p.S", List.of("q.P1", "q.P2"))
.build()
.provides();
assertTrue(set.size() == 1);
Provides p = set.iterator().next();
assertEquals(p, p);
assertEquals(p.service(), "p.S");
assertTrue(p.providers().size() == 2);
assertEquals(p.providers().get(0), "q.P1");
assertEquals(p.providers().get(1), "q.P2");
}
public void testProvidesCompare() {
Provides p1 = provides("p.S", "q.S1");
Provides p2 = provides("p.S", "q.S1");
assertEquals(p1, p2);
assertTrue(p1.hashCode() == p2.hashCode());
assertTrue(p1.compareTo(p2) == 0);
assertTrue(p2.compareTo(p1) == 0);
}
public void testProvidesCompareWithDifferentService() {
Provides p1 = provides("p.S2", "q.S1");
Provides p2 = provides("p.S1", "q.S1");
assertNotEquals(p1, p2);
assertTrue(p1.compareTo(p2) == 1);
assertTrue(p2.compareTo(p1) == -1);
}
public void testProvidesCompareWithDifferentProviders1() {
Provides p1 = provides("p.S", "q.S2");
Provides p2 = provides("p.S", "q.S1");
assertNotEquals(p1, p2);
assertTrue(p1.compareTo(p2) == 1);
assertTrue(p2.compareTo(p1) == -1);
}
public void testProvidesCompareWithDifferentProviders2() {
Provides p1 = provides("p.S", List.of("q.S1", "q.S2"));
Provides p2 = provides("p.S", "q.S1");
assertNotEquals(p1, p2);
assertTrue(p1.compareTo(p2) == 1);
assertTrue(p2.compareTo(p1) == -1);
}
public static void main(String[] args) throws Exception {
Module xml = ModuleLayer.boot().findModule("java.xml").get();
Set<String> allServices = new HashSet<>(Arrays.asList(expectedAllServices));
if (!allServices.equals(xml.getDescriptor().uses()))
throw new AssertionError("Expect xml module uses: " + allServices + " But actually uses: "
+ xml.getDescriptor().uses());
long violationCount = Stream.of(args)
.map(xmlProviderName -> ModuleLayer.boot().findModule(xmlProviderName).get())
.mapToLong(
// services provided by the implementation in provider module
provider -> provider.getDescriptor().provides().stream()
.map(Provides::service)
.filter(serviceName -> {
allServices.remove(serviceName); // remove service provided by
// customized module from allServices
return !belongToModule(serviceName, instantiateXMLService(serviceName), provider);
}).count())
.sum();
// the remaining services should be provided by the default implementation
violationCount += allServices.stream()
.filter(serviceName -> !belongToModule(serviceName, instantiateXMLService(serviceName), xml))
.count();
if (violationCount > 0)
throw new AssertionError(violationCount + " services are not provided by expected module");
}
private void printModuleInfo(PrintWriter writer, ModuleDescriptor md) {
writer.format("%smodule %s {%n", open ? "open " : "", md.name());
Map<String, Module> modules = configuration.getModules();
// first print requires
Set<Requires> reqs = md.requires().stream()
.filter(req -> !req.name().equals("java.base") && req.modifiers().isEmpty())
.collect(Collectors.toSet());
reqs.stream()
.sorted(Comparator.comparing(Requires::name))
.forEach(req -> writer.format(" requires %s;%n",
toString(req.modifiers(), req.name())));
if (!reqs.isEmpty()) {
writer.println();
}
// requires transitive
reqs = md.requires().stream()
.filter(req -> !req.name().equals("java.base") && !req.modifiers().isEmpty())
.collect(Collectors.toSet());
reqs.stream()
.sorted(Comparator.comparing(Requires::name))
.forEach(req -> writer.format(" requires %s;%n",
toString(req.modifiers(), req.name())));
if (!reqs.isEmpty()) {
writer.println();
}
if (!open) {
md.exports().stream()
.peek(exp -> {
if (exp.isQualified())
throw new InternalError(md.name() + " qualified exports: " + exp);
})
.sorted(Comparator.comparing(Exports::source))
.forEach(exp -> writer.format(" exports %s;%n", exp.source()));
if (!md.exports().isEmpty()) {
writer.println();
}
}
md.provides().stream()
.sorted(Comparator.comparing(Provides::service))
.map(p -> p.providers().stream()
.map(impl -> " " + impl.replace('$', '.'))
.collect(joining(",\n",
String.format(" provides %s with%n",
p.service().replace('$', '.')),
";")))
.forEach(writer::println);
if (!md.provides().isEmpty()) {
writer.println();
}
writer.println("}");
}
private void describeModule(ModuleDescriptor md,
ModuleTarget target,
ModuleHashes hashes,
String uriString)
throws IOException
{
StringBuilder sb = new StringBuilder();
sb.append(md.toNameAndVersion());
if (!uriString.equals(""))
sb.append(" ").append(uriString);
if (md.isOpen())
sb.append(" open");
if (md.isAutomatic())
sb.append(" automatic");
sb.append("\n");
// unqualified exports (sorted by package)
md.exports().stream()
.sorted(Comparator.comparing(Exports::source))
.filter(e -> !e.isQualified())
.forEach(e -> sb.append("exports ").append(e.source())
.append(toString(e.modifiers())).append("\n"));
// dependences
md.requires().stream().sorted()
.forEach(r -> sb.append("requires ").append(r.name())
.append(toString(r.modifiers())).append("\n"));
// service use and provides
md.uses().stream().sorted()
.forEach(s -> sb.append("uses ").append(s).append("\n"));
md.provides().stream()
.sorted(Comparator.comparing(Provides::service))
.forEach(p -> sb.append("provides ").append(p.service())
.append(" with")
.append(toString(p.providers()))
.append("\n"));
// qualified exports
md.exports().stream()
.sorted(Comparator.comparing(Exports::source))
.filter(Exports::isQualified)
.forEach(e -> sb.append("qualified exports ").append(e.source())
.append(" to").append(toString(e.targets()))
.append("\n"));
// open packages
md.opens().stream()
.sorted(Comparator.comparing(Opens::source))
.filter(o -> !o.isQualified())
.forEach(o -> sb.append("opens ").append(o.source())
.append(toString(o.modifiers()))
.append("\n"));
md.opens().stream()
.sorted(Comparator.comparing(Opens::source))
.filter(Opens::isQualified)
.forEach(o -> sb.append("qualified opens ").append(o.source())
.append(toString(o.modifiers()))
.append(" to").append(toString(o.targets()))
.append("\n"));
// non-exported/non-open packages
Set<String> concealed = new TreeSet<>(md.packages());
md.exports().stream().map(Exports::source).forEach(concealed::remove);
md.opens().stream().map(Opens::source).forEach(concealed::remove);
concealed.forEach(p -> sb.append("contains ").append(p).append("\n"));
md.mainClass().ifPresent(v -> sb.append("main-class ").append(v).append("\n"));
if (target != null) {
String targetPlatform = target.targetPlatform();
if (!targetPlatform.isEmpty())
sb.append("platform ").append(targetPlatform).append("\n");
}
if (hashes != null) {
hashes.names().stream().sorted().forEach(
mod -> sb.append("hashes ").append(mod).append(" ")
.append(hashes.algorithm()).append(" ")
.append(toHex(hashes.hashFor(mod)))
.append("\n"));
}
output(sb.toString());
}
private void describeModule(ModuleDescriptor md,
ModuleTarget target,
ModuleHashes hashes)
throws IOException
{
StringBuilder sb = new StringBuilder();
sb.append(md.toNameAndVersion());
if (md.isOpen())
sb.append(" open");
if (md.isAutomatic())
sb.append(" automatic");
sb.append("\n");
// unqualified exports (sorted by package)
md.exports().stream()
.sorted(Comparator.comparing(Exports::source))
.filter(e -> !e.isQualified())
.forEach(e -> sb.append("exports ").append(e.source())
.append(toString(e.modifiers())).append("\n"));
// dependences
md.requires().stream().sorted()
.forEach(r -> sb.append("requires ").append(r.name())
.append(toString(r.modifiers())).append("\n"));
// service use and provides
md.uses().stream().sorted()
.forEach(s -> sb.append("uses ").append(s).append("\n"));
md.provides().stream()
.sorted(Comparator.comparing(Provides::service))
.forEach(p -> sb.append("provides ").append(p.service())
.append(" with")
.append(toString(p.providers()))
.append("\n"));
// qualified exports
md.exports().stream()
.sorted(Comparator.comparing(Exports::source))
.filter(Exports::isQualified)
.forEach(e -> sb.append("qualified exports ").append(e.source())
.append(" to").append(toString(e.targets()))
.append("\n"));
// open packages
md.opens().stream()
.sorted(Comparator.comparing(Opens::source))
.filter(o -> !o.isQualified())
.forEach(o -> sb.append("opens ").append(o.source())
.append(toString(o.modifiers()))
.append("\n"));
md.opens().stream()
.sorted(Comparator.comparing(Opens::source))
.filter(Opens::isQualified)
.forEach(o -> sb.append("qualified opens ").append(o.source())
.append(toString(o.modifiers()))
.append(" to").append(toString(o.targets()))
.append("\n"));
// non-exported/non-open packages
Set<String> concealed = new TreeSet<>(md.packages());
md.exports().stream().map(Exports::source).forEach(concealed::remove);
md.opens().stream().map(Opens::source).forEach(concealed::remove);
concealed.forEach(p -> sb.append("contains ").append(p).append("\n"));
md.mainClass().ifPresent(v -> sb.append("main-class ").append(v).append("\n"));
if (target != null) {
String targetPlatform = target.targetPlatform();
if (!targetPlatform.isEmpty())
sb.append("platform ").append(targetPlatform).append("\n");
}
if (hashes != null) {
hashes.names().stream().sorted().forEach(
mod -> sb.append("hashes ").append(mod).append(" ")
.append(hashes.algorithm()).append(" ")
.append(toHex(hashes.hashFor(mod)))
.append("\n"));
}
out.println(sb.toString());
}
@Test(expectedExceptions = IllegalStateException.class )
public void testProvidesWithDuplicateProvides() {
Provides p = provides("p.S", "q.S2");
ModuleDescriptor.newModule("m").provides("p.S", List.of("q.S1")).provides(p);
}
@Test(expectedExceptions = NullPointerException.class )
public void testProvidesWithNullProvides() {
ModuleDescriptor.newModule("foo").provides((Provides) null);
}
private static boolean containsAtLeastAService(ModuleReference ref, List<String> serviceNames) {
Set<String> provides = ref.descriptor().provides().stream().map(Provides::service).collect(Collectors.toSet());
return serviceNames.stream().anyMatch(provides::contains);
}
public static ModuleDescriptor mergeModuleDescriptor(ModuleDescriptor sourceModule, ModuleDescriptor testModule) {
var open = sourceModule.isOpen() || testModule.isOpen();
var moduleModifiers = open? Set.of(Modifier.OPEN): Set.<Modifier>of();
var builder = ModuleDescriptor.newModule(testModule.name(), moduleModifiers);
var requires = merge(ModuleDescriptor::requires,
Requires::name, Requires::modifiers, ModuleHelper::mergeRequiresModifiers, sourceModule, testModule);
var exports = merge(ModuleDescriptor::exports,
Exports::source, Exports::targets, ModuleHelper::mergeRestrictions, sourceModule, testModule);
var packages = merge(ModuleDescriptor::packages,
x -> x, x -> true, (_1, _2) -> true, sourceModule, testModule);
var opens = merge(ModuleDescriptor::opens,
Opens::source, Opens::targets, ModuleHelper::mergeRestrictions, sourceModule, testModule);
var uses = merge(ModuleDescriptor::uses,
x -> x, x -> true, (_1, _2) -> true, sourceModule, testModule);
var provides = merge(ModuleDescriptor::provides,
Provides::service, p -> new HashSet<>(p.providers()), ModuleHelper::mergeAll, sourceModule, testModule);
requires.forEach((name, modifiers) -> builder.requires(modifiers, name));
exports.forEach((source, target) -> {
if (target.isEmpty()) {
builder.exports(Set.of(), source);
} else {
builder.exports(source, target);
}
});
packages.keySet().removeAll(exports.keySet());
builder.packages(packages.keySet());
opens.forEach((source, target) -> {
if (target.isEmpty()) {
builder.opens(Set.of(), source);
} else {
builder.opens(source, target);
}
});
uses.keySet().forEach(builder::uses);
provides.forEach((service, providers) -> builder.provides(service, providers.stream().collect(toUnmodifiableList())));
return builder.build();
}
/**
* Returns a {@link Provides} for a service with a given list of
* implementation classes.
*/
public static Provides newProvides(String st, List<String> pcs) {
return JLMA.newProvides(st, pcs);
}
/**
* Returns a {@code ModuleDescriptor.Provides}
* of the given service name and providers.
*/
Provides newProvides(String service, List<String> providers);
/**
* Returns a {@link Provides} for a service with a given list of
* implementation classes.
*/
public static Provides newProvides(String st, List<String> pcs) {
return JLMA.newProvides(st, pcs);
}
/**
* Returns a {@code ModuleDescriptor.Provides}
* of the given service name and providers.
*/
Provides newProvides(String service, List<String> providers);