use of java.lang.module.ModuleDescriptor.Provides in project Bytecoder by mirkosertic.
the class Resolver method bind.
/**
* Augments the set of resolved modules with modules induced by the
* service-use relation.
*/
Resolver bind() {
// Scan the finders for all available service provider modules. As
// java.base uses services then then 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()) {
for (Provides provides : descriptor.provides()) {
String sn = provides.service();
// computeIfAbsent
Set<ModuleReference> providers = availableProviders.get(sn);
if (providers == null) {
providers = new HashSet<>();
availableProviders.put(sn, providers);
}
providers.add(mref);
}
}
}
// create the visit stack
Deque<ModuleDescriptor> q = new ArrayDeque<>();
// the initial set of modules that may use services
Set<ModuleDescriptor> initialConsumers;
if (ModuleLayer.boot() == null) {
initialConsumers = new HashSet<>();
} else {
initialConsumers = parents.stream().flatMap(Configuration::configurations).distinct().flatMap(c -> c.descriptors().stream()).collect(Collectors.toSet());
}
for (ModuleReference mref : nameToReference.values()) {
initialConsumers.add(mref.descriptor());
}
// Where there is a consumer of a service then resolve all modules
// that provide an implementation of that service
Set<ModuleDescriptor> candidateConsumers = initialConsumers;
do {
for (ModuleDescriptor descriptor : candidateConsumers) {
if (!descriptor.uses().isEmpty()) {
// the modules that provide at least one service
Set<ModuleDescriptor> modulesToBind = null;
if (isTracing()) {
modulesToBind = new HashSet<>();
}
for (String service : descriptor.uses()) {
Set<ModuleReference> mrefs = availableProviders.get(service);
if (mrefs != null) {
for (ModuleReference mref : mrefs) {
ModuleDescriptor provider = mref.descriptor();
if (!provider.equals(descriptor)) {
if (isTracing() && modulesToBind.add(provider)) {
trace("%s binds %s", descriptor.name(), nameAndInfo(mref));
}
String pn = provider.name();
if (!nameToReference.containsKey(pn)) {
addFoundModule(mref);
q.push(provider);
}
}
}
}
}
}
}
candidateConsumers = resolve(q);
} while (!candidateConsumers.isEmpty());
return this;
}
use of java.lang.module.ModuleDescriptor.Provides in project Bytecoder by mirkosertic.
the class LauncherHelper method describeModule.
/**
* Called by the launcher to describe a module
*/
static void describeModule(String moduleName) {
initOutput(System.out);
ModuleFinder finder = ModuleBootstrap.limitedFinder();
ModuleReference mref = finder.find(moduleName).orElse(null);
if (mref == null) {
abort(null, "java.launcher.module.error4", moduleName);
}
ModuleDescriptor md = mref.descriptor();
// one-line summary
showModule(mref);
// unqualified exports (sorted by package)
md.exports().stream().filter(e -> !e.isQualified()).sorted(Comparator.comparing(Exports::source)).map(e -> Stream.concat(Stream.of(e.source()), toStringStream(e.modifiers())).collect(Collectors.joining(" "))).forEach(sourceAndMods -> ostream.format("exports %s%n", sourceAndMods));
// dependences
for (Requires r : md.requires()) {
String nameAndMods = Stream.concat(Stream.of(r.name()), toStringStream(r.modifiers())).collect(Collectors.joining(" "));
ostream.format("requires %s", nameAndMods);
finder.find(r.name()).map(ModuleReference::descriptor).filter(ModuleDescriptor::isAutomatic).ifPresent(any -> ostream.print(" automatic"));
ostream.println();
}
// service use and provides
for (String s : md.uses()) {
ostream.format("uses %s%n", s);
}
for (Provides ps : md.provides()) {
String names = ps.providers().stream().collect(Collectors.joining(" "));
ostream.format("provides %s with %s%n", ps.service(), names);
}
// qualified exports
for (Exports e : md.exports()) {
if (e.isQualified()) {
String who = e.targets().stream().collect(Collectors.joining(" "));
ostream.format("qualified exports %s to %s%n", e.source(), who);
}
}
// open packages
for (Opens opens : md.opens()) {
if (opens.isQualified())
ostream.print("qualified ");
String sourceAndMods = Stream.concat(Stream.of(opens.source()), toStringStream(opens.modifiers())).collect(Collectors.joining(" "));
ostream.format("opens %s", sourceAndMods);
if (opens.isQualified()) {
String who = opens.targets().stream().collect(Collectors.joining(" "));
ostream.format(" to %s", who);
}
ostream.println();
}
// 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 -> ostream.format("contains %s%n", p));
}
use of java.lang.module.ModuleDescriptor.Provides in project Bytecoder by mirkosertic.
the class Resolver method checkExportSuppliers.
/**
* Checks the readability graph to ensure that
* <ol>
* <li><p> A module does not read two or more modules with the same name.
* This includes the case where a module reads another another with the
* same name as itself. </p></li>
* <li><p> Two or more modules in the configuration don't export the same
* package to a module that reads both. This includes the case where a
* module {@code M} containing package {@code p} reads another module
* that exports {@code p} to {@code M}. </p></li>
* <li><p> A module {@code M} doesn't declare that it "{@code uses p.S}"
* or "{@code provides p.S with ...}" but package {@code p} is neither
* in module {@code M} nor exported to {@code M} by any module that
* {@code M} reads. </p></li>
* </ol>
*/
private void checkExportSuppliers(Map<ResolvedModule, Set<ResolvedModule>> graph) {
for (Map.Entry<ResolvedModule, Set<ResolvedModule>> e : graph.entrySet()) {
ModuleDescriptor descriptor1 = e.getKey().descriptor();
String name1 = descriptor1.name();
// the names of the modules that are read (including self)
Set<String> names = new HashSet<>();
names.add(name1);
// the map of packages that are local or exported to descriptor1
Map<String, ModuleDescriptor> packageToExporter = new HashMap<>();
// local packages
Set<String> packages = descriptor1.packages();
for (String pn : packages) {
packageToExporter.put(pn, descriptor1);
}
// descriptor1 reads descriptor2
Set<ResolvedModule> reads = e.getValue();
for (ResolvedModule endpoint : reads) {
ModuleDescriptor descriptor2 = endpoint.descriptor();
String name2 = descriptor2.name();
if (descriptor2 != descriptor1 && !names.add(name2)) {
if (name2.equals(name1)) {
resolveFail("Module %s reads another module named %s", name1, name1);
} else {
resolveFail("Module %s reads more than one module named %s", name1, name2);
}
}
if (descriptor2.isAutomatic()) {
// automatic modules read self and export all packages
if (descriptor2 != descriptor1) {
for (String source : descriptor2.packages()) {
ModuleDescriptor supplier = packageToExporter.putIfAbsent(source, descriptor2);
// descriptor2 and 'supplier' export source to descriptor1
if (supplier != null) {
failTwoSuppliers(descriptor1, source, descriptor2, supplier);
}
}
}
} else {
for (ModuleDescriptor.Exports export : descriptor2.exports()) {
if (export.isQualified()) {
if (!export.targets().contains(descriptor1.name()))
continue;
}
// source is exported by descriptor2
String source = export.source();
ModuleDescriptor supplier = packageToExporter.putIfAbsent(source, descriptor2);
// descriptor2 and 'supplier' export source to descriptor1
if (supplier != null) {
failTwoSuppliers(descriptor1, source, descriptor2, supplier);
}
}
}
}
// uses/provides checks not applicable to automatic modules
if (!descriptor1.isAutomatic()) {
// uses S
for (String service : descriptor1.uses()) {
String pn = packageName(service);
if (!packageToExporter.containsKey(pn)) {
resolveFail("Module %s does not read a module that exports %s", descriptor1.name(), pn);
}
}
// provides S
for (ModuleDescriptor.Provides provides : descriptor1.provides()) {
String pn = packageName(provides.service());
if (!packageToExporter.containsKey(pn)) {
resolveFail("Module %s does not read a module that exports %s", descriptor1.name(), pn);
}
}
}
}
}
use of java.lang.module.ModuleDescriptor.Provides in project Bytecoder by mirkosertic.
the class ServicesCatalog method register.
/**
* Registers the providers in the given module in this services catalog.
*/
public void register(Module module) {
ModuleDescriptor descriptor = module.getDescriptor();
for (Provides provides : descriptor.provides()) {
String service = provides.service();
List<String> providerNames = provides.providers();
int count = providerNames.size();
if (count == 1) {
String pn = providerNames.get(0);
providers(service).add(new ServiceProvider(module, pn));
} else {
List<ServiceProvider> list = new ArrayList<>(count);
for (String pn : providerNames) {
list.add(new ServiceProvider(module, pn));
}
providers(service).addAll(list);
}
}
}
Aggregations