diff --git a/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/workspace/RawWorkspaceReader.java b/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/workspace/RawWorkspaceReader.java deleted file mode 100644 index 3e2b3c50852817..00000000000000 --- a/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/workspace/RawWorkspaceReader.java +++ /dev/null @@ -1,213 +0,0 @@ -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; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.Consumer; -import java.util.function.Function; - -import org.apache.maven.model.Model; -import org.apache.maven.model.Parent; -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.maven.dependency.ArtifactCoords; -import io.quarkus.maven.dependency.GAV; - -public class RawWorkspaceReader implements WorkspaceReader, WorkspaceModelResolver { - - private static final String POM_XML = "pom.xml"; - - private static final Logger log = Logger.getLogger(RawWorkspaceReader.class); - - public static RawWorkspaceReader builder() { - return new RawWorkspaceReader(); - } - - private RawWorkspaceReader() { - } - - private final List moduleQueue = new ArrayList<>(); - private final Map loadedPoms = new HashMap<>(); - - private final WorkspaceRepository wr = new WorkspaceRepository(); - private Function modelProvider; - private final Map loadedModules = new HashMap<>(); - - public RawWorkspaceReader addModulePom(Path pom) { - if (pom != null) { - moduleQueue.add(new RawModule(pom)); - } - return this; - } - - public RawWorkspaceReader setModelProvider(Function modelProvider) { - RawWorkspaceReader.this.modelProvider = modelProvider; - return this; - } - - public RawWorkspaceReader build(Consumer consumer) throws IOException { - if (modelProvider == null) { - modelProvider = pom -> null; - } - int i = 0; - while (i < moduleQueue.size()) { - var newModules = new ArrayList(); - while (i < moduleQueue.size()) { - loadModule(moduleQueue.get(i++), newModules); - } - for (var newModule : newModules) { - newModule.process(consumer); - } - } - return RawWorkspaceReader.this; - } - - private void loadModule(RawModule rawModule, List newModules) throws IOException { - var moduleDir = rawModule.pom.getParent(); - if (moduleDir == null) { - moduleDir = Path.of("/"); - } - if (loadedPoms.containsKey(moduleDir)) { - return; - } - - rawModule.model = modelProvider == null ? null : modelProvider.apply(moduleDir); - if (rawModule.model == null) { - rawModule.model = readModel(rawModule.pom); - } - loadedPoms.put(moduleDir, rawModule.model); - if (rawModule.model == null) { - return; - } - newModules.add(rawModule); - - var added = loadedModules.putIfAbsent( - new GAV(ModelUtils.getGroupId(rawModule.model), rawModule.model.getArtifactId(), - ModelUtils.getVersion(rawModule.model)), - rawModule.model); - if (added != null) { - return; - } - for (var module : rawModule.model.getModules()) { - moduleQueue.add( - new RawModule(rawModule, rawModule.model.getProjectDirectory().toPath().resolve(module).resolve(POM_XML))); - } - for (var profile : rawModule.model.getProfiles()) { - for (var module : profile.getModules()) { - moduleQueue.add(new RawModule(rawModule, - rawModule.model.getProjectDirectory().toPath().resolve(module).resolve(POM_XML))); - } - } - if (rawModule.parent == null) { - final Path parentPom = rawModule.getParentPom(); - if (parentPom != null) { - var parent = new RawModule(parentPom); - rawModule.parent = parent; - moduleQueue.add(parent); - } - } - } - - @Override - public WorkspaceRepository getRepository() { - return wr; - } - - @Override - public File findArtifact(Artifact artifact) { - if (!ArtifactCoords.TYPE_POM.equals(artifact.getExtension())) { - return null; - } - var model = loadedModules.get(new GAV(artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion())); - return model == null ? null : model.getPomFile(); - } - - @Override - public List findVersions(Artifact artifact) { - var model = loadedModules.get(new GAV(artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion())); - return model == null ? List.of() : List.of(ModelUtils.getVersion(model)); - } - - @Override - public Model resolveRawModel(String groupId, String artifactId, String version) { - return loadedModules.get(new GAV(groupId, artifactId, version)); - } - - @Override - public Model resolveEffectiveModel(String groupId, String artifactId, String version) { - return null; - } - - private static Model readModel(Path pom) throws IOException { - try { - final Model model = ModelUtils.readModel(pom); - model.setPomFile(pom.toFile()); - return model; - } catch (NoSuchFileException e) { - // some projects may be missing pom.xml relying on Maven extensions (e.g. tycho-maven-plugin) to build them, - // which we don't support in this workspace loader - log.warn("Module(s) under " + pom.getParent() + " will be handled as thirdparty dependencies because " + pom - + " does not exist"); - return null; - } - } - - private static class RawModule { - final Path pom; - Model model; - RawModule parent; - boolean processed; - - private RawModule(Path pom) { - this(null, pom); - } - - private RawModule(RawModule parent, Path pom) { - this.pom = pom.normalize().toAbsolutePath(); - this.parent = parent; - } - - private Path getParentPom() { - if (model == null) { - return null; - } - Path parentPom = null; - final Parent parent = model.getParent(); - if (parent != null && parent.getRelativePath() != null && !parent.getRelativePath().isEmpty()) { - parentPom = pom.getParent().resolve(parent.getRelativePath()).normalize(); - if (Files.isDirectory(parentPom)) { - parentPom = parentPom.resolve(POM_XML); - } - } else { - final Path parentDir = pom.getParent().getParent(); - if (parentDir != null) { - parentPom = parentDir.resolve(POM_XML); - } - } - return parentPom != null && Files.exists(parentPom) ? parentPom : null; - } - - private void process(Consumer consumer) { - if (processed) { - return; - } - processed = true; - if (parent != null) { - parent.process(consumer); - } - if (model != null) { - consumer.accept(model); - } - } - } -} 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 85c38dcdd37b28..f057cecb6fbbd5 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 @@ -2,16 +2,21 @@ import java.io.File; import java.io.IOException; +import java.io.UncheckedIOException; import java.nio.file.Files; +import java.nio.file.NoSuchFileException; import java.nio.file.Path; import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; import java.util.function.Function; import org.apache.maven.model.Model; +import org.apache.maven.model.Parent; import org.apache.maven.model.Profile; import org.apache.maven.model.building.DefaultModelBuildingRequest; import org.apache.maven.model.building.ModelBuilder; @@ -27,6 +32,8 @@ import io.quarkus.bootstrap.resolver.maven.BootstrapModelBuilderFactory; import io.quarkus.bootstrap.resolver.maven.BootstrapModelResolver; import io.quarkus.bootstrap.resolver.maven.options.BootstrapMavenOptions; +import io.quarkus.maven.dependency.ArtifactCoords; +import io.quarkus.maven.dependency.GAV; public class WorkspaceLoader implements WorkspaceModelResolver, WorkspaceReader { @@ -46,7 +53,12 @@ private static Path locateCurrentProjectPom(Path path) throws BootstrapMavenExce throw new BootstrapMavenException("Failed to locate project pom.xml for " + path); } - private final RawWorkspaceReader wsReader; + private final List moduleQueue = new ArrayList<>(); + private final Map loadedPoms = new HashMap<>(); + + private final Function modelProvider; + private final Map loadedModules = new HashMap<>(); + private final LocalWorkspace workspace = new LocalWorkspace(); private final Path currentProjectPom; @@ -66,10 +78,8 @@ private static Path locateCurrentProjectPom(Path path) throws BootstrapMavenExce } catch (IOException e) { throw new IllegalArgumentException(currentProjectPom + " does not exist", e); } - - wsReader = RawWorkspaceReader.builder() - .setModelProvider(modelProvider) - .addModulePom(this.currentProjectPom); + addModulePom(this.currentProjectPom); + this.modelProvider = modelProvider == null ? pom -> null : modelProvider; if (ctx != null && ctx.isEffectiveModelBuilder()) { modelBuilder = BootstrapModelBuilderFactory.getDefaultModelBuilder(); @@ -88,8 +98,14 @@ private static Path locateCurrentProjectPom(Path path) throws BootstrapMavenExce workspace.setBootstrapMavenContext(ctx); } + private void addModulePom(Path pom) { + if (pom != null) { + moduleQueue.add(new RawModule(pom)); + } + } + void setWorkspaceRootPom(Path rootPom) { - wsReader.addModulePom(rootPom); + addModulePom(rootPom); } LocalProject load() throws BootstrapMavenException { @@ -125,25 +141,77 @@ LocalProject load() throws BootstrapMavenException { currentProject.set(project); } for (var module : project.getModelBuildingResult().getEffectiveModel().getModules()) { - wsReader.addModulePom(project.getDir().resolve(module).resolve(POM_XML)); + addModulePom(project.getDir().resolve(module).resolve(POM_XML)); } }; } - try { - wsReader.build(processor); - } catch (IOException e) { - throw new BootstrapMavenException("Failed to load workspace", e); + int i = 0; + while (i < moduleQueue.size()) { + var newModules = new ArrayList(); + while (i < moduleQueue.size()) { + loadModule(moduleQueue.get(i++), newModules); + } + for (var newModule : newModules) { + newModule.process(processor); + } } + if (currentProject.get() == null) { throw new BootstrapMavenException("Failed to load project " + currentProjectPom); } return currentProject.get(); } + private void loadModule(RawModule rawModule, List newModules) { + var moduleDir = rawModule.pom.getParent(); + if (moduleDir == null) { + moduleDir = Path.of("/"); + } + if (loadedPoms.containsKey(moduleDir)) { + return; + } + + rawModule.model = modelProvider == null ? null : modelProvider.apply(moduleDir); + if (rawModule.model == null) { + rawModule.model = readModel(rawModule.pom); + } + loadedPoms.put(moduleDir, rawModule.model); + if (rawModule.model == null) { + return; + } + newModules.add(rawModule); + + var added = loadedModules.putIfAbsent( + new GAV(ModelUtils.getGroupId(rawModule.model), rawModule.model.getArtifactId(), + ModelUtils.getVersion(rawModule.model)), + rawModule.model); + if (added != null) { + return; + } + for (var module : rawModule.model.getModules()) { + moduleQueue.add( + new RawModule(rawModule, rawModule.model.getProjectDirectory().toPath().resolve(module).resolve(POM_XML))); + } + for (var profile : rawModule.model.getProfiles()) { + for (var module : profile.getModules()) { + moduleQueue.add(new RawModule(rawModule, + rawModule.model.getProjectDirectory().toPath().resolve(module).resolve(POM_XML))); + } + } + if (rawModule.parent == null) { + final Path parentPom = rawModule.getParentPom(); + if (parentPom != null) { + var parent = new RawModule(parentPom); + rawModule.parent = parent; + moduleQueue.add(parent); + } + } + } + @Override public Model resolveRawModel(String groupId, String artifactId, String versionConstraint) { - return wsReader.resolveRawModel(groupId, artifactId, versionConstraint); + return loadedModules.get(new GAV(groupId, artifactId, versionConstraint)); } @Override @@ -161,11 +229,81 @@ public WorkspaceRepository getRepository() { @Override public File findArtifact(Artifact artifact) { - return wsReader.findArtifact(artifact); + if (!ArtifactCoords.TYPE_POM.equals(artifact.getExtension())) { + return null; + } + var model = loadedModules.get(new GAV(artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion())); + return model == null ? null : model.getPomFile(); } @Override public List findVersions(Artifact artifact) { - return wsReader.findVersions(artifact); + var model = loadedModules.get(new GAV(artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion())); + return model == null ? List.of() : List.of(ModelUtils.getVersion(model)); + } + + private static Model readModel(Path pom) { + try { + final Model model = ModelUtils.readModel(pom); + model.setPomFile(pom.toFile()); + return model; + } catch (NoSuchFileException e) { + // some projects may be missing pom.xml relying on Maven extensions (e.g. tycho-maven-plugin) to build them, + // which we don't support in this workspace loader + log.warn("Module(s) under " + pom.getParent() + " will be handled as thirdparty dependencies because " + pom + + " does not exist"); + return null; + } catch (IOException e) { + throw new UncheckedIOException("Failed to load POM from " + pom, e); + } + } + + private static class RawModule { + final Path pom; + Model model; + RawModule parent; + boolean processed; + + private RawModule(Path pom) { + this(null, pom); + } + + private RawModule(RawModule parent, Path pom) { + this.pom = pom.normalize().toAbsolutePath(); + this.parent = parent; + } + + private Path getParentPom() { + if (model == null) { + return null; + } + Path parentPom = null; + final Parent parent = model.getParent(); + if (parent != null && parent.getRelativePath() != null && !parent.getRelativePath().isEmpty()) { + parentPom = pom.getParent().resolve(parent.getRelativePath()).normalize(); + if (Files.isDirectory(parentPom)) { + parentPom = parentPom.resolve(POM_XML); + } + } else { + final Path parentDir = pom.getParent().getParent(); + if (parentDir != null) { + parentPom = parentDir.resolve(POM_XML); + } + } + return parentPom != null && Files.exists(parentPom) ? parentPom : null; + } + + private void process(Consumer consumer) { + if (processed) { + return; + } + processed = true; + if (parent != null) { + parent.process(consumer); + } + if (model != null) { + consumer.accept(model); + } + } } }