View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.project;
20  
21  import javax.inject.Inject;
22  import javax.inject.Named;
23  import javax.inject.Singleton;
24  
25  import java.io.ByteArrayInputStream;
26  import java.io.File;
27  import java.io.IOException;
28  import java.io.InputStream;
29  import java.nio.charset.StandardCharsets;
30  import java.nio.file.Path;
31  import java.util.*;
32  import java.util.concurrent.*;
33  import java.util.concurrent.atomic.AtomicInteger;
34  import java.util.concurrent.atomic.AtomicReference;
35  import java.util.function.Consumer;
36  import java.util.function.Supplier;
37  import java.util.stream.Collectors;
38  import java.util.stream.Stream;
39  
40  import org.apache.maven.ProjectCycleException;
41  import org.apache.maven.RepositoryUtils;
42  import org.apache.maven.api.Session;
43  import org.apache.maven.api.SessionData;
44  import org.apache.maven.api.feature.Features;
45  import org.apache.maven.api.model.*;
46  import org.apache.maven.api.services.ModelBuilder;
47  import org.apache.maven.api.services.ModelBuilderException;
48  import org.apache.maven.api.services.ModelBuilderRequest;
49  import org.apache.maven.api.services.ModelBuilderResult;
50  import org.apache.maven.api.services.ModelCache;
51  import org.apache.maven.api.services.ModelProblem;
52  import org.apache.maven.api.services.ModelResolver;
53  import org.apache.maven.api.services.ModelResolverException;
54  import org.apache.maven.api.services.ModelSource;
55  import org.apache.maven.api.services.ModelTransformerContext;
56  import org.apache.maven.api.services.ModelTransformerContextBuilder;
57  import org.apache.maven.api.services.Source;
58  import org.apache.maven.api.services.model.ModelBuildingListener;
59  import org.apache.maven.api.services.model.ModelProcessor;
60  import org.apache.maven.artifact.Artifact;
61  import org.apache.maven.artifact.InvalidArtifactRTException;
62  import org.apache.maven.artifact.InvalidRepositoryException;
63  import org.apache.maven.artifact.repository.ArtifactRepository;
64  import org.apache.maven.bridge.MavenRepositorySystem;
65  import org.apache.maven.internal.impl.InternalSession;
66  import org.apache.maven.internal.impl.resolver.DefaultModelCache;
67  import org.apache.maven.internal.impl.resolver.DefaultModelRepositoryHolder;
68  import org.apache.maven.model.building.ArtifactModelSource;
69  import org.apache.maven.model.building.DefaultModelProblem;
70  import org.apache.maven.model.building.FileModelSource;
71  import org.apache.maven.model.building.ModelSource2;
72  import org.apache.maven.model.building.ModelSource3;
73  import org.apache.maven.model.resolution.UnresolvableModelException;
74  import org.apache.maven.model.root.RootLocator;
75  import org.apache.maven.repository.internal.ArtifactDescriptorUtils;
76  import org.apache.maven.utils.Os;
77  import org.eclipse.aether.RepositorySystem;
78  import org.eclipse.aether.RepositorySystemSession;
79  import org.eclipse.aether.RequestTrace;
80  import org.eclipse.aether.impl.RemoteRepositoryManager;
81  import org.eclipse.aether.repository.LocalRepositoryManager;
82  import org.eclipse.aether.repository.RemoteRepository;
83  import org.eclipse.aether.repository.WorkspaceRepository;
84  import org.eclipse.aether.resolution.ArtifactRequest;
85  import org.eclipse.aether.resolution.ArtifactResult;
86  import org.slf4j.Logger;
87  import org.slf4j.LoggerFactory;
88  
89  /**
90   * DefaultProjectBuilder
91   */
92  @Named
93  @Singleton
94  public class DefaultProjectBuilder implements ProjectBuilder {
95      public static final String BUILDER_PARALLELISM = "maven.projectBuilder.parallelism";
96      public static final int DEFAULT_BUILDER_PARALLELISM = Runtime.getRuntime().availableProcessors() / 2 + 1;
97  
98      private final Logger logger = LoggerFactory.getLogger(getClass());
99      private final ModelBuilder modelBuilder;
100     private final ModelProcessor modelProcessor;
101     private final ProjectBuildingHelper projectBuildingHelper;
102     private final MavenRepositorySystem repositorySystem;
103     private final org.eclipse.aether.RepositorySystem repoSystem;
104     private final RemoteRepositoryManager repositoryManager;
105     private final ProjectDependenciesResolver dependencyResolver;
106 
107     private final RootLocator rootLocator;
108 
109     @SuppressWarnings("checkstyle:ParameterNumber")
110     @Inject
111     public DefaultProjectBuilder(
112             ModelBuilder modelBuilder,
113             ModelProcessor modelProcessor,
114             ProjectBuildingHelper projectBuildingHelper,
115             MavenRepositorySystem repositorySystem,
116             RepositorySystem repoSystem,
117             RemoteRepositoryManager repositoryManager,
118             ProjectDependenciesResolver dependencyResolver,
119             RootLocator rootLocator) {
120         this.modelBuilder = modelBuilder;
121         this.modelProcessor = modelProcessor;
122         this.projectBuildingHelper = projectBuildingHelper;
123         this.repositorySystem = repositorySystem;
124         this.repoSystem = repoSystem;
125         this.repositoryManager = repositoryManager;
126         this.dependencyResolver = dependencyResolver;
127         this.rootLocator = rootLocator;
128     }
129     // ----------------------------------------------------------------------
130     // MavenProjectBuilder Implementation
131     // ----------------------------------------------------------------------
132 
133     @Override
134     public ProjectBuildingResult build(File pomFile, ProjectBuildingRequest request) throws ProjectBuildingException {
135         try (BuildSession bs = new BuildSession(request, false)) {
136             Path path = pomFile.toPath();
137             return bs.build(path, ModelSource.fromPath(path));
138         }
139     }
140 
141     @Deprecated
142     @Override
143     public ProjectBuildingResult build(
144             org.apache.maven.model.building.ModelSource modelSource, ProjectBuildingRequest request)
145             throws ProjectBuildingException {
146         return build(toSource(modelSource), request);
147     }
148 
149     @Deprecated
150     static ModelSource toSource(org.apache.maven.model.building.ModelSource modelSource) {
151         if (modelSource instanceof FileModelSource fms) {
152             return ModelSource.fromPath(fms.getPath());
153         } else if (modelSource instanceof ArtifactModelSource ams) {
154             return ModelSource.fromPath(ams.getPath(), ams.toString());
155         } else {
156             return new ModelSource() {
157                 @Override
158                 public ModelSource resolve(ModelLocator modelLocator, String relative) {
159                     if (modelSource instanceof ModelSource3 ms) {
160                         return toSource(ms.getRelatedSource(
161                                 new org.apache.maven.model.locator.ModelLocator() {
162                                     @Override
163                                     public File locatePom(File projectDirectory) {
164                                         return null;
165                                     }
166 
167                                     @Override
168                                     public Path locatePom(Path projectDirectory) {
169                                         return null;
170                                     }
171 
172                                     @Override
173                                     public Path locateExistingPom(Path project) {
174                                         return modelLocator.locateExistingPom(project);
175                                     }
176                                 },
177                                 relative));
178                     }
179                     return null;
180                 }
181 
182                 @Override
183                 public Path getPath() {
184                     return null;
185                 }
186 
187                 @Override
188                 public InputStream openStream() throws IOException {
189                     return modelSource.getInputStream();
190                 }
191 
192                 @Override
193                 public String getLocation() {
194                     return modelSource.getLocation();
195                 }
196 
197                 @Override
198                 public Source resolve(String relative) {
199                     if (modelSource instanceof ModelSource2 ms) {
200                         return toSource(ms.getRelatedSource(relative));
201                     } else {
202                         return null;
203                     }
204                 }
205             };
206         }
207     }
208 
209     @Override
210     public ProjectBuildingResult build(ModelSource modelSource, ProjectBuildingRequest request)
211             throws ProjectBuildingException {
212         try (BuildSession bs = new BuildSession(request, false)) {
213             return bs.build(null, modelSource);
214         }
215     }
216 
217     @Override
218     public ProjectBuildingResult build(Artifact artifact, ProjectBuildingRequest request)
219             throws ProjectBuildingException {
220         return build(artifact, false, request);
221     }
222 
223     @Override
224     public ProjectBuildingResult build(Artifact artifact, boolean allowStubModel, ProjectBuildingRequest request)
225             throws ProjectBuildingException {
226         try (BuildSession bs = new BuildSession(request, false)) {
227             return bs.build(artifact, allowStubModel);
228         }
229     }
230 
231     @Override
232     public List<ProjectBuildingResult> build(List<File> pomFiles, boolean recursive, ProjectBuildingRequest request)
233             throws ProjectBuildingException {
234         try (BuildSession bs = new BuildSession(request, true)) {
235             return bs.build(pomFiles, recursive);
236         }
237     }
238 
239     static class InterimResult {
240 
241         File pomFile;
242 
243         ModelBuilderRequest request;
244 
245         ModelBuilderResult result;
246 
247         MavenProject project;
248 
249         boolean root;
250 
251         List<InterimResult> modules = Collections.emptyList();
252 
253         ProjectBuildingResult projectBuildingResult;
254 
255         InterimResult(
256                 File pomFile,
257                 ModelBuilderRequest request,
258                 ModelBuilderResult result,
259                 MavenProject project,
260                 boolean root) {
261             this.pomFile = pomFile;
262             this.request = request;
263             this.result = result;
264             this.project = project;
265             this.root = root;
266         }
267 
268         InterimResult(ModelBuilderRequest request, ProjectBuildingResult projectBuildingResult) {
269             this.request = request;
270             this.projectBuildingResult = projectBuildingResult;
271             this.pomFile = projectBuildingResult.getPomFile();
272             this.project = projectBuildingResult.getProject();
273         }
274     }
275 
276     class BuildSession implements AutoCloseable {
277         private final ProjectBuildingRequest request;
278         private final RepositorySystemSession session;
279         private final List<RemoteRepository> repositories;
280         private final ReactorModelPool modelPool;
281         private final ConcurrentMap<String, Object> parentCache;
282         private final ModelTransformerContextBuilder transformerContextBuilder;
283         private final ExecutorService executor;
284         private final ModelCache modelCache;
285         private final ModelResolver modelResolver;
286 
287         BuildSession(ProjectBuildingRequest request, boolean localProjects) {
288             this.request = request;
289             this.session =
290                     RepositoryUtils.overlay(request.getLocalRepository(), request.getRepositorySession(), repoSystem);
291             InternalSession.from(session);
292             this.repositories = RepositoryUtils.toRepos(request.getRemoteRepositories());
293             this.executor = createExecutor(getParallelism(request));
294             if (localProjects) {
295                 this.modelPool = new ReactorModelPool();
296                 this.transformerContextBuilder = modelBuilder.newTransformerContextBuilder();
297             } else {
298                 this.modelPool = null;
299                 this.transformerContextBuilder = null;
300             }
301             this.parentCache = new ConcurrentHashMap<>();
302             this.modelCache = DefaultModelCache.newInstance(session, true);
303             this.modelResolver = new ModelResolverWrapper() {
304                 @Override
305                 protected org.apache.maven.model.resolution.ModelResolver getResolver(
306                         List<RemoteRepository> repositories) {
307                     return new ProjectModelResolver(
308                             session,
309                             RequestTrace.newChild(null, request),
310                             repoSystem,
311                             repositoryManager,
312                             repositories,
313                             request.getRepositoryMerging(),
314                             modelPool,
315                             parentCache);
316                 }
317             };
318         }
319 
320         ExecutorService createExecutor(int parallelism) {
321             //
322             // We need an executor that will not block.
323             // We can't use work stealing, as we are building a graph
324             // and this could lead to cycles where a thread waits for
325             // a task to finish, then execute another one which waits
326             // for the initial task...
327             // In order to work around that problem, we override the
328             // invokeAll method, so that whenever the method is called,
329             // the pool core size will be incremented before submitting
330             // all the tasks, then the thread will block waiting for all
331             // those subtasks to finish.
332             // This ensures the number of running workers is no more than
333             // the defined parallism, while making sure the pool will not
334             // be exhausted
335             //
336             return new ThreadPoolExecutor(
337                     parallelism, Integer.MAX_VALUE, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>()) {
338                 final AtomicInteger parked = new AtomicInteger();
339 
340                 @Override
341                 public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
342                         throws InterruptedException {
343                     setCorePoolSize(parallelism + parked.incrementAndGet());
344                     try {
345                         return super.invokeAll(tasks);
346                     } finally {
347                         setCorePoolSize(parallelism + parked.decrementAndGet());
348                     }
349                 }
350             };
351         }
352 
353         @Override
354         public void close() {
355             this.executor.shutdownNow();
356         }
357 
358         private int getParallelism(ProjectBuildingRequest request) {
359             int parallelism = DEFAULT_BUILDER_PARALLELISM;
360             try {
361                 String str = request.getUserProperties().getProperty(BUILDER_PARALLELISM);
362                 if (str == null) {
363                     str = request.getSystemProperties().getProperty(BUILDER_PARALLELISM);
364                 }
365                 if (str != null) {
366                     parallelism = Integer.parseInt(str);
367                 }
368             } catch (Exception e) {
369                 // ignore
370             }
371             return Math.max(1, Math.min(parallelism, Runtime.getRuntime().availableProcessors()));
372         }
373 
374         ProjectBuildingResult build(Path pomFile, ModelSource modelSource) throws ProjectBuildingException {
375             ClassLoader oldContextClassLoader = Thread.currentThread().getContextClassLoader();
376 
377             try {
378                 MavenProject project = request.getProject();
379 
380                 List<ModelProblem> modelProblems = null;
381                 Throwable error = null;
382 
383                 if (project == null) {
384                     project = new MavenProject();
385                     project.setFile(pomFile != null ? pomFile.toFile() : null);
386 
387                     ModelBuildingListener listener =
388                             new DefaultModelBuildingListener(project, projectBuildingHelper, this.request);
389 
390                     ModelBuilderRequest.ModelBuilderRequestBuilder builder = getModelBuildingRequest();
391                     ModelBuilderRequest request = builder.projectBuild(modelPool != null)
392                             .source(modelSource)
393                             .projectBuild(true)
394                             .locationTracking(true)
395                             .listener(listener)
396                             .build();
397 
398                     if (pomFile != null) {
399                         project.setRootDirectory(rootLocator.findRoot(pomFile.getParent()));
400                     }
401 
402                     ModelBuilderResult result;
403                     try {
404                         result = modelBuilder.build(request);
405                     } catch (ModelBuilderException e) {
406                         result = e.getResult();
407                         if (result == null || result.getEffectiveModel() == null) {
408                             throw new ProjectBuildingException(
409                                     e.getModelId(), e.getMessage(), pomFile != null ? pomFile.toFile() : null, e);
410                         }
411                         // validation error, continue project building and delay failing to help IDEs
412                         error = e;
413                     }
414 
415                     modelProblems = result.getProblems();
416 
417                     initProject(project, Collections.emptyMap(), result);
418                 } else if (request.isResolveDependencies()) {
419                     projectBuildingHelper.selectProjectRealm(project);
420                 }
421 
422                 DependencyResolutionResult resolutionResult = null;
423 
424                 if (request.isResolveDependencies()) {
425                     resolutionResult = resolveDependencies(project);
426                 }
427 
428                 ProjectBuildingResult result =
429                         new DefaultProjectBuildingResult(project, convert(modelProblems), resolutionResult);
430 
431                 if (error != null) {
432                     ProjectBuildingException e = new ProjectBuildingException(List.of(result));
433                     e.initCause(error);
434                     throw e;
435                 }
436 
437                 return result;
438             } finally {
439                 Thread.currentThread().setContextClassLoader(oldContextClassLoader);
440             }
441         }
442 
443         ProjectBuildingResult build(Artifact artifact, boolean allowStubModel) throws ProjectBuildingException {
444             org.eclipse.aether.artifact.Artifact pomArtifact = RepositoryUtils.toArtifact(artifact);
445             pomArtifact = ArtifactDescriptorUtils.toPomArtifact(pomArtifact);
446 
447             boolean localProject;
448 
449             try {
450                 ArtifactRequest pomRequest = new ArtifactRequest();
451                 pomRequest.setArtifact(pomArtifact);
452                 pomRequest.setRepositories(repositories);
453                 ArtifactResult pomResult = repoSystem.resolveArtifact(session, pomRequest);
454 
455                 pomArtifact = pomResult.getArtifact();
456                 localProject = pomResult.getRepository() instanceof WorkspaceRepository;
457             } catch (org.eclipse.aether.resolution.ArtifactResolutionException e) {
458                 if (e.getResults().get(0).isMissing() && allowStubModel) {
459                     return build(null, createStubModelSource(artifact));
460                 }
461                 throw new ProjectBuildingException(
462                         artifact.getId(), "Error resolving project artifact: " + e.getMessage(), e);
463             }
464 
465             Path pomFile = pomArtifact.getPath();
466 
467             if (!artifact.isResolved() && "pom".equals(artifact.getType())) {
468                 artifact.selectVersion(pomArtifact.getVersion());
469                 artifact.setFile(pomFile.toFile());
470                 artifact.setResolved(true);
471             }
472 
473             if (localProject) {
474                 return build(pomFile, ModelSource.fromPath(pomFile));
475             } else {
476                 return build(
477                         null,
478                         ModelSource.fromPath(
479                                 pomFile,
480                                 artifact.getGroupId() + ":" + artifact.getArtifactId() + ":" + artifact.getVersion()));
481             }
482         }
483 
484         List<ProjectBuildingResult> build(List<File> pomFiles, boolean recursive) throws ProjectBuildingException {
485             List<ProjectBuildingResult> results = doBuild(pomFiles, recursive);
486             if (results.stream()
487                     .flatMap(r -> r.getProblems().stream())
488                     .anyMatch(p -> p.getSeverity() != org.apache.maven.model.building.ModelProblem.Severity.WARNING)) {
489                 org.apache.maven.model.building.ModelProblem cycle = results.stream()
490                         .flatMap(r -> r.getProblems().stream())
491                         .filter(p -> p.getException() instanceof CycleDetectedException)
492                         .findAny()
493                         .orElse(null);
494                 if (cycle != null) {
495                     throw new RuntimeException(new ProjectCycleException(
496                             "The projects in the reactor contain a cyclic reference: " + cycle.getMessage(),
497                             (CycleDetectedException) cycle.getException()));
498                 }
499                 throw new ProjectBuildingException(results);
500             }
501 
502             return results;
503         }
504 
505         List<ProjectBuildingResult> doBuild(List<File> pomFiles, boolean recursive) {
506             Map<File, MavenProject> projectIndex = new ConcurrentHashMap<>(256);
507 
508             // phase 1: get file Models from the reactor.
509             List<InterimResult> interimResults = build(projectIndex, pomFiles, new LinkedHashSet<>(), true, recursive);
510 
511             ClassLoader oldContextClassLoader = Thread.currentThread().getContextClassLoader();
512 
513             try {
514                 // Phase 2: get effective models from the reactor
515                 List<ProjectBuildingResult> results = build(projectIndex, interimResults);
516 
517                 if (Features.buildConsumer(request.getUserProperties())) {
518                     request.getRepositorySession()
519                             .getData()
520                             .set(ModelTransformerContext.KEY, transformerContextBuilder.build());
521                 }
522 
523                 return results;
524             } finally {
525                 Thread.currentThread().setContextClassLoader(oldContextClassLoader);
526             }
527         }
528 
529         @SuppressWarnings("checkstyle:parameternumber")
530         private List<InterimResult> build(
531                 Map<File, MavenProject> projectIndex,
532                 List<File> pomFiles,
533                 Set<File> aggregatorFiles,
534                 boolean root,
535                 boolean recursive) {
536             List<Callable<InterimResult>> tasks = pomFiles.stream()
537                     .map(pomFile -> ((Callable<InterimResult>)
538                             () -> build(projectIndex, pomFile, concat(aggregatorFiles, pomFile), root, recursive)))
539                     .collect(Collectors.toList());
540             try {
541                 List<Future<InterimResult>> futures = executor.invokeAll(tasks);
542                 List<InterimResult> list = new ArrayList<>();
543                 for (Future<InterimResult> future : futures) {
544                     InterimResult interimResult = future.get();
545                     list.add(interimResult);
546                 }
547                 return list;
548             } catch (Exception e) {
549                 throw new RuntimeException(e);
550             }
551         }
552 
553         private <T> Set<T> concat(Set<T> set, T elem) {
554             Set<T> newSet = new HashSet<>(set);
555             newSet.add(elem);
556             return newSet;
557         }
558 
559         @SuppressWarnings("checkstyle:parameternumber")
560         private InterimResult build(
561                 Map<File, MavenProject> projectIndex,
562                 File pomFile,
563                 Set<File> aggregatorFiles,
564                 boolean isRoot,
565                 boolean recursive) {
566             MavenProject project = new MavenProject();
567             project.setFile(pomFile);
568 
569             project.setRootDirectory(
570                     rootLocator.findRoot(pomFile.getParentFile().toPath()));
571 
572             DefaultModelBuildingListener listener =
573                     new DefaultModelBuildingListener(project, projectBuildingHelper, request);
574 
575             ModelBuilderRequest modelBuildingRequest = getModelBuildingRequest()
576                     .source(ModelSource.fromPath(pomFile.toPath()))
577                     .projectBuild(true)
578                     .twoPhaseBuilding(true)
579                     .locationTracking(true)
580                     .listener(listener)
581                     .build();
582 
583             ModelBuilderResult result;
584             try {
585                 result = modelBuilder.build(modelBuildingRequest);
586             } catch (ModelBuilderException e) {
587                 result = e.getResult();
588                 if (result == null || result.getFileModel() == null) {
589                     return new InterimResult(
590                             modelBuildingRequest,
591                             new DefaultProjectBuildingResult(e.getModelId(), pomFile, convert(e.getProblems())));
592                 }
593                 // validation error, continue project building and delay failing to help IDEs
594                 // result.getProblems().addAll(e.getProblems()) ?
595             }
596 
597             Model model = result.getActivatedFileModel();
598 
599             modelPool.put(model.getPomFile(), model);
600 
601             InterimResult interimResult = new InterimResult(pomFile, modelBuildingRequest, result, project, isRoot);
602 
603             if (recursive) {
604                 File basedir = pomFile.getParentFile();
605                 List<File> moduleFiles = new ArrayList<>();
606                 for (String module : model.getModules()) {
607                     if (module == null || module.isEmpty()) {
608                         continue;
609                     }
610 
611                     module = module.replace('\\', File.separatorChar).replace('/', File.separatorChar);
612 
613                     Path modulePath = modelProcessor.locateExistingPom(new File(basedir, module).toPath());
614                     File moduleFile = modulePath != null ? modulePath.toFile() : null;
615 
616                     if (moduleFile == null) {
617                         ModelProblem problem = new org.apache.maven.internal.impl.model.DefaultModelProblem(
618                                 "Child module " + moduleFile + " of " + pomFile + " does not exist",
619                                 ModelProblem.Severity.ERROR,
620                                 ModelProblem.Version.BASE,
621                                 model,
622                                 -1,
623                                 -1,
624                                 null);
625                         result.getProblems().add(problem);
626                         continue;
627                     }
628 
629                     if (Os.IS_WINDOWS) {
630                         // we don't canonicalize on unix to avoid interfering with symlinks
631                         try {
632                             moduleFile = moduleFile.getCanonicalFile();
633                         } catch (IOException e) {
634                             moduleFile = moduleFile.getAbsoluteFile();
635                         }
636                     } else {
637                         moduleFile = new File(moduleFile.toURI().normalize());
638                     }
639 
640                     if (aggregatorFiles.contains(moduleFile)) {
641                         StringBuilder buffer = new StringBuilder(256);
642                         for (File aggregatorFile : aggregatorFiles) {
643                             buffer.append(aggregatorFile).append(" -> ");
644                         }
645                         buffer.append(moduleFile);
646 
647                         ModelProblem problem = new org.apache.maven.internal.impl.model.DefaultModelProblem(
648                                 "Child module " + moduleFile + " of " + pomFile + " forms aggregation cycle " + buffer,
649                                 ModelProblem.Severity.ERROR,
650                                 ModelProblem.Version.BASE,
651                                 model,
652                                 -1,
653                                 -1,
654                                 null);
655                         result.getProblems().add(problem);
656 
657                         continue;
658                     }
659 
660                     moduleFiles.add(moduleFile);
661                 }
662 
663                 if (!moduleFiles.isEmpty()) {
664                     interimResult.modules = build(projectIndex, moduleFiles, aggregatorFiles, false, recursive);
665                 }
666             }
667 
668             projectIndex.put(pomFile, project);
669 
670             return interimResult;
671         }
672 
673         private List<ProjectBuildingResult> build(
674                 Map<File, MavenProject> projectIndex, List<InterimResult> interimResults) {
675             // The transformation may need to access dependencies raw models,
676             // which may cause some re-entrance in the build() method and can
677             // actually cause deadlocks.  In order to workaround the problem,
678             // we do a first pass by reading all rawModels in order.
679             List<ProjectBuildingResult> results = new ArrayList<>();
680             boolean failure = false;
681             for (InterimResult r : interimResults) {
682                 DefaultProjectBuildingResult res;
683                 try {
684                     Model model = modelBuilder.buildRawModel(r.request);
685                     res = new DefaultProjectBuildingResult(
686                             model.getId(),
687                             model.getPomFile() != null ? model.getPomFile().toFile() : null,
688                             null);
689                 } catch (ModelBuilderException e) {
690                     failure = true;
691                     res = new DefaultProjectBuildingResult(
692                             e.getModelId(),
693                             r.request.getSource().getPath() != null
694                                     ? r.request.getSource().getPath().toFile()
695                                     : null,
696                             convert(e.getProblems()));
697                 }
698                 results.add(res);
699             }
700             if (failure) {
701                 return results;
702             }
703 
704             List<Callable<List<ProjectBuildingResult>>> callables = interimResults.stream()
705                     .map(interimResult ->
706                             (Callable<List<ProjectBuildingResult>>) () -> doBuild(projectIndex, interimResult))
707                     .collect(Collectors.toList());
708 
709             try {
710                 List<Future<List<ProjectBuildingResult>>> futures = executor.invokeAll(callables);
711                 return futures.stream()
712                         .map(listFuture -> {
713                             try {
714                                 return listFuture.get();
715                             } catch (InterruptedException e) {
716                                 uncheckedThrow(e);
717                                 return null;
718                             } catch (ExecutionException e) {
719                                 uncheckedThrow(e.getCause());
720                                 return null;
721                             }
722                         })
723                         .flatMap(List::stream)
724                         .collect(Collectors.toList());
725             } catch (InterruptedException e) {
726                 uncheckedThrow(e);
727                 return null;
728             }
729         }
730 
731         private List<ProjectBuildingResult> doBuild(Map<File, MavenProject> projectIndex, InterimResult interimResult) {
732             if (interimResult.projectBuildingResult != null) {
733                 return Collections.singletonList(interimResult.projectBuildingResult);
734             }
735             MavenProject project = interimResult.project;
736             try {
737                 ModelBuilderResult result = modelBuilder.build(ModelBuilderRequest.builder(interimResult.request)
738                         .interimResult(interimResult.result)
739                         .build());
740 
741                 // 2nd pass of initialization: resolve and build parent if necessary
742                 List<org.apache.maven.model.building.ModelProblem> problems = convert(result.getProblems());
743                 try {
744                     initProject(project, projectIndex, result);
745                 } catch (InvalidArtifactRTException iarte) {
746                     problems.add(new DefaultModelProblem(
747                             null,
748                             org.apache.maven.model.building.ModelProblem.Severity.ERROR,
749                             null,
750                             new org.apache.maven.model.Model(result.getEffectiveModel()),
751                             -1,
752                             -1,
753                             iarte));
754                 }
755 
756                 List<ProjectBuildingResult> results = build(projectIndex, interimResult.modules);
757 
758                 project.setExecutionRoot(interimResult.root);
759                 project.setCollectedProjects(
760                         results.stream().map(ProjectBuildingResult::getProject).collect(Collectors.toList()));
761                 DependencyResolutionResult resolutionResult = null;
762                 if (request.isResolveDependencies()) {
763                     resolutionResult = resolveDependencies(project);
764                 }
765 
766                 results.add(new DefaultProjectBuildingResult(project, problems, resolutionResult));
767 
768                 return results;
769             } catch (ModelBuilderException e) {
770                 DefaultProjectBuildingResult result;
771                 if (project == null || interimResult.result.getEffectiveModel() == null) {
772                     result = new DefaultProjectBuildingResult(
773                             e.getModelId(), interimResult.pomFile, convert(e.getProblems()));
774                 } else {
775                     project.setModel(new org.apache.maven.model.Model(interimResult.result.getEffectiveModel()));
776                     result = new DefaultProjectBuildingResult(project, convert(e.getProblems()), null);
777                 }
778                 return Collections.singletonList(result);
779             }
780         }
781 
782         private List<org.apache.maven.model.building.ModelProblem> convert(List<ModelProblem> problems) {
783             if (problems == null) {
784                 return null;
785             }
786             return problems.stream()
787                     .map(p -> (org.apache.maven.model.building.ModelProblem) new DefaultModelProblem(
788                             p.getMessage(),
789                             org.apache.maven.model.building.ModelProblem.Severity.valueOf(
790                                     p.getSeverity().name()),
791                             org.apache.maven.model.building.ModelProblem.Version.valueOf(
792                                     p.getVersion().name()),
793                             p.getSource(),
794                             p.getLineNumber(),
795                             p.getColumnNumber(),
796                             p.getModelId(),
797                             p.getException()))
798                     .toList();
799         }
800 
801         @SuppressWarnings({"checkstyle:methodlength", "deprecation"})
802         private void initProject(MavenProject project, Map<File, MavenProject> projects, ModelBuilderResult result) {
803             project.setModel(new org.apache.maven.model.Model(result.getEffectiveModel()));
804             project.setOriginalModel(new org.apache.maven.model.Model(result.getFileModel()));
805 
806             initParent(project, projects, result);
807 
808             Artifact projectArtifact = repositorySystem.createArtifact(
809                     project.getGroupId(), project.getArtifactId(), project.getVersion(), null, project.getPackaging());
810             project.setArtifact(projectArtifact);
811 
812             // only set those on 2nd phase, ignore on 1st pass
813             if (project.getFile() != null) {
814                 Build build = project.getBuild().getDelegate();
815                 project.addScriptSourceRoot(build.getScriptSourceDirectory());
816                 project.addCompileSourceRoot(build.getSourceDirectory());
817                 project.addTestCompileSourceRoot(build.getTestSourceDirectory());
818             }
819 
820             project.setActiveProfiles(Stream.concat(
821                             result.getActivePomProfiles(result.getModelIds().get(0)).stream(),
822                             result.getActiveExternalProfiles().stream())
823                     .map(org.apache.maven.model.Profile::new)
824                     .toList());
825 
826             project.setInjectedProfileIds("external", getProfileIds(result.getActiveExternalProfiles()));
827             for (String modelId : result.getModelIds()) {
828                 project.setInjectedProfileIds(modelId, getProfileIds(result.getActivePomProfiles(modelId)));
829             }
830 
831             //
832             // All the parts that were taken out of MavenProject for Maven 4.0.0
833             //
834 
835             project.setProjectBuildingRequest(request);
836 
837             // pluginArtifacts
838             Set<Artifact> pluginArtifacts = new HashSet<>();
839             for (Plugin plugin : project.getModel().getDelegate().getBuild().getPlugins()) {
840                 Artifact artifact = repositorySystem.createPluginArtifact(new org.apache.maven.model.Plugin(plugin));
841 
842                 if (artifact != null) {
843                     pluginArtifacts.add(artifact);
844                 }
845             }
846             project.setPluginArtifacts(pluginArtifacts);
847 
848             // reportArtifacts
849             Set<Artifact> reportArtifacts = new HashSet<>();
850             for (ReportPlugin report :
851                     project.getModel().getDelegate().getReporting().getPlugins()) {
852                 Plugin pp = Plugin.newBuilder()
853                         .groupId(report.getGroupId())
854                         .artifactId(report.getArtifactId())
855                         .version(report.getVersion())
856                         .build();
857 
858                 Artifact artifact = repositorySystem.createPluginArtifact(new org.apache.maven.model.Plugin(pp));
859 
860                 if (artifact != null) {
861                     reportArtifacts.add(artifact);
862                 }
863             }
864             project.setReportArtifacts(reportArtifacts);
865 
866             // extensionArtifacts
867             Set<Artifact> extensionArtifacts = new HashSet<>();
868             List<Extension> extensions =
869                     project.getModel().getDelegate().getBuild().getExtensions();
870             if (extensions != null) {
871                 for (Extension ext : extensions) {
872                     String version;
873                     if (ext.getVersion() == null || ext.getVersion().isEmpty()) {
874                         version = "RELEASE";
875                     } else {
876                         version = ext.getVersion();
877                     }
878 
879                     Artifact artifact = repositorySystem.createArtifact(
880                             ext.getGroupId(), ext.getArtifactId(), version, null, "jar");
881 
882                     if (artifact != null) {
883                         extensionArtifacts.add(artifact);
884                     }
885                 }
886             }
887             project.setExtensionArtifacts(extensionArtifacts);
888 
889             // managedVersionMap
890             Map<String, Artifact> map = Collections.emptyMap();
891             final DependencyManagement dependencyManagement =
892                     project.getModel().getDelegate().getDependencyManagement();
893             if (dependencyManagement != null
894                     && dependencyManagement.getDependencies() != null
895                     && !dependencyManagement.getDependencies().isEmpty()) {
896                 map = new LazyMap<>(() -> {
897                     Map<String, Artifact> tmp = new HashMap<>();
898                     for (Dependency d : dependencyManagement.getDependencies()) {
899                         Artifact artifact =
900                                 repositorySystem.createDependencyArtifact(new org.apache.maven.model.Dependency(d));
901                         if (artifact != null) {
902                             tmp.put(d.getManagementKey(), artifact);
903                         }
904                     }
905                     return Collections.unmodifiableMap(tmp);
906                 });
907             }
908             project.setManagedVersionMap(map);
909 
910             // release artifact repository
911             if (project.getDistributionManagement() != null
912                     && project.getDistributionManagement().getRepository() != null) {
913                 try {
914                     DeploymentRepository r = project.getModel()
915                             .getDelegate()
916                             .getDistributionManagement()
917                             .getRepository();
918                     if (r.getId() != null
919                             && !r.getId().isEmpty()
920                             && r.getUrl() != null
921                             && !r.getUrl().isEmpty()) {
922                         ArtifactRepository repo = MavenRepositorySystem.buildArtifactRepository(
923                                 new org.apache.maven.model.DeploymentRepository(r));
924                         repositorySystem.injectProxy(request.getRepositorySession(), List.of(repo));
925                         repositorySystem.injectAuthentication(request.getRepositorySession(), List.of(repo));
926                         project.setReleaseArtifactRepository(repo);
927                     }
928                 } catch (InvalidRepositoryException e) {
929                     throw new IllegalStateException(
930                             "Failed to create release distribution repository for " + project.getId(), e);
931                 }
932             }
933 
934             // snapshot artifact repository
935             if (project.getDistributionManagement() != null
936                     && project.getDistributionManagement().getSnapshotRepository() != null) {
937                 try {
938                     DeploymentRepository r = project.getModel()
939                             .getDelegate()
940                             .getDistributionManagement()
941                             .getSnapshotRepository();
942                     if (r.getId() != null
943                             && !r.getId().isEmpty()
944                             && r.getUrl() != null
945                             && !r.getUrl().isEmpty()) {
946                         ArtifactRepository repo = MavenRepositorySystem.buildArtifactRepository(
947                                 new org.apache.maven.model.DeploymentRepository(r));
948                         repositorySystem.injectProxy(request.getRepositorySession(), List.of(repo));
949                         repositorySystem.injectAuthentication(request.getRepositorySession(), List.of(repo));
950                         project.setSnapshotArtifactRepository(repo);
951                     }
952                 } catch (InvalidRepositoryException e) {
953                     throw new IllegalStateException(
954                             "Failed to create snapshot distribution repository for " + project.getId(), e);
955                 }
956             }
957         }
958 
959         private void initParent(MavenProject project, Map<File, MavenProject> projects, ModelBuilderResult result) {
960             Model parentModel = result.getModelIds().size() > 1
961                             && !result.getModelIds().get(1).isEmpty()
962                     ? result.getRawModel(result.getModelIds().get(1)).orElse(null)
963                     : null;
964 
965             if (parentModel != null) {
966                 final String parentGroupId = inheritedGroupId(result, 1);
967                 final String parentVersion = inheritedVersion(result, 1);
968 
969                 project.setParentArtifact(repositorySystem.createProjectArtifact(
970                         parentGroupId, parentModel.getArtifactId(), parentVersion));
971 
972                 // org.apache.maven.its.mng4834:parent:0.1
973                 String parentModelId = result.getModelIds().get(1);
974                 Path parentPomFile =
975                         result.getRawModel(parentModelId).map(Model::getPomFile).orElse(null);
976                 MavenProject parent = parentPomFile != null ? projects.get(parentPomFile.toFile()) : null;
977                 if (parent == null) {
978                     //
979                     // At this point the DefaultModelBuildingListener has fired and it populates the
980                     // remote repositories with those found in the pom.xml, along with the existing externally
981                     // defined repositories.
982                     //
983                     request.setRemoteRepositories(project.getRemoteArtifactRepositories());
984                     if (parentPomFile != null) {
985                         project.setParentFile(parentPomFile.toFile());
986                         try {
987                             parent = build(parentPomFile, ModelSource.fromPath(parentPomFile))
988                                     .getProject();
989                         } catch (ProjectBuildingException e) {
990                             // MNG-4488 where let invalid parents slide on by
991                             if (logger.isDebugEnabled()) {
992                                 // Message below is checked for in the MNG-2199 core IT.
993                                 logger.warn("Failed to build parent project for " + project.getId(), e);
994                             } else {
995                                 // Message below is checked for in the MNG-2199 core IT.
996                                 logger.warn("Failed to build parent project for " + project.getId());
997                             }
998                         }
999                     } else {
1000                         Artifact parentArtifact = project.getParentArtifact();
1001                         try {
1002                             parent = build(parentArtifact, false).getProject();
1003                         } catch (ProjectBuildingException e) {
1004                             // MNG-4488 where let invalid parents slide on by
1005                             if (logger.isDebugEnabled()) {
1006                                 // Message below is checked for in the MNG-2199 core IT.
1007                                 logger.warn("Failed to build parent project for " + project.getId(), e);
1008                             } else {
1009                                 // Message below is checked for in the MNG-2199 core IT.
1010                                 logger.warn("Failed to build parent project for " + project.getId());
1011                             }
1012                         }
1013                     }
1014                 }
1015                 project.setParent(parent);
1016                 if (project.getParentFile() == null && parent != null) {
1017                     project.setParentFile(parent.getFile());
1018                 }
1019             }
1020         }
1021 
1022         private ModelBuilderRequest.ModelBuilderRequestBuilder getModelBuildingRequest() {
1023             ModelBuilderRequest.ModelBuilderRequestBuilder modelBuildingRequest = ModelBuilderRequest.builder();
1024 
1025             InternalSession internalSession = InternalSession.from(session);
1026             modelBuildingRequest.session(internalSession.withRemoteRepositories(request.getRemoteRepositories().stream()
1027                     .map(r -> internalSession.getRemoteRepository(RepositoryUtils.toRepo(r)))
1028                     .toList()));
1029             modelBuildingRequest.validationLevel(request.getValidationLevel());
1030             modelBuildingRequest.processPlugins(request.isProcessPlugins());
1031             modelBuildingRequest.profiles(
1032                     request.getProfiles() != null
1033                             ? request.getProfiles().stream()
1034                                     .map(org.apache.maven.model.Profile::getDelegate)
1035                                     .toList()
1036                             : null);
1037             modelBuildingRequest.activeProfileIds(request.getActiveProfileIds());
1038             modelBuildingRequest.inactiveProfileIds(request.getInactiveProfileIds());
1039             modelBuildingRequest.systemProperties(toMap(request.getSystemProperties()));
1040             modelBuildingRequest.userProperties(toMap(request.getUserProperties()));
1041             // bv4: modelBuildingRequest.setBuildStartTime(request.getBuildStartTime());
1042             modelBuildingRequest.modelResolver(modelResolver);
1043             DefaultModelRepositoryHolder holder = new DefaultModelRepositoryHolder(
1044                     internalSession,
1045                     DefaultModelRepositoryHolder.RepositoryMerging.valueOf(
1046                             request.getRepositoryMerging().name()),
1047                     repositories.stream()
1048                             .map(internalSession::getRemoteRepository)
1049                             .toList());
1050             modelBuildingRequest.modelRepositoryHolder(holder);
1051             modelBuildingRequest.modelCache(modelCache);
1052             modelBuildingRequest.transformerContextBuilder(transformerContextBuilder);
1053             /* TODO: bv4
1054             InternalMavenSession session =
1055                     (InternalMavenSession) this.session.getData().get(InternalMavenSession.class);
1056             if (session != null) {
1057                 try {
1058                     modelBuildingRequest.setRootDirectory(session.getRootDirectory());
1059                 } catch (IllegalStateException e) {
1060                     // can happen if root directory cannot be found, just ignore
1061                 }
1062             }
1063             */
1064             internalSession.getData().set(SessionData.key(ModelResolver.class), modelResolver);
1065 
1066             return modelBuildingRequest;
1067         }
1068 
1069         private DependencyResolutionResult resolveDependencies(MavenProject project) {
1070             DependencyResolutionResult resolutionResult;
1071 
1072             try {
1073                 DefaultDependencyResolutionRequest resolution =
1074                         new DefaultDependencyResolutionRequest(project, session);
1075                 resolutionResult = dependencyResolver.resolve(resolution);
1076             } catch (DependencyResolutionException e) {
1077                 resolutionResult = e.getResult();
1078             }
1079 
1080             Set<Artifact> artifacts = new LinkedHashSet<>();
1081             if (resolutionResult.getDependencyGraph() != null) {
1082                 RepositoryUtils.toArtifacts(
1083                         artifacts,
1084                         resolutionResult.getDependencyGraph().getChildren(),
1085                         Collections.singletonList(project.getArtifact().getId()),
1086                         null);
1087 
1088                 // Maven 2.x quirk: an artifact always points at the local repo, regardless whether resolved or not
1089                 LocalRepositoryManager lrm = session.getLocalRepositoryManager();
1090                 for (Artifact artifact : artifacts) {
1091                     if (!artifact.isResolved()) {
1092                         String path = lrm.getPathForLocalArtifact(RepositoryUtils.toArtifact(artifact));
1093                         artifact.setFile(
1094                                 lrm.getRepository().getBasePath().resolve(path).toFile());
1095                     }
1096                 }
1097             }
1098             project.setResolvedArtifacts(artifacts);
1099             project.setArtifacts(artifacts);
1100 
1101             return resolutionResult;
1102         }
1103     }
1104 
1105     private List<String> getProfileIds(List<Profile> profiles) {
1106         return profiles.stream().map(Profile::getId).collect(Collectors.toList());
1107     }
1108 
1109     private static ModelSource createStubModelSource(Artifact artifact) {
1110         StringBuilder buffer = new StringBuilder(1024);
1111 
1112         buffer.append("<?xml version='1.0'?>");
1113         buffer.append("<project>");
1114         buffer.append("<modelVersion>4.0.0</modelVersion>");
1115         buffer.append("<groupId>").append(artifact.getGroupId()).append("</groupId>");
1116         buffer.append("<artifactId>").append(artifact.getArtifactId()).append("</artifactId>");
1117         buffer.append("<version>").append(artifact.getBaseVersion()).append("</version>");
1118         buffer.append("<packaging>").append(artifact.getType()).append("</packaging>");
1119         buffer.append("</project>");
1120 
1121         return new ModelSource() {
1122             @Override
1123             public ModelSource resolve(ModelLocator modelLocator, String relative) {
1124                 return null;
1125             }
1126 
1127             @Override
1128             public Path getPath() {
1129                 return null;
1130             }
1131 
1132             @Override
1133             public InputStream openStream() throws IOException {
1134                 return new ByteArrayInputStream(buffer.toString().getBytes(StandardCharsets.UTF_8));
1135             }
1136 
1137             @Override
1138             public String getLocation() {
1139                 return artifact.getId();
1140             }
1141 
1142             @Override
1143             public Source resolve(String relative) {
1144                 return null;
1145             }
1146         };
1147     }
1148 
1149     private static String inheritedGroupId(final ModelBuilderResult result, final int modelIndex) {
1150         String groupId = null;
1151         final String modelId = result.getModelIds().get(modelIndex);
1152 
1153         if (!modelId.isEmpty()) {
1154             final Model model = result.getRawModel(modelId).orElseThrow();
1155             groupId = model.getGroupId() != null ? model.getGroupId() : inheritedGroupId(result, modelIndex + 1);
1156         }
1157 
1158         return groupId;
1159     }
1160 
1161     private static String inheritedVersion(final ModelBuilderResult result, final int modelIndex) {
1162         String version = null;
1163         final String modelId = result.getModelIds().get(modelIndex);
1164 
1165         if (!modelId.isEmpty()) {
1166             version = result.getRawModel(modelId).map(Model::getVersion).orElse(null);
1167             if (version == null) {
1168                 version = inheritedVersion(result, modelIndex + 1);
1169             }
1170         }
1171 
1172         return version;
1173     }
1174 
1175     private static Map<String, String> toMap(Properties properties) {
1176         if (properties != null && !properties.isEmpty()) {
1177             return properties.entrySet().stream()
1178                     .collect(Collectors.toMap(e -> String.valueOf(e.getKey()), e -> String.valueOf(e.getValue())));
1179 
1180         } else {
1181             return null;
1182         }
1183     }
1184 
1185     @SuppressWarnings("unchecked")
1186     static <T extends Throwable> void uncheckedThrow(Throwable t) throws T {
1187         throw (T) t; // rely on vacuous cast
1188     }
1189 
1190     static class LazyMap<K, V> extends AbstractMap<K, V> {
1191         private final Supplier<Map<K, V>> supplier;
1192         private volatile Map<K, V> delegate;
1193 
1194         LazyMap(Supplier<Map<K, V>> supplier) {
1195             this.supplier = supplier;
1196         }
1197 
1198         @Override
1199         public Set<Entry<K, V>> entrySet() {
1200             if (delegate == null) {
1201                 synchronized (this) {
1202                     if (delegate == null) {
1203                         delegate = supplier.get();
1204                     }
1205                 }
1206             }
1207             return delegate.entrySet();
1208         }
1209     }
1210 
1211     protected abstract class ModelResolverWrapper implements ModelResolver {
1212 
1213         protected abstract org.apache.maven.model.resolution.ModelResolver getResolver(
1214                 List<RemoteRepository> repositories);
1215 
1216         @Override
1217         public ModelSource resolveModel(
1218                 Session session, String groupId, String artifactId, String version, Consumer<String> resolved)
1219                 throws ModelResolverException {
1220             try {
1221                 InternalSession internalSession = InternalSession.from(session);
1222                 org.apache.maven.model.resolution.ModelResolver resolver =
1223                         getResolver(internalSession.toRepositories(internalSession.getRemoteRepositories()));
1224                 org.apache.maven.model.Parent p = new org.apache.maven.model.Parent(Parent.newBuilder()
1225                         .groupId(groupId)
1226                         .artifactId(artifactId)
1227                         .version(version)
1228                         .build());
1229                 org.apache.maven.model.building.ModelSource modelSource = resolver.resolveModel(p);
1230                 if (!p.getVersion().equals(version)) {
1231                     resolved.accept(p.getVersion());
1232                 }
1233                 return toSource(modelSource);
1234             } catch (UnresolvableModelException e) {
1235                 throw new ModelResolverException(e.getMessage(), e.getGroupId(), e.getArtifactId(), e.getVersion(), e);
1236             }
1237         }
1238 
1239         @Override
1240         public ModelSource resolveModel(Session session, Parent parent, AtomicReference<Parent> modified)
1241                 throws ModelResolverException {
1242             try {
1243                 org.apache.maven.model.Parent p = new org.apache.maven.model.Parent(parent);
1244                 InternalSession internalSession = InternalSession.from(session);
1245                 org.apache.maven.model.resolution.ModelResolver resolver =
1246                         getResolver(internalSession.toRepositories(internalSession.getRemoteRepositories()));
1247                 ModelSource source = toSource(resolver.resolveModel(p));
1248                 if (p.getDelegate() != parent) {
1249                     modified.set(p.getDelegate());
1250                 }
1251                 return source;
1252             } catch (UnresolvableModelException e) {
1253                 throw new ModelResolverException(e.getMessage(), e.getGroupId(), e.getArtifactId(), e.getVersion(), e);
1254             }
1255         }
1256 
1257         @Override
1258         public ModelSource resolveModel(Session session, Dependency dependency, AtomicReference<Dependency> modified)
1259                 throws ModelResolverException {
1260             try {
1261                 org.apache.maven.model.Dependency d = new org.apache.maven.model.Dependency(dependency);
1262                 InternalSession internalSession = InternalSession.from(session);
1263                 org.apache.maven.model.resolution.ModelResolver resolver =
1264                         getResolver(internalSession.toRepositories(internalSession.getRemoteRepositories()));
1265                 ModelSource source = toSource(resolver.resolveModel(d));
1266                 if (d.getDelegate() != dependency) {
1267                     modified.set(d.getDelegate());
1268                 }
1269                 return source;
1270             } catch (UnresolvableModelException e) {
1271                 throw new ModelResolverException(e.getMessage(), e.getGroupId(), e.getArtifactId(), e.getVersion(), e);
1272             }
1273         }
1274     }
1275 }