diff --git a/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/BootstrapModelResolver.java b/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/BootstrapModelResolver.java index 59eea3fa57360..d9df04c23c299 100644 --- a/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/BootstrapModelResolver.java +++ b/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/BootstrapModelResolver.java @@ -1,9 +1,7 @@ package io.quarkus.bootstrap.resolver.maven; -import java.io.File; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; @@ -28,6 +26,7 @@ import org.eclipse.aether.impl.RemoteRepositoryManager; import org.eclipse.aether.impl.VersionRangeResolver; import org.eclipse.aether.repository.RemoteRepository; +import org.eclipse.aether.repository.WorkspaceReader; import org.eclipse.aether.resolution.ArtifactRequest; import org.eclipse.aether.resolution.ArtifactResolutionException; import org.eclipse.aether.resolution.ArtifactResult; @@ -35,16 +34,17 @@ import org.eclipse.aether.resolution.VersionRangeResolutionException; import org.eclipse.aether.resolution.VersionRangeResult; -import io.quarkus.bootstrap.resolver.maven.workspace.LocalWorkspace; import io.quarkus.maven.dependency.ArtifactCoords; public class BootstrapModelResolver implements ModelResolver { - public static ModelResolver newInstance(BootstrapMavenContext ctx, LocalWorkspace workspace) + public static ModelResolver newInstance(BootstrapMavenContext ctx, WorkspaceReader workspace) throws BootstrapMavenException { final RepositorySystem repoSystem = ctx.getRepositorySystem(); - return new BootstrapModelResolver( - new DefaultRepositorySystemSession(ctx.getRepositorySystemSession()).setWorkspaceReader(workspace), null, null, + final RepositorySystemSession session = workspace == null + ? ctx.getRepositorySystemSession() + : new DefaultRepositorySystemSession(ctx.getRepositorySystemSession()).setWorkspaceReader(workspace); + return new BootstrapModelResolver(session, null, null, new ArtifactResolver() { @Override public ArtifactResult resolveArtifact(RepositorySystemSession session, ArtifactRequest request) @@ -114,19 +114,14 @@ public void addRepository(final Repository repository, boolean replace) if (session.isIgnoreArtifactDescriptorRepositories()) { return; } - if (!repositoryIds.add(repository.getId())) { if (!replace) { return; } - removeMatchingRepository(repositories, repository.getId()); } - - List newRepositories = Collections - .singletonList(ArtifactDescriptorUtils.toRemoteRepository(repository)); - - this.repositories = remoteRepositoryManager.aggregateRepositories(session, repositories, newRepositories, true); + this.repositories = remoteRepositoryManager.aggregateRepositories(session, repositories, + List.of(ArtifactDescriptorUtils.toRemoteRepository(repository)), true); } private static void removeMatchingRepository(Iterable repositories, final String id) { @@ -147,8 +142,8 @@ public ModelResolver newCopy() { @Override public ModelSource resolveModel(String groupId, String artifactId, String version) throws UnresolvableModelException { - Artifact pomArtifact = new DefaultArtifact(groupId, artifactId, "", "pom", version); - + Artifact pomArtifact = new DefaultArtifact(groupId, artifactId, ArtifactCoords.DEFAULT_CLASSIFIER, + ArtifactCoords.TYPE_POM, version); try { ArtifactRequest request = new ArtifactRequest(pomArtifact, repositories, context); request.setTrace(trace); @@ -156,17 +151,15 @@ public ModelSource resolveModel(String groupId, String artifactId, String versio } catch (ArtifactResolutionException e) { throw new UnresolvableModelException(e.getMessage(), groupId, artifactId, version, e); } - - File pomFile = pomArtifact.getFile(); - - return new FileModelSource(pomFile); + return new FileModelSource(pomArtifact.getFile()); } @Override public ModelSource resolveModel(final Parent parent) throws UnresolvableModelException { try { - final Artifact artifact = new DefaultArtifact(parent.getGroupId(), parent.getArtifactId(), "", "pom", + final Artifact artifact = new DefaultArtifact(parent.getGroupId(), parent.getArtifactId(), + ArtifactCoords.DEFAULT_CLASSIFIER, ArtifactCoords.TYPE_POM, parent.getVersion()); final VersionRangeRequest versionRangeRequest = new VersionRangeRequest(artifact, repositories, context); @@ -195,7 +188,7 @@ public ModelSource resolveModel(final Parent parent) parent.setVersion(versionRangeResult.getHighestVersion().toString()); return resolveModel(parent.getGroupId(), parent.getArtifactId(), parent.getVersion()); - } catch (final VersionRangeResolutionException e) { + } catch (VersionRangeResolutionException e) { throw new UnresolvableModelException(e.getMessage(), parent.getGroupId(), parent.getArtifactId(), parent.getVersion(), e); } diff --git a/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/MavenModelBuilder.java b/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/MavenModelBuilder.java index e0fc3ee7b6f3b..acbbf79875343 100644 --- a/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/MavenModelBuilder.java +++ b/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/MavenModelBuilder.java @@ -82,17 +82,23 @@ private Model getModel(ModelBuildingRequest request) { } private void completeWorkspaceProjectBuildRequest(ModelBuildingRequest request) throws BootstrapMavenException { - final Set addedProfiles = new HashSet<>(); + final Set addedProfiles; final List profiles = request.getProfiles(); - profiles.forEach(p -> addedProfiles.add(p.getId())); + if (profiles.isEmpty()) { + addedProfiles = Set.of(); + } else { + addedProfiles = new HashSet<>(profiles.size()); + for (Profile p : profiles) { + addedProfiles.add(p.getId()); + } + } - final List activeSettingsProfiles = ctx.getActiveSettingsProfiles(); - activeSettingsProfiles.forEach(p -> { + for (Profile p : ctx.getActiveSettingsProfiles()) { if (!addedProfiles.contains(p.getId())) { profiles.add(p); request.getActiveProfileIds().add(p.getId()); } - }); + } final BootstrapMavenOptions cliOptions = ctx.getCliOptions(); request.getActiveProfileIds().addAll(cliOptions.getActiveProfileIds()); diff --git a/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/workspace/LocalWorkspace.java b/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/workspace/LocalWorkspace.java index a4c84f32a29b7..e68e4affef2e8 100644 --- a/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/workspace/LocalWorkspace.java +++ b/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/workspace/LocalWorkspace.java @@ -5,7 +5,6 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -23,7 +22,6 @@ import io.quarkus.bootstrap.workspace.WorkspaceModule; import io.quarkus.maven.dependency.ArtifactCoords; import io.quarkus.maven.dependency.ArtifactKey; -import io.quarkus.maven.dependency.GACT; /** * @@ -56,7 +54,7 @@ protected void addProject(LocalProject project, long lastModified) { } public LocalProject getProject(String groupId, String artifactId) { - return getProject(new GACT(groupId, artifactId)); + return getProject(ArtifactKey.ga(groupId, artifactId)); } public LocalProject getProject(ArtifactKey key) { @@ -74,7 +72,7 @@ public int getId() { @Override public Model resolveRawModel(String groupId, String artifactId, String versionConstraint) throws UnresolvableModelException { - if (findArtifact(new DefaultArtifact(groupId, artifactId, null, "pom", versionConstraint)) != null) { + if (findArtifact(new DefaultArtifact(groupId, artifactId, null, ArtifactCoords.TYPE_POM, versionConstraint)) != null) { return getProject(groupId, artifactId).getRawModel(); } return null; @@ -217,7 +215,7 @@ public List findVersions(Artifact artifact) { return lastFindVersions; } if (findArtifact(artifact) == null) { - return Collections.emptyList(); + return List.of(); } lastFindVersionsKey = ArtifactKey.ga(artifact.getGroupId(), artifact.getArtifactId()); return lastFindVersions = List.of(artifact.getVersion()); diff --git a/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/workspace/WorkspaceLoader.java b/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/workspace/WorkspaceLoader.java index 588b2766a00f9..d26b0ac5b8126 100644 --- a/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/workspace/WorkspaceLoader.java +++ b/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/workspace/WorkspaceLoader.java @@ -1,5 +1,6 @@ package io.quarkus.bootstrap.resolver.maven.workspace; +import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.NoSuchFileException; @@ -20,6 +21,9 @@ import org.apache.maven.model.resolution.ModelResolver; import org.apache.maven.model.resolution.UnresolvableModelException; import org.apache.maven.model.resolution.WorkspaceModelResolver; +import org.eclipse.aether.artifact.Artifact; +import org.eclipse.aether.repository.WorkspaceReader; +import org.eclipse.aether.repository.WorkspaceRepository; import org.jboss.logging.Logger; import io.quarkus.bootstrap.resolver.maven.BootstrapMavenContext; @@ -28,7 +32,7 @@ import io.quarkus.bootstrap.resolver.maven.BootstrapModelResolver; import io.quarkus.bootstrap.resolver.maven.options.BootstrapMavenOptions; -public class WorkspaceLoader implements WorkspaceModelResolver { +public class WorkspaceLoader implements WorkspaceModelResolver, WorkspaceReader { private static final Logger log = Logger.getLogger(WorkspaceLoader.class); @@ -84,7 +88,7 @@ static Path locateCurrentProjectPom(Path path, boolean required) throws Bootstra this.modelProvider = modelProvider; if (ctx != null && ctx.isEffectiveModelBuilder()) { modelBuilder = BootstrapModelBuilderFactory.getDefaultModelBuilder(); - modelResolver = BootstrapModelResolver.newInstance(ctx, workspace); + modelResolver = BootstrapModelResolver.newInstance(ctx, this); modelCache = new BootstrapModelCache(ctx.getRepositorySystemSession()); profiles = ctx.getActiveSettingsProfiles(); @@ -119,8 +123,10 @@ private LocalProject project(Path pomFile) throws BootstrapMavenException { } private LocalProject loadAndCacheProject(Path pomFile) throws BootstrapMavenException { - Model cachedRawModel = rawModelCache.getOrDefault(pomFile.getParent(), - modelProvider == null ? null : modelProvider.apply(pomFile.getParent())); + final Model rawModel = rawModel(pomFile); + if (rawModel == null) { + return null; + } final LocalProject project; if (modelBuilder != null) { ModelBuildingRequest req = new DefaultModelBuildingRequest(); @@ -132,21 +138,15 @@ private LocalProject loadAndCacheProject(Path pomFile) throws BootstrapMavenExce req.setActiveProfileIds(activeProfileIds); req.setInactiveProfileIds(inactiveProfileIds); req.setProfiles(profiles); - req.setRawModel(cachedRawModel); + req.setRawModel(rawModel); req.setWorkspaceModelResolver(this); try { project = new LocalProject(modelBuilder.build(req), workspace); } catch (Exception e) { throw new BootstrapMavenException("Failed to resolve the effective model for " + pomFile, e); } - } else if (cachedRawModel != null) { - project = new LocalProject(cachedRawModel, workspace); } else { - Model model = readModel(pomFile); - if (model == null) { - return null; - } - project = new LocalProject(model, workspace); + project = new LocalProject(rawModel, workspace); } projectCache.put(pomFile.getParent(), project); return project; @@ -170,13 +170,9 @@ void setWorkspaceRootPom(Path rootPom) { this.workspaceRootPom = rootPom; } - private LocalProject loadProject(final Path projectPom, String skipModule) throws BootstrapMavenException { + private LocalProject loadProject(Path projectPom, String skipModule) throws BootstrapMavenException { final Model rawModel = rawModel(projectPom); - - final Path parentPom = getParentPom(projectPom, rawModel); - final LocalProject parentProject = parentPom == null || rawModelCache.containsKey(parentPom.getParent()) ? null - : loadProject(parentPom, parentPom.getParent().relativize(projectPom.getParent()).toString()); - + final LocalProject parentProject = loadParentProject(projectPom, rawModel); final LocalProject project = project(projectPom); if (project == null) { return null; @@ -188,6 +184,12 @@ private LocalProject loadProject(final Path projectPom, String skipModule) throw return project; } + private LocalProject loadParentProject(Path projectPom, final Model rawModel) throws BootstrapMavenException { + final Path parentPom = getParentPom(projectPom, rawModel); + return parentPom == null || rawModelCache.containsKey(parentPom.getParent()) ? null + : loadProject(parentPom, parentPom.getParent().relativize(projectPom.getParent()).toString()); + } + private Path getParentPom(Path projectPom, Model rawModel) { Path parentPom = null; final Path projectDir = projectPom.getParent(); @@ -214,7 +216,11 @@ private LocalProject loadProjectModules(LocalProject project, String skipModule) if (module.equals(skipModule)) { continue; } - final LocalProject childProject = project(project.getDir().resolve(module).resolve(POM_XML)); + final Path modulePom = project.getDir().resolve(module).resolve(POM_XML); + // some modules use different parent POMs than those that referred to them as their modules + // so make sure the parent project has been loaded, before resolving the effective model of the module + loadParentProject(modulePom, rawModel(modulePom)); + final LocalProject childProject = project(modulePom); if (childProject != null) { project.modules.add(loadProjectModules(childProject, null)); } @@ -255,4 +261,19 @@ public Model resolveEffectiveModel(String groupId, String artifactId, String ver ? project.getModelBuildingResult().getEffectiveModel() : null; } + + @Override + public WorkspaceRepository getRepository() { + return workspace.getRepository(); + } + + @Override + public File findArtifact(Artifact artifact) { + return workspace.findArtifact(artifact); + } + + @Override + public List findVersions(Artifact artifact) { + return workspace.findVersions(artifact); + } } diff --git a/independent-projects/bootstrap/maven-resolver/src/test/java/io/quarkus/bootstrap/workspace/test/LocalWorkspaceDiscoveryTest.java b/independent-projects/bootstrap/maven-resolver/src/test/java/io/quarkus/bootstrap/workspace/test/LocalWorkspaceDiscoveryTest.java index a9b07b0f2e160..3f3f7b478e2ea 100644 --- a/independent-projects/bootstrap/maven-resolver/src/test/java/io/quarkus/bootstrap/workspace/test/LocalWorkspaceDiscoveryTest.java +++ b/independent-projects/bootstrap/maven-resolver/src/test/java/io/quarkus/bootstrap/workspace/test/LocalWorkspaceDiscoveryTest.java @@ -124,6 +124,45 @@ public static void cleanup() { IoUtils.recursiveDelete(workDir); } + @Test + public void moduleWithDifferentParentPomRawModel() throws Exception { + final URL moduleUrl = Thread.currentThread().getContextClassLoader() + .getResource("workspace-module-with-different-parent"); + assertNotNull(moduleUrl); + final Path moduleDir = Path.of(moduleUrl.toURI()); + assertNotNull(moduleUrl); + + final LocalWorkspace ws = LocalProject.loadWorkspace(moduleDir).getWorkspace(); + + assertNotNull(ws.getProject("org.acme", "acme-runtimes")); + assertNotNull(ws.getProject("org.acme", "acme-parent")); + assertNotNull(ws.getProject("org.acme", "acme-build-no-bom-parent")); + assertNotNull(ws.getProject("org.acme", "acme-build-parent")); + assertNotNull(ws.getProject("org.acme", "acme-dependencies-bom")); + assertEquals(5, ws.getProjects().size()); + } + + @Test + public void moduleWithDifferentParentPomEffectiveModel() throws Exception { + final URL moduleUrl = Thread.currentThread().getContextClassLoader() + .getResource("workspace-module-with-different-parent"); + assertNotNull(moduleUrl); + final Path moduleDir = Path.of(moduleUrl.toURI()); + assertNotNull(moduleUrl); + + final LocalWorkspace ws = new BootstrapMavenContext(BootstrapMavenContext.config() + .setEffectiveModelBuilder(true) + .setCurrentProject(moduleDir.toString())) + .getWorkspace(); + + assertNotNull(ws.getProject("org.acme", "acme-runtimes")); + assertNotNull(ws.getProject("org.acme", "acme-parent")); + assertNotNull(ws.getProject("org.acme", "acme-build-no-bom-parent")); + assertNotNull(ws.getProject("org.acme", "acme-build-parent")); + assertNotNull(ws.getProject("org.acme", "acme-dependencies-bom")); + assertEquals(5, ws.getProjects().size()); + } + @Test public void nonParentAggregator() throws Exception { final URL moduleUrl = Thread.currentThread().getContextClassLoader() @@ -260,6 +299,26 @@ public void loadWorkspaceFromRootDirWithParentInChildDir() throws Exception { assertParents(project, "acme-parent", "acme-dependencies"); } + @Test + public void loadWorkspaceFromRootDirWithParentInChildDirEffectiveModel() throws Exception { + final URL projectUrl = Thread.currentThread().getContextClassLoader().getResource("workspace-parent-is-not-root-dir"); + assertNotNull(projectUrl); + final Path projectDir = Paths.get(projectUrl.toURI()); + assertTrue(Files.exists(projectDir)); + + final LocalProject module1 = new BootstrapMavenContext(BootstrapMavenContext.config() + .setEffectiveModelBuilder(true) + .setCurrentProject(projectDir.toString())) + .getCurrentProject(); + final LocalWorkspace ws = module1.getWorkspace(); + final LocalProject project = ws.getProject("org.acme", "acme"); + assertNotNull(project); + + assertEquals("acme", project.getArtifactId()); + assertWorkspaceWithParentInChildDir(project); + assertParents(project, "acme-parent", "acme-dependencies"); + } + @Test public void loadWorkspaceFromModuleDirWithParentInChildDir() throws Exception { final URL projectUrl = Thread.currentThread().getContextClassLoader() diff --git a/independent-projects/bootstrap/maven-resolver/src/test/resources/workspace-module-with-different-parent/acme-build/acme-build-no-bom-parent/pom.xml b/independent-projects/bootstrap/maven-resolver/src/test/resources/workspace-module-with-different-parent/acme-build/acme-build-no-bom-parent/pom.xml new file mode 100644 index 0000000000000..be0e124563591 --- /dev/null +++ b/independent-projects/bootstrap/maven-resolver/src/test/resources/workspace-module-with-different-parent/acme-build/acme-build-no-bom-parent/pom.xml @@ -0,0 +1,19 @@ + + + + 4.0.0 + + + org.acme + acme-dependencies-bom + 1.0-SNAPSHOT + ../acme-dependencies-bom/pom.xml + + + acme-build-no-bom-parent + pom + + diff --git a/independent-projects/bootstrap/maven-resolver/src/test/resources/workspace-module-with-different-parent/acme-build/acme-build-parent/pom.xml b/independent-projects/bootstrap/maven-resolver/src/test/resources/workspace-module-with-different-parent/acme-build/acme-build-parent/pom.xml new file mode 100644 index 0000000000000..74b0884e6e481 --- /dev/null +++ b/independent-projects/bootstrap/maven-resolver/src/test/resources/workspace-module-with-different-parent/acme-build/acme-build-parent/pom.xml @@ -0,0 +1,19 @@ + + + + 4.0.0 + + + org.acme + acme-build-no-bom-parent + 1.0-SNAPSHOT + ../acme-build-no-bom-parent + + + acme-build-parent + pom + + diff --git a/independent-projects/bootstrap/maven-resolver/src/test/resources/workspace-module-with-different-parent/acme-build/acme-dependencies-bom/pom.xml b/independent-projects/bootstrap/maven-resolver/src/test/resources/workspace-module-with-different-parent/acme-build/acme-dependencies-bom/pom.xml new file mode 100644 index 0000000000000..d75332a886be1 --- /dev/null +++ b/independent-projects/bootstrap/maven-resolver/src/test/resources/workspace-module-with-different-parent/acme-build/acme-dependencies-bom/pom.xml @@ -0,0 +1,14 @@ + + + + 4.0.0 + + org.acme + acme-dependencies-bom + 1.0-SNAPSHOT + pom + + diff --git a/independent-projects/bootstrap/maven-resolver/src/test/resources/workspace-module-with-different-parent/acme-build/pom.xml b/independent-projects/bootstrap/maven-resolver/src/test/resources/workspace-module-with-different-parent/acme-build/pom.xml new file mode 100644 index 0000000000000..c898722eb4f36 --- /dev/null +++ b/independent-projects/bootstrap/maven-resolver/src/test/resources/workspace-module-with-different-parent/acme-build/pom.xml @@ -0,0 +1,25 @@ + + + + 4.0.0 + + + org.acme + acme-runtimes + 1.0-SNAPSHOT + ../pom.xml + + + acme-parent + pom + + + acme-build-no-bom-parent + acme-build-parent + acme-dependencies-bom + + + diff --git a/independent-projects/bootstrap/maven-resolver/src/test/resources/workspace-module-with-different-parent/pom.xml b/independent-projects/bootstrap/maven-resolver/src/test/resources/workspace-module-with-different-parent/pom.xml new file mode 100644 index 0000000000000..c6255d9806030 --- /dev/null +++ b/independent-projects/bootstrap/maven-resolver/src/test/resources/workspace-module-with-different-parent/pom.xml @@ -0,0 +1,18 @@ + + + + 4.0.0 + + org.acme + acme-runtimes + 1.0-SNAPSHOT + pom + + + acme-build + + +