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.File;
26  import java.io.IOException;
27  import java.util.*;
28  import java.util.stream.Collectors;
29  
30  import org.apache.maven.RepositoryUtils;
31  import org.apache.maven.api.feature.Features;
32  import org.apache.maven.artifact.Artifact;
33  import org.apache.maven.artifact.InvalidArtifactRTException;
34  import org.apache.maven.artifact.InvalidRepositoryException;
35  import org.apache.maven.artifact.repository.ArtifactRepository;
36  import org.apache.maven.bridge.MavenRepositorySystem;
37  import org.apache.maven.internal.impl.DefaultSession;
38  import org.apache.maven.model.Build;
39  import org.apache.maven.model.Dependency;
40  import org.apache.maven.model.DependencyManagement;
41  import org.apache.maven.model.DeploymentRepository;
42  import org.apache.maven.model.Extension;
43  import org.apache.maven.model.Model;
44  import org.apache.maven.model.Plugin;
45  import org.apache.maven.model.Profile;
46  import org.apache.maven.model.ReportPlugin;
47  import org.apache.maven.model.building.ArtifactModelSource;
48  import org.apache.maven.model.building.DefaultModelBuildingRequest;
49  import org.apache.maven.model.building.DefaultModelProblem;
50  import org.apache.maven.model.building.FileModelSource;
51  import org.apache.maven.model.building.ModelBuilder;
52  import org.apache.maven.model.building.ModelBuildingException;
53  import org.apache.maven.model.building.ModelBuildingRequest;
54  import org.apache.maven.model.building.ModelBuildingResult;
55  import org.apache.maven.model.building.ModelProblem;
56  import org.apache.maven.model.building.ModelProcessor;
57  import org.apache.maven.model.building.ModelSource;
58  import org.apache.maven.model.building.StringModelSource;
59  import org.apache.maven.model.building.TransformerContext;
60  import org.apache.maven.model.building.TransformerContextBuilder;
61  import org.apache.maven.model.resolution.ModelResolver;
62  import org.apache.maven.model.root.RootLocator;
63  import org.apache.maven.repository.internal.ArtifactDescriptorUtils;
64  import org.apache.maven.repository.internal.ModelCacheFactory;
65  import org.apache.maven.utils.Os;
66  import org.eclipse.aether.RepositorySystem;
67  import org.eclipse.aether.RepositorySystemSession;
68  import org.eclipse.aether.RequestTrace;
69  import org.eclipse.aether.impl.RemoteRepositoryManager;
70  import org.eclipse.aether.repository.LocalRepositoryManager;
71  import org.eclipse.aether.repository.RemoteRepository;
72  import org.eclipse.aether.repository.WorkspaceRepository;
73  import org.eclipse.aether.resolution.ArtifactRequest;
74  import org.eclipse.aether.resolution.ArtifactResult;
75  import org.slf4j.Logger;
76  import org.slf4j.LoggerFactory;
77  
78  /**
79   * DefaultProjectBuilder
80   */
81  @Named
82  @Singleton
83  public class DefaultProjectBuilder implements ProjectBuilder {
84  
85      private final Logger logger = LoggerFactory.getLogger(getClass());
86      private final ModelBuilder modelBuilder;
87      private final ModelProcessor modelProcessor;
88      private final ProjectBuildingHelper projectBuildingHelper;
89      private final MavenRepositorySystem repositorySystem;
90      private final org.eclipse.aether.RepositorySystem repoSystem;
91      private final RemoteRepositoryManager repositoryManager;
92      private final ProjectDependenciesResolver dependencyResolver;
93      private final ModelCacheFactory modelCacheFactory;
94  
95      private final RootLocator rootLocator;
96  
97      @SuppressWarnings("checkstyle:ParameterNumber")
98      @Inject
99      public DefaultProjectBuilder(
100             ModelBuilder modelBuilder,
101             ModelProcessor modelProcessor,
102             ProjectBuildingHelper projectBuildingHelper,
103             MavenRepositorySystem repositorySystem,
104             RepositorySystem repoSystem,
105             RemoteRepositoryManager repositoryManager,
106             ProjectDependenciesResolver dependencyResolver,
107             ModelCacheFactory modelCacheFactory,
108             RootLocator rootLocator) {
109         this.modelBuilder = modelBuilder;
110         this.modelProcessor = modelProcessor;
111         this.projectBuildingHelper = projectBuildingHelper;
112         this.repositorySystem = repositorySystem;
113         this.repoSystem = repoSystem;
114         this.repositoryManager = repositoryManager;
115         this.dependencyResolver = dependencyResolver;
116         this.modelCacheFactory = modelCacheFactory;
117         this.rootLocator = rootLocator;
118     }
119     // ----------------------------------------------------------------------
120     // MavenProjectBuilder Implementation
121     // ----------------------------------------------------------------------
122 
123     @Override
124     public ProjectBuildingResult build(File pomFile, ProjectBuildingRequest request) throws ProjectBuildingException {
125         InternalConfig config = new InternalConfig(request, null, modelBuilder.newTransformerContextBuilder());
126         return build(pomFile, new FileModelSource(pomFile), config);
127     }
128 
129     @Override
130     public ProjectBuildingResult build(ModelSource modelSource, ProjectBuildingRequest request)
131             throws ProjectBuildingException {
132         return build(null, modelSource, new InternalConfig(request, null, null));
133     }
134 
135     private ProjectBuildingResult build(File pomFile, ModelSource modelSource, InternalConfig config)
136             throws ProjectBuildingException {
137         ClassLoader oldContextClassLoader = Thread.currentThread().getContextClassLoader();
138 
139         try {
140             ProjectBuildingRequest projectBuildingRequest = config.request;
141 
142             MavenProject project = projectBuildingRequest.getProject();
143 
144             List<ModelProblem> modelProblems = null;
145             Throwable error = null;
146 
147             if (project == null) {
148                 ModelBuildingRequest request = getModelBuildingRequest(config);
149 
150                 project = new MavenProject();
151                 project.setFile(pomFile);
152 
153                 DefaultModelBuildingListener listener =
154                         new DefaultModelBuildingListener(project, projectBuildingHelper, projectBuildingRequest);
155 
156                 request.setModelBuildingListener(listener);
157 
158                 request.setPomFile(pomFile);
159                 request.setModelSource(modelSource);
160                 request.setLocationTracking(true);
161 
162                 if (pomFile != null) {
163                     project.setRootDirectory(
164                             rootLocator.findRoot(pomFile.getParentFile().toPath()));
165                 }
166 
167                 ModelBuildingResult result;
168                 try {
169                     result = modelBuilder.build(request);
170                 } catch (ModelBuildingException e) {
171                     result = e.getResult();
172                     if (result == null || result.getEffectiveModel() == null) {
173                         throw new ProjectBuildingException(e.getModelId(), e.getMessage(), pomFile, e);
174                     }
175                     // validation error, continue project building and delay failing to help IDEs
176                     error = e;
177                 }
178 
179                 modelProblems = result.getProblems();
180 
181                 initProject(project, Collections.emptyMap(), true, result, new HashMap<>(), projectBuildingRequest);
182             } else if (projectBuildingRequest.isResolveDependencies()) {
183                 projectBuildingHelper.selectProjectRealm(project);
184             }
185 
186             DependencyResolutionResult resolutionResult = null;
187 
188             if (projectBuildingRequest.isResolveDependencies()) {
189                 resolutionResult = resolveDependencies(project, config.session);
190             }
191 
192             ProjectBuildingResult result = new DefaultProjectBuildingResult(project, modelProblems, resolutionResult);
193 
194             if (error != null) {
195                 ProjectBuildingException e = new ProjectBuildingException(Arrays.asList(result));
196                 e.initCause(error);
197                 throw e;
198             }
199 
200             return result;
201         } finally {
202             Thread.currentThread().setContextClassLoader(oldContextClassLoader);
203         }
204     }
205 
206     private DependencyResolutionResult resolveDependencies(MavenProject project, RepositorySystemSession session) {
207         DependencyResolutionResult resolutionResult;
208 
209         try {
210             DefaultDependencyResolutionRequest resolution = new DefaultDependencyResolutionRequest(project, session);
211             resolutionResult = dependencyResolver.resolve(resolution);
212         } catch (DependencyResolutionException e) {
213             resolutionResult = e.getResult();
214         }
215 
216         Set<Artifact> artifacts = new LinkedHashSet<>();
217         if (resolutionResult.getDependencyGraph() != null) {
218             RepositoryUtils.toArtifacts(
219                     artifacts,
220                     resolutionResult.getDependencyGraph().getChildren(),
221                     Collections.singletonList(project.getArtifact().getId()),
222                     null);
223 
224             // Maven 2.x quirk: an artifact always points at the local repo, regardless whether resolved or not
225             LocalRepositoryManager lrm = session.getLocalRepositoryManager();
226             for (Artifact artifact : artifacts) {
227                 if (!artifact.isResolved()) {
228                     String path = lrm.getPathForLocalArtifact(RepositoryUtils.toArtifact(artifact));
229                     artifact.setFile(new File(lrm.getRepository().getBasedir(), path));
230                 }
231             }
232         }
233         project.setResolvedArtifacts(artifacts);
234         project.setArtifacts(artifacts);
235 
236         return resolutionResult;
237     }
238 
239     private List<String> getProfileIds(List<org.apache.maven.model.Profile> profiles) {
240         return profiles.stream().map(org.apache.maven.model.Profile::getId).collect(Collectors.toList());
241     }
242 
243     private ModelBuildingRequest getModelBuildingRequest(InternalConfig config) {
244         ProjectBuildingRequest configuration = config.request;
245 
246         ModelBuildingRequest request = new DefaultModelBuildingRequest();
247 
248         RequestTrace trace = RequestTrace.newChild(null, configuration).newChild(request);
249 
250         ModelResolver resolver = new ProjectModelResolver(
251                 config.session,
252                 trace,
253                 repoSystem,
254                 repositoryManager,
255                 config.repositories,
256                 configuration.getRepositoryMerging(),
257                 config.modelPool);
258 
259         request.setValidationLevel(configuration.getValidationLevel());
260         request.setProcessPlugins(configuration.isProcessPlugins());
261         request.setProfiles(configuration.getProfiles());
262         request.setActiveProfileIds(configuration.getActiveProfileIds());
263         request.setInactiveProfileIds(configuration.getInactiveProfileIds());
264         request.setSystemProperties(configuration.getSystemProperties());
265         request.setUserProperties(configuration.getUserProperties());
266         request.setBuildStartTime(configuration.getBuildStartTime());
267         request.setModelResolver(resolver);
268         // this is a hint that we want to build 1 file, so don't cache. See MNG-7063
269         if (config.modelPool != null) {
270             request.setModelCache(modelCacheFactory.createCache(config.session));
271         }
272         request.setTransformerContextBuilder(config.transformerContextBuilder);
273         DefaultSession session = (DefaultSession) config.session.getData().get(DefaultSession.class);
274         if (session != null) {
275             try {
276                 request.setRootDirectory(session.getRootDirectory());
277             } catch (IllegalStateException e) {
278                 // can happen if root directory cannot be found, just ignore
279             }
280         }
281 
282         return request;
283     }
284 
285     @Override
286     public ProjectBuildingResult build(Artifact artifact, ProjectBuildingRequest request)
287             throws ProjectBuildingException {
288         return build(artifact, false, request);
289     }
290 
291     @Override
292     public ProjectBuildingResult build(Artifact artifact, boolean allowStubModel, ProjectBuildingRequest request)
293             throws ProjectBuildingException {
294         org.eclipse.aether.artifact.Artifact pomArtifact = RepositoryUtils.toArtifact(artifact);
295         pomArtifact = ArtifactDescriptorUtils.toPomArtifact(pomArtifact);
296 
297         InternalConfig config = new InternalConfig(request, null, null);
298 
299         boolean localProject;
300 
301         try {
302             ArtifactRequest pomRequest = new ArtifactRequest();
303             pomRequest.setArtifact(pomArtifact);
304             pomRequest.setRepositories(config.repositories);
305             ArtifactResult pomResult = repoSystem.resolveArtifact(config.session, pomRequest);
306 
307             pomArtifact = pomResult.getArtifact();
308             localProject = pomResult.getRepository() instanceof WorkspaceRepository;
309         } catch (org.eclipse.aether.resolution.ArtifactResolutionException e) {
310             if (e.getResults().get(0).isMissing() && allowStubModel) {
311                 return build(null, createStubModelSource(artifact), config);
312             }
313             throw new ProjectBuildingException(
314                     artifact.getId(), "Error resolving project artifact: " + e.getMessage(), e);
315         }
316 
317         File pomFile = pomArtifact.getFile();
318 
319         if ("pom".equals(artifact.getType())) {
320             artifact.selectVersion(pomArtifact.getVersion());
321             artifact.setFile(pomFile);
322             artifact.setResolved(true);
323         }
324 
325         if (localProject) {
326             return build(pomFile, new FileModelSource(pomFile), config);
327         } else {
328             return build(
329                     null,
330                     new ArtifactModelSource(
331                             pomFile, artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion()),
332                     config);
333         }
334     }
335 
336     private ModelSource createStubModelSource(Artifact artifact) {
337         StringBuilder buffer = new StringBuilder(1024);
338 
339         buffer.append("<?xml version='1.0'?>");
340         buffer.append("<project>");
341         buffer.append("<modelVersion>4.0.0</modelVersion>");
342         buffer.append("<groupId>").append(artifact.getGroupId()).append("</groupId>");
343         buffer.append("<artifactId>").append(artifact.getArtifactId()).append("</artifactId>");
344         buffer.append("<version>").append(artifact.getBaseVersion()).append("</version>");
345         buffer.append("<packaging>").append(artifact.getType()).append("</packaging>");
346         buffer.append("</project>");
347 
348         return new StringModelSource(buffer.toString(), artifact.getId());
349     }
350 
351     @Override
352     public List<ProjectBuildingResult> build(List<File> pomFiles, boolean recursive, ProjectBuildingRequest request)
353             throws ProjectBuildingException {
354         List<ProjectBuildingResult> results = new ArrayList<>();
355 
356         List<InterimResult> interimResults = new ArrayList<>();
357 
358         ReactorModelPool pool = new ReactorModelPool();
359 
360         InternalConfig config = new InternalConfig(request, pool, modelBuilder.newTransformerContextBuilder());
361 
362         Map<File, MavenProject> projectIndex = new HashMap<>(256);
363 
364         // phase 1: get file Models from the reactor.
365         boolean noErrors = build(
366                 results, interimResults, projectIndex, pomFiles, new LinkedHashSet<>(), true, recursive, config, pool);
367 
368         ClassLoader oldContextClassLoader = Thread.currentThread().getContextClassLoader();
369 
370         try {
371             // Phase 2: get effective models from the reactor
372             noErrors = build(
373                             results,
374                             new ArrayList<>(),
375                             projectIndex,
376                             interimResults,
377                             request,
378                             new HashMap<>(),
379                             config.session)
380                     && noErrors;
381         } finally {
382             Thread.currentThread().setContextClassLoader(oldContextClassLoader);
383         }
384 
385         if (Features.buildConsumer(request.getUserProperties())) {
386             request.getRepositorySession()
387                     .getData()
388                     .set(TransformerContext.KEY, config.transformerContextBuilder.build());
389         }
390 
391         if (!noErrors) {
392             throw new ProjectBuildingException(results);
393         }
394 
395         return results;
396     }
397 
398     @SuppressWarnings("checkstyle:parameternumber")
399     private boolean build(
400             List<ProjectBuildingResult> results,
401             List<InterimResult> interimResults,
402             Map<File, MavenProject> projectIndex,
403             List<File> pomFiles,
404             Set<File> aggregatorFiles,
405             boolean root,
406             boolean recursive,
407             InternalConfig config,
408             ReactorModelPool pool) {
409         boolean noErrors = true;
410 
411         for (File pomFile : pomFiles) {
412             aggregatorFiles.add(pomFile);
413 
414             if (!build(
415                     results, interimResults, projectIndex, pomFile, aggregatorFiles, root, recursive, config, pool)) {
416                 noErrors = false;
417             }
418 
419             aggregatorFiles.remove(pomFile);
420         }
421 
422         return noErrors;
423     }
424 
425     @SuppressWarnings("checkstyle:parameternumber")
426     private boolean build(
427             List<ProjectBuildingResult> results,
428             List<InterimResult> interimResults,
429             Map<File, MavenProject> projectIndex,
430             File pomFile,
431             Set<File> aggregatorFiles,
432             boolean isRoot,
433             boolean recursive,
434             InternalConfig config,
435             ReactorModelPool pool) {
436         boolean noErrors = true;
437 
438         MavenProject project = new MavenProject();
439         project.setFile(pomFile);
440 
441         project.setRootDirectory(rootLocator.findRoot(pomFile.getParentFile().toPath()));
442 
443         ModelBuildingRequest request = getModelBuildingRequest(config)
444                 .setPomFile(pomFile)
445                 .setTwoPhaseBuilding(true)
446                 .setLocationTracking(true);
447 
448         DefaultModelBuildingListener listener =
449                 new DefaultModelBuildingListener(project, projectBuildingHelper, config.request);
450         request.setModelBuildingListener(listener);
451 
452         ModelBuildingResult result;
453         try {
454             result = modelBuilder.build(request);
455         } catch (ModelBuildingException e) {
456             result = e.getResult();
457             if (result == null || result.getFileModel() == null) {
458                 results.add(new DefaultProjectBuildingResult(e.getModelId(), pomFile, e.getProblems()));
459 
460                 return false;
461             }
462             // validation error, continue project building and delay failing to help IDEs
463             // result.getProblems().addAll(e.getProblems()) ?
464             noErrors = false;
465         }
466 
467         Model model = request.getFileModel();
468 
469         pool.put(model.getPomFile().toPath(), model);
470 
471         InterimResult interimResult = new InterimResult(pomFile, request, result, listener, isRoot);
472         interimResults.add(interimResult);
473 
474         if (recursive) {
475             File basedir = pomFile.getParentFile();
476             List<File> moduleFiles = new ArrayList<>();
477             for (String module : model.getModules()) {
478                 if (module == null || module.isEmpty()) {
479                     continue;
480                 }
481 
482                 module = module.replace('\\', File.separatorChar).replace('/', File.separatorChar);
483 
484                 File moduleFile = modelProcessor.locateExistingPom(new File(basedir, module));
485 
486                 if (moduleFile == null) {
487                     ModelProblem problem = new DefaultModelProblem(
488                             "Child module " + module + " of " + pomFile + " does not exist",
489                             ModelProblem.Severity.ERROR,
490                             ModelProblem.Version.BASE,
491                             model,
492                             -1,
493                             -1,
494                             null);
495                     result.getProblems().add(problem);
496 
497                     noErrors = false;
498 
499                     continue;
500                 }
501 
502                 if (Os.IS_WINDOWS) {
503                     // we don't canonicalize on unix to avoid interfering with symlinks
504                     try {
505                         moduleFile = moduleFile.getCanonicalFile();
506                     } catch (IOException e) {
507                         moduleFile = moduleFile.getAbsoluteFile();
508                     }
509                 } else {
510                     moduleFile = new File(moduleFile.toURI().normalize());
511                 }
512 
513                 if (aggregatorFiles.contains(moduleFile)) {
514                     StringBuilder buffer = new StringBuilder(256);
515                     for (File aggregatorFile : aggregatorFiles) {
516                         buffer.append(aggregatorFile).append(" -> ");
517                     }
518                     buffer.append(moduleFile);
519 
520                     ModelProblem problem = new DefaultModelProblem(
521                             "Child module " + moduleFile + " of " + pomFile + " forms aggregation cycle " + buffer,
522                             ModelProblem.Severity.ERROR,
523                             ModelProblem.Version.BASE,
524                             model,
525                             -1,
526                             -1,
527                             null);
528                     result.getProblems().add(problem);
529 
530                     noErrors = false;
531 
532                     continue;
533                 }
534 
535                 moduleFiles.add(moduleFile);
536             }
537 
538             interimResult.modules = new ArrayList<>();
539 
540             if (!build(
541                     results,
542                     interimResult.modules,
543                     projectIndex,
544                     moduleFiles,
545                     aggregatorFiles,
546                     false,
547                     recursive,
548                     config,
549                     pool)) {
550                 noErrors = false;
551             }
552         }
553 
554         projectIndex.put(pomFile, project);
555 
556         return noErrors;
557     }
558 
559     static class InterimResult {
560 
561         File pomFile;
562 
563         ModelBuildingRequest request;
564 
565         ModelBuildingResult result;
566 
567         DefaultModelBuildingListener listener;
568 
569         boolean root;
570 
571         List<InterimResult> modules = Collections.emptyList();
572 
573         InterimResult(
574                 File pomFile,
575                 ModelBuildingRequest request,
576                 ModelBuildingResult result,
577                 DefaultModelBuildingListener listener,
578                 boolean root) {
579             this.pomFile = pomFile;
580             this.request = request;
581             this.result = result;
582             this.listener = listener;
583             this.root = root;
584         }
585     }
586 
587     private boolean build(
588             List<ProjectBuildingResult> results,
589             List<MavenProject> projects,
590             Map<File, MavenProject> projectIndex,
591             List<InterimResult> interimResults,
592             ProjectBuildingRequest request,
593             Map<File, Boolean> profilesXmls,
594             RepositorySystemSession session) {
595         boolean noErrors = true;
596 
597         for (InterimResult interimResult : interimResults) {
598             MavenProject project = interimResult.listener.getProject();
599             try {
600                 ModelBuildingResult result = modelBuilder.build(interimResult.request, interimResult.result);
601 
602                 // 2nd pass of initialization: resolve and build parent if necessary
603                 try {
604                     initProject(project, projectIndex, true, result, profilesXmls, request);
605                 } catch (InvalidArtifactRTException iarte) {
606                     result.getProblems()
607                             .add(new DefaultModelProblem(
608                                     null,
609                                     ModelProblem.Severity.ERROR,
610                                     null,
611                                     result.getEffectiveModel(),
612                                     -1,
613                                     -1,
614                                     iarte));
615                 }
616 
617                 List<MavenProject> modules = new ArrayList<>();
618                 noErrors = build(results, modules, projectIndex, interimResult.modules, request, profilesXmls, session)
619                         && noErrors;
620 
621                 projects.addAll(modules);
622                 projects.add(project);
623 
624                 project.setExecutionRoot(interimResult.root);
625                 project.setCollectedProjects(modules);
626                 DependencyResolutionResult resolutionResult = null;
627                 if (request.isResolveDependencies()) {
628                     resolutionResult = resolveDependencies(project, session);
629                 }
630 
631                 results.add(new DefaultProjectBuildingResult(project, result.getProblems(), resolutionResult));
632             } catch (ModelBuildingException e) {
633                 DefaultProjectBuildingResult result = null;
634                 if (project == null || interimResult.result.getEffectiveModel() == null) {
635                     result = new DefaultProjectBuildingResult(e.getModelId(), interimResult.pomFile, e.getProblems());
636                 } else {
637                     project.setModel(interimResult.result.getEffectiveModel());
638 
639                     result = new DefaultProjectBuildingResult(project, e.getProblems(), null);
640                 }
641                 results.add(result);
642 
643                 noErrors = false;
644             }
645         }
646 
647         return noErrors;
648     }
649 
650     @SuppressWarnings("checkstyle:methodlength")
651     private void initProject(
652             MavenProject project,
653             Map<File, MavenProject> projects,
654             boolean buildParentIfNotExisting,
655             ModelBuildingResult result,
656             Map<File, Boolean> profilesXmls,
657             ProjectBuildingRequest projectBuildingRequest) {
658         project.setModel(result.getEffectiveModel());
659         project.setOriginalModel(result.getFileModel());
660 
661         initParent(project, projects, buildParentIfNotExisting, result, projectBuildingRequest);
662 
663         Artifact projectArtifact = repositorySystem.createArtifact(
664                 project.getGroupId(), project.getArtifactId(), project.getVersion(), null, project.getPackaging());
665         project.setArtifact(projectArtifact);
666 
667         if (project.getFile() != null && buildParentIfNotExisting) // only set those on 2nd phase, ignore on 1st pass
668         {
669             Build build = project.getBuild();
670             project.addScriptSourceRoot(build.getScriptSourceDirectory());
671             project.addCompileSourceRoot(build.getSourceDirectory());
672             project.addTestCompileSourceRoot(build.getTestSourceDirectory());
673         }
674 
675         List<Profile> activeProfiles = new ArrayList<>();
676         activeProfiles.addAll(result.getActivePomProfiles(result.getModelIds().get(0)));
677         activeProfiles.addAll(result.getActiveExternalProfiles());
678         project.setActiveProfiles(activeProfiles);
679 
680         project.setInjectedProfileIds("external", getProfileIds(result.getActiveExternalProfiles()));
681         for (String modelId : result.getModelIds()) {
682             project.setInjectedProfileIds(modelId, getProfileIds(result.getActivePomProfiles(modelId)));
683         }
684 
685         //
686         // All the parts that were taken out of MavenProject for Maven 4.0.0
687         //
688 
689         project.setProjectBuildingRequest(projectBuildingRequest);
690 
691         // pluginArtifacts
692         Set<Artifact> pluginArtifacts = new HashSet<>();
693         for (Plugin plugin : project.getBuildPlugins()) {
694             Artifact artifact = repositorySystem.createPluginArtifact(plugin);
695 
696             if (artifact != null) {
697                 pluginArtifacts.add(artifact);
698             }
699         }
700         project.setPluginArtifacts(pluginArtifacts);
701 
702         // reportArtifacts
703         Set<Artifact> reportArtifacts = new HashSet<>();
704         for (ReportPlugin report : project.getReportPlugins()) {
705             Plugin pp = new Plugin();
706             pp.setGroupId(report.getGroupId());
707             pp.setArtifactId(report.getArtifactId());
708             pp.setVersion(report.getVersion());
709 
710             Artifact artifact = repositorySystem.createPluginArtifact(pp);
711 
712             if (artifact != null) {
713                 reportArtifacts.add(artifact);
714             }
715         }
716         project.setReportArtifacts(reportArtifacts);
717 
718         // extensionArtifacts
719         Set<Artifact> extensionArtifacts = new HashSet<>();
720         List<Extension> extensions = project.getBuildExtensions();
721         if (extensions != null) {
722             for (Extension ext : extensions) {
723                 String version;
724                 if (ext.getVersion() == null || ext.getVersion().isEmpty()) {
725                     version = "RELEASE";
726                 } else {
727                     version = ext.getVersion();
728                 }
729 
730                 Artifact artifact =
731                         repositorySystem.createArtifact(ext.getGroupId(), ext.getArtifactId(), version, null, "jar");
732 
733                 if (artifact != null) {
734                     extensionArtifacts.add(artifact);
735                 }
736             }
737         }
738         project.setExtensionArtifacts(extensionArtifacts);
739 
740         // managedVersionMap
741         Map<String, Artifact> map = null;
742         if (repositorySystem != null) {
743             final DependencyManagement dependencyManagement = project.getDependencyManagement();
744             if ((dependencyManagement != null)
745                     && ((dependencyManagement.getDependencies()) != null)
746                     && (dependencyManagement.getDependencies().size() > 0)) {
747                 map = new AbstractMap<String, Artifact>() {
748                     HashMap<String, Artifact> delegate;
749 
750                     @Override
751                     public Set<Entry<String, Artifact>> entrySet() {
752                         return Collections.unmodifiableSet(compute().entrySet());
753                     }
754 
755                     @Override
756                     public Set<String> keySet() {
757                         return Collections.unmodifiableSet(compute().keySet());
758                     }
759 
760                     @Override
761                     public Collection<Artifact> values() {
762                         return Collections.unmodifiableCollection(compute().values());
763                     }
764 
765                     @Override
766                     public boolean containsValue(Object value) {
767                         return compute().containsValue(value);
768                     }
769 
770                     @Override
771                     public boolean containsKey(Object key) {
772                         return compute().containsKey(key);
773                     }
774 
775                     @Override
776                     public Artifact get(Object key) {
777                         return compute().get(key);
778                     }
779 
780                     HashMap<String, Artifact> compute() {
781                         if (delegate == null) {
782                             delegate = new HashMap<>();
783                             for (Dependency d : dependencyManagement.getDependencies()) {
784                                 Artifact artifact = repositorySystem.createDependencyArtifact(d);
785 
786                                 if (artifact != null) {
787                                     delegate.put(d.getManagementKey(), artifact);
788                                 }
789                             }
790                         }
791 
792                         return delegate;
793                     }
794                 };
795             } else {
796                 map = Collections.emptyMap();
797             }
798         }
799         project.setManagedVersionMap(map);
800 
801         // release artifact repository
802         if (project.getDistributionManagement() != null
803                 && project.getDistributionManagement().getRepository() != null) {
804             try {
805                 DeploymentRepository r = project.getDistributionManagement().getRepository();
806                 if (r.getId() != null
807                         && !r.getId().isEmpty()
808                         && r.getUrl() != null
809                         && !r.getUrl().isEmpty()) {
810                     ArtifactRepository repo = MavenRepositorySystem.buildArtifactRepository(r);
811                     repositorySystem.injectProxy(projectBuildingRequest.getRepositorySession(), Arrays.asList(repo));
812                     repositorySystem.injectAuthentication(
813                             projectBuildingRequest.getRepositorySession(), Arrays.asList(repo));
814                     project.setReleaseArtifactRepository(repo);
815                 }
816             } catch (InvalidRepositoryException e) {
817                 throw new IllegalStateException(
818                         "Failed to create release distribution repository for " + project.getId(), e);
819             }
820         }
821 
822         // snapshot artifact repository
823         if (project.getDistributionManagement() != null
824                 && project.getDistributionManagement().getSnapshotRepository() != null) {
825             try {
826                 DeploymentRepository r = project.getDistributionManagement().getSnapshotRepository();
827                 if (r.getId() != null
828                         && !r.getId().isEmpty()
829                         && r.getUrl() != null
830                         && !r.getUrl().isEmpty()) {
831                     ArtifactRepository repo = MavenRepositorySystem.buildArtifactRepository(r);
832                     repositorySystem.injectProxy(projectBuildingRequest.getRepositorySession(), Arrays.asList(repo));
833                     repositorySystem.injectAuthentication(
834                             projectBuildingRequest.getRepositorySession(), Arrays.asList(repo));
835                     project.setSnapshotArtifactRepository(repo);
836                 }
837             } catch (InvalidRepositoryException e) {
838                 throw new IllegalStateException(
839                         "Failed to create snapshot distribution repository for " + project.getId(), e);
840             }
841         }
842     }
843 
844     private void initParent(
845             MavenProject project,
846             Map<File, MavenProject> projects,
847             boolean buildParentIfNotExisting,
848             ModelBuildingResult result,
849             ProjectBuildingRequest projectBuildingRequest) {
850         Model parentModel =
851                 result.getModelIds().size() > 1 && !result.getModelIds().get(1).isEmpty()
852                         ? result.getRawModel(result.getModelIds().get(1))
853                         : null;
854 
855         if (parentModel != null) {
856             final String parentGroupId = inheritedGroupId(result, 1);
857             final String parentVersion = inheritedVersion(result, 1);
858 
859             project.setParentArtifact(
860                     repositorySystem.createProjectArtifact(parentGroupId, parentModel.getArtifactId(), parentVersion));
861 
862             // org.apache.maven.its.mng4834:parent:0.1
863             String parentModelId = result.getModelIds().get(1);
864             File parentPomFile = result.getRawModel(parentModelId).getPomFile();
865             MavenProject parent = projects.get(parentPomFile);
866             if (parent == null && buildParentIfNotExisting) {
867                 //
868                 // At this point the DefaultModelBuildingListener has fired and it populates the
869                 // remote repositories with those found in the pom.xml, along with the existing externally
870                 // defined repositories.
871                 //
872                 projectBuildingRequest.setRemoteRepositories(project.getRemoteArtifactRepositories());
873                 if (parentPomFile != null) {
874                     project.setParentFile(parentPomFile);
875                     try {
876                         parent = build(parentPomFile, projectBuildingRequest).getProject();
877                     } catch (ProjectBuildingException e) {
878                         // MNG-4488 where let invalid parents slide on by
879                         if (logger.isDebugEnabled()) {
880                             // Message below is checked for in the MNG-2199 core IT.
881                             logger.warn("Failed to build parent project for " + project.getId(), e);
882                         } else {
883                             // Message below is checked for in the MNG-2199 core IT.
884                             logger.warn("Failed to build parent project for " + project.getId());
885                         }
886                     }
887                 } else {
888                     Artifact parentArtifact = project.getParentArtifact();
889                     try {
890                         parent = build(parentArtifact, projectBuildingRequest).getProject();
891                     } catch (ProjectBuildingException e) {
892                         // MNG-4488 where let invalid parents slide on by
893                         if (logger.isDebugEnabled()) {
894                             // Message below is checked for in the MNG-2199 core IT.
895                             logger.warn("Failed to build parent project for " + project.getId(), e);
896                         } else {
897                             // Message below is checked for in the MNG-2199 core IT.
898                             logger.warn("Failed to build parent project for " + project.getId());
899                         }
900                     }
901                 }
902             }
903             project.setParent(parent);
904             if (project.getParentFile() == null && parent != null) {
905                 project.setParentFile(parent.getFile());
906             }
907         }
908     }
909 
910     private static String inheritedGroupId(final ModelBuildingResult result, final int modelIndex) {
911         String groupId = null;
912         final String modelId = result.getModelIds().get(modelIndex);
913 
914         if (!modelId.isEmpty()) {
915             final Model model = result.getRawModel(modelId);
916             groupId = model.getGroupId() != null ? model.getGroupId() : inheritedGroupId(result, modelIndex + 1);
917         }
918 
919         return groupId;
920     }
921 
922     private static String inheritedVersion(final ModelBuildingResult result, final int modelIndex) {
923         String version = null;
924         final String modelId = result.getModelIds().get(modelIndex);
925 
926         if (!modelId.isEmpty()) {
927             version = result.getRawModel(modelId).getVersion();
928             if (version == null) {
929                 version = inheritedVersion(result, modelIndex + 1);
930             }
931         }
932 
933         return version;
934     }
935 
936     /**
937      * InternalConfig
938      */
939     class InternalConfig {
940 
941         private final ProjectBuildingRequest request;
942 
943         private final RepositorySystemSession session;
944 
945         private final List<RemoteRepository> repositories;
946 
947         private final ReactorModelPool modelPool;
948 
949         private final TransformerContextBuilder transformerContextBuilder;
950 
951         InternalConfig(
952                 ProjectBuildingRequest request,
953                 ReactorModelPool modelPool,
954                 TransformerContextBuilder transformerContextBuilder) {
955             this.request = request;
956             this.modelPool = modelPool;
957             this.transformerContextBuilder = transformerContextBuilder;
958 
959             session = RepositoryUtils.overlay(request.getLocalRepository(), request.getRepositorySession(), repoSystem);
960             repositories = RepositoryUtils.toRepos(request.getRemoteRepositories());
961         }
962     }
963 }