1 /* 2 * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /** 25 * @test 26 * @modules java.base/jdk.internal.module 27 * @library /test/lib 28 * @build ModuleFinderTest 29 * @run testng ModuleFinderTest 30 * @summary Basic tests for java.lang.module.ModuleFinder 31 */ 32 33 import java.io.File; 34 import java.io.OutputStream; 35 import java.lang.module.FindException; 36 import java.lang.module.InvalidModuleDescriptorException; 37 import java.lang.module.ModuleDescriptor; 38 import java.lang.module.ModuleFinder; 39 import java.lang.module.ModuleReference; 40 import java.nio.file.Files; 41 import java.nio.file.Path; 42 import java.nio.file.Paths; 43 import java.util.Optional; 44 import java.util.Set; 45 import java.util.jar.JarEntry; 46 import java.util.jar.JarOutputStream; 47 import java.util.stream.Collectors; 48 49 import jdk.test.lib.util.ModuleInfoWriter; 50 51 import org.testng.annotations.Test; 52 import static org.testng.Assert.*; 53 54 @Test 55 public class ModuleFinderTest { 56 57 private static final Path USER_DIR 58 = Paths.get(System.getProperty("user.dir")); 59 60 61 /** 62 * Test ModuleFinder.ofSystem 63 */ 64 public void testOfSystem() { 65 ModuleFinder finder = ModuleFinder.ofSystem(); 66 67 assertTrue(finder.find("java.se").isPresent()); 68 assertTrue(finder.find("java.base").isPresent()); 69 assertFalse(finder.find("java.rhubarb").isPresent()); 70 71 Set<String> names = finder.findAll().stream() 72 .map(ModuleReference::descriptor) 73 .map(ModuleDescriptor::name) 74 .collect(Collectors.toSet()); 75 assertTrue(names.contains("java.se")); 76 assertTrue(names.contains("java.base")); 77 assertFalse(names.contains("java.rhubarb")); 78 } 79 80 81 /** 82 * Test ModuleFinder.of with no entries 83 */ 84 public void testOfNoEntries() { 85 ModuleFinder finder = ModuleFinder.of(); 86 assertTrue(finder.findAll().isEmpty()); 87 assertFalse(finder.find("java.rhubarb").isPresent()); 88 } 89 90 91 /** 92 * Test ModuleFinder.of with one directory of modules 93 */ 94 public void testOfOneDirectory() throws Exception { 95 Path dir = Files.createTempDirectory(USER_DIR, "mods"); 96 createExplodedModule(dir.resolve("m1"), "m1"); 97 createModularJar(dir.resolve("m2.jar"), "m2"); 98 99 ModuleFinder finder = ModuleFinder.of(dir); 100 assertTrue(finder.findAll().size() == 2); 101 assertTrue(finder.find("m1").isPresent()); 102 assertTrue(finder.find("m2").isPresent()); 103 assertFalse(finder.find("java.rhubarb").isPresent()); 104 } 105 106 107 /** 108 * Test ModuleFinder.of with two directories 109 */ 110 public void testOfTwoDirectories() throws Exception { 111 Path dir1 = Files.createTempDirectory(USER_DIR, "mods1"); 112 createExplodedModule(dir1.resolve("m1"), "m1@1.0"); 113 createModularJar(dir1.resolve("m2.jar"), "m2@1.0"); 114 115 Path dir2 = Files.createTempDirectory(USER_DIR, "mods2"); 116 createExplodedModule(dir2.resolve("m1"), "m1@2.0"); 117 createModularJar(dir2.resolve("m2.jar"), "m2@2.0"); 118 createExplodedModule(dir2.resolve("m3"), "m3"); 119 createModularJar(dir2.resolve("m4.jar"), "m4"); 120 121 ModuleFinder finder = ModuleFinder.of(dir1, dir2); 122 assertTrue(finder.findAll().size() == 4); 123 assertTrue(finder.find("m1").isPresent()); 124 assertTrue(finder.find("m2").isPresent()); 125 assertTrue(finder.find("m3").isPresent()); 126 assertTrue(finder.find("m4").isPresent()); 127 assertFalse(finder.find("java.rhubarb").isPresent()); 128 129 // check that m1@1.0 (and not m1@2.0) is found 130 ModuleDescriptor m1 = finder.find("m1").get().descriptor(); 131 assertEquals(m1.version().get().toString(), "1.0"); 132 133 // check that m2@1.0 (and not m2@2.0) is found 134 ModuleDescriptor m2 = finder.find("m2").get().descriptor(); 135 assertEquals(m2.version().get().toString(), "1.0"); 136 } 137 138 139 /** 140 * Test ModuleFinder.of with one JAR file 141 */ 142 public void testOfOneJarFile() throws Exception { 143 Path dir = Files.createTempDirectory(USER_DIR, "mods"); 144 Path jar1 = createModularJar(dir.resolve("m1.jar"), "m1"); 145 146 ModuleFinder finder = ModuleFinder.of(jar1); 147 assertTrue(finder.findAll().size() == 1); 148 assertTrue(finder.find("m1").isPresent()); 149 assertFalse(finder.find("java.rhubarb").isPresent()); 150 } 151 152 153 /** 154 * Test ModuleFinder.of with two JAR files 155 */ 156 public void testOfTwoJarFiles() throws Exception { 157 Path dir = Files.createTempDirectory(USER_DIR, "mods"); 158 159 Path jar1 = createModularJar(dir.resolve("m1.jar"), "m1"); 160 Path jar2 = createModularJar(dir.resolve("m2.jar"), "m2"); 161 162 ModuleFinder finder = ModuleFinder.of(jar1, jar2); 163 assertTrue(finder.findAll().size() == 2); 164 assertTrue(finder.find("m1").isPresent()); 165 assertTrue(finder.find("m2").isPresent()); 166 assertFalse(finder.find("java.rhubarb").isPresent()); 167 } 168 169 170 /** 171 * Test ModuleFinder.of with many JAR files 172 */ 173 public void testOfManyJarFiles() throws Exception { 174 Path dir = Files.createTempDirectory(USER_DIR, "mods"); 175 176 Path jar1 = createModularJar(dir.resolve("m1@1.0.jar"), "m1@1.0"); 177 Path jar2 = createModularJar(dir.resolve("m2@1.0.jar"), "m2"); 178 Path jar3 = createModularJar(dir.resolve("m1@2.0.jar"), "m1@2.0"); // shadowed 179 Path jar4 = createModularJar(dir.resolve("m3@1.0.jar"), "m3"); 180 181 ModuleFinder finder = ModuleFinder.of(jar1, jar2, jar3, jar4); 182 assertTrue(finder.findAll().size() == 3); 183 assertTrue(finder.find("m1").isPresent()); 184 assertTrue(finder.find("m2").isPresent()); 185 assertTrue(finder.find("m3").isPresent()); 186 assertFalse(finder.find("java.rhubarb").isPresent()); 187 188 // check that m1@1.0 (and not m1@2.0) is found 189 ModuleDescriptor m1 = finder.find("m1").get().descriptor(); 190 assertEquals(m1.version().get().toString(), "1.0"); 191 } 192 193 194 /** 195 * Test ModuleFinder.of with one exploded module. 196 */ 197 public void testOfOneExplodedModule() throws Exception { 198 Path dir = Files.createTempDirectory(USER_DIR, "mods"); 199 Path m1_dir = createExplodedModule(dir.resolve("m1"), "m1"); 200 201 ModuleFinder finder = ModuleFinder.of(m1_dir); 202 assertTrue(finder.findAll().size() == 1); 203 assertTrue(finder.find("m1").isPresent()); 204 assertFalse(finder.find("java.rhubarb").isPresent()); 205 } 206 207 208 /** 209 * Test ModuleFinder.of with two exploded modules. 210 */ 211 public void testOfTwoExplodedModules() throws Exception { 212 Path dir = Files.createTempDirectory(USER_DIR, "mods"); 213 Path m1_dir = createExplodedModule(dir.resolve("m1"), "m1"); 214 Path m2_dir = createExplodedModule(dir.resolve("m2"), "m2"); 215 216 ModuleFinder finder = ModuleFinder.of(m1_dir, m2_dir); 217 assertTrue(finder.findAll().size() == 2); 218 assertTrue(finder.find("m1").isPresent()); 219 assertTrue(finder.find("m2").isPresent()); 220 assertFalse(finder.find("java.rhubarb").isPresent()); 221 } 222 223 224 /** 225 * Test ModuleFinder.of with a mix of module directories and JAR files. 226 */ 227 public void testOfMixDirectoriesAndJars() throws Exception { 228 229 // directory with m1@1.0 and m2@1.0 230 Path dir1 = Files.createTempDirectory(USER_DIR, "mods1"); 231 createExplodedModule(dir1.resolve("m1"), "m1@1.0"); 232 createModularJar(dir1.resolve("m2.jar"), "m2@1.0"); 233 234 // JAR files: m1@2.0, m2@2.0, m3@2.0, m4@2.0 235 Path dir2 = Files.createTempDirectory(USER_DIR, "mods2"); 236 Path jar1 = createModularJar(dir2.resolve("m1.jar"), "m1@2.0"); 237 Path jar2 = createModularJar(dir2.resolve("m2.jar"), "m2@2.0"); 238 Path jar3 = createModularJar(dir2.resolve("m3.jar"), "m3@2.0"); 239 Path jar4 = createModularJar(dir2.resolve("m4.jar"), "m4@2.0"); 240 241 // directory with m3@3.0 and m4@3.0 242 Path dir3 = Files.createTempDirectory(USER_DIR, "mods3"); 243 createExplodedModule(dir3.resolve("m3"), "m3@3.0"); 244 createModularJar(dir3.resolve("m4.jar"), "m4@3.0"); 245 246 // JAR files: m5 and m6 247 Path dir4 = Files.createTempDirectory(USER_DIR, "mods4"); 248 Path jar5 = createModularJar(dir4.resolve("m5.jar"), "m5@4.0"); 249 Path jar6 = createModularJar(dir4.resolve("m6.jar"), "m6@4.0"); 250 251 252 ModuleFinder finder 253 = ModuleFinder.of(dir1, jar1, jar2, jar3, jar4, dir3, jar5, jar6); 254 assertTrue(finder.findAll().size() == 6); 255 assertTrue(finder.find("m1").isPresent()); 256 assertTrue(finder.find("m2").isPresent()); 257 assertTrue(finder.find("m3").isPresent()); 258 assertTrue(finder.find("m4").isPresent()); 259 assertTrue(finder.find("m5").isPresent()); 260 assertTrue(finder.find("m6").isPresent()); 261 assertFalse(finder.find("java.rhubarb").isPresent()); 262 263 // m1 and m2 should be located in dir1 264 ModuleDescriptor m1 = finder.find("m1").get().descriptor(); 265 assertEquals(m1.version().get().toString(), "1.0"); 266 ModuleDescriptor m2 = finder.find("m2").get().descriptor(); 267 assertEquals(m2.version().get().toString(), "1.0"); 268 269 // m3 and m4 should be located in JAR files 270 ModuleDescriptor m3 = finder.find("m3").get().descriptor(); 271 assertEquals(m3.version().get().toString(), "2.0"); 272 ModuleDescriptor m4 = finder.find("m4").get().descriptor(); 273 assertEquals(m4.version().get().toString(), "2.0"); 274 275 // m5 and m6 should be located in JAR files 276 ModuleDescriptor m5 = finder.find("m5").get().descriptor(); 277 assertEquals(m5.version().get().toString(), "4.0"); 278 ModuleDescriptor m6 = finder.find("m6").get().descriptor(); 279 assertEquals(m6.version().get().toString(), "4.0"); 280 } 281 282 283 /** 284 * Test ModuleFinder.of with a mix of module directories and exploded 285 * modules. 286 */ 287 public void testOfMixDirectoriesAndExplodedModules() throws Exception { 288 // directory with m1@1.0 and m2@1.0 289 Path dir1 = Files.createTempDirectory(USER_DIR, "mods1"); 290 createExplodedModule(dir1.resolve("m1"), "m1@1.0"); 291 createModularJar(dir1.resolve("m2.jar"), "m2@1.0"); 292 293 // exploded modules: m1@2.0, m2@2.0, m3@2.0, m4@2.0 294 Path dir2 = Files.createTempDirectory(USER_DIR, "mods2"); 295 Path m1_dir = createExplodedModule(dir2.resolve("m1"), "m1@2.0"); 296 Path m2_dir = createExplodedModule(dir2.resolve("m2"), "m2@2.0"); 297 Path m3_dir = createExplodedModule(dir2.resolve("m3"), "m3@2.0"); 298 Path m4_dir = createExplodedModule(dir2.resolve("m4"), "m4@2.0"); 299 300 ModuleFinder finder = ModuleFinder.of(dir1, m1_dir, m2_dir, m3_dir, m4_dir); 301 assertTrue(finder.findAll().size() == 4); 302 assertTrue(finder.find("m1").isPresent()); 303 assertTrue(finder.find("m2").isPresent()); 304 assertTrue(finder.find("m3").isPresent()); 305 assertTrue(finder.find("m4").isPresent()); 306 assertFalse(finder.find("java.rhubarb").isPresent()); 307 308 // m1 and m2 should be located in dir1 309 ModuleDescriptor m1 = finder.find("m1").get().descriptor(); 310 assertEquals(m1.version().get().toString(), "1.0"); 311 ModuleDescriptor m2 = finder.find("m2").get().descriptor(); 312 assertEquals(m2.version().get().toString(), "1.0"); 313 314 // m3 and m4 should be located in dir2 315 ModuleDescriptor m3 = finder.find("m3").get().descriptor(); 316 assertEquals(m3.version().get().toString(), "2.0"); 317 ModuleDescriptor m4 = finder.find("m4").get().descriptor(); 318 assertEquals(m4.version().get().toString(), "2.0"); 319 } 320 321 322 /** 323 * Test ModuleFinder with a JAR file containing a mix of class and 324 * non-class resources. 325 */ 326 public void testOfOneJarFileWithResources() throws Exception { 327 Path dir = Files.createTempDirectory(USER_DIR, "mods"); 328 Path jar = createModularJar(dir.resolve("m.jar"), "m", 329 "LICENSE", 330 "README", 331 "WEB-INF/tags", 332 "p/Type.class", 333 "p/resources/m.properties", 334 "q-/Type.class", // not a legal package name 335 "q-/resources/m/properties"); 336 337 ModuleFinder finder = ModuleFinder.of(jar); 338 Optional<ModuleReference> mref = finder.find("m"); 339 assertTrue(mref.isPresent(), "m1 not found"); 340 341 ModuleDescriptor descriptor = mref.get().descriptor(); 342 343 assertTrue(descriptor.packages().size() == 2); 344 assertTrue(descriptor.packages().contains("p")); 345 assertTrue(descriptor.packages().contains("p.resources")); 346 } 347 348 349 /** 350 * Test ModuleFinder with an exploded module containing a mix of class 351 * and non-class resources 352 */ 353 public void testOfOneExplodedModuleWithResources() throws Exception { 354 Path dir = Files.createTempDirectory(USER_DIR, "mods"); 355 Path m_dir = createExplodedModule(dir.resolve("m"), "m", 356 "LICENSE", 357 "README", 358 "WEB-INF/tags", 359 "p/Type.class", 360 "p/resources/m.properties", 361 "q-/Type.class", // not a legal package name 362 "q-/resources/m/properties"); 363 364 ModuleFinder finder = ModuleFinder.of(m_dir); 365 Optional<ModuleReference> mref = finder.find("m"); 366 assertTrue(mref.isPresent(), "m not found"); 367 368 ModuleDescriptor descriptor = mref.get().descriptor(); 369 370 assertTrue(descriptor.packages().size() == 2); 371 assertTrue(descriptor.packages().contains("p")); 372 assertTrue(descriptor.packages().contains("p.resources")); 373 } 374 375 376 /** 377 * Test ModuleFinder with a JAR file containing a .class file in the top 378 * level directory. 379 */ 380 public void testOfOneJarFileWithTopLevelClass() throws Exception { 381 Path dir = Files.createTempDirectory(USER_DIR, "mods"); 382 Path jar = createModularJar(dir.resolve("m.jar"), "m", "Mojo.class"); 383 384 ModuleFinder finder = ModuleFinder.of(jar); 385 try { 386 finder.find("m"); 387 assertTrue(false); 388 } catch (FindException e) { 389 assertTrue(e.getCause() instanceof InvalidModuleDescriptorException); 390 assertTrue(e.getCause().getMessage().contains("Mojo.class")); 391 } 392 393 finder = ModuleFinder.of(jar); 394 try { 395 finder.findAll(); 396 assertTrue(false); 397 } catch (FindException e) { 398 assertTrue(e.getCause() instanceof InvalidModuleDescriptorException); 399 assertTrue(e.getCause().getMessage().contains("Mojo.class")); 400 } 401 } 402 403 /** 404 * Test ModuleFinder with a JAR file containing a .class file in the top 405 * level directory. 406 */ 407 public void testOfOneExplodedModuleWithTopLevelClass() throws Exception { 408 Path dir = Files.createTempDirectory(USER_DIR, "mods"); 409 Path m_dir = createExplodedModule(dir.resolve("m"), "m", "Mojo.class"); 410 411 ModuleFinder finder = ModuleFinder.of(m_dir); 412 try { 413 finder.find("m"); 414 assertTrue(false); 415 } catch (FindException e) { 416 assertTrue(e.getCause() instanceof InvalidModuleDescriptorException); 417 assertTrue(e.getCause().getMessage().contains("Mojo.class")); 418 } 419 420 finder = ModuleFinder.of(m_dir); 421 try { 422 finder.findAll(); 423 assertTrue(false); 424 } catch (FindException e) { 425 assertTrue(e.getCause() instanceof InvalidModuleDescriptorException); 426 assertTrue(e.getCause().getMessage().contains("Mojo.class")); 427 } 428 } 429 430 431 /** 432 * Test ModuleFinder.of with a path to a file that does not exist. 433 */ 434 public void testOfWithDoesNotExistEntry() throws Exception { 435 Path dir1 = Files.createTempDirectory(USER_DIR, "mods1"); 436 437 Path dir2 = Files.createTempDirectory(USER_DIR, "mods2"); 438 createModularJar(dir2.resolve("m2.jar"), "m2@1.0"); 439 440 Files.delete(dir1); 441 442 ModuleFinder finder = ModuleFinder.of(dir1, dir2); 443 444 assertTrue(finder.find("m2").isPresent()); 445 assertTrue(finder.findAll().size() == 1); 446 assertFalse(finder.find("java.rhubarb").isPresent()); 447 } 448 449 450 /** 451 * Test ModuleFinder.of with a file path to an unrecognized file type. 452 */ 453 public void testOfWithUnrecognizedEntry() throws Exception { 454 Path dir = Files.createTempDirectory(USER_DIR, "mods"); 455 Path mod = Files.createTempFile(dir, "m", ".junk"); 456 457 ModuleFinder finder = ModuleFinder.of(mod); 458 try { 459 finder.find("java.rhubarb"); 460 assertTrue(false); 461 } catch (FindException e) { 462 // expected 463 } 464 465 finder = ModuleFinder.of(mod); 466 try { 467 finder.findAll(); 468 assertTrue(false); 469 } catch (FindException e) { 470 // expected 471 } 472 } 473 474 475 /** 476 * Test ModuleFinder.of with a file path to a directory containing a file 477 * that will not be recognized as a module. 478 */ 479 public void testOfWithUnrecognizedEntryInDirectory1() throws Exception { 480 Path dir = Files.createTempDirectory(USER_DIR, "mods"); 481 Files.createTempFile(dir, "m", ".junk"); 482 483 ModuleFinder finder = ModuleFinder.of(dir); 484 assertFalse(finder.find("java.rhubarb").isPresent()); 485 486 finder = ModuleFinder.of(dir); 487 assertTrue(finder.findAll().isEmpty()); 488 } 489 490 491 /** 492 * Test ModuleFinder.of with a file path to a directory containing a file 493 * that will not be recognized as a module. 494 */ 495 public void testOfWithUnrecognizedEntryInDirectory2() throws Exception { 496 Path dir = Files.createTempDirectory(USER_DIR, "mods"); 497 createModularJar(dir.resolve("m1.jar"), "m1"); 498 Files.createTempFile(dir, "m2", ".junk"); 499 500 ModuleFinder finder = ModuleFinder.of(dir); 501 assertTrue(finder.find("m1").isPresent()); 502 assertFalse(finder.find("m2").isPresent()); 503 504 finder = ModuleFinder.of(dir); 505 assertTrue(finder.findAll().size() == 1); 506 } 507 508 509 /** 510 * Test ModuleFinder.of with a directory that contains two 511 * versions of the same module 512 */ 513 public void testOfDuplicateModulesInDirectory() throws Exception { 514 Path dir = Files.createTempDirectory(USER_DIR, "mods"); 515 createModularJar(dir.resolve("m1@1.0.jar"), "m1"); 516 createModularJar(dir.resolve("m1@2.0.jar"), "m1"); 517 518 ModuleFinder finder = ModuleFinder.of(dir); 519 try { 520 finder.find("m1"); 521 assertTrue(false); 522 } catch (FindException expected) { } 523 524 finder = ModuleFinder.of(dir); 525 try { 526 finder.findAll(); 527 assertTrue(false); 528 } catch (FindException expected) { } 529 } 530 531 532 /** 533 * Test ModuleFinder.of with a directory containing hidden files 534 */ 535 public void testOfWithHiddenFiles() throws Exception { 536 Path dir = Files.createTempDirectory(USER_DIR, "mods"); 537 createExplodedModule(dir.resolve("m"), "m", 538 "com/.ignore", 539 "com/foo/.ignore", 540 "com/foo/foo.properties"); 541 542 ModuleFinder finder = ModuleFinder.of(dir); 543 ModuleReference mref = finder.find("m").orElse(null); 544 assertNotNull(mref); 545 546 Set<String> expectedPackages; 547 if (System.getProperty("os.name").startsWith("Windows")) { 548 expectedPackages = Set.of("com", "com.foo"); 549 } else { 550 expectedPackages = Set.of("com.foo"); 551 } 552 assertEquals(mref.descriptor().packages(), expectedPackages); 553 } 554 555 556 /** 557 * Test ModuleFinder.of with a truncated module-info.class 558 */ 559 public void testOfWithTruncatedModuleInfo() throws Exception { 560 Path dir = Files.createTempDirectory(USER_DIR, "mods"); 561 562 // create an empty <dir>/rhubarb/module-info.class 563 Path subdir = Files.createDirectory(dir.resolve("rhubarb")); 564 Files.createFile(subdir.resolve("module-info.class")); 565 566 ModuleFinder finder = ModuleFinder.of(dir); 567 try { 568 finder.find("rhubarb"); 569 assertTrue(false); 570 } catch (FindException e) { 571 assertTrue(e.getCause() instanceof InvalidModuleDescriptorException); 572 } 573 574 finder = ModuleFinder.of(dir); 575 try { 576 finder.findAll(); 577 assertTrue(false); 578 } catch (FindException e) { 579 assertTrue(e.getCause() instanceof InvalidModuleDescriptorException); 580 } 581 } 582 583 584 /** 585 * Test ModuleFinder.compose with no module finders 586 */ 587 public void testComposeOfNone() throws Exception { 588 ModuleFinder finder = ModuleFinder.of(); 589 assertTrue(finder.findAll().isEmpty()); 590 assertFalse(finder.find("java.rhubarb").isPresent()); 591 } 592 593 594 /** 595 * Test ModuleFinder.compose with one module finder 596 */ 597 public void testComposeOfOne() throws Exception { 598 Path dir = Files.createTempDirectory(USER_DIR, "mods"); 599 createModularJar(dir.resolve("m1.jar"), "m1"); 600 createModularJar(dir.resolve("m2.jar"), "m2"); 601 602 ModuleFinder finder1 = ModuleFinder.of(dir); 603 604 ModuleFinder finder = ModuleFinder.compose(finder1); 605 assertTrue(finder.findAll().size() == 2); 606 assertTrue(finder.find("m1").isPresent()); 607 assertTrue(finder.find("m2").isPresent()); 608 assertFalse(finder.find("java.rhubarb").isPresent()); 609 } 610 611 612 /** 613 * Test ModuleFinder.compose with two module finders 614 */ 615 public void testComposeOfTwo() throws Exception { 616 Path dir1 = Files.createTempDirectory(USER_DIR, "mods1"); 617 createModularJar(dir1.resolve("m1.jar"), "m1@1.0"); 618 createModularJar(dir1.resolve("m2.jar"), "m2@1.0"); 619 620 Path dir2 = Files.createTempDirectory(USER_DIR, "mods2"); 621 createModularJar(dir2.resolve("m1.jar"), "m1@2.0"); 622 createModularJar(dir2.resolve("m2.jar"), "m2@2.0"); 623 createModularJar(dir2.resolve("m3.jar"), "m3"); 624 createModularJar(dir2.resolve("m4.jar"), "m4"); 625 626 ModuleFinder finder1 = ModuleFinder.of(dir1); 627 ModuleFinder finder2 = ModuleFinder.of(dir2); 628 629 ModuleFinder finder = ModuleFinder.compose(finder1, finder2); 630 assertTrue(finder.findAll().size() == 4); 631 assertTrue(finder.find("m1").isPresent()); 632 assertTrue(finder.find("m2").isPresent()); 633 assertTrue(finder.find("m3").isPresent()); 634 assertTrue(finder.find("m4").isPresent()); 635 assertFalse(finder.find("java.rhubarb").isPresent()); 636 637 // check that m1@1.0 is found 638 ModuleDescriptor m1 = finder.find("m1").get().descriptor(); 639 assertEquals(m1.version().get().toString(), "1.0"); 640 641 // check that m2@1.0 is found 642 ModuleDescriptor m2 = finder.find("m2").get().descriptor(); 643 assertEquals(m2.version().get().toString(), "1.0"); 644 } 645 646 647 /** 648 * Test ModuleFinder.compose with three module finders 649 */ 650 public void testComposeOfThree() throws Exception { 651 Path dir1 = Files.createTempDirectory(USER_DIR, "mods1"); 652 createModularJar(dir1.resolve("m1.jar"), "m1@1.0"); 653 createModularJar(dir1.resolve("m2.jar"), "m2@1.0"); 654 655 Path dir2 = Files.createTempDirectory(USER_DIR, "mods2"); 656 createModularJar(dir2.resolve("m1.jar"), "m1@2.0"); 657 createModularJar(dir2.resolve("m2.jar"), "m2@2.0"); 658 createModularJar(dir2.resolve("m3.jar"), "m3@2.0"); 659 createModularJar(dir2.resolve("m4.jar"), "m4@2.0"); 660 661 Path dir3 = Files.createTempDirectory(USER_DIR, "mods3"); 662 createModularJar(dir3.resolve("m3.jar"), "m3@3.0"); 663 createModularJar(dir3.resolve("m4.jar"), "m4@3.0"); 664 createModularJar(dir3.resolve("m5.jar"), "m5"); 665 createModularJar(dir3.resolve("m6.jar"), "m6"); 666 667 ModuleFinder finder1 = ModuleFinder.of(dir1); 668 ModuleFinder finder2 = ModuleFinder.of(dir2); 669 ModuleFinder finder3 = ModuleFinder.of(dir3); 670 671 ModuleFinder finder = ModuleFinder.compose(finder1, finder2, finder3); 672 assertTrue(finder.findAll().size() == 6); 673 assertTrue(finder.find("m1").isPresent()); 674 assertTrue(finder.find("m2").isPresent()); 675 assertTrue(finder.find("m3").isPresent()); 676 assertTrue(finder.find("m4").isPresent()); 677 assertTrue(finder.find("m5").isPresent()); 678 assertTrue(finder.find("m6").isPresent()); 679 assertFalse(finder.find("java.rhubarb").isPresent()); 680 681 // check that m1@1.0 is found 682 ModuleDescriptor m1 = finder.find("m1").get().descriptor(); 683 assertEquals(m1.version().get().toString(), "1.0"); 684 685 // check that m2@1.0 is found 686 ModuleDescriptor m2 = finder.find("m2").get().descriptor(); 687 assertEquals(m2.version().get().toString(), "1.0"); 688 689 // check that m3@2.0 is found 690 ModuleDescriptor m3 = finder.find("m3").get().descriptor(); 691 assertEquals(m3.version().get().toString(), "2.0"); 692 693 // check that m4@2.0 is found 694 ModuleDescriptor m4 = finder.find("m4").get().descriptor(); 695 assertEquals(m4.version().get().toString(), "2.0"); 696 } 697 698 699 /** 700 * Test null handling 701 */ 702 public void testNulls() { 703 704 // ofSystem 705 try { 706 ModuleFinder.ofSystem().find(null); 707 assertTrue(false); 708 } catch (NullPointerException expected) { } 709 710 // of 711 Path dir = Paths.get("d"); 712 try { 713 ModuleFinder.of().find(null); 714 assertTrue(false); 715 } catch (NullPointerException expected) { } 716 try { 717 ModuleFinder.of((Path)null); 718 assertTrue(false); 719 } catch (NullPointerException expected) { } 720 try { 721 ModuleFinder.of((Path[])null); 722 assertTrue(false); 723 } catch (NullPointerException expected) { } 724 try { 725 ModuleFinder.of(dir, null); 726 assertTrue(false); 727 } catch (NullPointerException expected) { } 728 try { 729 ModuleFinder.of(null, dir); 730 assertTrue(false); 731 } catch (NullPointerException expected) { } 732 733 // compose 734 ModuleFinder finder = ModuleFinder.of(); 735 try { 736 ModuleFinder.compose((ModuleFinder)null); 737 assertTrue(false); 738 } catch (NullPointerException expected) { } 739 try { 740 ModuleFinder.compose((ModuleFinder[])null); 741 assertTrue(false); 742 } catch (NullPointerException expected) { } 743 try { 744 ModuleFinder.compose(finder, null); 745 assertTrue(false); 746 } catch (NullPointerException expected) { } 747 try { 748 ModuleFinder.compose(null, finder); 749 assertTrue(false); 750 } catch (NullPointerException expected) { } 751 752 } 753 754 755 /** 756 * Parses a string of the form {@code name[@version]} and returns a 757 * ModuleDescriptor with that name and version. The ModuleDescriptor 758 * will have a requires on java.base. 759 */ 760 static ModuleDescriptor newModuleDescriptor(String mid) { 761 String mn; 762 String vs; 763 int i = mid.indexOf("@"); 764 if (i == -1) { 765 mn = mid; 766 vs = null; 767 } else { 768 mn = mid.substring(0, i); 769 vs = mid.substring(i+1); 770 } 771 ModuleDescriptor.Builder builder 772 = ModuleDescriptor.newModule(mn).requires("java.base"); 773 if (vs != null) 774 builder.version(vs); 775 return builder.build(); 776 } 777 778 /** 779 * Creates an exploded module in the given directory and containing a 780 * module descriptor with the given module name/version. 781 */ 782 static Path createExplodedModule(Path dir, String mid, String... entries) 783 throws Exception 784 { 785 ModuleDescriptor descriptor = newModuleDescriptor(mid); 786 Files.createDirectories(dir); 787 Path mi = dir.resolve("module-info.class"); 788 try (OutputStream out = Files.newOutputStream(mi)) { 789 ModuleInfoWriter.write(descriptor, out); 790 } 791 792 for (String entry : entries) { 793 Path file = dir.resolve(entry.replace('/', File.separatorChar)); 794 Files.createDirectories(file.getParent()); 795 Files.createFile(file); 796 } 797 798 return dir; 799 } 800 801 /** 802 * Creates a JAR file with the given file path and containing a module 803 * descriptor with the given module name/version. 804 */ 805 static Path createModularJar(Path file, String mid, String ... entries) 806 throws Exception 807 { 808 ModuleDescriptor descriptor = newModuleDescriptor(mid); 809 try (OutputStream out = Files.newOutputStream(file)) { 810 try (JarOutputStream jos = new JarOutputStream(out)) { 811 812 JarEntry je = new JarEntry("module-info.class"); 813 jos.putNextEntry(je); 814 ModuleInfoWriter.write(descriptor, jos); 815 jos.closeEntry(); 816 817 for (String entry : entries) { 818 je = new JarEntry(entry); 819 jos.putNextEntry(je); 820 jos.closeEntry(); 821 } 822 } 823 824 } 825 return file; 826 } 827 828 }