001    package 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    
022    import org.apache.maven.RepositoryUtils;
023    import org.apache.maven.artifact.Artifact;
024    import org.apache.maven.artifact.ArtifactUtils;
025    import org.apache.maven.artifact.DependencyResolutionRequiredException;
026    import org.apache.maven.artifact.InvalidRepositoryException;
027    import org.apache.maven.artifact.factory.ArtifactFactory;
028    import org.apache.maven.artifact.repository.ArtifactRepository;
029    import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
030    import org.apache.maven.model.Build;
031    import org.apache.maven.model.CiManagement;
032    import org.apache.maven.model.Contributor;
033    import org.apache.maven.model.Dependency;
034    import org.apache.maven.model.DependencyManagement;
035    import org.apache.maven.model.Developer;
036    import org.apache.maven.model.DistributionManagement;
037    import org.apache.maven.model.Extension;
038    import org.apache.maven.model.IssueManagement;
039    import org.apache.maven.model.License;
040    import org.apache.maven.model.MailingList;
041    import org.apache.maven.model.Model;
042    import org.apache.maven.model.Organization;
043    import org.apache.maven.model.Parent;
044    import org.apache.maven.model.Plugin;
045    import org.apache.maven.model.PluginExecution;
046    import org.apache.maven.model.PluginManagement;
047    import org.apache.maven.model.Prerequisites;
048    import org.apache.maven.model.Profile;
049    import org.apache.maven.model.ReportPlugin;
050    import org.apache.maven.model.ReportSet;
051    import org.apache.maven.model.Reporting;
052    import org.apache.maven.model.Repository;
053    import org.apache.maven.model.Resource;
054    import org.apache.maven.model.Scm;
055    import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
056    import org.apache.maven.project.artifact.InvalidDependencyVersionException;
057    import org.apache.maven.project.artifact.MavenMetadataSource;
058    import org.apache.maven.repository.RepositorySystem;
059    import org.codehaus.plexus.classworlds.realm.ClassRealm;
060    import org.codehaus.plexus.logging.Logger;
061    import org.codehaus.plexus.util.StringUtils;
062    import org.codehaus.plexus.util.xml.Xpp3Dom;
063    import org.eclipse.aether.graph.DependencyFilter;
064    import org.eclipse.aether.repository.RemoteRepository;
065    
066    import java.io.File;
067    import java.io.IOException;
068    import java.io.Writer;
069    import java.util.ArrayList;
070    import java.util.Arrays;
071    import java.util.Collections;
072    import java.util.HashMap;
073    import java.util.HashSet;
074    import java.util.Iterator;
075    import java.util.LinkedHashMap;
076    import java.util.LinkedHashSet;
077    import java.util.List;
078    import java.util.Map;
079    import java.util.Properties;
080    import java.util.Set;
081    
082    /**
083     * The concern of the project is provide runtime values based on the model.
084     * <p/>
085     * The values in the model remain untouched but during the process of building a project notions
086     * like inheritance and interpolation can be added. This allows to have an entity which is useful in
087     * a runtime while preserving the model so that it can be marshalled and unmarshalled without being
088     * tainted by runtime requirements.
089     * <p/>
090     * We need to leave the model intact because we don't want the following:
091     * <ol>
092     * <li>We don't want interpolated values being written back into the model.
093     * <li>We don't want inherited values being written back into the model.
094     * </ol>
095     */
096    public class MavenProject
097        implements Cloneable
098    {
099        public static final String EMPTY_PROJECT_GROUP_ID = "unknown";
100    
101        public static final String EMPTY_PROJECT_ARTIFACT_ID = "empty-project";
102    
103        public static final String EMPTY_PROJECT_VERSION = "0";
104    
105        private Model model;
106    
107        private MavenProject parent;
108    
109        private File file;
110    
111        private Set<Artifact> resolvedArtifacts;
112    
113        private ArtifactFilter artifactFilter;
114    
115        private Set<Artifact> artifacts;
116    
117        private Artifact parentArtifact;
118    
119        private Set<Artifact> pluginArtifacts;
120    
121        private List<ArtifactRepository> remoteArtifactRepositories;
122    
123        private List<ArtifactRepository> pluginArtifactRepositories;
124    
125        private List<RemoteRepository> remoteProjectRepositories;
126    
127        private List<RemoteRepository> remotePluginRepositories;
128    
129        private List<Artifact> attachedArtifacts;
130    
131        private MavenProject executionProject;
132    
133        private List<MavenProject> collectedProjects;
134    
135        private List<String> compileSourceRoots = new ArrayList<String>();
136    
137        private List<String> testCompileSourceRoots = new ArrayList<String>();
138    
139        private List<String> scriptSourceRoots = new ArrayList<String>();
140    
141        private ArtifactRepository releaseArtifactRepository;
142    
143        private ArtifactRepository snapshotArtifactRepository;
144    
145        private List<Profile> activeProfiles = new ArrayList<Profile>();
146    
147        private Map<String, List<String>> injectedProfileIds = new LinkedHashMap<String, List<String>>();
148    
149        private Set<Artifact> dependencyArtifacts;
150    
151        private Artifact artifact;
152    
153        // calculated.
154        private Map<String, Artifact> artifactMap;
155    
156        private Model originalModel;
157    
158        private Map<String, Artifact> pluginArtifactMap;
159    
160        private Set<Artifact> reportArtifacts;
161    
162        private Map<String, Artifact> reportArtifactMap;
163    
164        private Set<Artifact> extensionArtifacts;
165    
166        private Map<String, Artifact> extensionArtifactMap;
167    
168        private Map<String, Artifact> managedVersionMap;
169    
170        private Map<String, MavenProject> projectReferences = new HashMap<String, MavenProject>();
171    
172        private boolean executionRoot;
173    
174        private Map<String, String> moduleAdjustments;
175    
176        private ProjectBuilder mavenProjectBuilder;
177    
178        private ProjectBuildingRequest projectBuilderConfiguration;
179    
180        private RepositorySystem repositorySystem;
181        
182        private File parentFile;
183    
184        private Map<String, Object> context;
185    
186        private ClassRealm classRealm;
187    
188        private DependencyFilter extensionDependencyFilter;
189    
190        private final Set<String> lifecyclePhases = Collections.synchronizedSet( new LinkedHashSet<String>() );
191    
192        private Logger logger;
193    
194        public MavenProject()
195        {
196            Model model = new Model();
197    
198            model.setGroupId( EMPTY_PROJECT_GROUP_ID );
199            model.setArtifactId( EMPTY_PROJECT_ARTIFACT_ID );
200            model.setVersion( EMPTY_PROJECT_VERSION );
201    
202            setModel( model );
203        }
204    
205        public MavenProject( Model model )
206        {
207            setModel( model );
208        }
209    
210        /**
211         * @deprecated use {@link #clone()} so subclasses can provide a copy of the same class
212         */
213        @Deprecated
214        public MavenProject( MavenProject project )
215        {
216            repositorySystem = project.repositorySystem;
217            logger = project.logger;
218            mavenProjectBuilder = project.mavenProjectBuilder;
219            projectBuilderConfiguration = project.projectBuilderConfiguration;
220            deepCopy( project );
221        }
222        
223        @Deprecated
224        public MavenProject( Model model, RepositorySystem repositorySystem )
225        {        
226            this.repositorySystem = repositorySystem;
227            setModel( model );
228        }
229    
230        public File getParentFile()
231        {
232            return parentFile;
233        }
234    
235        public void setParentFile( File parentFile )
236        {
237            this.parentFile = parentFile;
238        }
239    
240        /**
241         * Constructor
242         * 
243         * @param repositorySystem - may not be null
244         * @param mavenProjectBuilder
245         * @param projectBuilderConfiguration
246         * @throws InvalidRepositoryException
247         */
248        MavenProject( RepositorySystem repositorySystem, ProjectBuilder mavenProjectBuilder,
249                      ProjectBuildingRequest projectBuilderConfiguration, Logger logger )
250        {
251            if ( repositorySystem == null )
252            {
253                throw new IllegalArgumentException( "mavenTools: null" );
254            }
255    
256            this.mavenProjectBuilder = mavenProjectBuilder;
257            this.projectBuilderConfiguration = projectBuilderConfiguration;
258            this.repositorySystem = repositorySystem;
259            this.logger = logger;
260        }
261    
262        @Deprecated
263        public Set<Artifact> createArtifacts( ArtifactFactory artifactFactory, String inheritedScope, ArtifactFilter filter )
264            throws InvalidDependencyVersionException
265        {
266            return MavenMetadataSource.createArtifacts( artifactFactory, getDependencies(), inheritedScope, filter, this );
267        }
268    
269        // TODO: Find a way to use <relativePath/> here...it's tricky, because the moduleProject
270        // usually doesn't have a file associated with it yet.
271        public String getModulePathAdjustment( MavenProject moduleProject )
272            throws IOException
273        {
274            // FIXME: This is hacky. What if module directory doesn't match artifactid, and parent
275            // is coming from the repository??
276            String module = moduleProject.getArtifactId();
277    
278            File moduleFile = moduleProject.getFile();
279    
280            if ( moduleFile != null )
281            {
282                File moduleDir = moduleFile.getCanonicalFile().getParentFile();
283    
284                module = moduleDir.getName();
285            }
286    
287            if ( moduleAdjustments == null )
288            {
289                moduleAdjustments = new HashMap<String, String>();
290    
291                List<String> modules = getModules();
292                if ( modules != null )
293                {
294                    for ( String modulePath : modules )
295                    {
296                        String moduleName = modulePath;
297    
298                        if ( moduleName.endsWith( "/" ) || moduleName.endsWith( "\\" ) )
299                        {
300                            moduleName = moduleName.substring( 0, moduleName.length() - 1 );
301                        }
302    
303                        int lastSlash = moduleName.lastIndexOf( '/' );
304    
305                        if ( lastSlash < 0 )
306                        {
307                            lastSlash = moduleName.lastIndexOf( '\\' );
308                        }
309    
310                        String adjustment = null;
311    
312                        if ( lastSlash > -1 )
313                        {
314                            moduleName = moduleName.substring( lastSlash + 1 );
315                            adjustment = modulePath.substring( 0, lastSlash );
316                        }
317    
318                        moduleAdjustments.put( moduleName, adjustment );
319                    }
320                }
321            }
322    
323            return moduleAdjustments.get( module );
324        }
325    
326        // ----------------------------------------------------------------------
327        // Accessors
328        // ----------------------------------------------------------------------
329    
330        public Artifact getArtifact()
331        {
332            return artifact;
333        }
334    
335        public void setArtifact( Artifact artifact )
336        {
337            this.artifact = artifact;
338        }
339    
340        //@todo I would like to get rid of this. jvz.
341        public Model getModel()
342        {
343            return model;
344        }
345    
346        public MavenProject getParent()
347        {
348            if ( parent == null )
349            {
350                /*
351                 * TODO: This is suboptimal. Without a cache in the project builder, rebuilding the parent chain currently
352                 * causes O(n^2) parser invocations for an inheritance hierarchy of depth n.
353                 */
354                if ( parentFile != null )
355                {
356                    checkProjectBuildingRequest();
357                    ProjectBuildingRequest request = new DefaultProjectBuildingRequest( projectBuilderConfiguration );
358                    request.setRemoteRepositories( getRemoteArtifactRepositories() );
359    
360                    try
361                    {
362                        parent = mavenProjectBuilder.build( parentFile, request ).getProject();
363                    }
364                    catch ( ProjectBuildingException e )
365                    {
366                        throw new IllegalStateException( "Failed to build parent project for " + getId(), e );
367                    }
368                }
369                else if ( model.getParent() != null )
370                {
371                    checkProjectBuildingRequest();
372                    ProjectBuildingRequest request = new DefaultProjectBuildingRequest( projectBuilderConfiguration );
373                    request.setRemoteRepositories( getRemoteArtifactRepositories() );
374    
375                    try
376                    {
377                        parent = mavenProjectBuilder.build( getParentArtifact(), request ).getProject();
378                    }
379                    catch ( ProjectBuildingException e )
380                    {
381                        throw new IllegalStateException( "Failed to build parent project for " + getId(), e );
382                    }
383                }
384            }
385            return parent;
386        }
387    
388        public void setParent( MavenProject parent )
389        {
390            this.parent = parent;
391        }
392        
393        public boolean hasParent()
394        {
395            return getParent() != null;
396        }
397    
398        public File getFile()
399        {
400            return file;
401        }
402    
403        public void setFile( File file )
404        {
405            this.file = file;
406        }
407    
408        public File getBasedir()
409        {
410            if ( getFile() != null )
411            {
412                return getFile().getParentFile();
413            }
414            else
415            {
416                // repository based POM
417                return null;
418            }
419        }
420    
421        public void setDependencies( List<Dependency> dependencies )
422        {
423            getModel().setDependencies( dependencies );
424        }
425    
426        public List<Dependency> getDependencies()
427        {
428            return getModel().getDependencies();
429        }
430    
431        public DependencyManagement getDependencyManagement()
432        {
433            return getModel().getDependencyManagement();
434        }
435    
436        // ----------------------------------------------------------------------
437        // Test and compile sourceroots.
438        // ----------------------------------------------------------------------
439    
440        private void addPath( List<String> paths, String path )
441        {
442            if ( path != null )
443            {
444                path = path.trim();
445                if ( path.length() > 0 )
446                {
447                    File file = new File( path );
448                    if ( file.isAbsolute() )
449                    {
450                        path = file.getAbsolutePath();
451                    }
452                    else
453                    {
454                        path = new File( getBasedir(), path ).getAbsolutePath();
455                    }
456    
457                    if ( !paths.contains( path ) )
458                    {
459                        paths.add( path );
460                    }
461                }
462            }
463        }
464    
465        public void addCompileSourceRoot( String path )
466        {
467            addPath( getCompileSourceRoots(), path );
468        }
469    
470        public void addScriptSourceRoot( String path )
471        {
472            if ( path != null )
473            {
474                path = path.trim();
475                if ( path.length() != 0 )
476                {
477                    if ( !getScriptSourceRoots().contains( path ) )
478                    {
479                        getScriptSourceRoots().add( path );
480                    }
481                }
482            }
483        }
484    
485        public void addTestCompileSourceRoot( String path )
486        {
487            addPath( getTestCompileSourceRoots(), path );
488        }
489    
490        public List<String> getCompileSourceRoots()
491        {
492            return compileSourceRoots;
493        }
494    
495        public List<String> getScriptSourceRoots()
496        {
497            return scriptSourceRoots;
498        }
499    
500        public List<String> getTestCompileSourceRoots()
501        {
502            return testCompileSourceRoots;
503        }
504    
505        public List<String> getCompileClasspathElements()
506            throws DependencyResolutionRequiredException
507        {
508            List<String> list = new ArrayList<String>( getArtifacts().size() + 1 );
509    
510            String d = getBuild().getOutputDirectory();
511            if ( d != null )
512            {
513                list.add( d );
514            }
515    
516            for ( Artifact a : getArtifacts() )
517            {                        
518                if ( a.getArtifactHandler().isAddedToClasspath() )
519                {
520                    // TODO: let the scope handler deal with this
521                    if ( Artifact.SCOPE_COMPILE.equals( a.getScope() ) || Artifact.SCOPE_PROVIDED.equals( a.getScope() ) || Artifact.SCOPE_SYSTEM.equals( a.getScope() ) )
522                    {
523                        addArtifactPath( a, list );
524                    }
525                }
526            }
527    
528            return list;
529        }
530    
531        @Deprecated
532        public List<Artifact> getCompileArtifacts()
533        {
534            List<Artifact> list = new ArrayList<Artifact>( getArtifacts().size() );
535    
536            for ( Artifact a : getArtifacts() )
537            {
538                // TODO: classpath check doesn't belong here - that's the other method
539                if ( a.getArtifactHandler().isAddedToClasspath() )
540                {
541                    // TODO: let the scope handler deal with this
542                    if ( Artifact.SCOPE_COMPILE.equals( a.getScope() ) || Artifact.SCOPE_PROVIDED.equals( a.getScope() ) || Artifact.SCOPE_SYSTEM.equals( a.getScope() ) )
543                    {
544                        list.add( a );
545                    }
546                }
547            }
548            return list;
549        }
550    
551        @Deprecated
552        public List<Dependency> getCompileDependencies()
553        {
554            Set<Artifact> artifacts = getArtifacts();
555    
556            if ( ( artifacts == null ) || artifacts.isEmpty() )
557            {
558                return Collections.emptyList();
559            }
560    
561            List<Dependency> list = new ArrayList<Dependency>( artifacts.size() );
562    
563            for ( Artifact a : getArtifacts()  )
564            {
565                // TODO: let the scope handler deal with this
566                if ( Artifact.SCOPE_COMPILE.equals( a.getScope() ) || Artifact.SCOPE_PROVIDED.equals( a.getScope() ) || Artifact.SCOPE_SYSTEM.equals( a.getScope() ) )
567                {
568                    Dependency dependency = new Dependency();
569    
570                    dependency.setArtifactId( a.getArtifactId() );
571                    dependency.setGroupId( a.getGroupId() );
572                    dependency.setVersion( a.getVersion() );
573                    dependency.setScope( a.getScope() );
574                    dependency.setType( a.getType() );
575                    dependency.setClassifier( a.getClassifier() );
576    
577                    list.add( dependency );
578                }
579            }
580            return list;
581        }
582    
583        //TODO: this checking for file == null happens because the resolver has been confused about the root
584        // artifact or not. things like the stupid dummy artifact coming from surefire.
585        public List<String> getTestClasspathElements()
586            throws DependencyResolutionRequiredException
587        {
588            List<String> list = new ArrayList<String>( getArtifacts().size() + 2 );
589    
590            String d = getBuild().getTestOutputDirectory();
591            if ( d != null )
592            {
593                list.add( d );
594            }
595    
596            d = getBuild().getOutputDirectory();
597            if ( d != null )
598            {
599                list.add( d );
600            }
601            
602            for ( Artifact a : getArtifacts() )
603            {            
604                if ( a.getArtifactHandler().isAddedToClasspath() )
605                {                
606                    addArtifactPath( a, list );
607                }
608            }
609    
610            return list;
611        }
612    
613        @Deprecated
614        public List<Artifact> getTestArtifacts()
615        {
616            List<Artifact> list = new ArrayList<Artifact>( getArtifacts().size() );
617    
618            for ( Artifact a : getArtifacts() )
619            {
620                // TODO: classpath check doesn't belong here - that's the other method
621                if ( a.getArtifactHandler().isAddedToClasspath() )
622                {
623                    list.add( a );
624                }
625            }
626            return list;
627        }
628    
629        @Deprecated
630        public List<Dependency> getTestDependencies()
631        {
632            Set<Artifact> artifacts = getArtifacts();
633    
634            if ( ( artifacts == null ) || artifacts.isEmpty() )
635            {
636                return Collections.emptyList();
637            }
638    
639            List<Dependency> list = new ArrayList<Dependency>( artifacts.size() );
640    
641            for ( Artifact a : getArtifacts()  )
642            {
643                Dependency dependency = new Dependency();
644    
645                dependency.setArtifactId( a.getArtifactId() );
646                dependency.setGroupId( a.getGroupId() );
647                dependency.setVersion( a.getVersion() );
648                dependency.setScope( a.getScope() );
649                dependency.setType( a.getType() );
650                dependency.setClassifier( a.getClassifier() );
651    
652                list.add( dependency );
653            }
654            return list;
655        }
656    
657        public List<String> getRuntimeClasspathElements()
658            throws DependencyResolutionRequiredException
659        {
660            List<String> list = new ArrayList<String>( getArtifacts().size() + 1 );
661    
662            String d = getBuild().getOutputDirectory();
663            if ( d != null )
664            {
665                list.add( d );
666            }
667    
668            for ( Artifact a : getArtifacts() )
669            {
670                if ( a.getArtifactHandler().isAddedToClasspath() )
671                {
672                    // TODO: let the scope handler deal with this
673                    if ( Artifact.SCOPE_COMPILE.equals( a.getScope() ) || Artifact.SCOPE_RUNTIME.equals( a.getScope() ) )
674                    {
675                        addArtifactPath( a, list );
676                    }
677                }
678            }
679            return list;
680        }
681    
682        @Deprecated
683        public List<Artifact> getRuntimeArtifacts()
684        {
685            List<Artifact> list = new ArrayList<Artifact>( getArtifacts().size() );
686    
687            for ( Artifact a : getArtifacts()  )
688            {
689                // TODO: classpath check doesn't belong here - that's the other method
690                if ( a.getArtifactHandler().isAddedToClasspath() )
691                {
692                    // TODO: let the scope handler deal with this
693                    if ( Artifact.SCOPE_COMPILE.equals( a.getScope() ) || Artifact.SCOPE_RUNTIME.equals( a.getScope() ) )
694                    {
695                        list.add( a );
696                    }
697                }
698            }
699            return list;
700        }
701    
702        @Deprecated
703        public List<Dependency> getRuntimeDependencies()
704        {
705            Set<Artifact> artifacts = getArtifacts();
706    
707            if ( ( artifacts == null ) || artifacts.isEmpty() )
708            {
709                return Collections.emptyList();
710            }
711    
712            List<Dependency> list = new ArrayList<Dependency>( artifacts.size() );
713    
714            for ( Artifact a : getArtifacts()  )
715            {
716                // TODO: let the scope handler deal with this
717                if ( Artifact.SCOPE_COMPILE.equals( a.getScope() ) || Artifact.SCOPE_RUNTIME.equals( a.getScope() ) )
718                {
719                    Dependency dependency = new Dependency();
720    
721                    dependency.setArtifactId( a.getArtifactId() );
722                    dependency.setGroupId( a.getGroupId() );
723                    dependency.setVersion( a.getVersion() );
724                    dependency.setScope( a.getScope() );
725                    dependency.setType( a.getType() );
726                    dependency.setClassifier( a.getClassifier() );
727    
728                    list.add( dependency );
729                }
730            }
731            return list;
732        }
733    
734        public List<String> getSystemClasspathElements()
735            throws DependencyResolutionRequiredException
736        {
737            List<String> list = new ArrayList<String>( getArtifacts().size() );
738    
739            String d = getBuild().getOutputDirectory();
740            if ( d != null )
741            {
742                list.add( d );
743            }
744    
745            for ( Artifact a : getArtifacts() )
746            {
747                if ( a.getArtifactHandler().isAddedToClasspath() )
748                {
749                    // TODO: let the scope handler deal with this
750                    if ( Artifact.SCOPE_SYSTEM.equals( a.getScope() ) )
751                    {
752                        addArtifactPath( a, list );
753                    }
754                }
755            }
756            return list;
757        }
758    
759        @Deprecated
760        public List<Artifact> getSystemArtifacts()
761        {
762            List<Artifact> list = new ArrayList<Artifact>( getArtifacts().size() );
763    
764            for ( Artifact a : getArtifacts()  )
765            {
766                // TODO: classpath check doesn't belong here - that's the other method
767                if ( a.getArtifactHandler().isAddedToClasspath() )
768                {
769                    // TODO: let the scope handler deal with this
770                    if ( Artifact.SCOPE_SYSTEM.equals( a.getScope() ) )
771                    {
772                        list.add( a );
773                    }
774                }
775            }
776            return list;
777        }
778    
779        @Deprecated
780        public List<Dependency> getSystemDependencies()
781        {
782            Set<Artifact> artifacts = getArtifacts();
783    
784            if ( ( artifacts == null ) || artifacts.isEmpty() )
785            {
786                return Collections.emptyList();
787            }
788    
789            List<Dependency> list = new ArrayList<Dependency>( artifacts.size() );
790    
791            for ( Artifact a : getArtifacts()  )
792            {
793                // TODO: let the scope handler deal with this
794                if ( Artifact.SCOPE_SYSTEM.equals( a.getScope() ) )
795                {
796                    Dependency dependency = new Dependency();
797    
798                    dependency.setArtifactId( a.getArtifactId() );
799                    dependency.setGroupId( a.getGroupId() );
800                    dependency.setVersion( a.getVersion() );
801                    dependency.setScope( a.getScope() );
802                    dependency.setType( a.getType() );
803                    dependency.setClassifier( a.getClassifier() );
804    
805                    list.add( dependency );
806                }
807            }
808            return list;
809        }
810    
811        // ----------------------------------------------------------------------
812        // Delegate to the model
813        // ----------------------------------------------------------------------
814    
815        public void setModelVersion( String pomVersion )
816        {
817            getModel().setModelVersion( pomVersion );
818        }
819    
820        public String getModelVersion()
821        {
822            return getModel().getModelVersion();
823        }
824    
825        public String getId()
826        {
827            return getModel().getId();
828        }
829    
830        public void setGroupId( String groupId )
831        {
832            getModel().setGroupId( groupId );
833        }
834    
835        public String getGroupId()
836        {
837            String groupId = getModel().getGroupId();
838    
839            if ( ( groupId == null ) && ( getModel().getParent() != null ) )
840            {
841                groupId = getModel().getParent().getGroupId();
842            }
843    
844            return groupId;
845        }
846    
847        public void setArtifactId( String artifactId )
848        {
849            getModel().setArtifactId( artifactId );
850        }
851    
852        public String getArtifactId()
853        {
854            return getModel().getArtifactId();
855        }
856    
857        public void setName( String name )
858        {
859            getModel().setName( name );
860        }
861    
862        public String getName()
863        {
864            // TODO: this should not be allowed to be null.
865            if ( getModel().getName() != null )
866            {
867                return getModel().getName();
868            }
869            else
870            {
871                return getArtifactId();
872            }
873        }
874    
875        public void setVersion( String version )
876        {
877            getModel().setVersion( version );
878        }
879    
880        public String getVersion()
881        {
882            String version = getModel().getVersion();
883    
884            if ( ( version == null ) && ( getModel().getParent() != null ) )
885            {
886                version = getModel().getParent().getVersion();
887            }
888    
889            return version;
890        }
891    
892        public String getPackaging()
893        {
894            return getModel().getPackaging();
895        }
896    
897        public void setPackaging( String packaging )
898        {
899            getModel().setPackaging( packaging );
900        }
901    
902        public void setInceptionYear( String inceptionYear )
903        {
904            getModel().setInceptionYear( inceptionYear );
905        }
906    
907        public String getInceptionYear()
908        {
909            return getModel().getInceptionYear();
910        }
911    
912        public void setUrl( String url )
913        {
914            getModel().setUrl( url );
915        }
916    
917        public String getUrl()
918        {
919            return getModel().getUrl();
920        }
921    
922        public Prerequisites getPrerequisites()
923        {
924            return getModel().getPrerequisites();
925        }
926    
927        public void setIssueManagement( IssueManagement issueManagement )
928        {
929            getModel().setIssueManagement( issueManagement );
930        }
931    
932        public CiManagement getCiManagement()
933        {
934            return getModel().getCiManagement();
935        }
936    
937        public void setCiManagement( CiManagement ciManagement )
938        {
939            getModel().setCiManagement( ciManagement );
940        }
941    
942        public IssueManagement getIssueManagement()
943        {
944            return getModel().getIssueManagement();
945        }
946    
947        public void setDistributionManagement( DistributionManagement distributionManagement )
948        {
949            getModel().setDistributionManagement( distributionManagement );
950        }
951    
952        public DistributionManagement getDistributionManagement()
953        {
954            return getModel().getDistributionManagement();
955        }
956    
957        public void setDescription( String description )
958        {
959            getModel().setDescription( description );
960        }
961    
962        public String getDescription()
963        {
964            return getModel().getDescription();
965        }
966    
967        public void setOrganization( Organization organization )
968        {
969            getModel().setOrganization( organization );
970        }
971    
972        public Organization getOrganization()
973        {
974            return getModel().getOrganization();
975        }
976    
977        public void setScm( Scm scm )
978        {
979            getModel().setScm( scm );
980        }
981    
982        public Scm getScm()
983        {
984            return getModel().getScm();
985        }
986    
987        public void setMailingLists( List<MailingList> mailingLists )
988        {
989            getModel().setMailingLists( mailingLists );
990        }
991    
992        public List<MailingList> getMailingLists()
993        {
994            return getModel().getMailingLists();
995        }
996    
997        public void addMailingList( MailingList mailingList )
998        {
999            getModel().addMailingList( mailingList );
1000        }
1001    
1002        public void setDevelopers( List<Developer> developers )
1003        {
1004            getModel().setDevelopers( developers );
1005        }
1006    
1007        public List<Developer> getDevelopers()
1008        {
1009            return getModel().getDevelopers();
1010        }
1011    
1012        public void addDeveloper( Developer developer )
1013        {
1014            getModel().addDeveloper( developer );
1015        }
1016    
1017        public void setContributors( List<Contributor> contributors )
1018        {
1019            getModel().setContributors( contributors );
1020        }
1021    
1022        public List<Contributor> getContributors()
1023        {
1024            return getModel().getContributors();
1025        }
1026    
1027        public void addContributor( Contributor contributor )
1028        {
1029            getModel().addContributor( contributor );
1030        }
1031    
1032        public void setBuild( Build build )
1033        {
1034            getModel().setBuild( build );
1035        }
1036    
1037        public Build getBuild()
1038        {
1039            return getModelBuild();
1040        }
1041    
1042        public List<Resource> getResources()
1043        {
1044            return getBuild().getResources();
1045        }
1046    
1047        public List<Resource> getTestResources()
1048        {
1049            return getBuild().getTestResources();
1050        }
1051    
1052        public void addResource( Resource resource )
1053        {
1054            getBuild().addResource( resource );
1055        }
1056    
1057        public void addTestResource( Resource testResource )
1058        {
1059            getBuild().addTestResource( testResource );
1060        }
1061    
1062        @Deprecated
1063        public void setReporting( Reporting reporting )
1064        {
1065            getModel().setReporting( reporting );
1066        }
1067    
1068        @Deprecated
1069        public Reporting getReporting()
1070        {
1071            return getModel().getReporting();
1072        }
1073    
1074        public void setLicenses( List<License> licenses )
1075        {
1076            getModel().setLicenses( licenses );
1077        }
1078    
1079        public List<License> getLicenses()
1080        {
1081            return getModel().getLicenses();
1082        }
1083    
1084        public void addLicense( License license )
1085        {
1086            getModel().addLicense( license );
1087        }
1088    
1089        public void setArtifacts( Set<Artifact> artifacts )
1090        {
1091            this.artifacts = artifacts;
1092    
1093            // flush the calculated artifactMap
1094            artifactMap = null;
1095        }
1096    
1097        /**
1098         * All dependencies that this project has, including transitive ones. Contents are lazily
1099         * populated, so depending on what phases have run dependencies in some scopes won't be
1100         * included. eg. if only compile phase has run, dependencies with scope test won't be included.
1101         * 
1102         * @return {@link Set} &lt; {@link Artifact} >
1103         * @see #getDependencyArtifacts() to get only direct dependencies
1104         */
1105        public Set<Artifact> getArtifacts()
1106        {
1107            if ( artifacts == null )
1108            {
1109                if ( artifactFilter == null || resolvedArtifacts == null )
1110                {
1111                    artifacts = new LinkedHashSet<Artifact>();
1112                }
1113                else
1114                {
1115                    artifacts = new LinkedHashSet<Artifact>( resolvedArtifacts.size() * 2 );
1116                    for ( Artifact artifact : resolvedArtifacts )
1117                    {
1118                        if ( artifactFilter.include( artifact ) )
1119                        {
1120                            artifacts.add( artifact );
1121                        }
1122                    }
1123                }
1124            }
1125            return artifacts;
1126        }
1127    
1128        public Map<String, Artifact> getArtifactMap()
1129        {
1130            if ( artifactMap == null )
1131            {
1132                artifactMap = ArtifactUtils.artifactMapByVersionlessId( getArtifacts() );
1133            }
1134            return artifactMap;
1135        }
1136    
1137        public void setPluginArtifacts( Set<Artifact> pluginArtifacts )
1138        {
1139            this.pluginArtifacts = pluginArtifacts;
1140    
1141            this.pluginArtifactMap = null;
1142        }
1143    
1144        public Set<Artifact> getPluginArtifacts()
1145        {
1146            if ( pluginArtifacts != null )
1147            {
1148                return pluginArtifacts;
1149            }
1150    
1151            pluginArtifacts = new HashSet<Artifact>();
1152    
1153            if ( repositorySystem != null )
1154            {
1155                for ( Plugin p : getBuildPlugins() )
1156                {
1157                    Artifact artifact = repositorySystem.createPluginArtifact( p );
1158    
1159                    if ( artifact != null )
1160                    {
1161                        pluginArtifacts.add( artifact );
1162                    }
1163                }
1164            }
1165    
1166            pluginArtifactMap = null;
1167    
1168            return pluginArtifacts;
1169        }
1170    
1171        public Map<String, Artifact> getPluginArtifactMap()
1172        {
1173            if ( pluginArtifactMap == null )
1174            {
1175                pluginArtifactMap = ArtifactUtils.artifactMapByVersionlessId( getPluginArtifacts() );
1176            }
1177    
1178            return pluginArtifactMap;
1179        }
1180    
1181        @Deprecated
1182        public void setReportArtifacts( Set<Artifact> reportArtifacts )
1183        {
1184            this.reportArtifacts = reportArtifacts;
1185    
1186            reportArtifactMap = null;
1187        }
1188    
1189        @Deprecated
1190        public Set<Artifact> getReportArtifacts()
1191        {
1192            if ( reportArtifacts != null )
1193            {
1194                return reportArtifacts;
1195            }
1196    
1197            reportArtifacts = new HashSet<Artifact>();
1198    
1199            if ( repositorySystem != null )
1200            {
1201                for ( ReportPlugin p : getReportPlugins() )
1202                {
1203                    Plugin pp = new Plugin();
1204                    pp.setGroupId( p.getGroupId() );
1205                    pp.setArtifactId( p.getArtifactId() );
1206                    pp.setVersion( p.getVersion() );
1207    
1208                    Artifact artifact = repositorySystem.createPluginArtifact( pp );
1209    
1210                    if ( artifact != null )
1211                    {
1212                        reportArtifacts.add( artifact );
1213                    }
1214                }
1215            }
1216    
1217            reportArtifactMap = null;
1218    
1219            return reportArtifacts;
1220        }
1221    
1222        @Deprecated
1223        public Map<String, Artifact> getReportArtifactMap()
1224        {
1225            if ( reportArtifactMap == null )
1226            {
1227                reportArtifactMap = ArtifactUtils.artifactMapByVersionlessId( getReportArtifacts() );
1228            }
1229    
1230            return reportArtifactMap;
1231        }
1232    
1233        public void setExtensionArtifacts( Set<Artifact> extensionArtifacts )
1234        {
1235            this.extensionArtifacts = extensionArtifacts;
1236    
1237            extensionArtifactMap = null;
1238        }
1239    
1240        public Set<Artifact> getExtensionArtifacts()
1241        {
1242            if ( extensionArtifacts != null )
1243            {
1244                return extensionArtifacts;
1245            }
1246            extensionArtifacts = new HashSet<Artifact>();
1247            List<Extension> extensions = getBuildExtensions();
1248            if ( extensions != null )
1249            {
1250                for ( Extension ext : extensions )
1251                {
1252                    String version;
1253                    if ( StringUtils.isEmpty( ext.getVersion() ) )
1254                    {
1255                        version = "RELEASE";
1256                    }
1257                    else
1258                    {
1259                        version = ext.getVersion();
1260                    }
1261    
1262                    Artifact artifact =
1263                        repositorySystem.createArtifact( ext.getGroupId(), ext.getArtifactId(), version, null, "jar" );
1264    
1265                    if ( artifact != null )
1266                    {
1267                        extensionArtifacts.add( artifact );
1268                    }
1269                }
1270            }
1271            extensionArtifactMap = null;
1272            return extensionArtifacts;
1273        }
1274    
1275        public Map<String, Artifact> getExtensionArtifactMap()
1276        {
1277            if ( extensionArtifactMap == null )
1278            {
1279                extensionArtifactMap = ArtifactUtils.artifactMapByVersionlessId( getExtensionArtifacts() );
1280            }
1281    
1282            return extensionArtifactMap;
1283        }
1284    
1285        public void setParentArtifact( Artifact parentArtifact )
1286        {
1287            this.parentArtifact = parentArtifact;
1288        }
1289    
1290        public Artifact getParentArtifact()
1291        {
1292            if ( parentArtifact == null && model.getParent() != null )
1293            {
1294                Parent p = model.getParent();
1295                parentArtifact = repositorySystem.createProjectArtifact( p.getGroupId(), p.getArtifactId(), p.getVersion() );
1296            }
1297            return parentArtifact;
1298        }
1299    
1300        public List<Repository> getRepositories()
1301        {
1302            return getModel().getRepositories();
1303        }
1304    
1305        // ----------------------------------------------------------------------
1306        // Plugins
1307        // ----------------------------------------------------------------------
1308    
1309        @Deprecated
1310        public List<ReportPlugin> getReportPlugins()
1311        {
1312            if ( getModel().getReporting() == null )
1313            {
1314                return Collections.emptyList();
1315            }
1316            return getModel().getReporting().getPlugins();
1317    
1318        }
1319    
1320        public List<Plugin> getBuildPlugins()
1321        {
1322            if ( getModel().getBuild() == null )
1323            {
1324                return Collections.emptyList();
1325            }
1326            return getModel().getBuild().getPlugins();
1327        }
1328    
1329        public List<String> getModules()
1330        {
1331            return getModel().getModules();
1332        }
1333    
1334        public PluginManagement getPluginManagement()
1335        {
1336            PluginManagement pluginMgmt = null;
1337    
1338            Build build = getModel().getBuild();
1339            if ( build != null )
1340            {
1341                pluginMgmt = build.getPluginManagement();
1342            }
1343    
1344            return pluginMgmt;
1345        }
1346    
1347        private Build getModelBuild()
1348        {
1349            Build build = getModel().getBuild();
1350    
1351            if ( build == null )
1352            {
1353                build = new Build();
1354    
1355                getModel().setBuild( build );
1356            }
1357    
1358            return build;
1359        }
1360    
1361        public void setRemoteArtifactRepositories( List<ArtifactRepository> remoteArtifactRepositories )
1362        {
1363            this.remoteArtifactRepositories = remoteArtifactRepositories;
1364            this.remoteProjectRepositories = RepositoryUtils.toRepos( getRemoteArtifactRepositories() );
1365        }
1366    
1367        public List<ArtifactRepository> getRemoteArtifactRepositories()
1368        {
1369            if ( remoteArtifactRepositories == null )
1370            {
1371                remoteArtifactRepositories = new ArrayList<ArtifactRepository>();
1372            }
1373    
1374            return remoteArtifactRepositories;
1375        }
1376    
1377        public void setPluginArtifactRepositories( List<ArtifactRepository> pluginArtifactRepositories )
1378        {
1379            this.pluginArtifactRepositories = pluginArtifactRepositories;
1380            this.remotePluginRepositories = RepositoryUtils.toRepos( getPluginArtifactRepositories() );
1381        }
1382    
1383        /**
1384         * @return a list of ArtifactRepository objects constructed from the Repository objects returned
1385         *         by getPluginRepositories.
1386         */
1387        public List<ArtifactRepository> getPluginArtifactRepositories()
1388        {
1389            if ( pluginArtifactRepositories == null )
1390            {
1391                pluginArtifactRepositories = new ArrayList<ArtifactRepository>();
1392            }
1393    
1394            return pluginArtifactRepositories;
1395        }
1396    
1397        public ArtifactRepository getDistributionManagementArtifactRepository()
1398        {
1399            return getArtifact().isSnapshot() && ( getSnapshotArtifactRepository() != null ) ? getSnapshotArtifactRepository() : getReleaseArtifactRepository();
1400        }
1401    
1402        public List<Repository> getPluginRepositories()
1403        {
1404            return getModel().getPluginRepositories();
1405        }
1406    
1407        public List<RemoteRepository> getRemoteProjectRepositories()
1408        {
1409            return remoteProjectRepositories;
1410        }
1411    
1412        public List<RemoteRepository> getRemotePluginRepositories()
1413        {
1414            return remotePluginRepositories;
1415        }
1416    
1417        public void setActiveProfiles( List<Profile> activeProfiles )
1418        {
1419            this.activeProfiles = activeProfiles;
1420        }
1421    
1422        public List<Profile> getActiveProfiles()
1423        {
1424            return activeProfiles;
1425        }
1426    
1427        public void setInjectedProfileIds( String source, List<String> injectedProfileIds )
1428        {
1429            if ( injectedProfileIds != null )
1430            {
1431                this.injectedProfileIds.put( source, new ArrayList<String>( injectedProfileIds ) );
1432            }
1433            else
1434            {
1435                this.injectedProfileIds.remove( source );
1436            }
1437        }
1438    
1439        /**
1440         * Gets the identifiers of all profiles that contributed to this project's effective model. This includes active
1441         * profiles from the project's POM and all its parent POMs as well as from external sources like the {@code
1442         * settings.xml}. The profile identifiers are grouped by the identifier of their source, e.g. {@code
1443         * <groupId>:<artifactId>:<version>} for a POM profile or {@code external} for profiles from the {@code
1444         * settings.xml}.
1445         * 
1446         * @return The identifiers of all injected profiles, indexed by the source from which the profiles originated, never
1447         *         {@code null}.
1448         */
1449        public Map<String, List<String>> getInjectedProfileIds()
1450        {
1451            return this.injectedProfileIds;
1452        }
1453    
1454        private String logStringForArtifactFile( Artifact a )
1455        {
1456            if ( a.getFile() != null )
1457            {
1458                return a.getFile().getAbsolutePath();
1459            }
1460            else
1461            {
1462                return "(no path)";
1463            }
1464        }
1465    
1466        /**
1467         * Add or replace an artifact.
1468         * In spite of the 'throws' declaration on this API, this method has never thrown an exception since Maven 3.0.x.
1469         * Historically, it logged and ignored a second addition of the same g/a/v/c/t. Now it replaces the file for
1470         * the artifact, so that plugins (e.g. shade) can change the pathname of the file for a particular set of
1471         * coordinates.
1472         * @param artifact the artifact to add or replace.
1473         * @throws DuplicateArtifactAttachmentException
1474         */
1475        public void addAttachedArtifact( Artifact artifact )
1476            throws DuplicateArtifactAttachmentException
1477        {
1478            List<Artifact> attachedArtifacts = getAttachedArtifacts();
1479            for ( int ax = 0; ax < attachedArtifacts.size(); ax++ )
1480            {
1481                Artifact a = attachedArtifacts.get( ax );
1482                if ( a.equals( artifact ) )
1483                {
1484                    if ( logger != null )
1485                    {
1486                        logger.debug( String.format( "Replacing attached artifact %s. Old path %s, new path %s. ",
1487                                                     a,
1488                                                     logStringForArtifactFile( a ),
1489                                                     logStringForArtifactFile( artifact ) ) );
1490                    }
1491                    attachedArtifacts.set( ax, artifact );
1492                    return;
1493                }
1494            }
1495    
1496            getAttachedArtifacts().add( artifact );
1497        }
1498    
1499        public List<Artifact> getAttachedArtifacts()
1500        {
1501            if ( attachedArtifacts == null )
1502            {
1503                attachedArtifacts = new ArrayList<Artifact>();
1504            }
1505            return attachedArtifacts;
1506        }
1507    
1508        public Xpp3Dom getGoalConfiguration( String pluginGroupId, String pluginArtifactId, String executionId,
1509                                             String goalId )
1510        {
1511            Xpp3Dom dom = null;
1512    
1513            if ( getBuildPlugins() != null )
1514            {
1515                for ( Plugin plugin : getBuildPlugins() )
1516                {
1517                    if ( pluginGroupId.equals( plugin.getGroupId() ) && pluginArtifactId.equals( plugin.getArtifactId() ) )
1518                    {
1519                        dom = (Xpp3Dom) plugin.getConfiguration();
1520    
1521                        if ( executionId != null )
1522                        {
1523                            PluginExecution execution = plugin.getExecutionsAsMap().get( executionId );
1524                            if ( execution != null )
1525                            {
1526                                // NOTE: The PluginConfigurationExpander already merged the plugin-level config in
1527                                dom = (Xpp3Dom) execution.getConfiguration();
1528                            }
1529                        }
1530                        break;
1531                    }
1532                }
1533            }
1534    
1535            if ( dom != null )
1536            {
1537                // make a copy so the original in the POM doesn't get messed with
1538                dom = new Xpp3Dom( dom );
1539            }
1540    
1541            return dom;
1542        }
1543    
1544        @Deprecated
1545        public Xpp3Dom getReportConfiguration( String pluginGroupId, String pluginArtifactId, String reportSetId )
1546        {
1547            Xpp3Dom dom = null;
1548    
1549            // ----------------------------------------------------------------------
1550            // I would like to be able to lookup the Mojo object using a key but
1551            // we have a limitation in modello that will be remedied shortly. So
1552            // for now I have to iterate through and see what we have.
1553            // ----------------------------------------------------------------------
1554    
1555            if ( getReportPlugins() != null )
1556            {
1557                for ( ReportPlugin plugin : getReportPlugins() )
1558                {
1559                    if ( pluginGroupId.equals( plugin.getGroupId() ) && pluginArtifactId.equals( plugin.getArtifactId() ) )
1560                    {
1561                        dom = (Xpp3Dom) plugin.getConfiguration();
1562    
1563                        if ( reportSetId != null )
1564                        {
1565                            ReportSet reportSet = plugin.getReportSetsAsMap().get( reportSetId );
1566                            if ( reportSet != null )
1567                            {
1568                                Xpp3Dom executionConfiguration = (Xpp3Dom) reportSet.getConfiguration();
1569                                if ( executionConfiguration != null )
1570                                {
1571                                    Xpp3Dom newDom = new Xpp3Dom( executionConfiguration );
1572                                    dom = Xpp3Dom.mergeXpp3Dom( newDom, dom );
1573                                }
1574                            }
1575                        }
1576                        break;
1577                    }
1578                }
1579            }
1580    
1581            if ( dom != null )
1582            {
1583                // make a copy so the original in the POM doesn't get messed with
1584                dom = new Xpp3Dom( dom );
1585            }
1586    
1587            return dom;
1588        }
1589    
1590        public MavenProject getExecutionProject()
1591        {
1592            return ( executionProject == null ? this : executionProject );
1593        }
1594    
1595        public void setExecutionProject( MavenProject executionProject )
1596        {
1597            this.executionProject = executionProject;
1598        }
1599    
1600        public List<MavenProject> getCollectedProjects()
1601        {
1602            return collectedProjects;
1603        }
1604    
1605        public void setCollectedProjects( List<MavenProject> collectedProjects )
1606        {
1607            this.collectedProjects = collectedProjects;
1608        }
1609    
1610        /**
1611         * Direct dependencies that this project has.
1612         * 
1613         * @return {@link Set} &lt; {@link Artifact} >
1614         * @see #getArtifacts() to get all transitive dependencies
1615         */
1616        public Set<Artifact> getDependencyArtifacts()
1617        {
1618            return dependencyArtifacts;
1619        }
1620    
1621        public void setDependencyArtifacts( Set<Artifact> dependencyArtifacts )
1622        {
1623            this.dependencyArtifacts = dependencyArtifacts;
1624        }
1625    
1626        public void setReleaseArtifactRepository( ArtifactRepository releaseArtifactRepository )
1627        {
1628            this.releaseArtifactRepository = releaseArtifactRepository;
1629        }
1630    
1631        public void setSnapshotArtifactRepository( ArtifactRepository snapshotArtifactRepository )
1632        {
1633            this.snapshotArtifactRepository = snapshotArtifactRepository;
1634        }
1635    
1636        public void setOriginalModel( Model originalModel )
1637        {
1638            this.originalModel = originalModel;
1639        }
1640    
1641        public Model getOriginalModel()
1642        {
1643            return originalModel;
1644        }
1645    
1646        public void setManagedVersionMap( Map<String, Artifact> map )
1647        {
1648            managedVersionMap = map;
1649        }
1650    
1651        public Map<String, Artifact> getManagedVersionMap()
1652        {
1653            if ( managedVersionMap != null )
1654            {
1655                return managedVersionMap;
1656            }
1657    
1658            Map<String, Artifact> map = null;
1659            if ( repositorySystem != null )
1660            {
1661    
1662                List<Dependency> deps;
1663                DependencyManagement dependencyManagement = getDependencyManagement();
1664                if ( ( dependencyManagement != null ) && ( ( deps = dependencyManagement.getDependencies() ) != null ) && ( deps.size() > 0 ) )
1665                {
1666                    map = new HashMap<String, Artifact>();
1667                    for ( Dependency d : dependencyManagement.getDependencies() )
1668                    {
1669                        Artifact artifact = repositorySystem.createDependencyArtifact( d );
1670    
1671                        if ( artifact == null )
1672                        {
1673                            map = Collections.emptyMap();
1674                        }
1675    
1676                        map.put( d.getManagementKey(), artifact );
1677                    }
1678                }
1679                else
1680                {
1681                    map = Collections.emptyMap();
1682                }
1683            }
1684            managedVersionMap = map;
1685            return managedVersionMap;
1686        }
1687    
1688        @Override
1689        public boolean equals( Object other )
1690        {
1691            if ( other == this )
1692            {
1693                return true;
1694            }
1695            else if ( !( other instanceof MavenProject ) )
1696            {
1697                return false;
1698            }
1699    
1700            MavenProject that = (MavenProject) other;
1701    
1702            return eq( getArtifactId(), that.getArtifactId() )
1703                && eq( getGroupId(), that.getGroupId() )
1704                && eq( getVersion(), that.getVersion() );
1705        }
1706    
1707        private static <T> boolean eq( T s1, T s2 )
1708        {
1709            return ( s1 != null ) ? s1.equals( s2 ) : s2 == null;
1710        }
1711    
1712        @Override
1713        public int hashCode()
1714        {
1715            int hash = 17;
1716            hash = 31 * hash + getGroupId().hashCode();
1717            hash = 31 * hash + getArtifactId().hashCode();
1718            hash = 31 * hash + getVersion().hashCode();
1719            return hash;
1720        }
1721    
1722        public List<Extension> getBuildExtensions()
1723        {
1724            Build build = getBuild();
1725            if ( ( build == null ) || ( build.getExtensions() == null ) )
1726            {
1727                return Collections.emptyList();
1728            }
1729            else
1730            {
1731                return build.getExtensions();
1732            }
1733        }
1734    
1735        public void addProjectReference( MavenProject project )
1736        {
1737            projectReferences.put( getProjectReferenceId( project.getGroupId(), project.getArtifactId(), project.getVersion() ), project );
1738        }
1739    
1740        /**
1741         * @deprecated Use MavenProjectHelper.attachArtifact(..) instead.
1742         */
1743        @Deprecated
1744        public void attachArtifact( String type, String classifier, File file )
1745        {
1746        }
1747    
1748        public Properties getProperties()
1749        {
1750            return getModel().getProperties();
1751        }
1752    
1753        public List<String> getFilters()
1754        {
1755            return getBuild().getFilters();
1756        }
1757    
1758        public Map<String, MavenProject> getProjectReferences()
1759        {
1760            return projectReferences;
1761        }
1762    
1763        public boolean isExecutionRoot()
1764        {
1765            return executionRoot;
1766        }
1767    
1768        public void setExecutionRoot( boolean executionRoot )
1769        {
1770            this.executionRoot = executionRoot;
1771        }
1772    
1773        public String getDefaultGoal()
1774        {
1775            return getBuild() != null ? getBuild().getDefaultGoal() : null;
1776        }
1777    
1778        public Plugin getPlugin( String pluginKey )
1779        {
1780            return getBuild().getPluginsAsMap().get( pluginKey );
1781        }
1782    
1783        /**
1784         * Default toString
1785         */
1786        @Override
1787        public String toString()
1788        {
1789            StringBuilder sb = new StringBuilder( 128 );
1790            sb.append( "MavenProject: " );
1791            sb.append( getGroupId() );
1792            sb.append( ":" );
1793            sb.append( getArtifactId() );
1794            sb.append( ":" );
1795            sb.append( getVersion() );
1796            sb.append( " @ " );
1797    
1798            try
1799            {
1800                sb.append( getFile().getPath() );
1801            }
1802            catch ( NullPointerException e )
1803            {
1804                //don't log it.
1805            }
1806    
1807            return sb.toString();
1808        }
1809    
1810        /**
1811         * @deprecated Use {@link org.apache.maven.model.io.ModelWriter}.
1812         */
1813        @Deprecated
1814        public void writeModel( Writer writer )
1815            throws IOException
1816        {
1817            MavenXpp3Writer pomWriter = new MavenXpp3Writer();
1818            pomWriter.write( writer, getModel() );
1819        }
1820    
1821        /**
1822         * @deprecated Use {@link org.apache.maven.model.io.ModelWriter}.
1823         */
1824        @Deprecated
1825        public void writeOriginalModel( Writer writer )
1826            throws IOException
1827        {
1828            MavenXpp3Writer pomWriter = new MavenXpp3Writer();
1829            pomWriter.write( writer, getOriginalModel() );
1830        }
1831    
1832        /**
1833         * @throws CloneNotSupportedException
1834         * @since 2.0.9
1835         */
1836        @Override
1837        public MavenProject clone()
1838        {
1839            MavenProject clone;
1840            try
1841            {
1842                clone = (MavenProject) super.clone();
1843            }
1844            catch ( CloneNotSupportedException e )
1845            {
1846                throw new UnsupportedOperationException( e );
1847            }
1848    
1849            clone.deepCopy( this );
1850    
1851            return clone;
1852        }
1853    
1854        protected void setModel( Model model )
1855        {
1856            this.model = model;
1857        }
1858    
1859        protected void setAttachedArtifacts( List<Artifact> attachedArtifacts )
1860        {
1861            this.attachedArtifacts = attachedArtifacts;
1862        }
1863    
1864        protected void setCompileSourceRoots( List<String> compileSourceRoots )
1865        {
1866            this.compileSourceRoots = compileSourceRoots;
1867        }
1868    
1869        protected void setTestCompileSourceRoots( List<String> testCompileSourceRoots )
1870        {
1871            this.testCompileSourceRoots = testCompileSourceRoots;
1872        }
1873    
1874        protected void setScriptSourceRoots( List<String> scriptSourceRoots )
1875        {
1876            this.scriptSourceRoots = scriptSourceRoots;
1877        }
1878    
1879        protected ArtifactRepository getReleaseArtifactRepository()
1880        {
1881            if ( releaseArtifactRepository == null )
1882            {
1883                if ( getDistributionManagement() != null && getDistributionManagement().getRepository() != null )
1884                {
1885                    checkProjectBuildingRequest();
1886                    try
1887                    {
1888                        ArtifactRepository repo =
1889                            repositorySystem.buildArtifactRepository( getDistributionManagement().getRepository() );
1890                        repositorySystem.injectProxy( projectBuilderConfiguration.getRepositorySession(),
1891                                                      Arrays.asList( repo ) );
1892                        repositorySystem.injectAuthentication( projectBuilderConfiguration.getRepositorySession(),
1893                                                               Arrays.asList( repo ) );
1894                        setReleaseArtifactRepository( repo );
1895                    }
1896                    catch ( InvalidRepositoryException e )
1897                    {
1898                        throw new IllegalStateException( "Failed to create release distribution repository for " + getId(),
1899                                                         e );
1900                    }
1901                }
1902            }
1903    
1904            return releaseArtifactRepository;
1905        }
1906    
1907        protected ArtifactRepository getSnapshotArtifactRepository()
1908        {
1909            if ( snapshotArtifactRepository == null )
1910            {
1911                if ( getDistributionManagement() != null && getDistributionManagement().getSnapshotRepository() != null )
1912                {
1913                    checkProjectBuildingRequest();
1914                    try
1915                    {
1916                        ArtifactRepository repo =
1917                            repositorySystem.buildArtifactRepository( getDistributionManagement().getSnapshotRepository() );
1918                        repositorySystem.injectProxy( projectBuilderConfiguration.getRepositorySession(),
1919                                                      Arrays.asList( repo ) );
1920                        repositorySystem.injectAuthentication( projectBuilderConfiguration.getRepositorySession(),
1921                                                               Arrays.asList( repo ) );
1922                        setSnapshotArtifactRepository( repo );
1923                    }
1924                    catch ( InvalidRepositoryException e )
1925                    {
1926                        throw new IllegalStateException(
1927                                                         "Failed to create snapshot distribution repository for " + getId(),
1928                                                         e );
1929                    }
1930                }
1931            }
1932    
1933            return snapshotArtifactRepository;
1934        }
1935    
1936        @Deprecated
1937        public Artifact replaceWithActiveArtifact( Artifact pluginArtifact )
1938        {
1939            return pluginArtifact;
1940        }
1941    
1942        private void deepCopy( MavenProject project )
1943        {
1944            // disown the parent
1945    
1946            // copy fields
1947            setFile( project.getFile() );
1948    
1949            // don't need a deep copy, they don't get modified or added/removed to/from - but make them unmodifiable to be
1950            // sure!
1951            if ( project.getDependencyArtifacts() != null )
1952            {
1953                setDependencyArtifacts( Collections.unmodifiableSet( project.getDependencyArtifacts() ) );
1954            }
1955    
1956            if ( project.getArtifacts() != null )
1957            {
1958                setArtifacts( Collections.unmodifiableSet( project.getArtifacts() ) );
1959            }
1960    
1961            if ( project.getParentFile() != null )
1962            {
1963                parentFile = new File( project.getParentFile().getAbsolutePath() );
1964            }
1965    
1966            if ( project.getPluginArtifacts() != null )
1967            {
1968                setPluginArtifacts( Collections.unmodifiableSet( project.getPluginArtifacts() ) );
1969            }
1970    
1971            if ( project.getReportArtifacts() != null )
1972            {
1973                setReportArtifacts( Collections.unmodifiableSet( project.getReportArtifacts() ) );
1974            }
1975    
1976            if ( project.getExtensionArtifacts() != null )
1977            {
1978                setExtensionArtifacts( Collections.unmodifiableSet( project.getExtensionArtifacts() ) );
1979            }
1980    
1981            setParentArtifact( ( project.getParentArtifact() ) );
1982    
1983            if ( project.getRemoteArtifactRepositories() != null )
1984            {
1985                setRemoteArtifactRepositories( Collections.unmodifiableList( project.getRemoteArtifactRepositories() ) );
1986            }
1987    
1988            if ( project.getPluginArtifactRepositories() != null )
1989            {
1990                setPluginArtifactRepositories( ( Collections.unmodifiableList( project.getPluginArtifactRepositories() ) ) );
1991            }
1992    
1993            if ( project.getActiveProfiles() != null )
1994            {
1995                setActiveProfiles( ( Collections.unmodifiableList( project.getActiveProfiles() ) ) );
1996            }
1997    
1998            if ( project.getAttachedArtifacts() != null )
1999            {
2000                // clone properties modifyable by plugins in a forked lifecycle
2001                setAttachedArtifacts( new ArrayList<Artifact>( project.getAttachedArtifacts() ) );
2002            }
2003    
2004            if ( project.getCompileSourceRoots() != null )
2005            {
2006                // clone source roots
2007                setCompileSourceRoots( ( new ArrayList<String>( project.getCompileSourceRoots() ) ) );
2008            }
2009    
2010            if ( project.getTestCompileSourceRoots() != null )
2011            {
2012                setTestCompileSourceRoots( ( new ArrayList<String>( project.getTestCompileSourceRoots() ) ) );
2013            }
2014    
2015            if ( project.getScriptSourceRoots() != null )
2016            {
2017                setScriptSourceRoots( ( new ArrayList<String>( project.getScriptSourceRoots() ) ) );
2018            }
2019    
2020            if ( project.getModel() != null )
2021            {
2022                setModel( project.getModel().clone() );
2023            }
2024    
2025            if ( project.getOriginalModel() != null )
2026            {
2027                setOriginalModel( project.getOriginalModel() );
2028            }
2029    
2030            setExecutionRoot( project.isExecutionRoot() );
2031    
2032            if ( project.getArtifact() != null )
2033            {
2034                setArtifact( ArtifactUtils.copyArtifact( project.getArtifact() ) );
2035            }
2036    
2037            if ( project.getManagedVersionMap() != null )
2038            {
2039                setManagedVersionMap( new HashMap<String, Artifact>( project.getManagedVersionMap() ) );
2040            }
2041    
2042            lifecyclePhases.addAll( project.lifecyclePhases );
2043        }
2044    
2045        private void addArtifactPath( Artifact artifact, List<String> classpath )
2046        {
2047            File file = artifact.getFile();
2048            if ( file != null )
2049            {
2050                classpath.add( file.getPath() );
2051            }
2052        }
2053    
2054        private static String getProjectReferenceId( String groupId, String artifactId, String version )
2055        {
2056            StringBuilder buffer = new StringBuilder( 128 );
2057            buffer.append( groupId ).append( ':' ).append( artifactId ).append( ':' ).append( version );
2058            return buffer.toString();
2059        }
2060    
2061        /**
2062         * Sets the value of the context value of this project identified
2063         * by the given key. If the supplied value is <code>null</code>,
2064         * the context value is removed from this project.
2065         * 
2066         * Context values are intended to allow core extensions to associate
2067         * derived state with project instances. 
2068         */
2069        public void setContextValue( String key, Object value )
2070        {
2071            if ( context == null )
2072            {
2073                context = new HashMap<String, Object>();
2074            }
2075            if ( value != null )
2076            {
2077                context.put( key, value );
2078            }
2079            else
2080            {
2081                context.remove( key );
2082            }
2083        }
2084    
2085        /**
2086         * Returns context value of this project associated with the given key 
2087         * or null if this project has no such value. 
2088         */
2089        public Object getContextValue( String key )
2090        {
2091            if ( context == null )
2092            {
2093                return null;
2094            }
2095            return context.get( key );
2096        }
2097    
2098        /**
2099         * Sets the project's class realm. <strong>Warning:</strong> This is an internal utility method that is only public
2100         * for technical reasons, it is not part of the public API. In particular, this method can be changed or deleted
2101         * without prior notice and must not be used by plugins.
2102         * 
2103         * @param classRealm The class realm hosting the build extensions of this project, may be {@code null}.
2104         */
2105        public void setClassRealm( ClassRealm classRealm )
2106        {
2107            this.classRealm = classRealm;
2108        }
2109    
2110        /**
2111         * Gets the project's class realm. This class realm hosts the build extensions of the project.
2112         * <strong>Warning:</strong> This is an internal utility method that is only public for technical reasons, it is not
2113         * part of the public API. In particular, this method can be changed or deleted without prior notice and must not be
2114         * used by plugins.
2115         * 
2116         * @return The project's class realm or {@code null}.
2117         */
2118        public ClassRealm getClassRealm()
2119        {
2120            return classRealm;
2121        }
2122    
2123        /**
2124         * Sets the artifact filter used to exclude shared extension artifacts from plugin realms. <strong>Warning:</strong>
2125         * This is an internal utility method that is only public for technical reasons, it is not part of the public API.
2126         * In particular, this method can be changed or deleted without prior notice and must not be used by plugins.
2127         * 
2128         * @param extensionDependencyFilter The dependency filter to apply to plugins, may be {@code null}.
2129         */
2130        public void setExtensionDependencyFilter( DependencyFilter extensionDependencyFilter )
2131        {
2132            this.extensionDependencyFilter = extensionDependencyFilter;
2133        }
2134    
2135        /**
2136         * Gets the dependency filter used to exclude shared extension artifacts from plugin realms.
2137         * <strong>Warning:</strong> This is an internal utility method that is only public for technical reasons, it is not
2138         * part of the public API. In particular, this method can be changed or deleted without prior notice and must not be
2139         * used by plugins.
2140         * 
2141         * @return The dependency filter or {@code null}.
2142         */
2143        public DependencyFilter getExtensionDependencyFilter()
2144        {
2145            return extensionDependencyFilter;
2146        }
2147    
2148        /**
2149         * Sets the transitive dependency artifacts that have been resolved/collected for this project.
2150         * <strong>Warning:</strong> This is an internal utility method that is only public for technical reasons, it is not
2151         * part of the public API. In particular, this method can be changed or deleted without prior notice and must not be
2152         * used by plugins.
2153         * 
2154         * @param artifacts The set of artifacts, may be {@code null}.
2155         */
2156        public void setResolvedArtifacts( Set<Artifact> artifacts )
2157        {
2158            this.resolvedArtifacts = ( artifacts != null ) ? artifacts : Collections.<Artifact> emptySet();
2159            this.artifacts = null;
2160            this.artifactMap = null;
2161        }
2162    
2163        /**
2164         * Sets the scope filter to select the artifacts being exposed to the currently executed mojo.
2165         * <strong>Warning:</strong> This is an internal utility method that is only public for technical reasons, it is not
2166         * part of the public API. In particular, this method can be changed or deleted without prior notice and must not be
2167         * used by plugins.
2168         * 
2169         * @param artifactFilter The artifact filter, may be {@code null} to exclude all artifacts.
2170         */
2171        public void setArtifactFilter( ArtifactFilter artifactFilter )
2172        {
2173            this.artifactFilter = artifactFilter;
2174            this.artifacts = null;
2175            this.artifactMap = null;
2176        }
2177    
2178        /**
2179         * <strong>Warning:</strong> This is an internal utility method that is only public for technical reasons, it is not
2180         * part of the public API. In particular, this method can be changed or deleted without prior notice and must not be
2181         * used by plugins.
2182         * 
2183         * @param phase The phase to check for, must not be {@code null}.
2184         * @return {@code true} if the phase has been seen.
2185         */
2186        public boolean hasLifecyclePhase( String phase )
2187        {
2188            return lifecyclePhases.contains( phase );
2189        }
2190    
2191        /**
2192         * <strong>Warning:</strong> This is an internal utility method that is only public for technical reasons, it is not
2193         * part of the public API. In particular, this method can be changed or deleted without prior notice and must not be
2194         * used by plugins.
2195         * 
2196         * @param lifecyclePhase The lifecycle phase to add, must not be {@code null}.
2197         */
2198        public void addLifecyclePhase( String lifecyclePhase )
2199        {
2200            lifecyclePhases.add( lifecyclePhase );
2201        }
2202    
2203        /**
2204         * Gets the project building request from which this project instance was created. <strong>Warning:</strong> This is
2205         * an utility method that is meant to assist integrators of Maven, it must not be used by Maven plugins.
2206         * 
2207         * @return The project building request or {@code null}.
2208         * @since 2.1
2209         */
2210        public ProjectBuildingRequest getProjectBuildingRequest()
2211        {
2212            return projectBuilderConfiguration;
2213        }
2214    
2215        /**
2216         * Sets the project building request from which this project instance was created. <strong>Warning:</strong> This is
2217         * an utility method that is meant to assist integrators of Maven, it must not be used by Maven plugins.
2218         * 
2219         * @param projectBuildingRequest The project building request, may be {@code null}.
2220         * @since 2.1
2221         */
2222        public void setProjectBuildingRequest( ProjectBuildingRequest projectBuildingRequest )
2223        {
2224            projectBuilderConfiguration = projectBuildingRequest;
2225        }
2226    
2227        private void checkProjectBuildingRequest()
2228        {
2229            if ( projectBuilderConfiguration == null )
2230            {
2231                throw new IllegalStateException( "project building request missing" );
2232            }
2233        }
2234    
2235    }