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