OpenJDK / jigsaw / jake / jdk
changeset 15569:47488e198f22
Improve post-resolution checks to include uses/provides
author | alanb |
---|---|
date | Tue, 08 Mar 2016 12:39:39 +0000 |
parents | a9f1485296c7 |
children | a562e16994cc |
files | src/java.base/share/classes/java/lang/module/Configuration.java src/java.base/share/classes/java/lang/module/Resolver.java test/jdk/jigsaw/module/ConfigurationTest.java |
diffstat | 3 files changed, 176 insertions(+), 5 deletions(-) [+] |
line wrap: on
line diff
--- a/src/java.base/share/classes/java/lang/module/Configuration.java Tue Mar 08 11:19:55 2016 +0000 +++ b/src/java.base/share/classes/java/lang/module/Configuration.java Tue Mar 08 12:39:39 2016 +0000 @@ -223,8 +223,12 @@ * * <li><p> Two or more modules in the configuration 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> + * 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} declares that it "{@code uses p.S}" or + * "{@code provides p.S}" but does not read a module that exports + * package {@code p} to {@code M}. </p></li> * * <li><p> Two or more modules in the configuration are specific to * different {@link ModuleDescriptor#osName() operating systems},
--- a/src/java.base/share/classes/java/lang/module/Resolver.java Tue Mar 08 11:19:55 2016 +0000 +++ b/src/java.base/share/classes/java/lang/module/Resolver.java Tue Mar 08 12:39:39 2016 +0000 @@ -825,6 +825,8 @@ * Checks the readability graph to ensure that no two modules export the * same package to a module. This includes the case where module M has * a local package P and M reads another module that exports P to M. + * Also checks the uses/provides of module M to ensure that it reads a + * module that exports the package of the service type to M. */ private void checkExportSuppliers(Map<ReadDependence, Set<ReadDependence>> graph) { @@ -854,7 +856,7 @@ // source is exported to descriptor2 String source = export.source(); ModuleDescriptor other - = packageToExporter.put(source, descriptor2); + = packageToExporter.put(source, descriptor2); if (other != null && other != descriptor2) { // package might be local to descriptor1 @@ -878,6 +880,26 @@ } } + // uses S + for (String service : descriptor1.uses()) { + int index = service.lastIndexOf("."); + String pn = service.substring(0, index); + if (!packageToExporter.containsKey(pn)) { + fail("Module %s does not read a module that exports %s", + descriptor1.name(), pn); + } + } + + // provides S + for (String service : descriptor1.provides().keySet()) { + int index = service.lastIndexOf("."); + String pn = service.substring(0, index); + if (!packageToExporter.containsKey(pn)) { + fail("Module %s does not read a module that exports %s", + descriptor1.name(), pn); + } + } + } }
--- a/test/jdk/jigsaw/module/ConfigurationTest.java Tue Mar 08 11:19:55 2016 +0000 +++ b/test/jdk/jigsaw/module/ConfigurationTest.java Tue Mar 08 12:39:39 2016 +0000 @@ -441,11 +441,13 @@ ModuleDescriptor descriptor1 = new ModuleDescriptor.Builder("m1") + .exports("p") .uses("p.Service") .build(); ModuleDescriptor descriptor2 = new ModuleDescriptor.Builder("m2") + .requires("m1") .provides("p.Service", "q.ServiceImpl") .build(); @@ -491,17 +493,20 @@ ModuleDescriptor descriptor1 = new ModuleDescriptor.Builder("m1") + .exports("p") .uses("p.Service1") .build(); ModuleDescriptor descriptor2 = new ModuleDescriptor.Builder("m2") + .requires("m1") .uses("p.Service2") .provides("p.Service1", "q.Service1Impl") .build(); ModuleDescriptor descriptor3 = new ModuleDescriptor.Builder("m3") + .requires("m1") .provides("p.Service2", "q.Service2Impl") .build(); @@ -548,6 +553,7 @@ ModuleDescriptor descriptor1 = new ModuleDescriptor.Builder("m1") + .exports("p") .uses("p.Service") .build(); @@ -561,6 +567,7 @@ ModuleDescriptor descriptor2 = new ModuleDescriptor.Builder("m2") + .requires("m1") .provides("p.Service", "q.ServiceImpl") .build(); @@ -595,12 +602,14 @@ ModuleDescriptor descriptor1 = new ModuleDescriptor.Builder("m1") + .exports("p") .uses("p.Service") .provides("p.Service", "m1.ServiceImpl") .build(); ModuleDescriptor descriptor2 = new ModuleDescriptor.Builder("m2") + .requires("m1") .provides("p.Service", "m2.ServiceImpl") .build(); @@ -628,11 +637,13 @@ ModuleDescriptor descriptor3 = new ModuleDescriptor.Builder("m3") + .requires("m1") .provides("p.Service", "m3.ServiceImpl") .build(); ModuleDescriptor descriptor4 = new ModuleDescriptor.Builder("m4") + .requires("m1") .provides("p.Service", "m4.ServiceImpl") .build(); @@ -665,13 +676,19 @@ */ public void testServiceBindingWithConfigurations3() { + ModuleDescriptor service + = new ModuleDescriptor.Builder("s") + .exports("p") + .build(); + ModuleDescriptor provider_v1 = new ModuleDescriptor.Builder("p") .version("1.0") + .requires("s") .provides("p.Service", "q.ServiceImpl") .build(); - ModuleFinder finder1 = ModuleUtils.finderOf(provider_v1); + ModuleFinder finder1 = ModuleUtils.finderOf(service, provider_v1); Configuration cf1 = Configuration.resolve(finder1, @@ -679,19 +696,22 @@ ModuleFinder.empty(), "p"); - assertTrue(cf1.descriptors().size() == 1); + assertTrue(cf1.descriptors().size() == 2); + assertTrue(cf1.descriptors().contains(service)); assertTrue(cf1.descriptors().contains(provider_v1)); assertTrue(cf1.provides("p.Service").contains(provider_v1)); ModuleDescriptor descriptor1 = new ModuleDescriptor.Builder("m1") + .requires("s") .uses("p.Service") .build(); ModuleDescriptor provider_v2 = new ModuleDescriptor.Builder("p") .version("2.0") + .requires("s") .provides("p.Service", "q.ServiceImpl") .build(); @@ -774,16 +794,19 @@ ModuleDescriptor descriptor1 = new ModuleDescriptor.Builder("m1") + .exports("p") .uses("p.Service") .build(); ModuleDescriptor descriptor2_v1 = new ModuleDescriptor.Builder("m2") + .requires("m1") .provides("p.Service", "q.ServiceImpl") .build(); ModuleDescriptor descriptor2_v2 = new ModuleDescriptor.Builder("m2") + .requires("m1") .provides("p.Service", "q.ServiceImpl") .build(); @@ -1009,11 +1032,13 @@ ModuleDescriptor descriptor1 = new ModuleDescriptor.Builder("m1") + .exports("p") .uses("p.Service") .build(); ModuleDescriptor descriptor2 = new ModuleDescriptor.Builder("m2") + .requires("m1") .requires("m3") .provides("p.Service", "q.ServiceImpl") .build(); @@ -1059,10 +1084,12 @@ ModuleDescriptor descriptor1 = new ModuleDescriptor.Builder("m1") + .exports("p") .uses("p.Service") .build(); ModuleDescriptor descriptor2 = new ModuleDescriptor.Builder("m2") + .requires("m1") .requires("m3") .provides("p.Service", "q.ServiceImpl") .build(); @@ -1196,6 +1223,124 @@ /** + * Test "uses p.S" where p is a concealed package in the same module. + */ + public void testConcealedService1() { + ModuleDescriptor descriptor1 + = new ModuleDescriptor.Builder("m1") + .conceals("p") + .uses("p.S") + .build(); + + ModuleFinder finder = ModuleUtils.finderOf(descriptor1); + + Configuration cf + = Configuration.resolve(finder, empty(), ModuleFinder.empty(), "m1"); + + assertTrue(cf.descriptors().size() == 1); + assertTrue(cf.descriptors().contains(descriptor1)); + } + + + /** + * Test "uses p.S" where p is a concealed package in a different module. + */ + @Test(expectedExceptions = { ResolutionException.class }) + public void testConcealedService2() { + ModuleDescriptor descriptor1 + = new ModuleDescriptor.Builder("m1") + .conceals("p") + .build(); + + ModuleDescriptor descriptor2 + = new ModuleDescriptor.Builder("m2") + .requires("m1") + .uses("p.S") + .build(); + + ModuleFinder finder = ModuleUtils.finderOf(descriptor1, descriptor2); + + Configuration.resolve(finder, empty(), ModuleFinder.empty(), "m2"); + } + + + /** + * Test "provides p.S" where p is a concealed package in the same module. + */ + public void testConcealedService3() { + ModuleDescriptor descriptor1 + = new ModuleDescriptor.Builder("m1") + .conceals("p") + .provides("p.S", "q.S1") + .build(); + + ModuleFinder finder = ModuleUtils.finderOf(descriptor1); + + Configuration cf + = Configuration.resolve(finder, empty(), ModuleFinder.empty(), "m1"); + + assertTrue(cf.descriptors().size() == 1); + assertTrue(cf.descriptors().contains(descriptor1)); + assertTrue(cf.provides("p.S").size() == 1); + assertTrue(cf.provides("p.S").contains(descriptor1)); + } + + + /** + * Test "provides p.S" where p is a concealed package in a different module. + */ + @Test(expectedExceptions = { ResolutionException.class }) + public void testConcealedService4() { + ModuleDescriptor descriptor1 + = new ModuleDescriptor.Builder("m1") + .conceals("p") + .build(); + + ModuleDescriptor descriptor2 + = new ModuleDescriptor.Builder("m2") + .requires("m1") + .provides("p.S", "q.S1") + .build(); + + ModuleFinder finder = ModuleUtils.finderOf(descriptor1, descriptor2); + + Configuration.resolve(finder, empty(), ModuleFinder.empty(), "m2"); + } + + + /** + * Test "uses p.S" where p is not exported to the module. + */ + @Test(expectedExceptions = { ResolutionException.class }) + public void testServiceTypePackageNotExported1() { + ModuleDescriptor descriptor1 + = new ModuleDescriptor.Builder("m1") + .uses("p.S") + .build(); + + ModuleFinder finder = ModuleUtils.finderOf(descriptor1); + + Configuration.resolve(finder, empty(), ModuleFinder.empty(), "m1"); + } + + + /** + * Test "provides p.S" where p is not exported to the module. + */ + @Test(expectedExceptions = { ResolutionException.class }) + public void testServiceTypePackageNotExported2() { + ModuleDescriptor descriptor1 + = new ModuleDescriptor.Builder("m1") + .provides("p.S", "q.ServiceImpl") + .build(); + + ModuleFinder finder = ModuleUtils.finderOf(descriptor1); + + Configuration.resolve(finder, empty(), ModuleFinder.empty(), "m1"); + } + + + /** * Test the empty configuration. */ public void testEmptyConfiguration() {