Repository: quarkusio/quarkus
Issue: Quarkus fails when using jgitver

### Describe the bug

Hi,

It seems that Quarkus doesn't work properly when the maven project is using the [jgitver-maven-plugin](https://github.com/jgitver/jgitver-maven-plugin) - a maven plugin to automatically define the maven project version based on git branches as tags.

Thanks.

### Expected behavior

The `./mvnw quarkus:dev` should start Quarkus in development mode, instead of failing.

### Actual behavior

Running `./mvnw quarkus:dev` fails with the following error:

```
Listening for transport dt_socket at address: 5005
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "io.quarkus.deployment.dev.DevModeContext$ModuleInfo.getMain()" because the return value of "io.quarkus.deployment.dev.DevModeContext.getApplicationRoot()" is null
	at io.quarkus.deployment.dev.DevModeMain.start(DevModeMain.java:90)
	at io.quarkus.deploy
[debug.txt](https://github.com/quarkusio/quarkus/files/9704780/debug.txt)
ment.dev.DevModeMain.main(DevModeMain.java:62)
```

Output from running `./mvnw quarkus:dev -X`: [debug.txt](https://github.com/quarkusio/quarkus/files/9704782/debug.txt)

### How to Reproduce?

1. Create a Quarkus project with `quarkus create`.
2. Add the jgitver maven extension, by adding a file `.mvn/extensions.xml` to the project with the following content:

```
<extensions xmlns="http://maven.apache.org/EXTENSIONS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/EXTENSIONS/1.0.0 http://maven.apache.org/xsd/core-extensions-1.0.0.xsd">
  <extension>
    <groupId>fr.brouillard.oss</groupId>
    <artifactId>jgitver-maven-plugin</artifactId>
    <version>1.9.0</version>
  </extension>
</extensions>
```

3. Optional: Initialize the git repo and do a commit, just so that jgitver computes the version as `0.0.0-SNAPSHOT` instead of `0.0.0-NOT_A_GIT_REPOSITORY`:

```
git init
git add .
git commit -m "test"
```

4. Run `./mvnw quarkus:dev`.

### Output of `uname -a` or `ver`

Linux laptop-2220 5.15.0-48-generic #54~20.04.1-Ubuntu SMP Thu Sep 1 16:17:26 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux

### Output of `java -version`

openjdk version "17.0.4" 2022-07-19 LTS
OpenJDK Runtime Environment Corretto-17.0.4.8.1 (build 17.0.4+8-LTS)
OpenJDK 64-Bit Server VM Corretto-17.0.4.8.1 (build 17.0.4+8-LTS, mixed mode, sharing)

### GraalVM version (if different from Java)

N/A

### Quarkus version or git rev

2.13.0.Final

### Build tool (ie. output of `mvnw --version` or `gradlew --version`)

Apache Maven 3.8.6 (84538c9988a25aec085021c365c560670ad80f63)


### Additional information

_No response_

Changed files:
independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/workspace/WorkspaceLoader.java
independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/BootstrapMavenContextConfig.java
independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/workspace/LocalProject.java
independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/BootstrapMavenContext.java
core/deployment/src/main/java/io/quarkus/deployment/dev/QuarkusDevModeLauncher.java
devtools/maven/src/main/java/io/quarkus/maven/DevMojo.java
devtools/maven/src/main/java/io/quarkus/maven/QuarkusBootstrapProvider.java

diff --git a/core/deployment/src/main/java/io/quarkus/deployment/dev/QuarkusDevModeLauncher.java b/core/deployment/src/main/java/io/quarkus/deployment/dev/QuarkusDevModeLauncher.java
index 7108a534536..b219f7e4e67 100644
--- a/core/deployment/src/main/java/io/quarkus/deployment/dev/QuarkusDevModeLauncher.java
+++ b/core/deployment/src/main/java/io/quarkus/deployment/dev/QuarkusDevModeLauncher.java
@@ -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);
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 f2172937fda..387fcb3a42f 100644
--- a/devtools/maven/src/main/java/io/quarkus/maven/DevMojo.java
+++ b/devtools/maven/src/main/java/io/quarkus/maven/DevMojo.java
@@ -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
diff --git a/devtools/maven/src/main/java/io/quarkus/maven/QuarkusBootstrapProvider.java b/devtools/maven/src/main/java/io/quarkus/maven/QuarkusBootstrapProvider.java
index 78158655364..f340b2048d4 100644
--- a/devtools/maven/src/main/java/io/quarkus/maven/QuarkusBootstrapProvider.java
+++ b/devtools/maven/src/main/java/io/quarkus/maven/QuarkusBootstrapProvider.java
@@ -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);
             }
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 b456a5c4b3c..22114d0a2b0 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
@@ -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);
         }
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 efa4ffa77d9..8b645d5b0c2 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
@@ -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 @@
     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;
     }
diff --git a/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/workspace/LocalProject.java b/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/workspace/LocalProject.java
index 29e84613bfb..c2fa020ce57 100644
--- a/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/workspace/LocalProject.java
+++ b/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/workspace/LocalProject.java
@@ -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,11 +266,11 @@ 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)));
     }
 
@@ -269,11 +278,11 @@ 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),
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 6a0cd9b5627..a30aad09d2f 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
@@ -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;
     }