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