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