Skip to content

Commit

Permalink
Merge pull request #28419 from aloubyansky/jgitver-support
Browse files Browse the repository at this point in the history
Make sure the app model is initialized from the POMs provided by the Maven plugin
aloubyansky authored Oct 6, 2022

Verified

This commit was signed with the committer’s verified signature.
dashpole David Ashpole
2 parents 9878204 + a426f6a commit 59c20da
Showing 7 changed files with 84 additions and 34 deletions.
Original file line number Diff line number Diff line change
@@ -419,7 +419,6 @@ protected void prepare() throws Exception {
devModeContext.setReleaseJavaVersion(releaseJavaVersion);
devModeContext.setSourceJavaVersion(sourceJavaVersion);
devModeContext.setTargetJvmVersion(targetJavaVersion);

devModeContext.getLocalArtifacts().addAll(localArtifacts);
devModeContext.setApplicationRoot(main);
devModeContext.getAdditionalModules().addAll(dependencies);
29 changes: 19 additions & 10 deletions devtools/maven/src/main/java/io/quarkus/maven/DevMojo.java
Original file line number Diff line number Diff line change
@@ -43,6 +43,7 @@
import org.apache.maven.execution.MavenSession;
import org.apache.maven.model.BuildBase;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.Model;
import org.apache.maven.model.Plugin;
import org.apache.maven.model.PluginExecution;
import org.apache.maven.model.Profile;
@@ -90,6 +91,8 @@
import io.quarkus.bootstrap.model.ApplicationModel;
import io.quarkus.bootstrap.model.PathsCollection;
import io.quarkus.bootstrap.resolver.BootstrapAppModelResolver;
import io.quarkus.bootstrap.resolver.maven.BootstrapMavenContext;
import io.quarkus.bootstrap.resolver.maven.BootstrapMavenContextConfig;
import io.quarkus.bootstrap.resolver.maven.MavenArtifactResolver;
import io.quarkus.bootstrap.resolver.maven.options.BootstrapMavenOptions;
import io.quarkus.bootstrap.util.BootstrapUtils;
@@ -759,7 +762,6 @@ private String getSourceEncoding() {
}

private void addProject(MavenDevModeLauncher.Builder builder, ResolvedDependency module, boolean root) throws Exception {

if (!module.isJar()) {
return;
}
@@ -1084,30 +1086,37 @@ private QuarkusDevModeLauncher newLauncher() throws Exception {
if (appModel != null) {
bootstrapProvider.close();
} else {
final MavenArtifactResolver.Builder resolverBuilder = MavenArtifactResolver.builder()
final BootstrapMavenContextConfig<?> mvnConfig = BootstrapMavenContext.config()
.setRemoteRepositories(repos)
.setRemoteRepositoryManager(remoteRepositoryManager)
.setWorkspaceDiscovery(true)
.setPreferPomsFromWorkspace(true)
.setCurrentProject(project.getFile().toString());

// if it already exists, it may be a reload triggered by a change in a POM
// in which case we should not be using the original Maven session
boolean reinitializeMavenSession = Files.exists(appModelLocation);
if (reinitializeMavenSession) {
// if a serialized model is found, it may be a reload triggered by a change in a POM
// in which case we should not be using the original Maven session initialized with the previous POM version
if (Files.exists(appModelLocation)) {
Files.delete(appModelLocation);
// we can't re-use the repo system because we want to use our interpolating model builder
// a use-case where it fails with the original repo system is when dev mode is launched with -Dquarkus.platform.version=xxx
// overriding the version of the quarkus-bom in the pom.xml
} else {
// we can re-use the original Maven session
resolverBuilder.setRepositorySystemSession(repoSession).setRepositorySystem(repoSystem);
// we can re-use the original Maven session and the system
mvnConfig.setRepositorySystemSession(repoSession).setRepositorySystem(repoSystem);
// there could be Maven extensions manipulating the project versions and models
// the ones returned from the Maven API could be different from the original pom.xml files
final Map<Path, Model> projectModels = new HashMap<>(session.getAllProjects().size());
for (MavenProject mp : session.getAllProjects()) {
projectModels.put(mp.getBasedir().toPath(), mp.getOriginalModel());
}
mvnConfig.setProjectModelProvider(projectModels::get);
}

appModel = new BootstrapAppModelResolver(resolverBuilder.build())
final BootstrapMavenContext mvnCtx = new BootstrapMavenContext(mvnConfig);
appModel = new BootstrapAppModelResolver(new MavenArtifactResolver(mvnCtx))
.setDevMode(true)
.setCollectReloadableDependencies(!noDeps)
.resolveModel(ArtifactCoords.jar(project.getGroupId(), project.getArtifactId(), project.getVersion()));
.resolveModel(mvnCtx.getCurrentProject().getAppArtifact());
}

// serialize the app model to avoid re-resolving it in the dev process
Original file line number Diff line number Diff line change
@@ -6,6 +6,8 @@
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -14,6 +16,7 @@
import java.util.concurrent.ExecutionException;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.model.Model;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.component.annotations.Component;
@@ -132,16 +135,21 @@ private MavenArtifactResolver artifactResolver(QuarkusBootstrapMojo mojo, Launch
throws MojoExecutionException {
isWorkspaceDiscovery(mojo);
try {
return MavenArtifactResolver.builder()
.setWorkspaceDiscovery(
mode == LaunchMode.DEVELOPMENT || mode == LaunchMode.TEST || isWorkspaceDiscovery(mojo))
final MavenArtifactResolver.Builder builder = MavenArtifactResolver.builder()
.setCurrentProject(mojo.mavenProject().getFile().toString())
.setPreferPomsFromWorkspace(mode == LaunchMode.DEVELOPMENT || mode == LaunchMode.TEST)
.setRepositorySystem(repoSystem)
.setRepositorySystemSession(mojo.repositorySystemSession())
.setRemoteRepositories(mojo.remoteRepositories())
.setRemoteRepositoryManager(remoteRepoManager)
.build();
.setRemoteRepositoryManager(remoteRepoManager);
if (mode == LaunchMode.DEVELOPMENT || mode == LaunchMode.TEST || isWorkspaceDiscovery(mojo)) {
final Map<Path, Model> projectModels = new HashMap<>(mojo.mavenSession().getAllProjects().size());
for (MavenProject mp : mojo.mavenSession().getAllProjects()) {
projectModels.put(mp.getBasedir().toPath(), mp.getOriginalModel());
}
builder.setWorkspaceDiscovery(true).setProjectModelProvider(projectModels::get);
}
return builder.build();
} catch (BootstrapMavenException e) {
throw new MojoExecutionException("Failed to initialize Quarkus bootstrap Maven artifact resolver", e);
}
Original file line number Diff line number Diff line change
@@ -12,6 +12,7 @@
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.function.Function;
import java.util.function.Supplier;

import org.apache.commons.lang3.StringUtils;
@@ -169,7 +170,7 @@ public BootstrapMavenContext(BootstrapMavenContextConfig<?> config)
this.currentPom = currentProject.getRawModel().getPomFile().toPath();
this.workspace = config.currentProject.getWorkspace();
} else if (config.workspaceDiscovery) {
currentProject = resolveCurrentProject();
currentProject = resolveCurrentProject(config.modelProvider);
this.workspace = currentProject == null ? null : currentProject.getWorkspace();
if (workspace != null) {
if (config.repoSession == null && repoSession != null && repoSession.getWorkspaceReader() == null) {
@@ -315,9 +316,9 @@ public String getLocalRepo() throws BootstrapMavenException {
return localRepo == null ? localRepo = resolveLocalRepo(getEffectiveSettings()) : localRepo;
}

private LocalProject resolveCurrentProject() throws BootstrapMavenException {
private LocalProject resolveCurrentProject(Function<Path, Model> modelProvider) throws BootstrapMavenException {
try {
return LocalProject.loadWorkspace(this);
return LocalProject.loadWorkspace(this, modelProvider);
} catch (Exception e) {
throw new BootstrapMavenException("Failed to load current project at " + getCurrentProjectPomOrNull(), e);
}
Original file line number Diff line number Diff line change
@@ -5,7 +5,9 @@
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.function.Function;

import org.apache.maven.model.Model;
import org.eclipse.aether.RepositorySystem;
import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.impl.RemoteRepositoryManager;
@@ -33,6 +35,7 @@ public class BootstrapMavenContextConfig<T extends BootstrapMavenContextConfig<?
protected boolean preferPomsFromWorkspace;
protected Boolean effectiveModelBuilder;
protected Boolean wsModuleParentHierarchy;
protected Function<Path, Model> modelProvider;

/**
* Local repository location
@@ -264,6 +267,20 @@ public T setWorkspaceModuleParentHierarchy(boolean wsModuleParentHierarchy) {
return (T) this;
}

/**
* When workspace discovery is enabled, this method allows to set a POM
* provider that would return a {@link org.apache.maven.model.Model} for
* a given workspace module directory.
*
* @param modelProvider POM provider
* @return this instance
*/
@SuppressWarnings("unchecked")
public T setProjectModelProvider(Function<Path, Model> modelProvider) {
this.modelProvider = modelProvider;
return (T) this;
}

private BootstrapMavenOptions getInitializedCliOptions() {
return cliOptions == null ? cliOptions = BootstrapMavenOptions.newInstance() : cliOptions;
}
Original file line number Diff line number Diff line change
@@ -47,6 +47,10 @@
*/
public class LocalProject {

private static final String SRC_TEST_RESOURCES = "src/test/resources";

private static final String SRC_MAIN_RESOURCES = "src/main/resources";

public static final String PROJECT_GROUPID = "${project.groupId}";

private static final String PROJECT_BASEDIR = "${project.basedir}";
@@ -78,7 +82,7 @@ public static LocalProject loadWorkspace(Path path) throws BootstrapMavenExcepti

public static LocalProject loadWorkspace(Path path, boolean required) throws BootstrapMavenException {
try {
return new WorkspaceLoader(null, path.normalize().toAbsolutePath()).load();
return new WorkspaceLoader(null, path.normalize().toAbsolutePath(), null).load();
} catch (Exception e) {
if (required) {
throw e;
@@ -96,12 +100,17 @@ public static LocalProject loadWorkspace(Path path, boolean required) throws Boo
* @throws BootstrapMavenException in case of an error
*/
public static LocalProject loadWorkspace(BootstrapMavenContext ctx) throws BootstrapMavenException {
return loadWorkspace(ctx, null);
}

public static LocalProject loadWorkspace(BootstrapMavenContext ctx, Function<Path, Model> modelProvider)
throws BootstrapMavenException {
final Path currentProjectPom = ctx.getCurrentProjectPomOrNull();
if (currentProjectPom == null) {
return null;
}
final Path rootProjectBaseDir = ctx.getRootProjectBaseDir();
final WorkspaceLoader wsLoader = new WorkspaceLoader(ctx, currentProjectPom);
final WorkspaceLoader wsLoader = new WorkspaceLoader(ctx, currentProjectPom, modelProvider);

if (rootProjectBaseDir != null && !rootProjectBaseDir.equals(currentProjectPom.getParent())) {
wsLoader.setWorkspaceRootPom(rootProjectBaseDir.resolve(POM_XML));
@@ -257,23 +266,23 @@ public PathCollection getResourcesSourcesDirs() {
final List<Resource> resources = rawModel.getBuild() == null ? List.of()
: rawModel.getBuild().getResources();
if (resources.isEmpty()) {
return PathList.of(resolveRelativeToBaseDir(null, "src/main/resources"));
return PathList.of(resolveRelativeToBaseDir(null, SRC_MAIN_RESOURCES));
}
return PathList.from(resources.stream()
.map(Resource::getDirectory)
.map(resourcesDir -> resolveRelativeToBaseDir(resourcesDir, "src/main/resources"))
.map(resourcesDir -> resolveRelativeToBaseDir(resourcesDir, SRC_MAIN_RESOURCES))
.collect(Collectors.toCollection(LinkedHashSet::new)));
}

public PathCollection getTestResourcesSourcesDirs() {
final List<Resource> resources = rawModel.getBuild() == null ? List.of()
: rawModel.getBuild().getTestResources();
if (resources.isEmpty()) {
return PathList.of(resolveRelativeToBaseDir(null, "src/test/resources"));
return PathList.of(resolveRelativeToBaseDir(null, SRC_TEST_RESOURCES));
}
return PathList.from(resources.stream()
.map(Resource::getDirectory)
.map(resourcesDir -> resolveRelativeToBaseDir(resourcesDir, "src/test/resources"))
.map(resourcesDir -> resolveRelativeToBaseDir(resourcesDir, SRC_TEST_RESOURCES))
.collect(Collectors.toCollection(LinkedHashSet::new)));
}

@@ -302,7 +311,8 @@ public ResolvedDependency getAppArtifact() {
}

public ResolvedDependency getAppArtifact(String extension) {
return new ResolvedArtifactDependency(key.getGroupId(), key.getArtifactId(), "", extension, getVersion(),
return new ResolvedArtifactDependency(key.getGroupId(), key.getArtifactId(), ArtifactCoords.DEFAULT_CLASSIFIER,
extension, getVersion(),
(PathCollection) null);
}

@@ -521,14 +531,14 @@ private Collection<SourceDir> collectMainResources(PathFilter filter) {
final Path classesDir = getClassesDir();
if (resources.isEmpty()) {
return List.of(new DefaultSourceDir(
new DirectoryPathTree(resolveRelativeToBaseDir(null, "src/main/resources")),
new DirectoryPathTree(resolveRelativeToBaseDir(null, SRC_MAIN_RESOURCES)),
new DirectoryPathTree(classesDir, filter), Map.of()));
}
final List<SourceDir> sourceDirs = new ArrayList<>(resources.size());
for (Resource r : resources) {
sourceDirs.add(
new DefaultSourceDir(
new DirectoryPathTree(resolveRelativeToBaseDir(r.getDirectory(), "src/main/resources")),
new DirectoryPathTree(resolveRelativeToBaseDir(r.getDirectory(), SRC_MAIN_RESOURCES)),
new DirectoryPathTree((r.getTargetPath() == null ? classesDir
: classesDir.resolve(stripProjectBasedirPrefix(r.getTargetPath(), PROJECT_OUTPUT_DIR))),
filter),
@@ -543,14 +553,14 @@ private Collection<SourceDir> collectTestResources(PathFilter filter) {
final Path testClassesDir = getTestClassesDir();
if (resources.isEmpty()) {
return List.of(new DefaultSourceDir(
new DirectoryPathTree(resolveRelativeToBaseDir(null, "src/test/resources")),
new DirectoryPathTree(resolveRelativeToBaseDir(null, SRC_TEST_RESOURCES)),
new DirectoryPathTree(testClassesDir, filter), Map.of()));
}
final List<SourceDir> sourceDirs = new ArrayList<>(resources.size());
for (Resource r : resources) {
sourceDirs.add(
new DefaultSourceDir(
new DirectoryPathTree(resolveRelativeToBaseDir(r.getDirectory(), "src/test/resources")),
new DirectoryPathTree(resolveRelativeToBaseDir(r.getDirectory(), SRC_TEST_RESOURCES)),
new DirectoryPathTree((r.getTargetPath() == null ? testClassesDir
: testClassesDir.resolve(stripProjectBasedirPrefix(r.getTargetPath(), PROJECT_OUTPUT_DIR))),
filter),
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

import org.apache.maven.model.Model;
import org.apache.maven.model.Parent;
@@ -69,6 +70,7 @@ static Path locateCurrentProjectPom(Path path, boolean required) throws Bootstra
private final Map<Path, LocalProject> projectCache = new HashMap<>();
private final Path currentProjectPom;
private Path workspaceRootPom;
private Function<Path, Model> modelProvider;

private ModelBuilder modelBuilder;
private ModelResolver modelResolver;
@@ -77,7 +79,9 @@ static Path locateCurrentProjectPom(Path path, boolean required) throws Bootstra
private List<String> inactiveProfileIds;
private List<Profile> profiles;

WorkspaceLoader(BootstrapMavenContext ctx, Path currentProjectPom) throws BootstrapMavenException {
WorkspaceLoader(BootstrapMavenContext ctx, Path currentProjectPom, Function<Path, Model> modelProvider)
throws BootstrapMavenException {
this.modelProvider = modelProvider;
if (ctx != null && ctx.isEffectiveModelBuilder()) {
modelBuilder = BootstrapModelBuilderFactory.getDefaultModelBuilder();
modelResolver = BootstrapModelResolver.newInstance(ctx, workspace);
@@ -100,7 +104,7 @@ static Path locateCurrentProjectPom(Path path, boolean required) throws Bootstra
private boolean isPom(Path p) {
if (Files.exists(p) && !Files.isDirectory(p)) {
try {
loadAndCacheRawModel(p);
rawModel(p);
return true;
} catch (BootstrapMavenException e) {
// not a POM file
@@ -115,7 +119,8 @@ private LocalProject project(Path pomFile) throws BootstrapMavenException {
}

private LocalProject loadAndCacheProject(Path pomFile) throws BootstrapMavenException {
final Model cachedRawModel = rawModelCache.get(pomFile.getParent());
Model cachedRawModel = rawModelCache.getOrDefault(pomFile.getParent(),
modelProvider == null ? null : modelProvider.apply(pomFile.getParent()));
final LocalProject project;
if (modelBuilder != null) {
ModelBuildingRequest req = new DefaultModelBuildingRequest();
@@ -148,7 +153,8 @@ private LocalProject loadAndCacheProject(Path pomFile) throws BootstrapMavenExce
}

private Model rawModel(Path pomFile) throws BootstrapMavenException {
final Model rawModel = rawModelCache.get(pomFile.getParent());
final Model rawModel = rawModelCache.getOrDefault(pomFile.getParent(),
modelProvider == null ? null : modelProvider.apply(pomFile.getParent()));
return rawModel == null ? loadAndCacheRawModel(pomFile) : rawModel;
}

0 comments on commit 59c20da

Please sign in to comment.