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 ModuleFinder 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 assertTrue(e.getCause().getMessage().contains("Mojo.class")); 390 } 391 392 finder = ModuleFinder.of(jar); 393 try { 394 finder.findAll(); 395 assertTrue(false); 396 } catch (FindException e) { 397 assertTrue(e.getCause() instanceof InvalidModuleDescriptorException); 398 assertTrue(e.getCause().getMessage().contains("Mojo.class")); 399 } 400 } 401 402 /** 403 * Test ModuleFinder with a JAR file containing a .class file in the top 404 * level directory. 405 */ 406 public void testOfOneExplodedModuleWithTopLevelClass() throws Exception { 407 Path dir = Files.createTempDirectory(USER_DIR, "mods"); 408 Path m_dir = createExplodedModule(dir.resolve("m"), "m", "Mojo.class"); 409 410 ModuleFinder finder = ModuleFinder.of(m_dir); 411 try { 412 finder.find("m"); 413 assertTrue(false); 414 } catch (FindException e) { 415 assertTrue(e.getCause() instanceof InvalidModuleDescriptorException); 416 assertTrue(e.getCause().getMessage().contains("Mojo.class")); 417 } 418 419 finder = ModuleFinder.of(m_dir); 420 try { 421 finder.findAll(); 422 assertTrue(false); 423 } catch (FindException e) { 424 assertTrue(e.getCause() instanceof InvalidModuleDescriptorException); 425 assertTrue(e.getCause().getMessage().contains("Mojo.class")); 426 } 427 } 428 429 430 /** 431 * Test ModuleFinder.of with a path to a file that does not exist. 432 */ 433 public void testOfWithDoesNotExistEntry() throws Exception { 434 Path dir1 = Files.createTempDirectory(USER_DIR, "mods1"); 435 436 Path dir2 = Files.createTempDirectory(USER_DIR, "mods2"); 437 createModularJar(dir2.resolve("m2.jar"), "m2@1.0"); 438 439 Files.delete(dir1); 440 441 ModuleFinder finder = ModuleFinder.of(dir1, dir2); 442 443 assertTrue(finder.find("m2").isPresent()); 444 assertTrue(finder.findAll().size() == 1); 445 assertFalse(finder.find("java.rhubarb").isPresent()); 446 } 447 448 449 /** 450 * Test ModuleFinder.of with a file path to an unrecognized file type. 451 */ 452 public void testOfWithUnrecognizedEntry() throws Exception { 453 Path dir = Files.createTempDirectory(USER_DIR, "mods"); 454 Path mod = Files.createTempFile(dir, "m", ".junk"); 455 456 ModuleFinder finder = ModuleFinder.of(mod); 457 try { 458 finder.find("java.rhubarb"); 459 assertTrue(false); 460 } catch (FindException e) { 461 // expected 462 } 463 464 finder = ModuleFinder.of(mod); 465 try { 466 finder.findAll(); 467 assertTrue(false); 468 } catch (FindException e) { 469 // expected 470 } 471 } 472 473 474 /** 475 * Test ModuleFinder.of with a file path to a directory containing a file 476 * that will not be recognized as a module. 477 */ 478 public void testOfWithUnrecognizedEntryInDirectory1() throws Exception { 479 Path dir = Files.createTempDirectory(USER_DIR, "mods"); 480 Files.createTempFile(dir, "m", ".junk"); 481 482 ModuleFinder finder = ModuleFinder.of(dir); 483 assertFalse(finder.find("java.rhubarb").isPresent()); 484 485 finder = ModuleFinder.of(dir); 486 assertTrue(finder.findAll().isEmpty()); 487 } 488 489 490 /** 491 * Test ModuleFinder.of with a file path to a directory containing a file 492 * that will not be recognized as a module. 493 */ 494 public void testOfWithUnrecognizedEntryInDirectory2() throws Exception { 495 Path dir = Files.createTempDirectory(USER_DIR, "mods"); 496 createModularJar(dir.resolve("m1.jar"), "m1"); 497 Files.createTempFile(dir, "m2", ".junk"); 498 499 ModuleFinder finder = ModuleFinder.of(dir); 500 assertTrue(finder.find("m1").isPresent()); 501 assertFalse(finder.find("m2").isPresent()); 502 503 finder = ModuleFinder.of(dir); 504 assertTrue(finder.findAll().size() == 1); 505 } 506 507 508 /** 509 * Test ModuleFinder.of with a directory that contains two 510 * versions of the same module 511 */ 512 public void testOfDuplicateModulesInDirectory() throws Exception { 513 Path dir = Files.createTempDirectory(USER_DIR, "mods"); 514 createModularJar(dir.resolve("m1@1.0.jar"), "m1"); 515 createModularJar(dir.resolve("m1@2.0.jar"), "m1"); 516 517 ModuleFinder finder = ModuleFinder.of(dir); 518 try { 519 finder.find("m1"); 520 assertTrue(false); 521 } catch (FindException expected) { } 522 523 finder = ModuleFinder.of(dir); 524 try { 525 finder.findAll(); 526 assertTrue(false); 527 } catch (FindException expected) { } 528 } 529 530 531 /** 532 * Test ModuleFinder.of with a truncated module-info.class 533 */ 534 public void testOfWithTruncatedModuleInfo() throws Exception { 535 Path dir = Files.createTempDirectory(USER_DIR, "mods"); 536 537 // create an empty <dir>/rhubarb/module-info.class 538 Path subdir = Files.createDirectory(dir.resolve("rhubarb")); 539 Files.createFile(subdir.resolve("module-info.class")); 540 541 ModuleFinder finder = ModuleFinder.of(dir); 542 try { 543 finder.find("rhubarb"); 544 assertTrue(false); 545 } catch (FindException e) { 546 assertTrue(e.getCause() instanceof InvalidModuleDescriptorException); 547 } 548 549 finder = ModuleFinder.of(dir); 550 try { 551 finder.findAll(); 552 assertTrue(false); 553 } catch (FindException e) { 554 assertTrue(e.getCause() instanceof InvalidModuleDescriptorException); 555 } 556 } 557 558 559 /** 560 * Test ModuleFinder.compose with no module finders 561 */ 562 public void testComposeOfNone() throws Exception { 563 ModuleFinder finder = ModuleFinder.of(); 564 assertTrue(finder.findAll().isEmpty()); 565 assertFalse(finder.find("java.rhubarb").isPresent()); 566 } 567 568 569 /** 570 * Test ModuleFinder.compose with one module finder 571 */ 572 public void testComposeOfOne() throws Exception { 573 Path dir = Files.createTempDirectory(USER_DIR, "mods"); 574 createModularJar(dir.resolve("m1.jar"), "m1"); 575 createModularJar(dir.resolve("m2.jar"), "m2"); 576 577 ModuleFinder finder1 = ModuleFinder.of(dir); 578 579 ModuleFinder finder = ModuleFinder.compose(finder1); 580 assertTrue(finder.findAll().size() == 2); 581 assertTrue(finder.find("m1").isPresent()); 582 assertTrue(finder.find("m2").isPresent()); 583 assertFalse(finder.find("java.rhubarb").isPresent()); 584 } 585 586 587 /** 588 * Test ModuleFinder.compose with two module finders 589 */ 590 public void testComposeOfTwo() throws Exception { 591 Path dir1 = Files.createTempDirectory(USER_DIR, "mods1"); 592 createModularJar(dir1.resolve("m1.jar"), "m1@1.0"); 593 createModularJar(dir1.resolve("m2.jar"), "m2@1.0"); 594 595 Path dir2 = Files.createTempDirectory(USER_DIR, "mods2"); 596 createModularJar(dir2.resolve("m1.jar"), "m1@2.0"); 597 createModularJar(dir2.resolve("m2.jar"), "m2@2.0"); 598 createModularJar(dir2.resolve("m3.jar"), "m3"); 599 createModularJar(dir2.resolve("m4.jar"), "m4"); 600 601 ModuleFinder finder1 = ModuleFinder.of(dir1); 602 ModuleFinder finder2 = ModuleFinder.of(dir2); 603 604 ModuleFinder finder = ModuleFinder.compose(finder1, finder2); 605 assertTrue(finder.findAll().size() == 4); 606 assertTrue(finder.find("m1").isPresent()); 607 assertTrue(finder.find("m2").isPresent()); 608 assertTrue(finder.find("m3").isPresent()); 609 assertTrue(finder.find("m4").isPresent()); 610 assertFalse(finder.find("java.rhubarb").isPresent()); 611 612 // check that m1@1.0 is found 613 ModuleDescriptor m1 = finder.find("m1").get().descriptor(); 614 assertEquals(m1.version().get().toString(), "1.0"); 615 616 // check that m2@1.0 is found 617 ModuleDescriptor m2 = finder.find("m2").get().descriptor(); 618 assertEquals(m2.version().get().toString(), "1.0"); 619 } 620 621 622 /** 623 * Test ModuleFinder.compose with three module finders 624 */ 625 public void testComposeOfThree() throws Exception { 626 Path dir1 = Files.createTempDirectory(USER_DIR, "mods1"); 627 createModularJar(dir1.resolve("m1.jar"), "m1@1.0"); 628 createModularJar(dir1.resolve("m2.jar"), "m2@1.0"); 629 630 Path dir2 = Files.createTempDirectory(USER_DIR, "mods2"); 631 createModularJar(dir2.resolve("m1.jar"), "m1@2.0"); 632 createModularJar(dir2.resolve("m2.jar"), "m2@2.0"); 633 createModularJar(dir2.resolve("m3.jar"), "m3@2.0"); 634 createModularJar(dir2.resolve("m4.jar"), "m4@2.0"); 635 636 Path dir3 = Files.createTempDirectory(USER_DIR, "mods3"); 637 createModularJar(dir3.resolve("m3.jar"), "m3@3.0"); 638 createModularJar(dir3.resolve("m4.jar"), "m4@3.0"); 639 createModularJar(dir3.resolve("m5.jar"), "m5"); 640 createModularJar(dir3.resolve("m6.jar"), "m6"); 641 642 ModuleFinder finder1 = ModuleFinder.of(dir1); 643 ModuleFinder finder2 = ModuleFinder.of(dir2); 644 ModuleFinder finder3 = ModuleFinder.of(dir3); 645 646 ModuleFinder finder = ModuleFinder.compose(finder1, finder2, finder3); 647 assertTrue(finder.findAll().size() == 6); 648 assertTrue(finder.find("m1").isPresent()); 649 assertTrue(finder.find("m2").isPresent()); 650 assertTrue(finder.find("m3").isPresent()); 651 assertTrue(finder.find("m4").isPresent()); 652 assertTrue(finder.find("m5").isPresent()); 653 assertTrue(finder.find("m6").isPresent()); 654 assertFalse(finder.find("java.rhubarb").isPresent()); 655 656 // check that m1@1.0 is found 657 ModuleDescriptor m1 = finder.find("m1").get().descriptor(); 658 assertEquals(m1.version().get().toString(), "1.0"); 659 660 // check that m2@1.0 is found 661 ModuleDescriptor m2 = finder.find("m2").get().descriptor(); 662 assertEquals(m2.version().get().toString(), "1.0"); 663 664 // check that m3@2.0 is found 665 ModuleDescriptor m3 = finder.find("m3").get().descriptor(); 666 assertEquals(m3.version().get().toString(), "2.0"); 667 668 // check that m4@2.0 is found 669 ModuleDescriptor m4 = finder.find("m4").get().descriptor(); 670 assertEquals(m4.version().get().toString(), "2.0"); 671 } 672 673 674 /** 675 * Test null handling 676 */ 677 public void testNulls() { 678 679 // ofSystem 680 try { 681 ModuleFinder.ofSystem().find(null); 682 assertTrue(false); 683 } catch (NullPointerException expected) { } 684 685 // of 686 Path dir = Paths.get("d"); 687 try { 688 ModuleFinder.of().find(null); 689 assertTrue(false); 690 } catch (NullPointerException expected) { } 691 try { 692 ModuleFinder.of((Path)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(dir, null); 701 assertTrue(false); 702 } catch (NullPointerException expected) { } 703 try { 704 ModuleFinder.of(null, dir); 705 assertTrue(false); 706 } catch (NullPointerException expected) { } 707 708 // compose 709 ModuleFinder finder = ModuleFinder.of(); 710 try { 711 ModuleFinder.compose((ModuleFinder)null); 712 assertTrue(false); 713 } catch (NullPointerException expected) { } 714 try { 715 ModuleFinder.compose((ModuleFinder[])null); 716 assertTrue(false); 717 } catch (NullPointerException expected) { } 718 try { 719 ModuleFinder.compose(finder, null); 720 assertTrue(false); 721 } catch (NullPointerException expected) { } 722 try { 723 ModuleFinder.compose(null, finder); 724 assertTrue(false); 725 } catch (NullPointerException expected) { } 726 727 } 728 729 730 /** 731 * Parses a string of the form {@code name[@version]} and returns a 732 * ModuleDescriptor with that name and version. The ModuleDescriptor 733 * will have a requires on java.base. 734 */ 735 static ModuleDescriptor newModuleDescriptor(String mid) { 736 String mn; 737 String vs; 738 int i = mid.indexOf("@"); 739 if (i == -1) { 740 mn = mid; 741 vs = null; 742 } else { 743 mn = mid.substring(0, i); 744 vs = mid.substring(i+1); 745 } 746 ModuleDescriptor.Builder builder 747 = ModuleDescriptor.newModule(mn).requires("java.base"); 748 if (vs != null) 749 builder.version(vs); 750 return builder.build(); 751 } 752 753 /** 754 * Creates an exploded module in the given directory and containing a 755 * module descriptor with the given module name/version. 756 */ 757 static Path createExplodedModule(Path dir, String mid, String... entries) 758 throws Exception 759 { 760 ModuleDescriptor descriptor = newModuleDescriptor(mid); 761 Files.createDirectories(dir); 762 Path mi = dir.resolve("module-info.class"); 763 try (OutputStream out = Files.newOutputStream(mi)) { 764 ModuleInfoWriter.write(descriptor, out); 765 } 766 767 for (String entry : entries) { 768 Path file = dir.resolve(entry.replace('/', File.separatorChar)); 769 Files.createDirectories(file.getParent()); 770 Files.createFile(file); 771 } 772 773 return dir; 774 } 775 776 /** 777 * Creates a JAR file with the given file path and containing a module 778 * descriptor with the given module name/version. 779 */ 780 static Path createModularJar(Path file, String mid, String ... entries) 781 throws Exception 782 { 783 ModuleDescriptor descriptor = newModuleDescriptor(mid); 784 try (OutputStream out = Files.newOutputStream(file)) { 785 try (JarOutputStream jos = new JarOutputStream(out)) { 786 787 JarEntry je = new JarEntry("module-info.class"); 788 jos.putNextEntry(je); 789 ModuleInfoWriter.write(descriptor, jos); 790 jos.closeEntry(); 791 792 for (String entry : entries) { 793 je = new JarEntry(entry); 794 jos.putNextEntry(je); 795 jos.closeEntry(); 796 } 797 } 798 799 } 800 return file; 801 } 802 803 } 804