/* * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions.
*/
// JAR file names that do not map to a legal module name
@DataProvider(name = "badjarnames") public Object[][] createBadNames() { returnnew Object[][]{
/** * Test JAR files with the Automatic-Module-Name attribute with a value * that is not a legal module name.
*/
@Test(dataProvider = "badmodulenames", expectedExceptions = FindException.class) publicvoid testBadAutomaticModuleNameAttribute(String name, String ignore) throws IOException
{ // should throw FindException
testAutomaticModuleNameAttribute(name, null);
}
/** * Test all packages are exported
*/ publicvoid testPackages() throws IOException {
Path dir = Files.createTempDirectory(USER_DIR, "mods");
createDummyJarFile(dir.resolve("m.jar"), "p/C1.class", "p/C2.class", "q/C1.class");
ModuleFinder finder = ModuleFinder.of(dir);
Optional<ModuleReference> mref = finder.find("m");
assertTrue(mref.isPresent(), "m not found");
/** * Test class files in JAR file where the entry does not correspond to a * legal package name.
*/ publicvoid testBadPackage() throws IOException {
Path dir = Files.createTempDirectory(USER_DIR, "mods");
createDummyJarFile(dir.resolve("m.jar"), "p/C1.class", "p-/C2.class");
ModuleFinder finder = ModuleFinder.of(dir);
Optional<ModuleReference> mref = finder.find("m");
assertTrue(mref.isPresent(), "m not found");
// META-INF/services files that don't map to legal service names
@DataProvider(name = "badservices") public Object[][] createBadServices() { returnnew Object[][] {
// service type provider type
{ "-", "p.S1" },
{ ".S", "p.S1" },
};
}
/** * Test JAR file with META-INF/services configuration file with bad * values or names.
*/
@Test(dataProvider = "badservices") publicvoid testBadServicesNames(String service, String provider) throws IOException
{
Path tmpdir = Files.createTempDirectory(USER_DIR, "tmp");
Path services = tmpdir.resolve("META-INF").resolve("services");
Files.createDirectories(services);
Files.write(services.resolve(service), Set.of(provider));
Path dir = Files.createTempDirectory(USER_DIR, "mods");
JarUtils.createJarFile(dir.resolve("m.jar"), tmpdir);
// META-INF/services configuration file entries that are not legal
@DataProvider(name = "badproviders") public Object[][] createBadProviders() { returnnew Object[][] {
// service type provider type
{ "p.S", "-" },
{ "p.S", "p..S1" },
{ "p.S", "S1." },
};
}
/** * Test JAR file with META-INF/services configuration file with bad * values or names.
*/
@Test(dataProvider = "badproviders", expectedExceptions = FindException.class) publicvoid testBadProviderNames(String service, String provider) throws IOException
{
Path tmpdir = Files.createTempDirectory(USER_DIR, "tmp");
Path dir = Files.createTempDirectory(USER_DIR, "mods");
JarUtils.createJarFile(dir.resolve("m.jar"), tmpdir);
// should throw FindException
ModuleFinder.of(dir).findAll();
}
/** * Test JAR file with META-INF/services configuration file listing a * provider that is not in the module.
*/
@Test(expectedExceptions = FindException.class) publicvoid testMissingProviderPackage() throws IOException {
Path tmpdir = Files.createTempDirectory(USER_DIR, "tmp");
// catch FindException, inspect its cause's type and details, and rethrow var expectedMessage = "Provider class q.P not in JAR file " + jarfile.getFileName(); try {
ModuleFinder.of(dir).findAll();
} catch (FindException exception) { if (exception.getCause() instanceof InvalidModuleDescriptorException imde) { var actualMessage = imde.getMessage(); if (actualMessage.equals(expectedMessage)) { throw exception; // rethrow as expected
} thrownew AssertionError( """
Unexpected detail message in InvalidModuleDescriptorException:
Expected message -> '%s'
Actual message -> '%s' """.formatted(expectedMessage, actualMessage));
} thrownew AssertionError("Unexpected exception cause: " + exception.getCause());
}
}
/** * Test that a JAR file with a Main-Class attribute results * in a module with a main class.
*/ publicvoid testMainClass() throws IOException {
String mainClass = "p.Main";
Manifest man = new Manifest();
Attributes attrs = man.getMainAttributes();
attrs.put(Attributes.Name.MANIFEST_VERSION, "1.0.0");
attrs.put(Attributes.Name.MAIN_CLASS, mainClass);
// Main-Class files that do not map to a legal qualified type name
@DataProvider(name = "badmainclass") public Object[][] createBadMainClass() { returnnew Object[][] {
{ "p..Main", null },
{ "p-.Main", null },
};
}
/** * Test that a JAR file with a Main-Class attribute that is not a qualified * type name.
*/
@Test(dataProvider = "badmainclass") publicvoid testBadMainClass(String mainClass, String ignore) throws IOException {
Manifest man = new Manifest();
Attributes attrs = man.getMainAttributes();
attrs.put(Attributes.Name.MANIFEST_VERSION, "1.0.0");
attrs.put(Attributes.Name.MAIN_CLASS, mainClass);
// bad Main-Class value should be ignored
Optional<ModuleReference> omref = ModuleFinder.of(dir).find("m");
assertTrue(omref.isPresent());
ModuleDescriptor descriptor = omref.get().descriptor();
assertFalse(descriptor.mainClass().isPresent());
}
/** * Test that a JAR file with a Main-Class attribute that is not in the module
*/ publicvoid testMissingMainClassPackage() throws IOException {
Manifest man = new Manifest();
Attributes attrs = man.getMainAttributes();
attrs.put(Attributes.Name.MANIFEST_VERSION, "1.0.0");
attrs.put(Attributes.Name.MAIN_CLASS, "p.Main");
Path dir = Files.createTempDirectory(USER_DIR, "mods");
createDummyJarFile(dir.resolve("m.jar"), man);
// Main-Class should be ignored because package p is not in module
Optional<ModuleReference> omref = ModuleFinder.of(dir).find("m");
assertTrue(omref.isPresent());
ModuleDescriptor descriptor = omref.get().descriptor();
assertFalse(descriptor.mainClass().isPresent());
}
/** * Basic test of a configuration created with automatic modules. * a requires b* * a requires c* * b* * c*
*/ publicvoid testConfiguration1() throws Exception {
ModuleDescriptor descriptor1
= ModuleDescriptor.newModule("a")
.requires("b")
.requires("c")
.requires("java.base")
.build();
// b and c are automatic modules
Path dir = Files.createTempDirectory(USER_DIR, "mods");
createDummyJarFile(dir.resolve("b.jar"), "p/T.class");
createDummyJarFile(dir.resolve("c.jar"), "q/T.class");
// module finder locates a and the modules in the directory
ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1);
ModuleFinder finder2 = ModuleFinder.of(dir);
ModuleFinder finder = ModuleFinder.compose(finder1, finder2);
ResolvedModule base = cf.findModule("java.base").get();
assertTrue(base.configuration() == ModuleLayer.boot().configuration());
ResolvedModule a = cf.findModule("a").get();
ResolvedModule b = cf.findModule("b").get();
ResolvedModule c = cf.findModule("c").get();
// b && c only require java.base
assertTrue(b.reference().descriptor().requires().size() == 1);
assertTrue(c.reference().descriptor().requires().size() == 1);
assertTrue(b.reads().contains(a));
assertTrue(b.reads().contains(c));
testReadAllBootModules(cf, "b"); // b reads all modules in boot layer
assertTrue(c.reads().contains(a));
assertTrue(c.reads().contains(b));
testReadAllBootModules(cf, "c"); // c reads all modules in boot layer
}
/** * Basic test of a configuration created with automatic modules * a requires b * b requires c* * c* * d*
*/ publicvoid testInConfiguration2() throws IOException {
ModuleDescriptor descriptor1
= ModuleDescriptor.newModule("a")
.requires("b")
.requires("java.base")
.build();
// c and d are automatic modules
Path dir = Files.createTempDirectory(USER_DIR, "mods");
createDummyJarFile(dir.resolve("c.jar"), "p/T.class");
createDummyJarFile(dir.resolve("d.jar"), "q/T.class");
// module finder locates a and the modules in the directory
ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1, descriptor2);
ModuleFinder finder2 = ModuleFinder.of(dir);
ModuleFinder finder = ModuleFinder.compose(finder1, finder2);
// c && d should only require java.base
assertTrue(findDescriptor(cf, "c").requires().size() == 1);
assertTrue(findDescriptor(cf, "d").requires().size() == 1);
// readability
ResolvedModule base = cf.findModule("java.base").get();
assertTrue(base.configuration() == ModuleLayer.boot().configuration());
ResolvedModule a = cf.findModule("a").get();
ResolvedModule b = cf.findModule("b").get();
ResolvedModule c = cf.findModule("c").get();
ResolvedModule d = cf.findModule("d").get();
assertTrue(c.reads().contains(a));
assertTrue(c.reads().contains(b));
assertTrue(c.reads().contains(d));
testReadAllBootModules(cf, "c"); // c reads all modules in boot layer
assertTrue(d.reads().contains(a));
assertTrue(d.reads().contains(b));
assertTrue(d.reads().contains(c));
testReadAllBootModules(cf, "d"); // d reads all modules in boot layer
}
/** * Basic test of a configuration created with automatic modules * a requires b * b requires transitive c* * c* * d*
*/ publicvoid testInConfiguration3() throws IOException {
ModuleDescriptor descriptor1
= ModuleDescriptor.newModule("a")
.requires("b")
.requires("java.base")
.build();
// c and d are automatic modules
Path dir = Files.createTempDirectory(USER_DIR, "mods");
createDummyJarFile(dir.resolve("c.jar"), "p/T.class");
createDummyJarFile(dir.resolve("d.jar"), "q/T.class");
// module finder locates a and the modules in the directory
ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1, descriptor2);
ModuleFinder finder2 = ModuleFinder.of(dir);
ModuleFinder finder = ModuleFinder.compose(finder1, finder2);
ResolvedModule base = cf.findModule("java.base").get();
assertTrue(base.configuration() == ModuleLayer.boot().configuration());
ResolvedModule a = cf.findModule("a").get();
ResolvedModule b = cf.findModule("b").get();
ResolvedModule c = cf.findModule("c").get();
ResolvedModule d = cf.findModule("d").get();
// c && d should only require java.base
assertTrue(findDescriptor(cf, "c").requires().size() == 1);
assertTrue(findDescriptor(cf, "d").requires().size() == 1);
assertTrue(c.reads().contains(a));
assertTrue(c.reads().contains(b));
assertTrue(c.reads().contains(d));
testReadAllBootModules(cf, "c"); // c reads all modules in boot layer
assertTrue(d.reads().contains(a));
assertTrue(d.reads().contains(b));
assertTrue(d.reads().contains(c));
testReadAllBootModules(cf, "d"); // d reads all modules in boot layer
}
/** * Basic test to ensure that no automatic modules are resolved when * an automatic module is not a root or required by other modules.
*/ publicvoid testInConfiguration4() throws IOException {
ModuleDescriptor descriptor1
= ModuleDescriptor.newModule("m1")
.requires("java.base")
.build();
// module finder locates m1 and the modules in the directory
ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1);
ModuleFinder finder2 = ModuleFinder.of(dir);
ModuleFinder finder = ModuleFinder.compose(finder1, finder2);
// ensure that no automatic module is resolved
assertTrue(cf.modules().size() == 1);
assertTrue(cf.findModule("m1").isPresent());
}
/** * Basic test to ensure that if an automatic module is resolved then * all observable automatic modules are resolved.
*/ publicvoid testInConfiguration5() throws IOException { // m1 requires m2
ModuleDescriptor descriptor1
= ModuleDescriptor.newModule("m1")
.requires("m2").build();
// module finder locates m1, m2, and the modules in the directory
ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1, descriptor2);
ModuleFinder finder2 = ModuleFinder.of(dir);
ModuleFinder finder = ModuleFinder.compose(finder1, finder2);
// all automatic modules should be resolved
assertTrue(cf.modules().size() == 5);
assertTrue(cf.findModule("m1").isPresent());
assertTrue(cf.findModule("m2").isPresent());
assertTrue(cf.findModule("auto1").isPresent());
assertTrue(cf.findModule("auto2").isPresent());
assertTrue(cf.findModule("auto3").isPresent());
// m1 does not read the automatic modules
assertTrue(m1.reads().size() == 2);
assertTrue(m1.reads().contains(m2));
assertTrue(m1.reads().contains(base));
// m2 should read all the automatic modules
assertTrue(m2.reads().size() == 4);
assertTrue(m2.reads().contains(auto1));
assertTrue(m2.reads().contains(auto2));
assertTrue(m2.reads().contains(auto3));
assertTrue(m2.reads().contains(base));
/** * Basic test of automatic modules in a child configuration. All automatic * modules that are found with the before finder should be resolved. The * automatic modules that are found by the after finder and not shadowed * by the before finder, or parent configurations, should also be resolved.
*/ publicvoid testInConfiguration6() throws IOException { // m1 requires auto1
ModuleDescriptor descriptor1
= ModuleDescriptor.newModule("m1")
.requires("auto1")
.build();
Path dir = Files.createTempDirectory(USER_DIR, "mods");
createDummyJarFile(dir.resolve("auto1.jar"), "p1/C.class");
// module finder locates m1 and auto1
ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1);
ModuleFinder finder2 = ModuleFinder.of(dir);
ModuleFinder finder = ModuleFinder.compose(finder1, finder2);
// auto1 should be found in parent and should not be in cf2
assertTrue(cf2.modules().size() == 2);
assertTrue(cf2.findModule("auto2").isPresent());
assertTrue(cf2.findModule("auto3").isPresent());
/** * Basic test for a module requiring an automatic module in a parent * configuration. If an explicit module in a child configuration reads an * automatic module in a parent configuration then it should read all * automatic modules in the parent configuration.
*/ publicvoid testInConfiguration7() throws Exception { // m1 requires auto1
ModuleDescriptor descriptor1 = ModuleDescriptor.newModule("m1")
.requires("auto1")
.build();
/** * Basic test of a configuration created with automatic modules * a requires b* and c* * b* contains p * c* contains p
*/
@Test(expectedExceptions = { ResolutionException.class }) publicvoid testDuplicateSuppliers1() throws IOException {
ModuleDescriptor descriptor
= ModuleDescriptor.newModule("a")
.requires("b")
.requires("c")
.build();
// c and d are automatic modules with the same package
Path dir = Files.createTempDirectory(USER_DIR, "mods");
createDummyJarFile(dir.resolve("b.jar"), "p/T.class");
createDummyJarFile(dir.resolve("c.jar"), "p/T.class");
// module finder locates 'a' and the modules in the directory
ModuleFinder finder
= ModuleFinder.compose(ModuleUtils.finderOf(descriptor),
ModuleFinder.of(dir));
/** * Basic test of a configuration created with automatic modules * a contains p, requires b* * b* contains p
*/
@Test(expectedExceptions = { ResolutionException.class }) publicvoid testDuplicateSuppliers2() throws IOException {
ModuleDescriptor descriptor
= ModuleDescriptor.newModule("a")
.packages(Set.of("p"))
.requires("b")
.build();
// c and d are automatic modules with the same package
Path dir = Files.createTempDirectory(USER_DIR, "mods");
createDummyJarFile(dir.resolve("b.jar"), "p/T.class");
// module finder locates 'a' and the modules in the directory
ModuleFinder finder
= ModuleFinder.compose(ModuleUtils.finderOf(descriptor),
ModuleFinder.of(dir));
// b and c are simple JAR files
Path dir = Files.createTempDirectory(USER_DIR, "mods");
createDummyJarFile(dir.resolve("b.jar"), "p/T.class");
createDummyJarFile(dir.resolve("c.jar"), "q/T2.class");
// module finder locates a and the modules in the directory
ModuleFinder finder
= ModuleFinder.compose(ModuleUtils.finderOf(descriptor),
ModuleFinder.of(dir));
assertTrue(finder.find("m").isPresent());
ModuleDescriptor m = finder.find("m").get().descriptor();
// test miscellaneous methods
assertTrue(m.isAutomatic());
assertFalse(m.modifiers().contains(ModuleDescriptor.Modifier.SYNTHETIC));
}
/** * Invokes parent.resolve to resolve the given root modules.
*/ static Configuration resolve(Configuration parent,
ModuleFinder finder,
String... roots) { return parent.resolve(finder, ModuleFinder.of(), Set.of(roots));
}
/** * Finds a module in the given configuration or its parents, returning * the module descriptor (or null if not found)
*/ static ModuleDescriptor findDescriptor(Configuration cf, String name) {
Optional<ResolvedModule> om = cf.findModule(name); if (om.isPresent()) { return om.get().reference().descriptor();
} else { returnnull;
}
}
/** * Test that a module in a configuration reads all modules in the boot * configuration.
*/ staticvoid testReadAllBootModules(Configuration cf, String mn) {
/** * Test that the given Module reads all module in the given layer * and its parent layers.
*/ staticvoid testsReadsAll(Module m, ModuleLayer layer) { // check that m reads all modules in the layer
layer.configuration().modules().stream()
.map(ResolvedModule::name)
.map(layer::findModule)
.map(Optional::get)
.forEach(other -> assertTrue(m.canRead(other)));
// also check parent layers
layer.parents().forEach(l -> testsReadsAll(m, l));
}
/** * Returns {@code true} if the configuration contains module mn1 * that reads module mn2.
*/ staticboolean reads(Configuration cf, String mn1, String mn2) {
Optional<ResolvedModule> om = cf.findModule(mn1); if (!om.isPresent()) returnfalse;
/** * Creates a JAR file, optionally with a manifest, and with the given * entries. The entries will be empty in the resulting JAR file.
*/ static Path createDummyJarFile(Path jarfile, Manifest man, String... entries) throws IOException
{
Path dir = Files.createTempDirectory(USER_DIR, "tmp");
/** * Creates a JAR file and with the given entries. The entries will be empty * in the resulting JAR file.
*/ static Path createDummyJarFile(Path jarfile, String... entries) throws IOException
{ return createDummyJarFile(jarfile, null, entries);
}
}
¤ Dauer der Verarbeitung: 0.32 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.