--- old/test/jdk/modules/etc/JdkQualifiedExportTest.java 2017-04-21 13:40:19.000000000 -0700 +++ new/test/jdk/modules/etc/JdkQualifiedExportTest.java 2017-04-21 13:40:19.000000000 -0700 @@ -35,6 +35,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.UncheckedIOException; +import java.lang.module.Configuration; import java.lang.module.ModuleDescriptor; import java.lang.module.ModuleDescriptor.Exports; import java.lang.module.ModuleDescriptor.Opens; @@ -69,9 +70,8 @@ static Set KNOWN_EXCEPTIONS = Set.of("java.xml/com.sun.xml.internal.stream.writers", + "jdk.internal.vm.ci/jdk.vm.ci.services", "jdk.jsobject/jdk.internal.netscape.javascript.spi"); - static Set DEPLOY_MODULES = - Set.of("jdk.deploy", "jdk.plugin", "jdk.javaws"); static void checkExports(ModuleDescriptor md) { // build a map of upgradeable module to Exports that are qualified to it @@ -80,8 +80,7 @@ md.exports().stream() .filter(Exports::isQualified) .forEach(e -> e.targets().stream() - .filter(mn -> !HashedModules.contains(mn) && - ModuleFinder.ofSystem().find(mn).isPresent()) + .filter(mn -> accept(md, mn)) .forEach(t -> targetToExports.computeIfAbsent(t, _k -> new HashSet<>()) .add(e))); @@ -97,10 +96,9 @@ exp.source(), e.getKey())); }); - // workaround until all qualified exports to upgradeable modules - // are eliminated + // no qualified exports to upgradeable modules are expected + // except the known exception cases if (targetToExports.entrySet().stream() - .filter(e -> !DEPLOY_MODULES.contains(e.getKey())) .flatMap(e -> e.getValue().stream()) .anyMatch(e -> !KNOWN_EXCEPTIONS.contains(mn + "/" + e.source()))) { throw new RuntimeException(mn + " can't export package to upgradeable modules"); @@ -115,8 +113,7 @@ md.opens().stream() .filter(Opens::isQualified) .forEach(e -> e.targets().stream() - .filter(mn -> !HashedModules.contains(mn) && - ModuleFinder.ofSystem().find(mn).isPresent()) + .filter(mn -> accept(md, mn)) .forEach(t -> targetToOpens.computeIfAbsent(t, _k -> new HashSet<>()) .add(e))); @@ -136,6 +133,23 @@ } } + /** + * Returns true if target is an upgradeable module but not required + * by the source module directly and indirectly. + */ + private static boolean accept(ModuleDescriptor source, String target) { + if (HashedModules.contains(target)) + return false; + + if (!ModuleFinder.ofSystem().find(target).isPresent()) + return false; + + Configuration cf = Configuration.empty().resolve(ModuleFinder.of(), + ModuleFinder.ofSystem(), + Set.of(source.name())); + return cf.findModule(target).orElse(null) == null; + } + private static class HashedModules { static Set HASHED_MODULES = hashedModules();