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