From be54bc479a36ecc8507476c91cc529863c6dff61 Mon Sep 17 00:00:00 2001 From: "Henning P. Schmiedehausen" Date: Thu, 17 Aug 2023 18:29:28 -0700 Subject: [PATCH] Fail on duplicate modules on the module path When resolving the module path, no module id is allowed to exist multiple times. The location manager used to drop duplicates silently which led to hard to understand error messages when a plugin using plexus-java dropped a dependency without any notice. This change enforces uniqueness of module names on the module path and will add an exception to the PathResolveResult in that case. --- .../languages/java/jpms/LocationManager.java | 6 ++ .../java/jpms/LocationManagerTest.java | 76 +++++++++++++++++- .../plexus-java-1.0.0-SNAPSHOT-tests.jar | Bin 0 -> 371 bytes .../jar.tests/plexus-java-1.0.0-SNAPSHOT.jar | Bin 0 -> 855 bytes 4 files changed, 78 insertions(+), 4 deletions(-) create mode 100644 plexus-java/src/test/resources/jar.tests/plexus-java-1.0.0-SNAPSHOT-tests.jar create mode 100644 plexus-java/src/test/resources/jar.tests/plexus-java-1.0.0-SNAPSHOT.jar diff --git a/plexus-java/src/main/java/org/codehaus/plexus/languages/java/jpms/LocationManager.java b/plexus-java/src/main/java/org/codehaus/plexus/languages/java/jpms/LocationManager.java index a5b2f50..8b8b72b 100644 --- a/plexus-java/src/main/java/org/codehaus/plexus/languages/java/jpms/LocationManager.java +++ b/plexus-java/src/main/java/org/codehaus/plexus/languages/java/jpms/LocationManager.java @@ -262,6 +262,12 @@ public String extract(Path path) throws IOException { .put( entry.getKey(), moduleNameSources.get(entry.getValue().name())); + } else { + result.getPathExceptions() + .put( + entry.getKey(), + new IllegalStateException( + "Module '" + entry.getValue().name() + "' is already on the module path!")); } } else { result.getClasspathElements().add(entry.getKey()); diff --git a/plexus-java/src/test/java/org/codehaus/plexus/languages/java/jpms/LocationManagerTest.java b/plexus-java/src/test/java/org/codehaus/plexus/languages/java/jpms/LocationManagerTest.java index acd825d..92444e7 100644 --- a/plexus-java/src/test/java/org/codehaus/plexus/languages/java/jpms/LocationManagerTest.java +++ b/plexus-java/src/test/java/org/codehaus/plexus/languages/java/jpms/LocationManagerTest.java @@ -161,6 +161,36 @@ void testIdenticalModuleNames() throws Exception { ResolvePathsRequest request = ResolvePathsRequest.ofPaths(Arrays.asList(pj1, pj2)).setMainModuleDescriptor(mockModuleInfoJava); + when(asmParser.getModuleDescriptor(pj1)) + .thenReturn(JavaModuleDescriptor.newModule("plexus.java").build()); + when(asmParser.getModuleDescriptor(pj2)) + .thenReturn(JavaModuleDescriptor.newModule("plexus.java").build()); + + ResolvePathsResult result = locationManager.resolvePaths(request); + + assertThat(result.getMainModuleDescriptor()).isEqualTo(descriptor); + assertThat(result.getPathElements()).hasSize(2); + assertThat(result.getModulepathElements()).hasSize(1); + assertThat(result.getModulepathElements()).containsKey(pj1); + assertThat(result.getModulepathElements()).doesNotContainKey(pj2); + assertThat(result.getClasspathElements()).isEmpty(); + // duplicate is flagged as an error + assertThat(result.getPathExceptions()).containsOnlyKeys(pj2); + assertThat(result.getPathExceptions().get(pj2)) + .isInstanceOf(IllegalStateException.class) + .hasMessageContaining("Module 'plexus.java' is already on the module path!"); + } + + @Test + public void testIdenticalAutomaticModuleNames() throws Exception { + Path pj1 = Paths.get("src/test/resources/jar.empty/plexus-java-1.0.0-SNAPSHOT.jar"); + Path pj2 = Paths.get("src/test/resources/jar.empty.2/plexus-java-2.0.0-SNAPSHOT.jar"); + JavaModuleDescriptor descriptor = + JavaModuleDescriptor.newModule("base").requires("plexus.java").build(); + when(qdoxParser.fromSourcePath(any(Path.class))).thenReturn(descriptor); + ResolvePathsRequest request = + ResolvePathsRequest.ofPaths(Arrays.asList(pj1, pj2)).setMainModuleDescriptor(mockModuleInfoJava); + when(asmParser.getModuleDescriptor(pj1)) .thenReturn( JavaModuleDescriptor.newAutomaticModule("plexus.java").build()); @@ -173,8 +203,42 @@ void testIdenticalModuleNames() throws Exception { assertThat(result.getPathElements()).hasSize(2); assertThat(result.getModulepathElements()).containsOnlyKeys(pj1); assertThat(result.getModulepathElements()).doesNotContainKey(pj2); - assertThat(result.getClasspathElements()).hasSize(0); - assertThat(result.getPathExceptions()).hasSize(0); + assertThat(result.getClasspathElements()).isEmpty(); + // duplicate is flagged as an error + assertThat(result.getPathExceptions()).containsOnlyKeys(pj2); + assertThat(result.getPathExceptions().get(pj2)) + .isInstanceOf(IllegalStateException.class) + .hasMessageContaining("Module 'plexus.java' is already on the module path!"); + } + + @Test + public void testMainJarModuleAndTestJarAutomatic() throws Exception { + Path pj1 = Paths.get("src/test/resources/jar.tests/plexus-java-1.0.0-SNAPSHOT.jar"); + Path pj2 = Paths.get("src/test/resources/jar.tests/plexus-java-1.0.0-SNAPSHOT-tests.jar"); + JavaModuleDescriptor descriptor = + JavaModuleDescriptor.newModule("base").requires("plexus.java").build(); + when(qdoxParser.fromSourcePath(any(Path.class))).thenReturn(descriptor); + ResolvePathsRequest request = + ResolvePathsRequest.ofPaths(Arrays.asList(pj1, pj2)).setMainModuleDescriptor(mockModuleInfoJava); + + when(asmParser.getModuleDescriptor(pj1)) + .thenReturn(JavaModuleDescriptor.newModule("plexus.java").build()); + when(asmParser.getModuleDescriptor(pj2)).thenReturn(null); + + ResolvePathsResult result = locationManager.resolvePaths(request); + + assertThat(result.getMainModuleDescriptor()).isEqualTo(descriptor); + assertThat(result.getPathElements()).hasSize(2); + assertThat(result.getModulepathElements()).hasSize(1); + assertThat(result.getModulepathElements()).containsKey(pj1); + assertThat(result.getModulepathElements()).doesNotContainKey(pj2); + assertThat(result.getClasspathElements()).isEmpty(); + + // duplicate is flagged as an error + assertThat(result.getPathExceptions()).containsOnlyKeys(pj2); + assertThat(result.getPathExceptions().get(pj2)) + .isInstanceOf(IllegalStateException.class) + .hasMessageContaining("Module 'plexus.java' is already on the module path!"); } @Test @@ -473,9 +537,13 @@ void testDuplicateModule() throws Exception { ResolvePathsResult result = locationManager.resolvePaths(request); assertThat(result.getPathElements()).hasSize(2); assertThat(result.getModulepathElements()).containsOnlyKeys(moduleB); - // with current default the duplicate will be ignored assertThat(result.getClasspathElements()).hasSize(0); - assertThat(result.getPathExceptions()).hasSize(0); + assertThat(result.getPathExceptions()).hasSize(1); + // duplicate (module B / module C) is flagged as an error + assertThat(result.getPathExceptions()).containsOnlyKeys(moduleC); + assertThat(result.getPathExceptions().get(moduleC)) + .isInstanceOf(IllegalStateException.class) + .hasMessageContaining("Module 'anonymous' is already on the module path!"); } @Test diff --git a/plexus-java/src/test/resources/jar.tests/plexus-java-1.0.0-SNAPSHOT-tests.jar b/plexus-java/src/test/resources/jar.tests/plexus-java-1.0.0-SNAPSHOT-tests.jar new file mode 100644 index 0000000000000000000000000000000000000000..a6afd0fbf5a82ef0664819fe60f023082ec1e6d6 GIT binary patch literal 371 zcmWIWW@Zs#;Nak3crsBioB;`NGO#fCx`sIFdiuHP|2xINz|0Wf&CUT*!30$nfK#&w zPz7AGucM!*n`>~0p06A4>5Y621_BHh_ImzbsO&7QmgL;i^R0W{lOVWO9x zX{d$l<(;VcJBUlu4&=mr@FaE0S*myjj^ms+fSV7Dzt;aTox%Ia4

*(j{<{BKL=j-;__snS@Z(Y5MyxzK6=gyqp9At3C_`%a6JuhD!Pv48Bt5~>Z zyq0_ssgbcm?Rkor$Z{=z@oRyN$$1T4Nm zNdgtX;~11c0=!YRBF7WRT?k+cWWu!~B@c8HkV6F&p9pXO$VB!dICeqWxfpN<9YXsQ oMp!^1oD2#|