From 9bf94d87eb50e9655d306be076881932707d8e98 Mon Sep 17 00:00:00 2001 From: Gabor Garancsi Date: Fri, 16 Dec 2022 16:28:55 +0100 Subject: [PATCH] #858 Fix child module resolution for multi-level projects Child modules were processed in a parallel stream which added elements to an unsynchonized LinkedHashMap. This may resulted an incomplete set of child modules. Note that as the stream items are not processed heavily there is no or minor advantage of parallel processing. --- .../codehaus/mojo/versions/api/PomHelper.java | 2 +- .../mojo/versions/api/PomHelperTest.java | 56 +++++++++++++++++++ 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/api/PomHelper.java b/versions-common/src/main/java/org/codehaus/mojo/versions/api/PomHelper.java index 7feaf42633..1b041fc1b9 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/api/PomHelper.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/api/PomHelper.java @@ -1356,7 +1356,7 @@ private static Map getChildModels(Model model, Log logger) throws I File baseDir = model.getPomFile().getParentFile(); - getAllChildModules(model, logger).parallelStream() + getAllChildModules(model, logger).stream() .map(moduleName -> new File(baseDir, moduleName)) .map(file -> file.isFile() ? file : new File(file, "pom.xml")) .filter(File::exists) diff --git a/versions-common/src/test/java/org/codehaus/mojo/versions/api/PomHelperTest.java b/versions-common/src/test/java/org/codehaus/mojo/versions/api/PomHelperTest.java index 3b68895020..2db345689d 100644 --- a/versions-common/src/test/java/org/codehaus/mojo/versions/api/PomHelperTest.java +++ b/versions-common/src/test/java/org/codehaus/mojo/versions/api/PomHelperTest.java @@ -25,8 +25,16 @@ import java.io.File; import java.io.StringReader; import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; +import org.apache.commons.io.FileUtils; import org.apache.maven.model.Model; +import org.apache.maven.model.io.DefaultModelWriter; +import org.apache.maven.model.io.ModelWriter; import org.apache.maven.model.io.xpp3.MavenXpp3Reader; import org.apache.maven.plugin.logging.SystemStreamLog; import org.apache.maven.plugin.testing.AbstractMojoTestCase; @@ -49,6 +57,8 @@ * Tests the methods of {@link PomHelper}. */ public class PomHelperTest extends AbstractMojoTestCase { + private static final int NUMBER_OF_CHILD_PROJECTS = 30; + @Rule public MojoRule mojoRule = new MojoRule(this); @@ -219,4 +229,50 @@ public void testIssue505ChildModules() throws Exception { mojoRule.readMavenProject(new File("src/test/resources/org/codehaus/mojo/versions/api/issue-505")); assertThat(PomHelper.getChildModels(project, new SystemStreamLog()).entrySet(), hasSize(3)); } + + @Test + public void testChildModelsForMultiLevelProject() throws Exception { + Path tempDirectory = Files.createTempDirectory("testChildModelsForLargeNumberOfModules"); + ModelWriter modelWriter = new DefaultModelWriter(); + Map createdModels = new LinkedHashMap<>(); + + try { + Model rootProject = createSimpleModel("root"); + createdModels.put(tempDirectory, rootProject); + for (int levelOne = 0; levelOne < NUMBER_OF_CHILD_PROJECTS; levelOne++) { + Model levelOneProject = createSimpleModel("child-" + levelOne); + Path levelOneProjectDirectory = tempDirectory.resolve(levelOneProject.getArtifactId()); + rootProject.addModule(levelOneProject.getArtifactId()); + createdModels.put(levelOneProjectDirectory, levelOneProject); + + for (int levelTwo = 0; levelTwo < NUMBER_OF_CHILD_PROJECTS; levelTwo++) { + Model levelTwoProject = createSimpleModel("child-" + levelOne + "-" + levelTwo); + Path levelTwoProjectDirectory = levelOneProjectDirectory.resolve(levelTwoProject.getArtifactId()); + levelOneProject.addModule(levelTwoProject.getArtifactId()); + createdModels.put(levelTwoProjectDirectory, levelTwoProject); + } + } + + for (Map.Entry entry : createdModels.entrySet()) { + modelWriter.write(entry.getKey().resolve("pom.xml").toFile(), Collections.emptyMap(), entry.getValue()); + } + + MavenProject project = mojoRule.readMavenProject(tempDirectory.toFile()); + + assertThat( + PomHelper.getChildModels(project, new SystemStreamLog()).entrySet(), hasSize(createdModels.size())); + } finally { + FileUtils.deleteDirectory(tempDirectory.toFile()); + } + } + + private Model createSimpleModel(String artifactId) { + Model module = new Model(); + module.setGroupId("child.test"); + module.setArtifactId(artifactId); + module.setVersion("1.0.0-SNAPSHOT"); + module.setPackaging("pom"); + module.setModelVersion("4.0.0"); + return module; + } }