/** * Returns a {@link Requires} for a dependence on a module with the given * (and possibly empty) set of modifiers, and optionally the version * recorded at compile time. */ public static Requires newRequires(Set<Requires.Modifier> mods, String mn, String compiledVersion) { Version version = null; if (compiledVersion != null) { // use the cached version if the same version string Version ver = cachedVersion; if (ver != null && compiledVersion.equals(ver.toString())) { version = ver; } else { version = Version.parse(compiledVersion); } } return JLMA.newRequires(mods, mn, version); }
private void dedups(ModuleDescriptor md) { // exports for (Exports e : md.exports()) { dedupSetBuilder.stringSet(e.targets()); dedupSetBuilder.exportsModifiers(e.modifiers()); } // opens for (Opens opens : md.opens()) { dedupSetBuilder.stringSet(opens.targets()); dedupSetBuilder.opensModifiers(opens.modifiers()); } // requires for (Requires r : md.requires()) { dedupSetBuilder.requiresModifiers(r.modifiers()); } // uses dedupSetBuilder.stringSet(md.uses()); }
/** * Basic test of "requires static": * m1 requires static m2 * m2 * resolve m1 */ public void testRequiresStatic2() { ModuleDescriptor descriptor1 = newBuilder("m1") .requires(Set.of(Requires.Modifier.STATIC), "m2") .build(); ModuleDescriptor descriptor2 = newBuilder("m2") .build(); ModuleFinder finder = ModuleUtils.finderOf(descriptor1, descriptor2); Configuration cf = resolve(finder, "m1"); assertTrue(cf.modules().size() == 1); ResolvedModule m1 = cf.findModule("m1").get(); assertTrue(m1.reads().size() == 0); }
/** * Basic test of "requires static": * m1 requires static m2 * m2 * resolve m1, m2 */ public void testRequiresStatic3() { ModuleDescriptor descriptor1 = newBuilder("m1") .requires(Set.of(Requires.Modifier.STATIC), "m2") .build(); ModuleDescriptor descriptor2 = newBuilder("m2") .build(); ModuleFinder finder = ModuleUtils.finderOf(descriptor1, descriptor2); Configuration cf = resolve(finder, "m1", "m2"); assertTrue(cf.modules().size() == 2); ResolvedModule m1 = cf.findModule("m1").get(); ResolvedModule m2 = cf.findModule("m2").get(); assertTrue(m1.reads().size() == 1); assertTrue(m1.reads().contains(m2)); assertTrue(m2.reads().size() == 0); }
/** * Basic test to detect reading a module with the same name as itself * * The test consists of three configurations: * - Configuration cf1: m1, m2 requires transitive m1 * - Configuration cf2: m1 requires m2 */ @Test(expectedExceptions = { ResolutionException.class }) public void testReadModuleWithSameNameAsSelf() { ModuleDescriptor descriptor1_v1 = newBuilder("m1") .build(); ModuleDescriptor descriptor2 = newBuilder("m2") .requires(Set.of(Requires.Modifier.TRANSITIVE), "m1") .build(); ModuleDescriptor descriptor1_v2 = newBuilder("m1") .requires("m2") .build(); ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1_v1, descriptor2); Configuration cf1 = resolve(finder1, "m2"); assertTrue(cf1.modules().size() == 2); // resolve should throw ResolutionException ModuleFinder finder2 = ModuleUtils.finderOf(descriptor1_v2); resolve(cf1, finder2, "m1"); }
/** * Basic test for requiring a module with an unparseable version recorded * at compile version. */ @Test(dataProvider = "unparseableVersions") public void testUnparseableCompiledVersion(String vs1, String vs2) { Requires r1 = newRequires("m", vs1); Requires r2 = newRequires("m", vs2); if (vs1 != null && !isParsableVersion(vs1)) { assertFalse(r1.compiledVersion().isPresent()); assertTrue(r1.rawCompiledVersion().isPresent()); assertEquals(r1.rawCompiledVersion().get(), vs1); } if (vs2 != null && !isParsableVersion(vs2)) { assertFalse(r2.compiledVersion().isPresent()); assertTrue(r2.rawCompiledVersion().isPresent()); assertEquals(r2.rawCompiledVersion().get(), vs2); } assertFalse(r1.equals(r2)); assertFalse(r2.equals(r1)); assertTrue(r1.compareTo(r2) == -1); assertTrue(r2.compareTo(r1) == 1); }
public void testAutomaticModule() { ModuleDescriptor descriptor = ModuleDescriptor.newAutomaticModule("foo") .packages(Set.of("p")) .provides("p.Service", List.of("q.ServiceImpl")) .build(); // modifiers assertTrue(descriptor.modifiers().contains(ModuleDescriptor.Modifier.AUTOMATIC)); assertTrue(descriptor.isAutomatic()); // requires assertTrue(descriptor.requires().size() == 1); Set<String> names = descriptor.requires() .stream() .map(Requires::name) .collect(Collectors.toSet()); assertEquals(names, Set.of("java.base")); // packages assertEquals(descriptor.packages(), Set.of("p", "q")); assertTrue(descriptor.exports().isEmpty()); assertTrue(descriptor.opens().isEmpty()); }
private void printModuleInfo(PrintWriter writer, ModuleDescriptor descriptor) { writer.format("module %s {%n", descriptor.name()); Map<String, Module> modules = configuration.getModules(); // first print the JDK modules descriptor.requires().stream() .filter(req -> !req.name().equals("java.base")) // implicit requires .sorted(Comparator.comparing(Requires::name)) .forEach(req -> writer.format(" requires %s;%n", req)); descriptor.exports().stream() .peek(exp -> { if (exp.targets().size() > 0) throw new InternalError(descriptor.name() + " qualified exports: " + exp); }) .sorted(Comparator.comparing(Exports::source)) .forEach(exp -> writer.format(" exports %s;%n", exp.source())); descriptor.provides().values().stream() .sorted(Comparator.comparing(Provides::service)) .forEach(p -> p.providers().stream() .sorted() .forEach(impl -> writer.format(" provides %s with %s;%n", p.service(), impl))); writer.println("}"); }
/** * Returns a new {@code ModuleDescriptor} instance. */ ModuleDescriptor newModuleDescriptor(String name, boolean automatic, boolean synthetic, Set<Requires> requires, Set<String> uses, Set<Exports> exports, Map<String, Provides> provides, Version version, String mainClass, String osName, String osArch, String osVersion, Set<String> conceals, Set<String> packages, ModuleHashes hashes);
/** * Lookup the class in this pool and the required pools. NB: static module * readability can be different at execution time. * * @param binaryName The class to lookup. * @return The reader or null if not found */ @Override public ClassReader getClassReaderInDependencies(String binaryName) { Objects.requireNonNull(binaryName); ClassReader reader = getClassReader(binaryName); if (reader == null) { for (Requires requires : descriptor.requires()) { AsmModulePool pool = pools.getModulePool(requires.name()); reader = pool.getExportedClassReader(moduleName, binaryName); if (reader != null) { break; } } } return reader; }
private static Set<Requires.Modifier> requireModifiers(int modifiers) { return Map.of( ACC_MANDATED, Requires.Modifier.MANDATED, ACC_SYNTHETIC, Requires.Modifier.SYNTHETIC, ACC_TRANSITIVE, Requires.Modifier.TRANSITIVE, ACC_STATIC_PHASE, Requires.Modifier.STATIC) .entrySet() .stream() .map(entry -> (modifiers & entry.getKey()) != 0? entry.getValue(): null) .filter(Objects::nonNull) .collect(Collectors.toSet()); }
private static int modifierToInt(Requires.Modifier modifier) { switch(modifier) { case MANDATED: return ACC_MANDATED; case SYNTHETIC: return ACC_SYNTHETIC; case STATIC: return ACC_STATIC_PHASE; case TRANSITIVE: return ACC_TRANSITIVE; default: throw new IllegalStateException("unknown modifier " + modifier); } }
public void printModuleDescriptor(Module module) { if (!module.isNamed()) return; writer.format("%s%s%n", module.name(), module.isAutomatic() ? " automatic" : ""); writer.format(" [%s]%n", module.location()); module.descriptor().requires() .stream() .sorted(Comparator.comparing(Requires::name)) .forEach(req -> writer.format(" requires %s%n", req)); }
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("}"); }
/** * 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);
void newRequires(Set<Requires.Modifier> mods, String name, String compiledVersion) { int varIndex = dedupSetBuilder.indexOfRequiresModifiers(mods); mv.visitVarInsn(ALOAD, varIndex); mv.visitLdcInsn(name); if (compiledVersion != null) { mv.visitLdcInsn(compiledVersion); mv.visitMethodInsn(INVOKESTATIC, MODULE_DESCRIPTOR_BUILDER, "newRequires", REQUIRES_SET_STRING_STRING_SIG, false); } else { mv.visitMethodInsn(INVOKESTATIC, MODULE_DESCRIPTOR_BUILDER, "newRequires", REQUIRES_SET_STRING_SIG, false); } }
/** * Basic test of "requires static": * m1 requires static m2 * m2 is not observable * resolve m1 */ public void testRequiresStatic1() { ModuleDescriptor descriptor1 = newBuilder("m1") .requires(Set.of(Requires.Modifier.STATIC), "m2") .build(); ModuleFinder finder = ModuleUtils.finderOf(descriptor1); Configuration cf = resolve(finder, "m1"); assertTrue(cf.modules().size() == 1); ResolvedModule m1 = cf.findModule("m1").get(); assertTrue(m1.reads().size() == 0); }
/** * Basic test of "requires static": * m1 requires m2, m3 * m2 requires static m2 * m3 */ public void testRequiresStatic4() { ModuleDescriptor descriptor1 = newBuilder("m1") .requires("m2") .requires("m3") .build(); ModuleDescriptor descriptor2 = newBuilder("m2") .requires(Set.of(Requires.Modifier.STATIC), "m3") .build(); ModuleDescriptor descriptor3 = newBuilder("m3") .build(); ModuleFinder finder = ModuleUtils.finderOf(descriptor1, descriptor2, descriptor3); Configuration cf = resolve(finder, "m1"); assertTrue(cf.modules().size() == 3); ResolvedModule m1 = cf.findModule("m1").get(); ResolvedModule m2 = cf.findModule("m2").get(); ResolvedModule m3 = cf.findModule("m3").get(); assertTrue(m1.reads().size() == 2); assertTrue(m1.reads().contains(m2)); assertTrue(m1.reads().contains(m3)); assertTrue(m2.reads().size() == 1); assertTrue(m2.reads().contains(m3)); assertTrue(m3.reads().size() == 0); }
/** * Basic test of "requires static": * The test consists of three configurations: * - Configuration cf1: m1, m2 * - Configuration cf2: m3 requires m1, requires static m2 */ public void testRequiresStatic5() { ModuleDescriptor descriptor1 = newBuilder("m1") .build(); ModuleDescriptor descriptor2 = newBuilder("m2") .build(); ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1, descriptor2); Configuration cf1 = resolve(finder1, "m1", "m2"); assertTrue(cf1.modules().size() == 2); assertTrue(cf1.findModule("m1").isPresent()); assertTrue(cf1.findModule("m2").isPresent()); ModuleDescriptor descriptor3 = newBuilder("m3") .requires("m1") .requires(Set.of(Requires.Modifier.STATIC), "m2") .build(); ModuleFinder finder2 = ModuleUtils.finderOf(descriptor3); Configuration cf2 = resolve(cf1, finder2, "m3"); assertTrue(cf2.modules().size() == 1); assertTrue(cf2.findModule("m3").isPresent()); ResolvedModule m1 = cf1.findModule("m1").get(); ResolvedModule m2 = cf1.findModule("m2").get(); ResolvedModule m3 = cf2.findModule("m3").get(); assertTrue(m3.reads().size() == 2); assertTrue(m3.reads().contains(m1)); assertTrue(m3.reads().contains(m2)); }
/** * Basic test of "requires static": * The test consists of three configurations: * - Configuration cf1: m1 * - Configuration cf2: m3 requires m1, requires static m2 */ public void testRequiresStatic6() { ModuleDescriptor descriptor1 = newBuilder("m1") .build(); ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1); Configuration cf1 = resolve(finder1, "m1"); assertTrue(cf1.modules().size() == 1); assertTrue(cf1.findModule("m1").isPresent()); ModuleDescriptor descriptor3 = newBuilder("m3") .requires("m1") .requires(Set.of(Requires.Modifier.STATIC), "m2") .build(); ModuleFinder finder2 = ModuleUtils.finderOf(descriptor3); Configuration cf2 = resolve(cf1, finder2, "m3"); assertTrue(cf2.modules().size() == 1); assertTrue(cf2.findModule("m3").isPresent()); ResolvedModule m1 = cf1.findModule("m1").get(); ResolvedModule m3 = cf2.findModule("m3").get(); assertTrue(m3.reads().size() == 1); assertTrue(m3.reads().contains(m1)); }
/** * Basic test of "requires static": * (m1 not observable) * m2 requires transitive static m1 * m3 requires m2 */ public void testRequiresStatic7() { ModuleDescriptor descriptor1 = null; // not observable ModuleDescriptor descriptor2 = newBuilder("m2") .requires(Set.of(Requires.Modifier.TRANSITIVE, Requires.Modifier.STATIC), "m1") .build(); ModuleDescriptor descriptor3 = newBuilder("m3") .requires("m2") .build(); ModuleFinder finder = ModuleUtils.finderOf(descriptor2, descriptor3); Configuration cf = resolve(finder, "m3"); assertTrue(cf.modules().size() == 2); assertTrue(cf.findModule("m2").isPresent()); assertTrue(cf.findModule("m3").isPresent()); ResolvedModule m2 = cf.findModule("m2").get(); ResolvedModule m3 = cf.findModule("m3").get(); assertTrue(m2.reads().isEmpty()); assertTrue(m3.reads().size() == 1); assertTrue(m3.reads().contains(m2)); }
/** * Basic test of "requires static": * - Configuration cf1: m2 requires transitive static m1 * - Configuration cf2: m3 requires m2 */ public void testRequiresStatic8() { ModuleDescriptor descriptor1 = null; // not observable ModuleDescriptor descriptor2 = newBuilder("m2") .requires(Set.of(Requires.Modifier.TRANSITIVE, Requires.Modifier.STATIC), "m1") .build(); ModuleFinder finder1 = ModuleUtils.finderOf(descriptor2); Configuration cf1 = resolve(finder1, "m2"); assertTrue(cf1.modules().size() == 1); assertTrue(cf1.findModule("m2").isPresent()); ResolvedModule m2 = cf1.findModule("m2").get(); assertTrue(m2.reads().isEmpty()); ModuleDescriptor descriptor3 = newBuilder("m3") .requires("m2") .build(); ModuleFinder finder2 = ModuleUtils.finderOf(descriptor3); Configuration cf2 = resolve(cf1, finder2, "m3"); assertTrue(cf2.modules().size() == 1); assertTrue(cf2.findModule("m3").isPresent()); ResolvedModule m3 = cf2.findModule("m3").get(); assertTrue(m3.reads().size() == 1); assertTrue(m3.reads().contains(m2)); }
/** * Basic test to detect reading two modules with the same name * * The test consists of three configurations: * - Configuration cf1: m1, m2 requires transitive m1 * - Configuration cf2: m1, m3 requires transitive m1 * - Configuration cf3(cf1,cf2): m4 requires m2, m3 */ @Test(expectedExceptions = { ResolutionException.class }) public void testReadTwoModuleWithSameName() { ModuleDescriptor descriptor1 = newBuilder("m1") .build(); ModuleDescriptor descriptor2 = newBuilder("m2") .requires(Set.of(Requires.Modifier.TRANSITIVE), "m1") .build(); ModuleDescriptor descriptor3 = newBuilder("m3") .requires(Set.of(Requires.Modifier.TRANSITIVE), "m1") .build(); ModuleDescriptor descriptor4 = newBuilder("m4") .requires("m2") .requires("m3") .build(); ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1, descriptor2); Configuration cf1 = resolve(finder1, "m2"); assertTrue(cf1.modules().size() == 2); ModuleFinder finder2 = ModuleUtils.finderOf(descriptor1, descriptor3); Configuration cf2 = resolve(finder2, "m3"); assertTrue(cf2.modules().size() == 2); // should throw ResolutionException as m4 will read modules named "m1". ModuleFinder finder3 = ModuleUtils.finderOf(descriptor4); Configuration.resolve(finder3, List.of(cf1, cf2), ModuleFinder.of(), Set.of("m4")); }
public void testRequiresWithNoModifiers() { Requires r = requires(EnumSet.noneOf(Requires.Modifier.class), "foo"); assertEquals(r, r); assertTrue(r.compareTo(r) == 0); assertTrue(r.modifiers().isEmpty()); assertEquals(r.name(), "foo"); assertFalse(r.compiledVersion().isPresent()); }
public void testRequiresWithOneModifier() { Requires r = requires(EnumSet.of(TRANSITIVE), "foo"); assertEquals(r, r); assertTrue(r.compareTo(r) == 0); assertEquals(r.modifiers(), EnumSet.of(TRANSITIVE)); assertEquals(r.name(), "foo"); assertFalse(r.compiledVersion().isPresent()); }
public void testRequiresWithTwoModifiers() { Requires r = requires(EnumSet.of(TRANSITIVE, SYNTHETIC), "foo"); assertEquals(r, r); assertTrue(r.compareTo(r) == 0); assertEquals(r.modifiers(), EnumSet.of(TRANSITIVE, SYNTHETIC)); assertEquals(r.name(), "foo"); assertFalse(r.compiledVersion().isPresent()); }
public void testRequiresWithAllModifiers() { Requires r = requires(EnumSet.allOf(Modifier.class), "foo"); assertEquals(r, r); assertTrue(r.compareTo(r) == 0); assertEquals(r.modifiers(), EnumSet.of(TRANSITIVE, STATIC, SYNTHETIC, MANDATED)); assertEquals(r.name(), "foo"); assertFalse(r.compiledVersion().isPresent()); }
public void testRequiresWithCompiledVersion() { Version v = Version.parse("1.0"); Requires r = requires(Set.of(), "foo", v); assertEquals(r, r); assertTrue(r.compareTo(r) == 0); assertEquals(r.modifiers(), Set.of()); assertEquals(r.name(), "foo"); assertTrue(r.compiledVersion().isPresent()); assertEquals(r.compiledVersion().get().toString(), "1.0"); }
public void testRequiresCompare() { Requires r1 = requires(EnumSet.noneOf(Modifier.class), "foo"); Requires r2 = requires(EnumSet.noneOf(Modifier.class), "bar"); int n = "foo".compareTo("bar"); assertTrue(r1.compareTo(r2) == n); assertTrue(r2.compareTo(r1) == -n); }
public void testRequiresCompareWithDifferentModifiers() { Requires r1 = requires(EnumSet.of(TRANSITIVE), "foo"); Requires r2 = requires(EnumSet.of(SYNTHETIC), "foo"); int n = Integer.compare(1 << TRANSITIVE.ordinal(), 1 << SYNTHETIC.ordinal()); assertTrue(r1.compareTo(r2) == n); assertTrue(r2.compareTo(r1) == -n); }
public void testRequiresEqualsAndHashCode() { Requires r1 = requires("foo"); Requires r2 = requires("foo"); assertEquals(r1, r2); assertTrue(r1.hashCode() == r2.hashCode()); r1 = requires(EnumSet.allOf(Requires.Modifier.class), "foo"); r2 = requires(EnumSet.allOf(Requires.Modifier.class), "foo"); assertEquals(r1, r2); assertTrue(r1.hashCode() == r2.hashCode()); r1 = requires("foo"); r2 = requires("bar"); assertNotEquals(r1, r2); r1 = requires(EnumSet.allOf(Requires.Modifier.class), "foo"); r2 = requires(Set.of(), "foo"); assertNotEquals(r1, r2); Version v1 = Version.parse("1.0"); r1 = requires(EnumSet.allOf(Requires.Modifier.class), "foo", v1); r2 = requires(EnumSet.allOf(Requires.Modifier.class), "foo", v1); assertEquals(r1, r2); assertTrue(r1.hashCode() == r2.hashCode()); Version v2 = Version.parse("2.0"); r1 = requires(EnumSet.allOf(Requires.Modifier.class), "foo", v1); r2 = requires(EnumSet.allOf(Requires.Modifier.class), "foo", v2); assertNotEquals(r1, r2); }
public void testOpenModule() { ModuleDescriptor descriptor = ModuleDescriptor.newOpenModule("foo") .requires("bar") .exports("p") .provides("p.Service", List.of("q.ServiceImpl")) .build(); // modifiers assertTrue(descriptor.modifiers().contains(ModuleDescriptor.Modifier.OPEN)); assertTrue(descriptor.isOpen()); // requires assertTrue(descriptor.requires().size() == 2); Set<String> names = descriptor.requires() .stream() .map(Requires::name) .collect(Collectors.toSet()); assertEquals(names, Set.of("bar", "java.base")); // packages assertEquals(descriptor.packages(), Set.of("p", "q")); // exports assertTrue(descriptor.exports().size() == 1); names = descriptor.exports() .stream() .map(Exports::source) .collect(Collectors.toSet()); assertEquals(names, Set.of("p")); // opens assertTrue(descriptor.opens().isEmpty()); }
/** * Test layers with a qualified export. The module exporting the package * reads the target module in the parent layer (due to requires transitive). * * - Configuration/layer1: m1, m2 { requires transitive m1; } * - Configuration/layer2: m1, m3 { requires m2; exports p to m1; } */ public void testQualifiedExports6() { // create layer1 with m1 and m2 ModuleDescriptor descriptor1 = newBuilder("m1").build(); ModuleDescriptor descriptor2 = newBuilder("m2") .requires(Set.of(Requires.Modifier.TRANSITIVE), "m1") .build(); ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1, descriptor2); Configuration cf1 = resolve(finder1, "m2"); ClassLoader loader1 = new ClassLoader() { }; ModuleLayer layer1 = ModuleLayer.empty().defineModules(cf1, mn -> loader1); assertTrue(layer1.modules().size() == 2); // create layer2 with m1 and m3 ModuleDescriptor descriptor3 = newBuilder("m3") .requires("m2") .exports("p", Set.of("m1")) .build(); ModuleFinder finder2 = ModuleUtils.finderOf(descriptor1, descriptor3); Configuration cf2 = resolve(cf1, finder2, "m1", "m3"); ClassLoader loader2 = new ClassLoader() { }; ModuleLayer layer2 = layer1.defineModules(cf2, mn -> loader2); assertTrue(layer2.modules().size() == 2); Module m1_v1 = layer1.findModule("m1").get(); Module m2 = layer1.findModule("m2").get(); Module m1_v2 = layer2.findModule("m1").get(); Module m3 = layer2.findModule("m3").get(); assertTrue(m3.canRead(m1_v1)); assertFalse(m3.canRead(m1_v2)); assertFalse(m3.isExported("p")); assertTrue(m3.isExported("p", m1_v1)); assertFalse(m3.isExported("p", m1_v2)); assertFalse(m3.isExported("p", m2)); }
/** * Adds a module dependence with the given modifier. */ public Builder requires(Requires.Modifier mod, String mn) { if (mod == Requires.Modifier.MANDATED) { requires.add(jlma.newRequires(MANDATED, mn)); } else if (mod == Requires.Modifier.PUBLIC) { requires.add(jlma.newRequires(PUBLIC, mn)); } else { requires.add(jlma.newRequires(Collections.singleton(mod), mn)); } return this; }
@Override public Set<String> getAccessiblePackages(String module) { AsmModulePool p = pools.get(module); if (p == null) { return null; } ModuleDescriptor desc = p.getDescriptor(); Set<String> packages = new HashSet<>(); packages.addAll(p.getAllPackages()); // Retrieve direct dependencies and indirect ones (public) Set<String> modules = new HashSet<>(); for (Requires req : desc.requires()) { modules.add(req.name()); addAllRequirePublicModules(req.name(), modules); } // Add exported packages of readable modules for (String readable : modules) { AsmModulePool mp = pools.get(readable); if (mp != null) { for (Exports e : mp.getDescriptor().exports()) { // exported to all or to the targeted module if (e.targets().isEmpty() || e.targets().contains(module)) { packages.add(e.source().replaceAll("\\.", "/")); } } } } return packages; }
private void addAllRequirePublicModules(String module, Set<String> modules) { AsmModulePool p = pools.get(module); if (p != null) { for (Requires req : p.getDescriptor().requires()) { if (req.modifiers().contains(PUBLIC)) { modules.add(req.name()); addAllRequirePublicModules(req.name(), modules); } } } }
/** * Lookup the class in the exported packages of this module. "public * requires" modules are looked up. NB: static module readability can be * different at execution time. * * @param callerModule Name of calling module. * @param binaryName The class to lookup. * @return The reader or null if not found */ @Override public ClassReader getExportedClassReader(String callerModule, String binaryName) { Objects.requireNonNull(callerModule); Objects.requireNonNull(binaryName); boolean exported = false; ClassReader clazz = null; for (Exports e : descriptor.exports()) { String pkg = e.source(); Set<String> targets = e.targets(); System.out.println("PKG " + pkg); if (targets.isEmpty() || targets.contains(callerModule)) { if (binaryName.startsWith(pkg)) { String className = binaryName.substring(pkg.length()); System.out.println("CLASS " + className); exported = !className.contains("."); } if (exported) { break; } } } // public requires (re-export) if (!exported) { for (Requires requires : descriptor.requires()) { if (requires.modifiers().contains(Modifier.PUBLIC)) { AsmModulePool pool = pools.getModulePool(requires.name()); clazz = pool.getExportedClassReader(moduleName, binaryName); if (clazz != null) { break; } } } } else { clazz = getClassReader(binaryName); } return clazz; }
private Requires requires(Set<Modifier> mods, String mn) { return new Builder("m") .requires(mods, mn) .build() .requires() .iterator() .next(); }
public void testRequiresWithNullModifiers() { Requires r = requires(null, "foo"); assertEquals(r, r); assertTrue(r.compareTo(r) == 0); assertTrue(r.modifiers().isEmpty()); assertEquals(r.name(), "foo"); }