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