diff --git a/devtools/maven/src/main/java/io/quarkus/maven/DevMojo.java b/devtools/maven/src/main/java/io/quarkus/maven/DevMojo.java index 1374f6fc1f761..9ea99983b5026 100644 --- a/devtools/maven/src/main/java/io/quarkus/maven/DevMojo.java +++ b/devtools/maven/src/main/java/io/quarkus/maven/DevMojo.java @@ -635,16 +635,16 @@ void prepare(final boolean triggerCompile) throws Exception { setKotlinSpecificFlags(devModeContext); final LocalProject localProject; if (noDeps) { - localProject = LocalProject.load(outputDirectory.toPath()); + localProject = LocalProject.load(project.getModel().getPomFile().toPath()); addProject(devModeContext, localProject, true); - pomFiles.add(localProject.getDir().resolve("pom.xml")); + pomFiles.add(localProject.getRawModel().getPomFile().toPath()); devModeContext.getLocalArtifacts() .add(new AppArtifactKey(localProject.getGroupId(), localProject.getArtifactId(), null, "jar")); } else { - localProject = LocalProject.loadWorkspace(outputDirectory.toPath()); + localProject = LocalProject.loadWorkspace(project.getModel().getPomFile().toPath()); for (LocalProject project : filterExtensionDependencies(localProject)) { addProject(devModeContext, project, project == localProject); - pomFiles.add(project.getDir().resolve("pom.xml")); + pomFiles.add(project.getRawModel().getPomFile().toPath()); devModeContext.getLocalArtifacts() .add(new AppArtifactKey(project.getGroupId(), project.getArtifactId(), null, "jar")); } diff --git a/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/BootstrapAppModelFactory.java b/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/BootstrapAppModelFactory.java index 0c69f49aec1fc..2593bcea18d3b 100644 --- a/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/BootstrapAppModelFactory.java +++ b/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/BootstrapAppModelFactory.java @@ -208,8 +208,9 @@ private BootstrapMavenContext createBootstrapMavenContext() throws AppModelResol config.setOffline(offline); } // Currently projectRoot may be an app location which is not exactly a Maven project dir - if (projectRoot != null && Files.isDirectory(projectRoot) && Files.exists(projectRoot.resolve("pom.xml"))) { - config.setCurrentProject(projectRoot.toString()); + final Path projectPom = config.getPomForDirOrNull(projectRoot); + if (projectPom != null) { + config.setCurrentProject(projectPom.toString()); } config.setWorkspaceDiscovery(isWorkspaceDiscoveryEnabled()); return mvnContext = new BootstrapMavenContext(config); diff --git a/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/BootstrapMavenContext.java b/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/BootstrapMavenContext.java index 882888bd10773..607885d1e1372 100644 --- a/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/BootstrapMavenContext.java +++ b/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/BootstrapMavenContext.java @@ -126,7 +126,7 @@ public BootstrapMavenContext(BootstrapMavenContextConfig config) * This means the values that are available in the config should be set before * the instance method invocations. */ - this.alternatePomName = config.alternativePomName; + this.alternatePomName = config.alternatePomName; this.artifactTransferLogging = config.artifactTransferLogging; this.localRepo = config.localRepo; this.offline = config.offline; @@ -134,6 +134,7 @@ public BootstrapMavenContext(BootstrapMavenContextConfig config) this.repoSession = config.repoSession; this.remoteRepos = config.remoteRepos; this.remoteRepoManager = config.remoteRepoManager; + this.cliOptions = config.cliOptions; if (config.currentProject != null) { this.currentProject = config.currentProject; this.currentPom = currentProject.getRawModel().getPomFile().toPath(); @@ -655,32 +656,7 @@ private Path resolveCurrentPom() { final String basedirProp = PropertyUtils.getProperty(BASEDIR); if (basedirProp != null) { // this is the actual current project dir - final Path basedir = Paths.get(basedirProp); - - // if the basedir matches the parent of the alternate pom, it's the alternate pom - if (alternatePom != null - && alternatePom.isAbsolute() - && alternatePom.getParent().equals(basedir)) { - return alternatePom; - } - // even if the alternate pom has been specified we try the default pom.xml first - // since unlike Maven CLI we don't know which project originated the build - Path pom = basedir.resolve("pom.xml"); - if (Files.exists(pom)) { - return pom; - } - - // if alternate pom path has a single element we can try it - // if it has more, it won't match the basedir - if (alternatePom != null && !alternatePom.isAbsolute() && alternatePom.getNameCount() == 1) { - pom = basedir.resolve(alternatePom); - if (Files.exists(pom)) { - return pom; - } - } - - // give up - return null; + return getPomForDirOrNull(Paths.get(basedirProp), alternatePom); } // we are not in the context of a Maven build @@ -697,6 +673,33 @@ private Path resolveCurrentPom() { return Files.exists(pom) ? pom : null; } + static Path getPomForDirOrNull(final Path basedir, Path alternatePom) { + // if the basedir matches the parent of the alternate pom, it's the alternate pom + if (alternatePom != null + && alternatePom.isAbsolute() + && alternatePom.getParent().equals(basedir)) { + return alternatePom; + } + // even if the alternate pom has been specified we try the default pom.xml first + // since unlike Maven CLI we don't know which project originated the build + Path pom = basedir.resolve("pom.xml"); + if (Files.exists(pom)) { + return pom; + } + + // if alternate pom path has a single element we can try it + // if it has more, it won't match the basedir + if (alternatePom != null && !alternatePom.isAbsolute() && alternatePom.getNameCount() == 1) { + pom = basedir.resolve(alternatePom); + if (Files.exists(pom)) { + return pom; + } + } + + // give up + return null; + } + private static Path pomXmlOrNull(Path path) { if (Files.isDirectory(path)) { path = path.resolve("pom.xml"); diff --git a/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/BootstrapMavenContextConfig.java b/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/BootstrapMavenContextConfig.java index 017c20c249d5f..26bd0cfad2df0 100644 --- a/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/BootstrapMavenContextConfig.java +++ b/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/BootstrapMavenContextConfig.java @@ -1,7 +1,11 @@ package io.quarkus.bootstrap.resolver.maven; +import io.quarkus.bootstrap.resolver.maven.options.BootstrapMavenOptions; import io.quarkus.bootstrap.resolver.maven.workspace.LocalProject; import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.List; import org.eclipse.aether.RepositorySystem; import org.eclipse.aether.RepositorySystemSession; @@ -18,9 +22,10 @@ public class BootstrapMavenContextConfig remoteRepos; protected RemoteRepositoryManager remoteRepoManager; - protected String alternativePomName; + protected String alternatePomName; protected File userSettings; protected boolean artifactTransferLogging = true; + protected BootstrapMavenOptions cliOptions; /** * Local repository location @@ -133,7 +138,7 @@ public T setRemoteRepositoryManager(RemoteRepositoryManager remoteRepoManager) { */ @SuppressWarnings("unchecked") public T setCurrentProject(String currentProject) { - this.alternativePomName = currentProject; + this.alternatePomName = currentProject; return (T) this; } @@ -161,4 +166,24 @@ public T setArtifactTransferLogging(boolean artifactTransferLogging) { this.artifactTransferLogging = artifactTransferLogging; return (T) this; } + + /** + * Resolves a POM file for a basedir. + * + * @param basedir project's basedir + * @return POM file for the basedir or null, if it could not be resolved + */ + public Path getPomForDirOrNull(Path basedir) { + if (!Files.isDirectory(basedir)) { + return null; + } + final String altPom = alternatePomName == null + ? getInitializedCliOptions().getOptionValue(BootstrapMavenOptions.ALTERNATE_POM_FILE) + : alternatePomName; + return BootstrapMavenContext.getPomForDirOrNull(basedir, altPom == null ? null : Paths.get(altPom)); + } + + private BootstrapMavenOptions getInitializedCliOptions() { + return cliOptions == null ? cliOptions = BootstrapMavenOptions.newInstance() : cliOptions; + } } 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 1c86986a3e330..07b495619ee63 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 @@ -148,9 +148,9 @@ public File findArtifact(Artifact artifact) { // otherwise, this project hasn't been built yet } else if (type.equals(AppArtifactCoords.TYPE_POM)) { - final Path path = lp.getDir().resolve("pom.xml"); - if (Files.exists(path)) { - return path.toFile(); + final File pom = lp.getRawModel().getPomFile(); + if (pom.exists()) { + return pom; } } return null; diff --git a/integration-tests/maven/src/test/java/io/quarkus/maven/it/DevMojoIT.java b/integration-tests/maven/src/test/java/io/quarkus/maven/it/DevMojoIT.java index 93266f33d216c..3b739c23abbc7 100644 --- a/integration-tests/maven/src/test/java/io/quarkus/maven/it/DevMojoIT.java +++ b/integration-tests/maven/src/test/java/io/quarkus/maven/it/DevMojoIT.java @@ -166,6 +166,54 @@ public void testThatSourceChangesAreDetectedOnPomChange() throws Exception { } + @Test + public void testAlternatePom() throws Exception { + testDir = initProject("projects/classic", "projects/project-classic-alternate-pom"); + + File pom = new File(testDir, "pom.xml"); + if (!pom.exists()) { + throw new IllegalStateException("Failed to locate project's pom.xml at " + pom); + } + final String alternatePomName = "alternate-pom.xml"; + File alternatePom = new File(testDir, alternatePomName); + if (alternatePom.exists()) { + alternatePom.delete(); + } + pom.renameTo(alternatePom); + if (pom.exists()) { + throw new IllegalStateException(pom + " was expected to be renamed to " + alternatePom); + } + runAndCheck("-f", alternatePomName); + + // Edit a Java file too + final File javaSource = new File(testDir, "src/main/java/org/acme/HelloResource.java"); + final String uuid = UUID.randomUUID().toString(); + filter(javaSource, Collections.singletonMap("return \"hello\";", "return \"hello " + uuid + "\";")); + + // edit the application.properties too + final File applicationProps = new File(testDir, "src/main/resources/application.properties"); + filter(applicationProps, Collections.singletonMap("greeting=bonjour", "greeting=" + uuid + "")); + + // Now edit the pom.xml to trigger the dev mode restart + filter(alternatePom, Collections.singletonMap("", + " \n" + + " io.quarkus\n" + + " quarkus-smallrye-openapi\n" + + " ")); + + // Wait until we get the updated responses + await() + .pollDelay(100, TimeUnit.MILLISECONDS) + .atMost(1, TimeUnit.MINUTES) + .until(() -> DevModeTestUtils.getHttpResponse("/app/hello").contains("hello " + uuid)); + + await() + .pollDelay(100, TimeUnit.MILLISECONDS) + .atMost(1, TimeUnit.MINUTES) + .until(() -> DevModeTestUtils.getHttpResponse("/app/hello/greeting").contains(uuid)); + + } + @Test public void testThatTheApplicationIsReloadedOnPomChange() throws MavenInvocationException, IOException { testDir = initProject("projects/classic", "projects/project-classic-run-pom-change");