View Javadoc

1   package org.apache.maven.project;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
5    * agreements. See the NOTICE file distributed with this work for additional information regarding
6    * copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance with the License. You may obtain a
8    * copy of the License at
9    * 
10   * http://www.apache.org/licenses/LICENSE-2.0
11   * 
12   * Unless required by applicable law or agreed to in writing, software distributed under the License
13   * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
14   * or implied. See the License for the specific language governing permissions and limitations under
15   * the License.
16   */
17  
18  import java.io.File;
19  import java.io.IOException;
20  import java.io.Writer;
21  import java.util.ArrayList;
22  import java.util.Arrays;
23  import java.util.Collections;
24  import java.util.HashMap;
25  import java.util.HashSet;
26  import java.util.Iterator;
27  import java.util.LinkedHashMap;
28  import java.util.LinkedHashSet;
29  import java.util.List;
30  import java.util.Map;
31  import java.util.Properties;
32  import java.util.Set;
33  
34  import org.apache.maven.RepositoryUtils;
35  import org.apache.maven.artifact.Artifact;
36  import org.apache.maven.artifact.ArtifactUtils;
37  import org.apache.maven.artifact.DependencyResolutionRequiredException;
38  import org.apache.maven.artifact.InvalidRepositoryException;
39  import org.apache.maven.artifact.factory.ArtifactFactory;
40  import org.apache.maven.artifact.repository.ArtifactRepository;
41  import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
42  import org.apache.maven.model.Build;
43  import org.apache.maven.model.CiManagement;
44  import org.apache.maven.model.Contributor;
45  import org.apache.maven.model.Dependency;
46  import org.apache.maven.model.DependencyManagement;
47  import org.apache.maven.model.Developer;
48  import org.apache.maven.model.DistributionManagement;
49  import org.apache.maven.model.Extension;
50  import org.apache.maven.model.IssueManagement;
51  import org.apache.maven.model.License;
52  import org.apache.maven.model.MailingList;
53  import org.apache.maven.model.Model;
54  import org.apache.maven.model.Organization;
55  import org.apache.maven.model.Parent;
56  import org.apache.maven.model.Plugin;
57  import org.apache.maven.model.PluginExecution;
58  import org.apache.maven.model.PluginManagement;
59  import org.apache.maven.model.Prerequisites;
60  import org.apache.maven.model.Profile;
61  import org.apache.maven.model.ReportPlugin;
62  import org.apache.maven.model.ReportSet;
63  import org.apache.maven.model.Reporting;
64  import org.apache.maven.model.Repository;
65  import org.apache.maven.model.Resource;
66  import org.apache.maven.model.Scm;
67  import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
68  import org.apache.maven.project.artifact.InvalidDependencyVersionException;
69  import org.apache.maven.project.artifact.MavenMetadataSource;
70  import org.apache.maven.repository.RepositorySystem;
71  import org.codehaus.plexus.classworlds.realm.ClassRealm;
72  import org.codehaus.plexus.logging.Logger;
73  import org.codehaus.plexus.util.StringUtils;
74  import org.codehaus.plexus.util.xml.Xpp3Dom;
75  import org.sonatype.aether.graph.DependencyFilter;
76  import org.sonatype.aether.repository.RemoteRepository;
77  
78  /**
79   * The concern of the project is provide runtime values based on the model.
80   * <p/>
81   * The values in the model remain untouched but during the process of building a project notions
82   * like inheritance and interpolation can be added. This allows to have an entity which is useful in
83   * a runtime while preserving the model so that it can be marshalled and unmarshalled without being
84   * tainted by runtime requirements.
85   * <p/>
86   * We need to leave the model intact because we don't want the following:
87   * <ol>
88   * <li>We don't want interpolated values being written back into the model.
89   * <li>We don't want inherited values being written back into the model.
90   * </ol>
91   */
92  public class MavenProject
93      implements Cloneable
94  {
95      public static final String EMPTY_PROJECT_GROUP_ID = "unknown";
96  
97      public static final String EMPTY_PROJECT_ARTIFACT_ID = "empty-project";
98  
99      public static final String EMPTY_PROJECT_VERSION = "0";
100 
101     private Model model;
102 
103     private MavenProject parent;
104 
105     private File file;
106 
107     private Set<Artifact> resolvedArtifacts;
108 
109     private ArtifactFilter artifactFilter;
110 
111     private Set<Artifact> artifacts;
112 
113     private Artifact parentArtifact;
114 
115     private Set<Artifact> pluginArtifacts;
116 
117     private List<ArtifactRepository> remoteArtifactRepositories;
118 
119     private List<ArtifactRepository> pluginArtifactRepositories;
120 
121     private List<RemoteRepository> remoteProjectRepositories;
122 
123     private List<RemoteRepository> remotePluginRepositories;
124 
125     private List<Artifact> attachedArtifacts;
126 
127     private MavenProject executionProject;
128 
129     private List<MavenProject> collectedProjects;
130 
131     private List<String> compileSourceRoots = new ArrayList<String>();
132 
133     private List<String> testCompileSourceRoots = new ArrayList<String>();
134 
135     private List<String> scriptSourceRoots = new ArrayList<String>();
136 
137     private ArtifactRepository releaseArtifactRepository;
138 
139     private ArtifactRepository snapshotArtifactRepository;
140 
141     private List<Profile> activeProfiles = new ArrayList<Profile>();
142 
143     private Map<String, List<String>> injectedProfileIds = new LinkedHashMap<String, List<String>>();
144 
145     private Set<Artifact> dependencyArtifacts;
146 
147     private Artifact artifact;
148 
149     // calculated.
150     private Map<String, Artifact> artifactMap;
151 
152     private Model originalModel;
153 
154     private Map<String, Artifact> pluginArtifactMap;
155 
156     private Set<Artifact> reportArtifacts;
157 
158     private Map<String, Artifact> reportArtifactMap;
159 
160     private Set<Artifact> extensionArtifacts;
161 
162     private Map<String, Artifact> extensionArtifactMap;
163 
164     private Map<String, Artifact> managedVersionMap;
165 
166     private Map<String, MavenProject> projectReferences = new HashMap<String, MavenProject>();
167 
168     private boolean executionRoot;
169 
170     private Map<String, String> moduleAdjustments;
171 
172     private ProjectBuilder mavenProjectBuilder;
173 
174     private ProjectBuildingRequest projectBuilderConfiguration;
175 
176     private RepositorySystem repositorySystem;
177     
178     private File parentFile;
179 
180     private Map<String, Object> context;
181 
182     private ClassRealm classRealm;
183 
184     private DependencyFilter extensionDependencyFilter;
185 
186     private final Set<String> lifecyclePhases = Collections.synchronizedSet( new LinkedHashSet<String>() );
187 
188     private Logger logger;
189 
190     public MavenProject()
191     {
192         Model model = new Model();
193 
194         model.setGroupId( EMPTY_PROJECT_GROUP_ID );
195         model.setArtifactId( EMPTY_PROJECT_ARTIFACT_ID );
196         model.setVersion( EMPTY_PROJECT_VERSION );
197 
198         setModel( model );
199     }
200 
201     public MavenProject( Model model )
202     {
203         setModel( model );
204     }
205 
206     /**
207      * @deprecated use {@link #clone()} so subclasses can provide a copy of the same class
208      */
209     @Deprecated
210     public MavenProject( MavenProject project )
211     {
212         repositorySystem = project.repositorySystem;
213         logger = project.logger;
214         mavenProjectBuilder = project.mavenProjectBuilder;
215         projectBuilderConfiguration = project.projectBuilderConfiguration;
216         deepCopy( project );
217     }
218     
219     @Deprecated
220     public MavenProject( Model model, RepositorySystem repositorySystem )
221     {        
222         this.repositorySystem = repositorySystem;
223         setModel( model );
224     }
225 
226     public File getParentFile()
227     {
228         return parentFile;
229     }
230 
231     public void setParentFile( File parentFile )
232     {
233         this.parentFile = parentFile;
234     }
235 
236     /**
237      * Constructor
238      * 
239      * @param repositorySystem - may not be null
240      * @param mavenProjectBuilder
241      * @param projectBuilderConfiguration
242      * @throws InvalidRepositoryException
243      */
244     MavenProject( RepositorySystem repositorySystem, ProjectBuilder mavenProjectBuilder,
245                   ProjectBuildingRequest projectBuilderConfiguration, Logger logger )
246     {
247         if ( repositorySystem == null )
248         {
249             throw new IllegalArgumentException( "mavenTools: null" );
250         }
251 
252         this.mavenProjectBuilder = mavenProjectBuilder;
253         this.projectBuilderConfiguration = projectBuilderConfiguration;
254         this.repositorySystem = repositorySystem;
255         this.logger = logger;
256     }
257 
258     @Deprecated
259     public Set<Artifact> createArtifacts( ArtifactFactory artifactFactory, String inheritedScope, ArtifactFilter filter )
260         throws InvalidDependencyVersionException
261     {
262         return MavenMetadataSource.createArtifacts( artifactFactory, getDependencies(), inheritedScope, filter, this );
263     }
264 
265     // TODO: Find a way to use <relativePath/> here...it's tricky, because the moduleProject
266     // usually doesn't have a file associated with it yet.
267     public String getModulePathAdjustment( MavenProject moduleProject )
268         throws IOException
269     {
270         // FIXME: This is hacky. What if module directory doesn't match artifactid, and parent
271         // is coming from the repository??
272         String module = moduleProject.getArtifactId();
273 
274         File moduleFile = moduleProject.getFile();
275 
276         if ( moduleFile != null )
277         {
278             File moduleDir = moduleFile.getCanonicalFile().getParentFile();
279 
280             module = moduleDir.getName();
281         }
282 
283         if ( moduleAdjustments == null )
284         {
285             moduleAdjustments = new HashMap<String, String>();
286 
287             List<String> modules = getModules();
288             if ( modules != null )
289             {
290                 for ( Iterator<String> it = modules.iterator(); it.hasNext(); )
291                 {
292                     String modulePath = it.next();
293                     String moduleName = modulePath;
294 
295                     if ( moduleName.endsWith( "/" ) || moduleName.endsWith( "\\" ) )
296                     {
297                         moduleName = moduleName.substring( 0, moduleName.length() - 1 );
298                     }
299 
300                     int lastSlash = moduleName.lastIndexOf( '/' );
301 
302                     if ( lastSlash < 0 )
303                     {
304                         lastSlash = moduleName.lastIndexOf( '\\' );
305                     }
306 
307                     String adjustment = null;
308 
309                     if ( lastSlash > -1 )
310                     {
311                         moduleName = moduleName.substring( lastSlash + 1 );
312                         adjustment = modulePath.substring( 0, lastSlash );
313                     }
314 
315                     moduleAdjustments.put( moduleName, adjustment );
316                 }
317             }
318         }
319 
320         return moduleAdjustments.get( module );
321     }
322 
323     // ----------------------------------------------------------------------
324     // Accessors
325     // ----------------------------------------------------------------------
326 
327     public Artifact getArtifact()
328     {
329         return artifact;
330     }
331 
332     public void setArtifact( Artifact artifact )
333     {
334         this.artifact = artifact;
335     }
336 
337     //@todo I would like to get rid of this. jvz.
338     public Model getModel()
339     {
340         return model;
341     }
342 
343     public MavenProject getParent()
344     {
345         if ( parent == null )
346         {
347             /*
348              * TODO: This is suboptimal. Without a cache in the project builder, rebuilding the parent chain currently
349              * causes O(n^2) parser invocations for an inheritance hierarchy of depth n.
350              */
351             if ( parentFile != null )
352             {
353                 checkProjectBuildingRequest();
354                 ProjectBuildingRequest request = new DefaultProjectBuildingRequest( projectBuilderConfiguration );
355                 request.setRemoteRepositories( getRemoteArtifactRepositories() );
356 
357                 try
358                 {
359                     parent = mavenProjectBuilder.build( parentFile, request ).getProject();
360                 }
361                 catch ( ProjectBuildingException e )
362                 {
363                     throw new IllegalStateException( "Failed to build parent project for " + getId(), e );
364                 }
365             }
366             else if ( model.getParent() != null )
367             {
368                 checkProjectBuildingRequest();
369                 ProjectBuildingRequest request = new DefaultProjectBuildingRequest( projectBuilderConfiguration );
370                 request.setRemoteRepositories( getRemoteArtifactRepositories() );
371 
372                 try
373                 {
374                     parent = mavenProjectBuilder.build( getParentArtifact(), request ).getProject();
375                 }
376                 catch ( ProjectBuildingException e )
377                 {
378                     throw new IllegalStateException( "Failed to build parent project for " + getId(), e );
379                 }
380             }
381         }
382         return parent;
383     }
384 
385     public void setParent( MavenProject parent )
386     {
387         this.parent = parent;
388     }
389     
390     public boolean hasParent()
391     {
392         return getParent() != null;
393     }
394 
395     public File getFile()
396     {
397         return file;
398     }
399 
400     public void setFile( File file )
401     {
402         this.file = file;
403     }
404 
405     public File getBasedir()
406     {
407         if ( getFile() != null )
408         {
409             return getFile().getParentFile();
410         }
411         else
412         {
413             // repository based POM
414             return null;
415         }
416     }
417 
418     public void setDependencies( List<Dependency> dependencies )
419     {
420         getModel().setDependencies( dependencies );
421     }
422 
423     public List<Dependency> getDependencies()
424     {
425         return getModel().getDependencies();
426     }
427 
428     public DependencyManagement getDependencyManagement()
429     {
430         return getModel().getDependencyManagement();
431     }
432 
433     // ----------------------------------------------------------------------
434     // Test and compile sourceroots.
435     // ----------------------------------------------------------------------
436 
437     private void addPath( List<String> paths, String path )
438     {
439         if ( path != null )
440         {
441             path = path.trim();
442             if ( path.length() > 0 )
443             {
444                 File file = new File( path );
445                 if ( file.isAbsolute() )
446                 {
447                     path = file.getAbsolutePath();
448                 }
449                 else
450                 {
451                     path = new File( getBasedir(), path ).getAbsolutePath();
452                 }
453 
454                 if ( !paths.contains( path ) )
455                 {
456                     paths.add( path );
457                 }
458             }
459         }
460     }
461 
462     public void addCompileSourceRoot( String path )
463     {
464         addPath( getCompileSourceRoots(), path );
465     }
466 
467     public void addScriptSourceRoot( String path )
468     {
469         if ( path != null )
470         {
471             path = path.trim();
472             if ( path.length() != 0 )
473             {
474                 if ( !getScriptSourceRoots().contains( path ) )
475                 {
476                     getScriptSourceRoots().add( path );
477                 }
478             }
479         }
480     }
481 
482     public void addTestCompileSourceRoot( String path )
483     {
484         addPath( getTestCompileSourceRoots(), path );
485     }
486 
487     public List<String> getCompileSourceRoots()
488     {
489         return compileSourceRoots;
490     }
491 
492     public List<String> getScriptSourceRoots()
493     {
494         return scriptSourceRoots;
495     }
496 
497     public List<String> getTestCompileSourceRoots()
498     {
499         return testCompileSourceRoots;
500     }
501 
502     public List<String> getCompileClasspathElements()
503         throws DependencyResolutionRequiredException
504     {
505         List<String> list = new ArrayList<String>( getArtifacts().size() + 1 );
506 
507         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 void setPluginArtifacts( Set<Artifact> pluginArtifacts )
1115     {
1116         this.pluginArtifacts = pluginArtifacts;
1117 
1118         this.pluginArtifactMap = null;
1119     }
1120 
1121     public Set<Artifact> getPluginArtifacts()
1122     {
1123         if ( pluginArtifacts != null )
1124         {
1125             return pluginArtifacts;
1126         }
1127 
1128         pluginArtifacts = new HashSet<Artifact>();
1129 
1130         if ( repositorySystem != null )
1131         {
1132             for ( Plugin p : getBuildPlugins() )
1133             {
1134                 Artifact artifact = repositorySystem.createPluginArtifact( p );
1135 
1136                 if ( artifact != null )
1137                 {
1138                     pluginArtifacts.add( artifact );
1139                 }
1140             }
1141         }
1142 
1143         pluginArtifactMap = null;
1144 
1145         return pluginArtifacts;
1146     }
1147 
1148     public Map<String, Artifact> getPluginArtifactMap()
1149     {
1150         if ( pluginArtifactMap == null )
1151         {
1152             pluginArtifactMap = ArtifactUtils.artifactMapByVersionlessId( getPluginArtifacts() );
1153         }
1154 
1155         return pluginArtifactMap;
1156     }
1157 
1158     @Deprecated
1159     public void setReportArtifacts( Set<Artifact> reportArtifacts )
1160     {
1161         this.reportArtifacts = reportArtifacts;
1162 
1163         reportArtifactMap = null;
1164     }
1165 
1166     @Deprecated
1167     public Set<Artifact> getReportArtifacts()
1168     {
1169         if ( reportArtifacts != null )
1170         {
1171             return reportArtifacts;
1172         }
1173 
1174         reportArtifacts = new HashSet<Artifact>();
1175 
1176         if ( repositorySystem != null )
1177         {
1178             for ( ReportPlugin p : getReportPlugins() )
1179             {
1180                 Plugin pp = new Plugin();
1181                 pp.setGroupId( p.getGroupId() );
1182                 pp.setArtifactId( p.getArtifactId() );
1183                 pp.setVersion( p.getVersion() );
1184 
1185                 Artifact artifact = repositorySystem.createPluginArtifact( pp );
1186 
1187                 if ( artifact != null )
1188                 {
1189                     reportArtifacts.add( artifact );
1190                 }
1191             }
1192         }
1193 
1194         reportArtifactMap = null;
1195 
1196         return reportArtifacts;
1197     }
1198 
1199     @Deprecated
1200     public Map<String, Artifact> getReportArtifactMap()
1201     {
1202         if ( reportArtifactMap == null )
1203         {
1204             reportArtifactMap = ArtifactUtils.artifactMapByVersionlessId( getReportArtifacts() );
1205         }
1206 
1207         return reportArtifactMap;
1208     }
1209 
1210     public void setExtensionArtifacts( Set<Artifact> extensionArtifacts )
1211     {
1212         this.extensionArtifacts = extensionArtifacts;
1213 
1214         extensionArtifactMap = null;
1215     }
1216 
1217     public Set<Artifact> getExtensionArtifacts()
1218     {
1219         if ( extensionArtifacts != null )
1220         {
1221             return extensionArtifacts;
1222         }
1223         extensionArtifacts = new HashSet<Artifact>();
1224         List<Extension> extensions = getBuildExtensions();
1225         if ( extensions != null )
1226         {
1227             for ( Iterator<Extension> i = extensions.iterator(); i.hasNext(); )
1228             {
1229                 Extension ext = i.next();
1230 
1231                 String version;
1232                 if ( StringUtils.isEmpty( ext.getVersion() ) )
1233                 {
1234                     version = "RELEASE";
1235                 }
1236                 else
1237                 {
1238                     version = ext.getVersion();
1239                 }
1240 
1241                 Artifact artifact = repositorySystem.createArtifact( ext.getGroupId(), ext.getArtifactId(), version, null, "jar" );
1242 
1243                 if ( artifact != null )
1244                 {
1245                     extensionArtifacts.add( artifact );
1246                 }
1247             }
1248         }
1249         extensionArtifactMap = null;
1250         return extensionArtifacts;
1251     }
1252 
1253     public Map<String, Artifact> getExtensionArtifactMap()
1254     {
1255         if ( extensionArtifactMap == null )
1256         {
1257             extensionArtifactMap = ArtifactUtils.artifactMapByVersionlessId( getExtensionArtifacts() );
1258         }
1259 
1260         return extensionArtifactMap;
1261     }
1262 
1263     public void setParentArtifact( Artifact parentArtifact )
1264     {
1265         this.parentArtifact = parentArtifact;
1266     }
1267 
1268     public Artifact getParentArtifact()
1269     {
1270         if ( parentArtifact == null && model.getParent() != null )
1271         {
1272             Parent p = model.getParent();
1273             parentArtifact = repositorySystem.createProjectArtifact( p.getGroupId(), p.getArtifactId(), p.getVersion() );
1274         }
1275         return parentArtifact;
1276     }
1277 
1278     public List<Repository> getRepositories()
1279     {
1280         return getModel().getRepositories();
1281     }
1282 
1283     // ----------------------------------------------------------------------
1284     // Plugins
1285     // ----------------------------------------------------------------------
1286 
1287     @Deprecated
1288     public List<ReportPlugin> getReportPlugins()
1289     {
1290         if ( getModel().getReporting() == null )
1291         {
1292             return Collections.emptyList();
1293         }
1294         return getModel().getReporting().getPlugins();
1295 
1296     }
1297 
1298     public List<Plugin> getBuildPlugins()
1299     {
1300         if ( getModel().getBuild() == null )
1301         {
1302             return Collections.emptyList();
1303         }
1304         return getModel().getBuild().getPlugins();
1305     }
1306 
1307     public List<String> getModules()
1308     {
1309         return getModel().getModules();
1310     }
1311 
1312     public PluginManagement getPluginManagement()
1313     {
1314         PluginManagement pluginMgmt = null;
1315 
1316         Build build = getModel().getBuild();
1317         if ( build != null )
1318         {
1319             pluginMgmt = build.getPluginManagement();
1320         }
1321 
1322         return pluginMgmt;
1323     }
1324 
1325     private Build getModelBuild()
1326     {
1327         Build build = getModel().getBuild();
1328 
1329         if ( build == null )
1330         {
1331             build = new Build();
1332 
1333             getModel().setBuild( build );
1334         }
1335 
1336         return build;
1337     }
1338 
1339     public void setRemoteArtifactRepositories( List<ArtifactRepository> remoteArtifactRepositories )
1340     {
1341         this.remoteArtifactRepositories = remoteArtifactRepositories;
1342         this.remoteProjectRepositories = RepositoryUtils.toRepos( getRemoteArtifactRepositories() );
1343     }
1344 
1345     public List<ArtifactRepository> getRemoteArtifactRepositories()
1346     {
1347         if ( remoteArtifactRepositories == null )
1348         {
1349             remoteArtifactRepositories = new ArrayList<ArtifactRepository>();
1350         }
1351 
1352         return remoteArtifactRepositories;
1353     }
1354 
1355     public void setPluginArtifactRepositories( List<ArtifactRepository> pluginArtifactRepositories )
1356     {
1357         this.pluginArtifactRepositories = pluginArtifactRepositories;
1358         this.remotePluginRepositories = RepositoryUtils.toRepos( getPluginArtifactRepositories() );
1359     }
1360 
1361     /**
1362      * @return a list of ArtifactRepository objects constructed from the Repository objects returned
1363      *         by getPluginRepositories.
1364      */
1365     public List<ArtifactRepository> getPluginArtifactRepositories()
1366     {
1367         if ( pluginArtifactRepositories == null )
1368         {
1369             pluginArtifactRepositories = new ArrayList<ArtifactRepository>();
1370         }
1371 
1372         return pluginArtifactRepositories;
1373     }
1374 
1375     public ArtifactRepository getDistributionManagementArtifactRepository()
1376     {
1377         return getArtifact().isSnapshot() && ( getSnapshotArtifactRepository() != null ) ? getSnapshotArtifactRepository() : getReleaseArtifactRepository();
1378     }
1379 
1380     public List<Repository> getPluginRepositories()
1381     {
1382         return getModel().getPluginRepositories();
1383     }
1384 
1385     public List<RemoteRepository> getRemoteProjectRepositories()
1386     {
1387         return remoteProjectRepositories;
1388     }
1389 
1390     public List<RemoteRepository> getRemotePluginRepositories()
1391     {
1392         return remotePluginRepositories;
1393     }
1394 
1395     public void setActiveProfiles( List<Profile> activeProfiles )
1396     {
1397         this.activeProfiles = activeProfiles;
1398     }
1399 
1400     public List<Profile> getActiveProfiles()
1401     {
1402         return activeProfiles;
1403     }
1404 
1405     public void setInjectedProfileIds( String source, List<String> injectedProfileIds )
1406     {
1407         if ( injectedProfileIds != null )
1408         {
1409             this.injectedProfileIds.put( source, new ArrayList<String>( injectedProfileIds ) );
1410         }
1411         else
1412         {
1413             this.injectedProfileIds.remove( source );
1414         }
1415     }
1416 
1417     /**
1418      * Gets the identifiers of all profiles that contributed to this project's effective model. This includes active
1419      * profiles from the project's POM and all its parent POMs as well as from external sources like the {@code
1420      * settings.xml}. The profile identifiers are grouped by the identifier of their source, e.g. {@code
1421      * <groupId>:<artifactId>:<version>} for a POM profile or {@code external} for profiles from the {@code
1422      * settings.xml}.
1423      * 
1424      * @return The identifiers of all injected profiles, indexed by the source from which the profiles originated, never
1425      *         {@code null}.
1426      */
1427     public Map<String, List<String>> getInjectedProfileIds()
1428     {
1429         return this.injectedProfileIds;
1430     }
1431 
1432     public void addAttachedArtifact( Artifact artifact )
1433         throws DuplicateArtifactAttachmentException
1434     {
1435         List<Artifact> attachedArtifacts = getAttachedArtifacts();
1436 
1437         if ( attachedArtifacts.contains( artifact ) )
1438         {
1439             if ( logger != null )
1440             {
1441                 logger.warn( "Artifact " + artifact + " already attached to project, ignoring duplicate" );
1442             }
1443             return;
1444             //throw new DuplicateArtifactAttachmentException( this, artifact );
1445         }
1446 
1447         getAttachedArtifacts().add( artifact );
1448     }
1449 
1450     public List<Artifact> getAttachedArtifacts()
1451     {
1452         if ( attachedArtifacts == null )
1453         {
1454             attachedArtifacts = new ArrayList<Artifact>();
1455         }
1456         return attachedArtifacts;
1457     }
1458 
1459     public Xpp3Dom getGoalConfiguration( String pluginGroupId, String pluginArtifactId, String executionId,
1460                                          String goalId )
1461     {
1462         Xpp3Dom dom = null;
1463 
1464         if ( getBuildPlugins() != null )
1465         {
1466             for ( Plugin plugin : getBuildPlugins() )
1467             {
1468                 if ( pluginGroupId.equals( plugin.getGroupId() ) && pluginArtifactId.equals( plugin.getArtifactId() ) )
1469                 {
1470                     dom = (Xpp3Dom) plugin.getConfiguration();
1471 
1472                     if ( executionId != null )
1473                     {
1474                         PluginExecution execution = plugin.getExecutionsAsMap().get( executionId );
1475                         if ( execution != null )
1476                         {
1477                             // NOTE: The PluginConfigurationExpander already merged the plugin-level config in
1478                             dom = (Xpp3Dom) execution.getConfiguration();
1479                         }
1480                     }
1481                     break;
1482                 }
1483             }
1484         }
1485 
1486         if ( dom != null )
1487         {
1488             // make a copy so the original in the POM doesn't get messed with
1489             dom = new Xpp3Dom( dom );
1490         }
1491 
1492         return dom;
1493     }
1494 
1495     @Deprecated
1496     public Xpp3Dom getReportConfiguration( String pluginGroupId, String pluginArtifactId, String reportSetId )
1497     {
1498         Xpp3Dom dom = null;
1499 
1500         // ----------------------------------------------------------------------
1501         // I would like to be able to lookup the Mojo object using a key but
1502         // we have a limitation in modello that will be remedied shortly. So
1503         // for now I have to iterate through and see what we have.
1504         // ----------------------------------------------------------------------
1505 
1506         if ( getReportPlugins() != null )
1507         {
1508             for ( Iterator<ReportPlugin> iterator = getReportPlugins().iterator(); iterator.hasNext(); )
1509             {
1510                 ReportPlugin plugin = iterator.next();
1511 
1512                 if ( pluginGroupId.equals( plugin.getGroupId() ) && pluginArtifactId.equals( plugin.getArtifactId() ) )
1513                 {
1514                     dom = (Xpp3Dom) plugin.getConfiguration();
1515 
1516                     if ( reportSetId != null )
1517                     {
1518                         ReportSet reportSet = plugin.getReportSetsAsMap().get( reportSetId );
1519                         if ( reportSet != null )
1520                         {
1521                             Xpp3Dom executionConfiguration = (Xpp3Dom) reportSet.getConfiguration();
1522                             if ( executionConfiguration != null )
1523                             {
1524                                 Xpp3Dom newDom = new Xpp3Dom( executionConfiguration );
1525                                 dom = Xpp3Dom.mergeXpp3Dom( newDom, dom );
1526                             }
1527                         }
1528                     }
1529                     break;
1530                 }
1531             }
1532         }
1533 
1534         if ( dom != null )
1535         {
1536             // make a copy so the original in the POM doesn't get messed with
1537             dom = new Xpp3Dom( dom );
1538         }
1539 
1540         return dom;
1541     }
1542 
1543     public MavenProject getExecutionProject()
1544     {
1545         return ( executionProject == null ? this : executionProject );
1546     }
1547 
1548     public void setExecutionProject( MavenProject executionProject )
1549     {
1550         this.executionProject = executionProject;
1551     }
1552 
1553     public List<MavenProject> getCollectedProjects()
1554     {
1555         return collectedProjects;
1556     }
1557 
1558     public void setCollectedProjects( List<MavenProject> collectedProjects )
1559     {
1560         this.collectedProjects = collectedProjects;
1561     }
1562 
1563     /**
1564      * Direct dependencies that this project has.
1565      * 
1566      * @return {@link Set} &lt; {@link Artifact} >
1567      * @see #getArtifacts() to get all transitive dependencies
1568      */
1569     public Set<Artifact> getDependencyArtifacts()
1570     {
1571         return dependencyArtifacts;
1572     }
1573 
1574     public void setDependencyArtifacts( Set<Artifact> dependencyArtifacts )
1575     {
1576         this.dependencyArtifacts = dependencyArtifacts;
1577     }
1578 
1579     public void setReleaseArtifactRepository( ArtifactRepository releaseArtifactRepository )
1580     {
1581         this.releaseArtifactRepository = releaseArtifactRepository;
1582     }
1583 
1584     public void setSnapshotArtifactRepository( ArtifactRepository snapshotArtifactRepository )
1585     {
1586         this.snapshotArtifactRepository = snapshotArtifactRepository;
1587     }
1588 
1589     public void setOriginalModel( Model originalModel )
1590     {
1591         this.originalModel = originalModel;
1592     }
1593 
1594     public Model getOriginalModel()
1595     {
1596         return originalModel;
1597     }
1598 
1599     public void setManagedVersionMap( Map<String, Artifact> map )
1600     {
1601         managedVersionMap = map;
1602     }
1603 
1604     public Map<String, Artifact> getManagedVersionMap()
1605     {
1606         if ( managedVersionMap != null )
1607         {
1608             return managedVersionMap;
1609         }
1610 
1611         Map<String, Artifact> map = null;
1612         if ( repositorySystem != null )
1613         {
1614 
1615             List<Dependency> deps;
1616             DependencyManagement dependencyManagement = getDependencyManagement();
1617             if ( ( dependencyManagement != null ) && ( ( deps = dependencyManagement.getDependencies() ) != null ) && ( deps.size() > 0 ) )
1618             {
1619                 map = new HashMap<String, Artifact>();
1620                 for ( Iterator<Dependency> i = dependencyManagement.getDependencies().iterator(); i.hasNext(); )
1621                 {
1622                     Dependency d = i.next();
1623 
1624                     Artifact artifact = repositorySystem.createDependencyArtifact( d );
1625 
1626                     if ( artifact == null )
1627                     {
1628                         map = Collections.emptyMap();
1629                     }
1630 
1631                     map.put( d.getManagementKey(), artifact );
1632                 }
1633             }
1634             else
1635             {
1636                 map = Collections.emptyMap();
1637             }
1638         }
1639         managedVersionMap = map;
1640         return managedVersionMap;
1641     }
1642 
1643     @Override
1644     public boolean equals( Object other )
1645     {
1646         if ( other == this )
1647         {
1648             return true;
1649         }
1650         else if ( !( other instanceof MavenProject ) )
1651         {
1652             return false;
1653         }
1654 
1655         MavenProject that = (MavenProject) other;
1656 
1657         return eq( getArtifactId(), that.getArtifactId() )
1658             && eq( getGroupId(), that.getGroupId() )
1659             && eq( getVersion(), that.getVersion() );
1660     }
1661 
1662     private static <T> boolean eq( T s1, T s2 )
1663     {
1664         return ( s1 != null ) ? s1.equals( s2 ) : s2 == null;
1665     }
1666 
1667     @Override
1668     public int hashCode()
1669     {
1670         int hash = 17;
1671         hash = 31 * hash + getGroupId().hashCode();
1672         hash = 31 * hash + getArtifactId().hashCode();
1673         hash = 31 * hash + getVersion().hashCode();
1674         return hash;
1675     }
1676 
1677     public List<Extension> getBuildExtensions()
1678     {
1679         Build build = getBuild();
1680         if ( ( build == null ) || ( build.getExtensions() == null ) )
1681         {
1682             return Collections.emptyList();
1683         }
1684         else
1685         {
1686             return build.getExtensions();
1687         }
1688     }
1689 
1690     public void addProjectReference( MavenProject project )
1691     {
1692         projectReferences.put( getProjectReferenceId( project.getGroupId(), project.getArtifactId(), project.getVersion() ), project );
1693     }
1694 
1695     /**
1696      * @deprecated Use MavenProjectHelper.attachArtifact(..) instead.
1697      */
1698     @Deprecated
1699     public void attachArtifact( String type, String classifier, File file )
1700     {
1701     }
1702 
1703     public Properties getProperties()
1704     {
1705         return getModel().getProperties();
1706     }
1707 
1708     public List<String> getFilters()
1709     {
1710         return getBuild().getFilters();
1711     }
1712 
1713     public Map<String, MavenProject> getProjectReferences()
1714     {
1715         return projectReferences;
1716     }
1717 
1718     public boolean isExecutionRoot()
1719     {
1720         return executionRoot;
1721     }
1722 
1723     public void setExecutionRoot( boolean executionRoot )
1724     {
1725         this.executionRoot = executionRoot;
1726     }
1727 
1728     public String getDefaultGoal()
1729     {
1730         return getBuild() != null ? getBuild().getDefaultGoal() : null;
1731     }
1732 
1733     public Plugin getPlugin( String pluginKey )
1734     {
1735         return getBuild().getPluginsAsMap().get( pluginKey );
1736     }
1737 
1738     /**
1739      * Default toString
1740      */
1741     @Override
1742     public String toString()
1743     {
1744         StringBuilder sb = new StringBuilder( 128 );
1745         sb.append( "MavenProject: " );
1746         sb.append( getGroupId() );
1747         sb.append( ":" );
1748         sb.append( getArtifactId() );
1749         sb.append( ":" );
1750         sb.append( getVersion() );
1751         sb.append( " @ " );
1752 
1753         try
1754         {
1755             sb.append( getFile().getPath() );
1756         }
1757         catch ( NullPointerException e )
1758         {
1759             //don't log it.
1760         }
1761 
1762         return sb.toString();
1763     }
1764 
1765     /**
1766      * @deprecated Use {@link org.apache.maven.model.io.ModelWriter}.
1767      */
1768     @Deprecated
1769     public void writeModel( Writer writer )
1770         throws IOException
1771     {
1772         MavenXpp3Writer pomWriter = new MavenXpp3Writer();
1773         pomWriter.write( writer, getModel() );
1774     }
1775 
1776     /**
1777      * @deprecated Use {@link org.apache.maven.model.io.ModelWriter}.
1778      */
1779     @Deprecated
1780     public void writeOriginalModel( Writer writer )
1781         throws IOException
1782     {
1783         MavenXpp3Writer pomWriter = new MavenXpp3Writer();
1784         pomWriter.write( writer, getOriginalModel() );
1785     }
1786 
1787     /**
1788      * @throws CloneNotSupportedException
1789      * @since 2.0.9
1790      */
1791     @Override
1792     public MavenProject clone()
1793     {
1794         MavenProject clone;
1795         try
1796         {
1797             clone = (MavenProject) super.clone();
1798         }
1799         catch ( CloneNotSupportedException e )
1800         {
1801             throw new UnsupportedOperationException( e );
1802         }
1803 
1804         clone.deepCopy( this );
1805 
1806         return clone;
1807     }
1808 
1809     protected void setModel( Model model )
1810     {
1811         this.model = model;
1812     }
1813 
1814     protected void setAttachedArtifacts( List<Artifact> attachedArtifacts )
1815     {
1816         this.attachedArtifacts = attachedArtifacts;
1817     }
1818 
1819     protected void setCompileSourceRoots( List<String> compileSourceRoots )
1820     {
1821         this.compileSourceRoots = compileSourceRoots;
1822     }
1823 
1824     protected void setTestCompileSourceRoots( List<String> testCompileSourceRoots )
1825     {
1826         this.testCompileSourceRoots = testCompileSourceRoots;
1827     }
1828 
1829     protected void setScriptSourceRoots( List<String> scriptSourceRoots )
1830     {
1831         this.scriptSourceRoots = scriptSourceRoots;
1832     }
1833 
1834     protected ArtifactRepository getReleaseArtifactRepository()
1835     {
1836         if ( releaseArtifactRepository == null )
1837         {
1838             if ( getDistributionManagement() != null && getDistributionManagement().getRepository() != null )
1839             {
1840                 checkProjectBuildingRequest();
1841                 try
1842                 {
1843                     ArtifactRepository repo =
1844                         repositorySystem.buildArtifactRepository( getDistributionManagement().getRepository() );
1845                     repositorySystem.injectProxy( projectBuilderConfiguration.getRepositorySession(),
1846                                                   Arrays.asList( repo ) );
1847                     repositorySystem.injectAuthentication( projectBuilderConfiguration.getRepositorySession(),
1848                                                            Arrays.asList( repo ) );
1849                     setReleaseArtifactRepository( repo );
1850                 }
1851                 catch ( InvalidRepositoryException e )
1852                 {
1853                     throw new IllegalStateException( "Failed to create release distribution repository for " + getId(),
1854                                                      e );
1855                 }
1856             }
1857         }
1858 
1859         return releaseArtifactRepository;
1860     }
1861 
1862     protected ArtifactRepository getSnapshotArtifactRepository()
1863     {
1864         if ( snapshotArtifactRepository == null )
1865         {
1866             if ( getDistributionManagement() != null && getDistributionManagement().getSnapshotRepository() != null )
1867             {
1868                 checkProjectBuildingRequest();
1869                 try
1870                 {
1871                     ArtifactRepository repo =
1872                         repositorySystem.buildArtifactRepository( getDistributionManagement().getSnapshotRepository() );
1873                     repositorySystem.injectProxy( projectBuilderConfiguration.getRepositorySession(),
1874                                                   Arrays.asList( repo ) );
1875                     repositorySystem.injectAuthentication( projectBuilderConfiguration.getRepositorySession(),
1876                                                            Arrays.asList( repo ) );
1877                     setSnapshotArtifactRepository( repo );
1878                 }
1879                 catch ( InvalidRepositoryException e )
1880                 {
1881                     throw new IllegalStateException(
1882                                                      "Failed to create snapshot distribution repository for " + getId(),
1883                                                      e );
1884                 }
1885             }
1886         }
1887 
1888         return snapshotArtifactRepository;
1889     }
1890 
1891     @Deprecated
1892     public Artifact replaceWithActiveArtifact( Artifact pluginArtifact )
1893     {
1894         return pluginArtifact;
1895     }
1896 
1897     private void deepCopy( MavenProject project )
1898     {
1899         // disown the parent
1900 
1901         // copy fields
1902         setFile( project.getFile() );
1903 
1904         // don't need a deep copy, they don't get modified or added/removed to/from - but make them unmodifiable to be
1905         // sure!
1906         if ( project.getDependencyArtifacts() != null )
1907         {
1908             setDependencyArtifacts( Collections.unmodifiableSet( project.getDependencyArtifacts() ) );
1909         }
1910 
1911         if ( project.getArtifacts() != null )
1912         {
1913             setArtifacts( Collections.unmodifiableSet( project.getArtifacts() ) );
1914         }
1915 
1916         if ( project.getParentFile() != null )
1917         {
1918             parentFile = new File( project.getParentFile().getAbsolutePath() );
1919         }
1920 
1921         if ( project.getPluginArtifacts() != null )
1922         {
1923             setPluginArtifacts( Collections.unmodifiableSet( project.getPluginArtifacts() ) );
1924         }
1925 
1926         if ( project.getReportArtifacts() != null )
1927         {
1928             setReportArtifacts( Collections.unmodifiableSet( project.getReportArtifacts() ) );
1929         }
1930 
1931         if ( project.getExtensionArtifacts() != null )
1932         {
1933             setExtensionArtifacts( Collections.unmodifiableSet( project.getExtensionArtifacts() ) );
1934         }
1935 
1936         setParentArtifact( ( project.getParentArtifact() ) );
1937 
1938         if ( project.getRemoteArtifactRepositories() != null )
1939         {
1940             setRemoteArtifactRepositories( Collections.unmodifiableList( project.getRemoteArtifactRepositories() ) );
1941         }
1942 
1943         if ( project.getPluginArtifactRepositories() != null )
1944         {
1945             setPluginArtifactRepositories( ( Collections.unmodifiableList( project.getPluginArtifactRepositories() ) ) );
1946         }
1947 
1948         if ( project.getActiveProfiles() != null )
1949         {
1950             setActiveProfiles( ( Collections.unmodifiableList( project.getActiveProfiles() ) ) );
1951         }
1952 
1953         if ( project.getAttachedArtifacts() != null )
1954         {
1955             // clone properties modifyable by plugins in a forked lifecycle
1956             setAttachedArtifacts( new ArrayList<Artifact>( project.getAttachedArtifacts() ) );
1957         }
1958 
1959         if ( project.getCompileSourceRoots() != null )
1960         {
1961             // clone source roots
1962             setCompileSourceRoots( ( new ArrayList<String>( project.getCompileSourceRoots() ) ) );
1963         }
1964 
1965         if ( project.getTestCompileSourceRoots() != null )
1966         {
1967             setTestCompileSourceRoots( ( new ArrayList<String>( project.getTestCompileSourceRoots() ) ) );
1968         }
1969 
1970         if ( project.getScriptSourceRoots() != null )
1971         {
1972             setScriptSourceRoots( ( new ArrayList<String>( project.getScriptSourceRoots() ) ) );
1973         }
1974 
1975         if ( project.getModel() != null )
1976         {
1977             setModel( project.getModel().clone() );
1978         }
1979 
1980         if ( project.getOriginalModel() != null )
1981         {
1982             setOriginalModel( project.getOriginalModel() );
1983         }
1984 
1985         setExecutionRoot( project.isExecutionRoot() );
1986 
1987         if ( project.getArtifact() != null )
1988         {
1989             setArtifact( ArtifactUtils.copyArtifact( project.getArtifact() ) );
1990         }
1991 
1992         if ( project.getManagedVersionMap() != null )
1993         {
1994             setManagedVersionMap( new HashMap<String, Artifact>( project.getManagedVersionMap() ) );
1995         }
1996 
1997         lifecyclePhases.addAll( project.lifecyclePhases );
1998     }
1999 
2000     private void addArtifactPath( Artifact artifact, List<String> classpath )
2001     {
2002         File file = artifact.getFile();
2003         if ( file != null )
2004         {
2005             classpath.add( file.getPath() );
2006         }
2007     }
2008 
2009     private static String getProjectReferenceId( String groupId, String artifactId, String version )
2010     {
2011         StringBuilder buffer = new StringBuilder( 128 );
2012         buffer.append( groupId ).append( ':' ).append( artifactId ).append( ':' ).append( version );
2013         return buffer.toString();
2014     }
2015 
2016     /**
2017      * Sets the value of the context value of this project identified
2018      * by the given key. If the supplied value is <code>null</code>,
2019      * the context value is removed from this project.
2020      * 
2021      * Context values are intended to allow core extensions to associate
2022      * derived state with project instances. 
2023      */
2024     public void setContextValue( String key, Object value )
2025     {
2026         if ( context == null )
2027         {
2028             context = new HashMap<String, Object>();
2029         }
2030         if ( value != null )
2031         {
2032             context.put( key, value );
2033         }
2034         else
2035         {
2036             context.remove( key );
2037         }
2038     }
2039 
2040     /**
2041      * Returns context value of this project associated with the given key 
2042      * or null if this project has no such value. 
2043      */
2044     public Object getContextValue( String key )
2045     {
2046         if ( context == null )
2047         {
2048             return null;
2049         }
2050         return context.get( key );
2051     }
2052 
2053     /**
2054      * Sets the project's class realm. <strong>Warning:</strong> This is an internal utility method that is only public
2055      * for technical reasons, it is not part of the public API. In particular, this method can be changed or deleted
2056      * without prior notice and must not be used by plugins.
2057      * 
2058      * @param classRealm The class realm hosting the build extensions of this project, may be {@code null}.
2059      */
2060     public void setClassRealm( ClassRealm classRealm )
2061     {
2062         this.classRealm = classRealm;
2063     }
2064 
2065     /**
2066      * Gets the project's class realm. This class realm hosts the build extensions of the project.
2067      * <strong>Warning:</strong> This is an internal utility method that is only public for technical reasons, it is not
2068      * part of the public API. In particular, this method can be changed or deleted without prior notice and must not be
2069      * used by plugins.
2070      * 
2071      * @return The project's class realm or {@code null}.
2072      */
2073     public ClassRealm getClassRealm()
2074     {
2075         return classRealm;
2076     }
2077 
2078     /**
2079      * Sets the artifact filter used to exclude shared extension artifacts from plugin realms. <strong>Warning:</strong>
2080      * This is an internal utility method that is only public for technical reasons, it is not part of the public API.
2081      * In particular, this method can be changed or deleted without prior notice and must not be used by plugins.
2082      * 
2083      * @param extensionDependencyFilter The dependency filter to apply to plugins, may be {@code null}.
2084      */
2085     public void setExtensionDependencyFilter( DependencyFilter extensionDependencyFilter )
2086     {
2087         this.extensionDependencyFilter = extensionDependencyFilter;
2088     }
2089 
2090     /**
2091      * Gets the dependency filter used to exclude shared extension artifacts from plugin realms.
2092      * <strong>Warning:</strong> This is an internal utility method that is only public for technical reasons, it is not
2093      * part of the public API. In particular, this method can be changed or deleted without prior notice and must not be
2094      * used by plugins.
2095      * 
2096      * @return The dependency filter or {@code null}.
2097      */
2098     public DependencyFilter getExtensionDependencyFilter()
2099     {
2100         return extensionDependencyFilter;
2101     }
2102 
2103     /**
2104      * Sets the transitive dependency artifacts that have been resolved/collected for this project.
2105      * <strong>Warning:</strong> This is an internal utility method that is only public for technical reasons, it is not
2106      * part of the public API. In particular, this method can be changed or deleted without prior notice and must not be
2107      * used by plugins.
2108      * 
2109      * @param artifacts The set of artifacts, may be {@code null}.
2110      */
2111     public void setResolvedArtifacts( Set<Artifact> artifacts )
2112     {
2113         this.resolvedArtifacts = ( artifacts != null ) ? artifacts : Collections.<Artifact> emptySet();
2114         this.artifacts = null;
2115         this.artifactMap = null;
2116     }
2117 
2118     /**
2119      * Sets the scope filter to select the artifacts being exposed to the currently executed mojo.
2120      * <strong>Warning:</strong> This is an internal utility method that is only public for technical reasons, it is not
2121      * part of the public API. In particular, this method can be changed or deleted without prior notice and must not be
2122      * used by plugins.
2123      * 
2124      * @param artifactFilter The artifact filter, may be {@code null} to exclude all artifacts.
2125      */
2126     public void setArtifactFilter( ArtifactFilter artifactFilter )
2127     {
2128         this.artifactFilter = artifactFilter;
2129         this.artifacts = null;
2130         this.artifactMap = null;
2131     }
2132 
2133     /**
2134      * <strong>Warning:</strong> This is an internal utility method that is only public for technical reasons, it is not
2135      * part of the public API. In particular, this method can be changed or deleted without prior notice and must not be
2136      * used by plugins.
2137      * 
2138      * @param phase The phase to check for, must not be {@code null}.
2139      * @return {@code true} if the phase has been seen.
2140      */
2141     public boolean hasLifecyclePhase( String phase )
2142     {
2143         return lifecyclePhases.contains( phase );
2144     }
2145 
2146     /**
2147      * <strong>Warning:</strong> This is an internal utility method that is only public for technical reasons, it is not
2148      * part of the public API. In particular, this method can be changed or deleted without prior notice and must not be
2149      * used by plugins.
2150      * 
2151      * @param lifecyclePhase The lifecycle phase to add, must not be {@code null}.
2152      */
2153     public void addLifecyclePhase( String lifecyclePhase )
2154     {
2155         lifecyclePhases.add( lifecyclePhase );
2156     }
2157 
2158     /**
2159      * Gets the project building request from which this project instance was created. <strong>Warning:</strong> This is
2160      * an utility method that is meant to assist integrators of Maven, it must not be used by Maven plugins.
2161      * 
2162      * @return The project building request or {@code null}.
2163      */
2164     public ProjectBuildingRequest getProjectBuildingRequest()
2165     {
2166         return projectBuilderConfiguration;
2167     }
2168 
2169     /**
2170      * Sets 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      * @param projectBuildingRequest The project building request, may be {@code null}.
2174      */
2175     public void setProjectBuildingRequest( ProjectBuildingRequest projectBuildingRequest )
2176     {
2177         projectBuilderConfiguration = projectBuildingRequest;
2178     }
2179 
2180     private void checkProjectBuildingRequest()
2181     {
2182         if ( projectBuilderConfiguration == null )
2183         {
2184             throw new IllegalStateException( "project building request missing" );
2185         }
2186     }
2187 
2188 }