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