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