View Javadoc

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