001package org.apache.maven.project;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *  http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import java.io.File;
023import java.io.IOException;
024import java.util.ArrayList;
025import java.util.Arrays;
026import java.util.Collections;
027import java.util.HashMap;
028import java.util.HashSet;
029import java.util.LinkedHashSet;
030import java.util.List;
031import java.util.Map;
032import java.util.Set;
033
034import org.apache.maven.RepositoryUtils;
035import org.apache.maven.artifact.Artifact;
036import org.apache.maven.artifact.InvalidRepositoryException;
037import org.apache.maven.artifact.repository.ArtifactRepository;
038import org.apache.maven.artifact.repository.LegacyLocalRepositoryManager;
039import org.apache.maven.bridge.MavenRepositorySystem;
040import org.apache.maven.model.Build;
041import org.apache.maven.model.Dependency;
042import org.apache.maven.model.DependencyManagement;
043import org.apache.maven.model.DeploymentRepository;
044import org.apache.maven.model.Extension;
045import org.apache.maven.model.Model;
046import org.apache.maven.model.Parent;
047import org.apache.maven.model.Plugin;
048import org.apache.maven.model.Profile;
049import org.apache.maven.model.ReportPlugin;
050import org.apache.maven.model.building.DefaultModelBuildingRequest;
051import org.apache.maven.model.building.DefaultModelProblem;
052import org.apache.maven.model.building.FileModelSource;
053import org.apache.maven.model.building.ModelBuilder;
054import org.apache.maven.model.building.ModelBuildingException;
055import org.apache.maven.model.building.ModelBuildingRequest;
056import org.apache.maven.model.building.ModelBuildingResult;
057import org.apache.maven.model.building.ModelProblem;
058import org.apache.maven.model.building.ModelProcessor;
059import org.apache.maven.model.building.ModelSource;
060import org.apache.maven.model.building.StringModelSource;
061import org.apache.maven.model.resolution.ModelResolver;
062import org.apache.maven.repository.internal.ArtifactDescriptorUtils;
063import org.codehaus.plexus.component.annotations.Component;
064import org.codehaus.plexus.component.annotations.Requirement;
065import org.codehaus.plexus.logging.Logger;
066import org.codehaus.plexus.util.Os;
067import org.codehaus.plexus.util.StringUtils;
068import org.eclipse.aether.RepositorySystemSession;
069import org.eclipse.aether.RequestTrace;
070import org.eclipse.aether.impl.RemoteRepositoryManager;
071import org.eclipse.aether.repository.LocalRepositoryManager;
072import org.eclipse.aether.repository.RemoteRepository;
073import org.eclipse.aether.repository.WorkspaceRepository;
074import org.eclipse.aether.resolution.ArtifactRequest;
075import org.eclipse.aether.resolution.ArtifactResult;
076import org.eclipse.aether.resolution.VersionRangeRequest;
077import org.eclipse.aether.resolution.VersionRangeResolutionException;
078import org.eclipse.aether.resolution.VersionRangeResult;
079
080/**
081 */
082@Component( role = ProjectBuilder.class )
083public class DefaultProjectBuilder
084    implements ProjectBuilder
085{
086
087    @Requirement
088    private Logger logger;
089
090    @Requirement
091    private ModelBuilder modelBuilder;
092
093    @Requirement
094    private ModelProcessor modelProcessor;
095
096    @Requirement
097    private ProjectBuildingHelper projectBuildingHelper;
098
099    @Requirement
100    private MavenRepositorySystem repositorySystem;
101
102    @Requirement
103    private org.eclipse.aether.RepositorySystem repoSystem;
104
105    @Requirement
106    private RemoteRepositoryManager repositoryManager;
107
108    @Requirement
109    private ProjectDependenciesResolver dependencyResolver;
110
111    // ----------------------------------------------------------------------
112    // MavenProjectBuilder Implementation
113    // ----------------------------------------------------------------------
114
115    public ProjectBuildingResult build( File pomFile, ProjectBuildingRequest request )
116        throws ProjectBuildingException
117    {
118        return build( pomFile, new FileModelSource( pomFile ), new InternalConfig( request, null ) );
119    }
120
121    public ProjectBuildingResult build( ModelSource modelSource, ProjectBuildingRequest request )
122        throws ProjectBuildingException
123    {
124        return build( null, modelSource, new InternalConfig( request, null ) );
125    }
126
127    private ProjectBuildingResult build( File pomFile, ModelSource modelSource, InternalConfig config )
128        throws ProjectBuildingException
129    {
130        ClassLoader oldContextClassLoader = Thread.currentThread().getContextClassLoader();
131
132        try
133        {
134            ProjectBuildingRequest projectBuildingRequest = config.request;            
135
136            MavenProject project = projectBuildingRequest.getProject();
137
138            List<ModelProblem> modelProblems = null;
139            Throwable error = null;
140
141            if ( project == null )
142            {
143                ModelBuildingRequest request = getModelBuildingRequest( config );
144
145                project = new MavenProject();
146                project.setFile( pomFile );
147
148                DefaultModelBuildingListener listener =
149                    new DefaultModelBuildingListener( project, projectBuildingHelper, projectBuildingRequest );
150                request.setModelBuildingListener( listener );
151
152                request.setPomFile( pomFile );
153                request.setModelSource( modelSource );
154                request.setLocationTracking( true );
155
156                ModelBuildingResult result;
157                try
158                {
159                    result = modelBuilder.build( request );
160                }
161                catch ( ModelBuildingException e )
162                {
163                    result = e.getResult();
164                    if ( result == null || result.getEffectiveModel() == null )
165                    {
166                        throw new ProjectBuildingException( e.getModelId(), e.getMessage(), pomFile, e );
167                    }
168                    // validation error, continue project building and delay failing to help IDEs
169                    error = e;
170                }
171
172                modelProblems = result.getProblems();
173
174                initProject( project, Collections.<String, MavenProject> emptyMap(), result,
175                             new HashMap<File, Boolean>(), projectBuildingRequest );
176            }
177            else if ( projectBuildingRequest.isResolveDependencies() )
178            {
179                projectBuildingHelper.selectProjectRealm( project );
180            }
181
182            DependencyResolutionResult resolutionResult = null;
183
184            if ( projectBuildingRequest.isResolveDependencies() )
185            {
186                resolutionResult = resolveDependencies( project, config.session );
187            }
188
189            ProjectBuildingResult result = new DefaultProjectBuildingResult( project, modelProblems, resolutionResult );
190
191            if ( error != null )
192            {
193                ProjectBuildingException e = new ProjectBuildingException( Arrays.asList( result ) );
194                e.initCause( error );
195                throw e;
196            }
197
198            return result;
199        }
200        finally
201        {
202            Thread.currentThread().setContextClassLoader( oldContextClassLoader );
203        }
204    }
205
206    private DependencyResolutionResult resolveDependencies( MavenProject project, RepositorySystemSession session )
207    {
208        DependencyResolutionResult resolutionResult;
209
210        try
211        {
212            DefaultDependencyResolutionRequest resolution = new DefaultDependencyResolutionRequest( project, session );
213            resolutionResult = dependencyResolver.resolve( resolution );
214        }
215        catch ( DependencyResolutionException e )
216        {
217            resolutionResult = e.getResult();
218        }
219
220        Set<Artifact> artifacts = new LinkedHashSet<Artifact>();
221        if ( resolutionResult.getDependencyGraph() != null )
222        {
223            RepositoryUtils.toArtifacts( artifacts, resolutionResult.getDependencyGraph().getChildren(),
224                                         Collections.singletonList( project.getArtifact().getId() ), null );
225
226            // Maven 2.x quirk: an artifact always points at the local repo, regardless whether resolved or not
227            LocalRepositoryManager lrm = session.getLocalRepositoryManager();
228            for ( Artifact artifact : artifacts )
229            {
230                if ( !artifact.isResolved() )
231                {
232                    String path = lrm.getPathForLocalArtifact( RepositoryUtils.toArtifact( artifact ) );
233                    artifact.setFile( new File( lrm.getRepository().getBasedir(), path ) );
234                }
235            }
236        }
237        project.setResolvedArtifacts( artifacts );
238        project.setArtifacts( artifacts );
239
240        return resolutionResult;
241    }
242
243    private List<String> getProfileIds( List<Profile> profiles )
244    {
245        List<String> ids = new ArrayList<String>( profiles.size() );
246
247        for ( Profile profile : profiles )
248        {
249            ids.add( profile.getId() );
250        }
251
252        return ids;
253    }
254
255    private ModelBuildingRequest getModelBuildingRequest( InternalConfig config )
256    {
257        ProjectBuildingRequest configuration = config.request;
258
259        ModelBuildingRequest request = new DefaultModelBuildingRequest();
260
261        RequestTrace trace = RequestTrace.newChild( null, configuration ).newChild( request );
262
263        ModelResolver resolver =
264            new ProjectModelResolver( config.session, trace, repoSystem, repositoryManager, config.repositories,
265                                      configuration.getRepositoryMerging(), config.modelPool );
266
267        request.setValidationLevel( configuration.getValidationLevel() );
268        request.setProcessPlugins( configuration.isProcessPlugins() );
269        request.setProfiles( configuration.getProfiles() );
270        request.setActiveProfileIds( configuration.getActiveProfileIds() );
271        request.setInactiveProfileIds( configuration.getInactiveProfileIds() );
272        request.setSystemProperties( configuration.getSystemProperties() );
273        request.setUserProperties( configuration.getUserProperties() );
274        request.setBuildStartTime( configuration.getBuildStartTime() );
275        request.setModelResolver( resolver );
276        request.setModelCache( new ReactorModelCache() );
277
278        return request;
279    }
280
281    public ProjectBuildingResult build( Artifact artifact, ProjectBuildingRequest request )
282        throws ProjectBuildingException
283    {
284        return build( artifact, false, request );
285    }
286
287    public ProjectBuildingResult build( Artifact artifact, boolean allowStubModel, ProjectBuildingRequest request )
288        throws ProjectBuildingException
289    {
290        org.eclipse.aether.artifact.Artifact pomArtifact = RepositoryUtils.toArtifact( artifact );
291        pomArtifact = ArtifactDescriptorUtils.toPomArtifact( pomArtifact );
292
293        InternalConfig config = new InternalConfig( request, null );
294
295        boolean localProject;
296
297        if ( request.isResolveVersionRanges() )
298        {
299            VersionRangeRequest versionRangeRequest = new VersionRangeRequest( pomArtifact, config.repositories, null );
300
301            try
302            {
303                VersionRangeResult versionRangeResult =
304                    repoSystem.resolveVersionRange( config.session, versionRangeRequest );
305
306                if ( versionRangeResult.getHighestVersion() == null )
307                {
308                    throw new ProjectBuildingException(
309                        artifact.getId(), "Error resolving project artifact: No versions matched the requested range",
310                        (Throwable) null );
311
312                }
313
314                if ( versionRangeResult.getVersionConstraint() != null
315                         && versionRangeResult.getVersionConstraint().getRange() != null
316                         && versionRangeResult.getVersionConstraint().getRange().getUpperBound() == null )
317                {
318                    throw new ProjectBuildingException(
319                        artifact.getId(),
320                        "Error resolving project artifact: The requested version range does not specify an upper bound",
321                        (Throwable) null );
322
323                }
324
325                pomArtifact = pomArtifact.setVersion( versionRangeResult.getHighestVersion().toString() );
326            }
327            catch ( VersionRangeResolutionException e )
328            {
329                throw new ProjectBuildingException(
330                    artifact.getId(), "Error resolving project artifact: " + e.getMessage(), e );
331
332            }
333        }
334
335        try
336        {
337            ArtifactRequest pomRequest = new ArtifactRequest();
338            pomRequest.setArtifact( pomArtifact );
339            pomRequest.setRepositories( config.repositories );
340            ArtifactResult pomResult = repoSystem.resolveArtifact( config.session, pomRequest );
341
342            pomArtifact = pomResult.getArtifact();
343            localProject = pomResult.getRepository() instanceof WorkspaceRepository;
344        }
345        catch ( org.eclipse.aether.resolution.ArtifactResolutionException e )
346        {
347            if ( e.getResults().get( 0 ).isMissing() && allowStubModel )
348            {
349                return build( null, createStubModelSource( artifact ), config );
350            }
351            throw new ProjectBuildingException( artifact.getId(),
352                                                "Error resolving project artifact: " + e.getMessage(), e );
353        }
354
355        File pomFile = pomArtifact.getFile();
356
357        if ( "pom".equals( artifact.getType() ) )
358        {
359            artifact.selectVersion( pomArtifact.getVersion() );
360            artifact.setFile( pomFile );
361            artifact.setResolved( true );
362        }
363
364        return build( localProject ? pomFile : null, new FileModelSource( pomFile ), config );
365    }
366
367    private ModelSource createStubModelSource( Artifact artifact )
368    {
369        StringBuilder buffer = new StringBuilder( 1024 );
370
371        buffer.append( "<?xml version='1.0'?>" );
372        buffer.append( "<project>" );
373        buffer.append( "<modelVersion>4.0.0</modelVersion>" );
374        buffer.append( "<groupId>" ).append( artifact.getGroupId() ).append( "</groupId>" );
375        buffer.append( "<artifactId>" ).append( artifact.getArtifactId() ).append( "</artifactId>" );
376        buffer.append( "<version>" ).append( artifact.getBaseVersion() ).append( "</version>" );
377        buffer.append( "<packaging>" ).append( artifact.getType() ).append( "</packaging>" );
378        buffer.append( "</project>" );
379
380        return new StringModelSource( buffer, artifact.getId() );
381    }
382
383    public List<ProjectBuildingResult> build( List<File> pomFiles, boolean recursive, ProjectBuildingRequest request )
384        throws ProjectBuildingException
385    {
386        List<ProjectBuildingResult> results = new ArrayList<ProjectBuildingResult>();
387
388        List<InterimResult> interimResults = new ArrayList<InterimResult>();
389
390        ReactorModelPool modelPool = new ReactorModelPool();
391
392        InternalConfig config = new InternalConfig( request, modelPool );
393
394        Map<String, MavenProject> projectIndex = new HashMap<String, MavenProject>( 256 );
395
396        boolean noErrors =
397            build( results, interimResults, projectIndex, pomFiles, new LinkedHashSet<File>(), true, recursive, config );
398
399        populateReactorModelPool( modelPool, interimResults );
400
401        ClassLoader oldContextClassLoader = Thread.currentThread().getContextClassLoader();
402
403        try
404        {
405            noErrors =
406                build( results, new ArrayList<MavenProject>(), projectIndex, interimResults, request,
407                       new HashMap<File, Boolean>() ) && noErrors;
408        }
409        finally
410        {
411            Thread.currentThread().setContextClassLoader( oldContextClassLoader );
412        }
413
414        if ( !noErrors )
415        {
416            throw new ProjectBuildingException( results );
417        }
418
419        return results;
420    }
421
422    private boolean build( List<ProjectBuildingResult> results, List<InterimResult> interimResults,
423                           Map<String, MavenProject> projectIndex, List<File> pomFiles, Set<File> aggregatorFiles,
424                           boolean isRoot, boolean recursive, InternalConfig config )
425    {
426        boolean noErrors = true;
427
428        for ( File pomFile : pomFiles )
429        {
430            aggregatorFiles.add( pomFile );
431
432            if ( !build( results, interimResults, projectIndex, pomFile, aggregatorFiles, isRoot, recursive, config ) )
433            {
434                noErrors = false;
435            }
436
437            aggregatorFiles.remove( pomFile );
438        }
439
440        return noErrors;
441    }
442
443    private boolean build( List<ProjectBuildingResult> results, List<InterimResult> interimResults,
444                           Map<String, MavenProject> projectIndex, File pomFile, Set<File> aggregatorFiles,
445                           boolean isRoot, boolean recursive, InternalConfig config )
446    {
447        boolean noErrors = true;
448
449        ModelBuildingRequest request = getModelBuildingRequest( config );
450
451        MavenProject project = new MavenProject();
452
453        request.setPomFile( pomFile );
454        request.setTwoPhaseBuilding( true );
455        request.setLocationTracking( true );
456
457        DefaultModelBuildingListener listener =
458            new DefaultModelBuildingListener( project, projectBuildingHelper, config.request );
459        request.setModelBuildingListener( listener );
460
461        try
462        {
463            ModelBuildingResult result = modelBuilder.build( request );
464
465            Model model = result.getEffectiveModel();
466
467            projectIndex.put( result.getModelIds().get( 0 ), project );
468
469            InterimResult interimResult = new InterimResult( pomFile, request, result, listener, isRoot );
470            interimResults.add( interimResult );
471
472            if ( recursive && !model.getModules().isEmpty() )
473            {
474                File basedir = pomFile.getParentFile();
475
476                List<File> moduleFiles = new ArrayList<File>();
477
478                for ( String module : model.getModules() )
479                {
480                    if ( StringUtils.isEmpty( module ) )
481                    {
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                    {
491                        moduleFile = modelProcessor.locatePom( moduleFile );
492                    }
493
494                    if ( !moduleFile.isFile() )
495                    {
496                        ModelProblem problem =
497                            new DefaultModelProblem( "Child module " + moduleFile + " of " + pomFile
498                                + " does not exist", ModelProblem.Severity.ERROR, ModelProblem.Version.BASE, model, -1,
499                                                     -1, null );
500                        result.getProblems().add( problem );
501
502                        noErrors = false;
503
504                        continue;
505                    }
506
507                    if ( Os.isFamily( Os.FAMILY_WINDOWS ) )
508                    {
509                        // we don't canonicalize on unix to avoid interfering with symlinks
510                        try
511                        {
512                            moduleFile = moduleFile.getCanonicalFile();
513                        }
514                        catch ( IOException e )
515                        {
516                            moduleFile = moduleFile.getAbsoluteFile();
517                        }
518                    }
519                    else
520                    {
521                        moduleFile = new File( moduleFile.toURI().normalize() );
522                    }
523
524                    if ( aggregatorFiles.contains( moduleFile ) )
525                    {
526                        StringBuilder buffer = new StringBuilder( 256 );
527                        for ( File aggregatorFile : aggregatorFiles )
528                        {
529                            buffer.append( aggregatorFile ).append( " -> " );
530                        }
531                        buffer.append( moduleFile );
532
533                        ModelProblem problem =
534                            new DefaultModelProblem( "Child module " + moduleFile + " of " + pomFile
535                                + " forms aggregation cycle " + buffer, ModelProblem.Severity.ERROR,
536                                                     ModelProblem.Version.BASE, model, -1, -1, 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<InterimResult>();
548
549                if ( !build( results, interimResult.modules, projectIndex, moduleFiles, aggregatorFiles, false,
550                             recursive, config ) )
551                {
552                    noErrors = false;
553                }
554            }
555        }
556        catch ( ModelBuildingException e )
557        {
558            results.add( new DefaultProjectBuildingResult( e.getModelId(), pomFile, e.getProblems() ) );
559
560            noErrors = false;
561        }
562
563        return noErrors;
564    }
565
566    static class InterimResult
567    {
568
569        File pomFile;
570
571        ModelBuildingRequest request;
572
573        ModelBuildingResult result;
574
575        DefaultModelBuildingListener listener;
576
577        boolean root;
578
579        List<InterimResult> modules = Collections.emptyList();
580
581        InterimResult( File pomFile, ModelBuildingRequest request, ModelBuildingResult result,
582                       DefaultModelBuildingListener listener, boolean root )
583        {
584            this.pomFile = pomFile;
585            this.request = request;
586            this.result = result;
587            this.listener = listener;
588            this.root = root;
589        }
590
591    }
592
593    private void populateReactorModelPool( ReactorModelPool reactorModelPool, List<InterimResult> interimResults )
594    {
595        for ( InterimResult interimResult : interimResults )
596        {
597            Model model = interimResult.result.getEffectiveModel();
598            reactorModelPool.put( model.getGroupId(), model.getArtifactId(), model.getVersion(), model.getPomFile() );
599
600            populateReactorModelPool( reactorModelPool, interimResult.modules );
601        }
602    }
603
604    private boolean build( List<ProjectBuildingResult> results, List<MavenProject> projects,
605                           Map<String, MavenProject> projectIndex, List<InterimResult> interimResults,
606                           ProjectBuildingRequest request, Map<File, Boolean> profilesXmls )
607    {
608        boolean noErrors = true;
609
610        for ( InterimResult interimResult : interimResults )
611        {
612            try
613            {
614                ModelBuildingResult result = modelBuilder.build( interimResult.request, interimResult.result );
615
616                MavenProject project = interimResult.listener.getProject();
617                initProject( project, projectIndex, result, profilesXmls, request );
618
619                List<MavenProject> modules = new ArrayList<MavenProject>();
620                noErrors =
621                    build( results, modules, projectIndex, interimResult.modules, request, profilesXmls ) && noErrors;
622
623                projects.addAll( modules );
624                projects.add( project );
625
626                project.setExecutionRoot( interimResult.root );
627                project.setCollectedProjects( modules );
628
629                results.add( new DefaultProjectBuildingResult( project, result.getProblems(), null ) );
630            }
631            catch ( ModelBuildingException e )
632            {
633                results.add( new DefaultProjectBuildingResult( e.getModelId(), interimResult.pomFile, e.getProblems() ) );
634
635                noErrors = false;
636            }
637        }
638
639        return noErrors;
640    }
641
642    private void initProject( MavenProject project, Map<String, MavenProject> projects, ModelBuildingResult result,
643                              Map<File, Boolean> profilesXmls, ProjectBuildingRequest projectBuildingRequest )
644    {
645        Model model = result.getEffectiveModel();
646
647        project.setModel( model );
648        project.setOriginalModel( result.getRawModel() );
649        project.setFile( model.getPomFile() );
650        Parent p = model.getParent();
651        if ( p != null )
652        {
653            project.setParentArtifact( repositorySystem.createProjectArtifact( p.getGroupId(), p.getArtifactId(),
654                                                                               p.getVersion() ) );
655            // org.apache.maven.its.mng4834:parent:0.1
656            String parentModelId = result.getModelIds().get( 1 );
657            File parentPomFile = result.getRawModel( parentModelId ).getPomFile();
658            MavenProject parent = projects.get( parentModelId );
659            if ( parent == null )
660            {
661                //
662                // At this point the DefaultModelBuildingListener has fired and it populates the
663                // remote repositories with those found in the pom.xml, along with the existing externally
664                // defined repositories.
665                //
666                projectBuildingRequest.setRemoteRepositories( project.getRemoteArtifactRepositories() );
667                if ( parentPomFile != null )
668                {
669                    project.setParentFile( parentPomFile );
670                    try
671                    {
672                        parent = build( parentPomFile, projectBuildingRequest ).getProject();
673                    }
674                    catch ( ProjectBuildingException e )
675                    {
676                        // MNG-4488 where let invalid parents slide on by
677                        logger.warn( "Failed to build parent project for " + project.getId() );
678                    }
679                }
680                else
681                {
682                    Artifact parentArtifact = project.getParentArtifact();
683                    try
684                    {
685                        parent = build( parentArtifact, projectBuildingRequest ).getProject();
686                    }
687                    catch ( ProjectBuildingException e )
688                    {
689                        // MNG-4488 where let invalid parents slide on by
690                        logger.warn( "Failed to build parent project for " + project.getId() );
691                    }
692                }
693            }
694            project.setParent( parent );
695        }
696
697        Artifact projectArtifact =
698            repositorySystem.createArtifact( project.getGroupId(), project.getArtifactId(), project.getVersion(), null,
699                                             project.getPackaging() );
700        project.setArtifact( projectArtifact );
701
702        if ( project.getFile() != null )
703        {
704            Build build = project.getBuild();
705            project.addScriptSourceRoot( build.getScriptSourceDirectory() );
706            project.addCompileSourceRoot( build.getSourceDirectory() );
707            project.addTestCompileSourceRoot( build.getTestSourceDirectory() );
708        }
709
710        List<Profile> activeProfiles = new ArrayList<Profile>();
711        activeProfiles.addAll( result.getActivePomProfiles( result.getModelIds().get( 0 ) ) );
712        activeProfiles.addAll( result.getActiveExternalProfiles() );
713        project.setActiveProfiles( activeProfiles );
714
715        project.setInjectedProfileIds( "external", getProfileIds( result.getActiveExternalProfiles() ) );
716        for ( String modelId : result.getModelIds() )
717        {
718            project.setInjectedProfileIds( modelId, getProfileIds( result.getActivePomProfiles( modelId ) ) );
719        }
720
721        String modelId = findProfilesXml( result, profilesXmls );
722        if ( modelId != null )
723        {
724            ModelProblem problem =
725                new DefaultModelProblem( "Detected profiles.xml alongside " + modelId
726                    + ", this file is no longer supported and was ignored" + ", please use the settings.xml instead",
727                                         ModelProblem.Severity.WARNING, ModelProblem.Version.V30, model, -1, -1, null );
728            result.getProblems().add( problem );
729        }
730
731        //
732        // All the parts that were taken out of MavenProject for Maven 4.0.0
733        //
734        
735        project.setProjectBuildingRequest( projectBuildingRequest );
736        
737        // pluginArtifacts
738        Set<Artifact> pluginArtifacts = new HashSet<Artifact>();
739        for ( Plugin plugin : project.getBuildPlugins() )
740        {
741            Artifact artifact = repositorySystem.createPluginArtifact( plugin );
742
743            if ( artifact != null )
744            {
745                pluginArtifacts.add( artifact );
746            }
747        }
748        project.setPluginArtifacts( pluginArtifacts );
749
750        // reportArtifacts
751        Set<Artifact> reportArtifacts = new HashSet<Artifact>();
752        for ( ReportPlugin report : project.getReportPlugins() )
753        {
754            Plugin pp = new Plugin();
755            pp.setGroupId( report.getGroupId() );
756            pp.setArtifactId( report.getArtifactId() );
757            pp.setVersion( report.getVersion() );
758
759            Artifact artifact = repositorySystem.createPluginArtifact( pp );
760
761            if ( artifact != null )
762            {
763                reportArtifacts.add( artifact );
764            }
765        }
766        project.setReportArtifacts( reportArtifacts );
767
768        // extensionArtifacts
769        Set<Artifact> extensionArtifacts = new HashSet<Artifact>();
770        List<Extension> extensions = project.getBuildExtensions();
771        if ( extensions != null )
772        {
773            for ( Extension ext : extensions )
774            {
775                String version;
776                if ( StringUtils.isEmpty( ext.getVersion() ) )
777                {
778                    version = "RELEASE";
779                }
780                else
781                {
782                    version = ext.getVersion();
783                }
784
785                Artifact artifact =
786                    repositorySystem.createArtifact( ext.getGroupId(), ext.getArtifactId(), version, null, "jar" );
787
788                if ( artifact != null )
789                {
790                    extensionArtifacts.add( artifact );
791                }
792            }
793        }
794        project.setExtensionArtifacts( extensionArtifacts );
795
796        // managedVersionMap
797        Map<String, Artifact> map = null;
798        if ( repositorySystem != null )
799        {
800            List<Dependency> deps;
801            DependencyManagement dependencyManagement = project.getDependencyManagement();
802            if ( ( dependencyManagement != null ) && ( ( deps = dependencyManagement.getDependencies() ) != null )
803                && ( deps.size() > 0 ) )
804            {
805                map = new HashMap<String, Artifact>();
806                for ( Dependency d : dependencyManagement.getDependencies() )
807                {
808                    Artifact artifact = repositorySystem.createDependencyArtifact( d );
809
810                    if ( artifact == null )
811                    {
812                        map = Collections.emptyMap();
813                    }
814
815                    map.put( d.getManagementKey(), artifact );
816                }
817            }
818            else
819            {
820                map = Collections.emptyMap();
821            }
822        }
823        project.setManagedVersionMap( map );
824
825        // release artifact repository
826        if ( project.getDistributionManagement() != null && project.getDistributionManagement().getRepository() != null )
827        {
828            try
829            {
830                DeploymentRepository r = project.getDistributionManagement().getRepository();
831                if ( !StringUtils.isEmpty( r.getId() ) && !StringUtils.isEmpty( r.getUrl() ) )
832                {
833                    ArtifactRepository repo =
834                        repositorySystem.buildArtifactRepository( project.getDistributionManagement().getRepository() );
835                    repositorySystem.injectProxy( projectBuildingRequest.getRepositorySession(), Arrays.asList( repo ) );
836                    repositorySystem.injectAuthentication( projectBuildingRequest.getRepositorySession(), Arrays.asList( repo ) );
837                    project.setReleaseArtifactRepository( repo );
838                }
839            }
840            catch ( InvalidRepositoryException e )
841            {
842                throw new IllegalStateException( "Failed to create release distribution repository for "
843                    + project.getId(), e );
844            }
845        }
846
847        // snapshot artifact repository
848        if ( project.getDistributionManagement() != null
849            && project.getDistributionManagement().getSnapshotRepository() != null )
850        {
851            try
852            {
853                DeploymentRepository r = project.getDistributionManagement().getSnapshotRepository();
854                if ( !StringUtils.isEmpty( r.getId() ) && !StringUtils.isEmpty( r.getUrl() ) )
855                {
856                    ArtifactRepository repo =
857                        repositorySystem.buildArtifactRepository( project.getDistributionManagement().getSnapshotRepository() );
858                    repositorySystem.injectProxy( projectBuildingRequest.getRepositorySession(), Arrays.asList( repo ) );
859                    repositorySystem.injectAuthentication( projectBuildingRequest.getRepositorySession(), Arrays.asList( repo ) );
860                    project.setSnapshotArtifactRepository( repo );
861                }
862            }
863            catch ( InvalidRepositoryException e )
864            {
865                throw new IllegalStateException( "Failed to create snapshot distribution repository for "
866                    + project.getId(), e );
867            }
868        }
869    }
870
871    private String findProfilesXml( ModelBuildingResult result, Map<File, Boolean> profilesXmls )
872    {
873        for ( String modelId : result.getModelIds() )
874        {
875            Model model = result.getRawModel( modelId );
876
877            File basedir = model.getProjectDirectory();
878            if ( basedir == null )
879            {
880                break;
881            }
882
883            Boolean profilesXml = profilesXmls.get( basedir );
884            if ( profilesXml == null )
885            {
886                profilesXml = new File( basedir, "profiles.xml" ).exists();
887                profilesXmls.put( basedir, profilesXml );
888            }
889            if ( profilesXml )
890            {
891                return modelId;
892            }
893        }
894
895        return null;
896    }
897
898    class InternalConfig
899    {
900
901        public final ProjectBuildingRequest request;
902
903        public final RepositorySystemSession session;
904
905        public final List<RemoteRepository> repositories;
906
907        public final ReactorModelPool modelPool;
908
909        InternalConfig( ProjectBuildingRequest request, ReactorModelPool modelPool )
910        {
911            this.request = request;
912            this.modelPool = modelPool;
913            session =
914                LegacyLocalRepositoryManager.overlay( request.getLocalRepository(), request.getRepositorySession(),
915                                                      repoSystem );
916            repositories = RepositoryUtils.toRepos( request.getRemoteRepositories() );
917        }
918
919    }
920
921}