View Javadoc

1   package org.apache.maven.project;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import org.apache.maven.RepositoryUtils;
23  import org.apache.maven.artifact.Artifact;
24  import org.apache.maven.artifact.ArtifactUtils;
25  import org.apache.maven.artifact.DependencyResolutionRequiredException;
26  import org.apache.maven.artifact.InvalidRepositoryException;
27  import org.apache.maven.artifact.factory.ArtifactFactory;
28  import org.apache.maven.artifact.repository.ArtifactRepository;
29  import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
30  import org.apache.maven.model.Build;
31  import org.apache.maven.model.CiManagement;
32  import org.apache.maven.model.Contributor;
33  import org.apache.maven.model.Dependency;
34  import org.apache.maven.model.DependencyManagement;
35  import org.apache.maven.model.Developer;
36  import org.apache.maven.model.DistributionManagement;
37  import org.apache.maven.model.Extension;
38  import org.apache.maven.model.IssueManagement;
39  import org.apache.maven.model.License;
40  import org.apache.maven.model.MailingList;
41  import org.apache.maven.model.Model;
42  import org.apache.maven.model.Organization;
43  import org.apache.maven.model.Parent;
44  import org.apache.maven.model.Plugin;
45  import org.apache.maven.model.PluginExecution;
46  import org.apache.maven.model.PluginManagement;
47  import org.apache.maven.model.Prerequisites;
48  import org.apache.maven.model.Profile;
49  import org.apache.maven.model.ReportPlugin;
50  import org.apache.maven.model.ReportSet;
51  import org.apache.maven.model.Reporting;
52  import org.apache.maven.model.Repository;
53  import org.apache.maven.model.Resource;
54  import org.apache.maven.model.Scm;
55  import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
56  import org.apache.maven.project.artifact.InvalidDependencyVersionException;
57  import org.apache.maven.project.artifact.MavenMetadataSource;
58  import org.apache.maven.repository.RepositorySystem;
59  import org.codehaus.plexus.classworlds.realm.ClassRealm;
60  import org.codehaus.plexus.logging.Logger;
61  import org.codehaus.plexus.util.StringUtils;
62  import org.codehaus.plexus.util.xml.Xpp3Dom;
63  import org.eclipse.aether.graph.DependencyFilter;
64  import org.eclipse.aether.repository.RemoteRepository;
65  
66  import java.io.File;
67  import java.io.IOException;
68  import java.io.Writer;
69  import java.util.ArrayList;
70  import java.util.Arrays;
71  import java.util.Collections;
72  import java.util.HashMap;
73  import java.util.HashSet;
74  import java.util.Iterator;
75  import java.util.LinkedHashMap;
76  import java.util.LinkedHashSet;
77  import java.util.List;
78  import java.util.Map;
79  import java.util.Properties;
80  import java.util.Set;
81  
82  /**
83   * The concern of the project is provide runtime values based on the model.
84   * <p/>
85   * The values in the model remain untouched but during the process of building a project notions
86   * like inheritance and interpolation can be added. This allows to have an entity which is useful in
87   * a runtime while preserving the model so that it can be marshalled and unmarshalled without being
88   * tainted by runtime requirements.
89   * <p/>
90   * We need to leave the model intact because we don't want the following:
91   * <ol>
92   * <li>We don't want interpolated values being written back into the model.
93   * <li>We don't want inherited values being written back into the model.
94   * </ol>
95   */
96  public class MavenProject
97      implements Cloneable
98  {
99      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 }