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