View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a 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,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.project;
20  
21  import java.io.File;
22  import java.io.IOException;
23  import java.io.Writer;
24  import java.nio.file.Path;
25  import java.util.ArrayList;
26  import java.util.Collections;
27  import java.util.HashMap;
28  import java.util.LinkedHashMap;
29  import java.util.LinkedHashSet;
30  import java.util.List;
31  import java.util.Map;
32  import java.util.Objects;
33  import java.util.Properties;
34  import java.util.Set;
35  
36  import org.apache.maven.RepositoryUtils;
37  import org.apache.maven.artifact.Artifact;
38  import org.apache.maven.artifact.ArtifactUtils;
39  import org.apache.maven.artifact.DependencyResolutionRequiredException;
40  import org.apache.maven.artifact.factory.ArtifactFactory;
41  import org.apache.maven.artifact.repository.ArtifactRepository;
42  import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
43  import org.apache.maven.lifecycle.internal.DefaultProjectArtifactFactory;
44  import org.apache.maven.model.Build;
45  import org.apache.maven.model.CiManagement;
46  import org.apache.maven.model.Contributor;
47  import org.apache.maven.model.Dependency;
48  import org.apache.maven.model.DependencyManagement;
49  import org.apache.maven.model.Developer;
50  import org.apache.maven.model.DistributionManagement;
51  import org.apache.maven.model.Extension;
52  import org.apache.maven.model.IssueManagement;
53  import org.apache.maven.model.License;
54  import org.apache.maven.model.MailingList;
55  import org.apache.maven.model.Model;
56  import org.apache.maven.model.Organization;
57  import org.apache.maven.model.Plugin;
58  import org.apache.maven.model.PluginExecution;
59  import org.apache.maven.model.PluginManagement;
60  import org.apache.maven.model.Prerequisites;
61  import org.apache.maven.model.Profile;
62  import org.apache.maven.model.ReportPlugin;
63  import org.apache.maven.model.ReportSet;
64  import org.apache.maven.model.Reporting;
65  import org.apache.maven.model.Repository;
66  import org.apache.maven.model.Resource;
67  import org.apache.maven.model.Scm;
68  import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
69  import org.apache.maven.model.root.RootLocator;
70  import org.apache.maven.project.artifact.InvalidDependencyVersionException;
71  import org.codehaus.plexus.classworlds.realm.ClassRealm;
72  import org.codehaus.plexus.util.xml.Xpp3Dom;
73  import org.eclipse.aether.graph.DependencyFilter;
74  import org.eclipse.aether.repository.RemoteRepository;
75  import org.slf4j.Logger;
76  import org.slf4j.LoggerFactory;
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 like inheritance and
82   * interpolation can be added. This allows to have an entity which is useful in a runtime while preserving the model so
83   * that it can be marshalled and unmarshalled without being tainted by runtime requirements.
84   * </p>
85   * <p>
86   * With changes during 3.2.2 release MavenProject is closer to being immutable after construction with the removal of
87   * all components from this class, and the upfront construction taken care of entirely by the {@link ProjectBuilder}.
88   * There is still the issue of having to run the lifecycle in order to find all the compile source roots and resource
89   * directories but I hope to take care of this during the Maven 4.0 release (jvz).
90   * </p>
91   */
92  public class MavenProject implements Cloneable {
93  
94      private static final Logger LOGGER = LoggerFactory.getLogger(MavenProject.class);
95  
96      public static final String EMPTY_PROJECT_GROUP_ID = "unknown";
97  
98      public static final String EMPTY_PROJECT_ARTIFACT_ID = "empty-project";
99  
100     public static final String EMPTY_PROJECT_VERSION = "0";
101 
102     private Model model;
103 
104     private MavenProject parent;
105 
106     private File file;
107 
108     private File basedir;
109 
110     private Path rootDirectory;
111 
112     private Set<Artifact> resolvedArtifacts;
113 
114     private ArtifactFilter artifactFilter;
115 
116     private Set<Artifact> artifacts;
117 
118     private Artifact parentArtifact;
119 
120     private Set<Artifact> pluginArtifacts;
121 
122     private List<ArtifactRepository> remoteArtifactRepositories;
123 
124     private List<ArtifactRepository> pluginArtifactRepositories;
125 
126     private List<RemoteRepository> remoteProjectRepositories;
127 
128     private List<RemoteRepository> remotePluginRepositories;
129 
130     private List<Artifact> attachedArtifacts = new ArrayList<>();
131 
132     private MavenProject executionProject;
133 
134     private List<MavenProject> collectedProjects;
135 
136     private List<String> compileSourceRoots = new ArrayList<>();
137 
138     private List<String> testCompileSourceRoots = new ArrayList<>();
139 
140     private List<String> scriptSourceRoots = new ArrayList<>();
141 
142     private ArtifactRepository releaseArtifactRepository;
143 
144     private ArtifactRepository snapshotArtifactRepository;
145 
146     private List<Profile> activeProfiles = new ArrayList<>();
147 
148     private Map<String, List<String>> injectedProfileIds = new LinkedHashMap<>();
149 
150     private Set<Artifact> dependencyArtifacts;
151 
152     private Artifact artifact;
153 
154     // calculated.
155     private Map<String, Artifact> artifactMap;
156 
157     private Model originalModel;
158 
159     private Map<String, Artifact> pluginArtifactMap;
160 
161     private Set<Artifact> reportArtifacts;
162 
163     private Map<String, Artifact> reportArtifactMap;
164 
165     private Set<Artifact> extensionArtifacts;
166 
167     private Map<String, Artifact> extensionArtifactMap;
168 
169     private Map<String, Artifact> managedVersionMap;
170 
171     private Map<String, MavenProject> projectReferences = new HashMap<>();
172 
173     private boolean executionRoot;
174 
175     private File parentFile;
176 
177     private Map<String, Object> context;
178 
179     private ClassRealm classRealm;
180 
181     private DependencyFilter extensionDependencyFilter;
182 
183     private final Set<String> lifecyclePhases = Collections.synchronizedSet(new LinkedHashSet<>());
184 
185     public MavenProject() {
186         Model model = new Model();
187 
188         model.setGroupId(EMPTY_PROJECT_GROUP_ID);
189         model.setArtifactId(EMPTY_PROJECT_ARTIFACT_ID);
190         model.setVersion(EMPTY_PROJECT_VERSION);
191 
192         setModel(model);
193     }
194 
195     public MavenProject(org.apache.maven.api.model.Model model) {
196         this(new Model(model));
197     }
198 
199     public MavenProject(Model model) {
200         setModel(model);
201     }
202 
203     public MavenProject(MavenProject project) {
204         deepCopy(project);
205     }
206 
207     public File getParentFile() {
208         return parentFile;
209     }
210 
211     public void setParentFile(File parentFile) {
212         this.parentFile = parentFile;
213     }
214 
215     // ----------------------------------------------------------------------
216     // Accessors
217     // ----------------------------------------------------------------------
218 
219     public Artifact getArtifact() {
220         return artifact;
221     }
222 
223     public void setArtifact(Artifact artifact) {
224         this.artifact = artifact;
225     }
226 
227     // TODO I would like to get rid of this. jvz.
228     public Model getModel() {
229         return model;
230     }
231 
232     /**
233      * Returns the project corresponding to a declared parent.
234      *
235      * @return the parent, or null if no parent is declared or there was an error building it
236      */
237     public MavenProject getParent() {
238         return parent;
239     }
240 
241     public void setParent(MavenProject parent) {
242         this.parent = parent;
243     }
244 
245     public boolean hasParent() {
246         return getParent() != null;
247     }
248 
249     public File getFile() {
250         return file;
251     }
252 
253     public void setFile(File file) {
254         this.file = file;
255         this.basedir = file != null ? file.getParentFile() : null;
256     }
257 
258     /**
259      * Sets project {@code file} without changing project {@code basedir}.
260      *
261      * @since 3.2.4
262      */
263     public void setPomFile(File file) {
264         this.file = file;
265     }
266 
267     public File getBasedir() {
268         return basedir;
269     }
270 
271     public void setDependencies(List<Dependency> dependencies) {
272         getModel().setDependencies(dependencies);
273     }
274 
275     public List<Dependency> getDependencies() {
276         return getModel().getDependencies();
277     }
278 
279     public DependencyManagement getDependencyManagement() {
280         return getModel().getDependencyManagement();
281     }
282 
283     // ----------------------------------------------------------------------
284     // Test and compile source roots.
285     // ----------------------------------------------------------------------
286 
287     private void addPath(List<String> paths, String path) {
288         if (path != null) {
289             path = path.trim();
290             if (path.length() > 0) {
291                 File file = new File(path);
292                 if (file.isAbsolute()) {
293                     path = file.getAbsolutePath();
294                 } else if (".".equals(path)) {
295                     path = getBasedir().getAbsolutePath();
296                 } else {
297                     path = new File(getBasedir(), path).getAbsolutePath();
298                 }
299 
300                 if (!paths.contains(path)) {
301                     paths.add(path);
302                 }
303             }
304         }
305     }
306 
307     public void addCompileSourceRoot(String path) {
308         addPath(getCompileSourceRoots(), path);
309     }
310 
311     public void addTestCompileSourceRoot(String path) {
312         addPath(getTestCompileSourceRoots(), path);
313     }
314 
315     public List<String> getCompileSourceRoots() {
316         return compileSourceRoots;
317     }
318 
319     public List<String> getTestCompileSourceRoots() {
320         return testCompileSourceRoots;
321     }
322 
323     public List<String> getCompileClasspathElements() throws DependencyResolutionRequiredException {
324         List<String> list = new ArrayList<>(getArtifacts().size() + 1);
325 
326         String d = getBuild().getOutputDirectory();
327         if (d != null) {
328             list.add(d);
329         }
330 
331         for (Artifact a : getArtifacts()) {
332             if (a.getArtifactHandler().isAddedToClasspath()) {
333                 // TODO let the scope handler deal with this
334                 if (Artifact.SCOPE_COMPILE.equals(a.getScope())
335                         || Artifact.SCOPE_PROVIDED.equals(a.getScope())
336                         || Artifact.SCOPE_SYSTEM.equals(a.getScope())) {
337                     addArtifactPath(a, list);
338                 }
339             }
340         }
341 
342         return list;
343     }
344 
345     // TODO this checking for file == null happens because the resolver has been confused about the root
346     // artifact or not. things like the stupid dummy artifact coming from surefire.
347     public List<String> getTestClasspathElements() throws DependencyResolutionRequiredException {
348         List<String> list = new ArrayList<>(getArtifacts().size() + 2);
349 
350         String d = getBuild().getTestOutputDirectory();
351         if (d != null) {
352             list.add(d);
353         }
354 
355         d = getBuild().getOutputDirectory();
356         if (d != null) {
357             list.add(d);
358         }
359 
360         for (Artifact a : getArtifacts()) {
361             if (a.getArtifactHandler().isAddedToClasspath()) {
362                 addArtifactPath(a, list);
363             }
364         }
365 
366         return list;
367     }
368 
369     public List<String> getRuntimeClasspathElements() throws DependencyResolutionRequiredException {
370         List<String> list = new ArrayList<>(getArtifacts().size() + 1);
371 
372         String d = getBuild().getOutputDirectory();
373         if (d != null) {
374             list.add(d);
375         }
376 
377         for (Artifact a : getArtifacts()) {
378             if (a.getArtifactHandler().isAddedToClasspath()
379                     // TODO let the scope handler deal with this
380                     && (Artifact.SCOPE_COMPILE.equals(a.getScope()) || Artifact.SCOPE_RUNTIME.equals(a.getScope()))) {
381                 addArtifactPath(a, list);
382             }
383         }
384         return list;
385     }
386 
387     // ----------------------------------------------------------------------
388     // Delegate to the model
389     // ----------------------------------------------------------------------
390 
391     public void setModelVersion(String pomVersion) {
392         getModel().setModelVersion(pomVersion);
393     }
394 
395     public String getModelVersion() {
396         return getModel().getModelVersion();
397     }
398 
399     public String getId() {
400         return getModel().getId();
401     }
402 
403     public void setGroupId(String groupId) {
404         getModel().setGroupId(groupId);
405     }
406 
407     public String getGroupId() {
408         String groupId = getModel().getGroupId();
409 
410         if ((groupId == null) && (getModel().getParent() != null)) {
411             groupId = getModel().getParent().getGroupId();
412         }
413 
414         return groupId;
415     }
416 
417     public void setArtifactId(String artifactId) {
418         getModel().setArtifactId(artifactId);
419     }
420 
421     public String getArtifactId() {
422         return getModel().getArtifactId();
423     }
424 
425     public void setName(String name) {
426         getModel().setName(name);
427     }
428 
429     public String getName() {
430         // TODO this should not be allowed to be null.
431         if (getModel().getName() != null) {
432             return getModel().getName();
433         } else {
434             return getArtifactId();
435         }
436     }
437 
438     public void setVersion(String version) {
439         getModel().setVersion(version);
440     }
441 
442     public String getVersion() {
443         String version = getModel().getVersion();
444 
445         if ((version == null) && (getModel().getParent() != null)) {
446             version = getModel().getParent().getVersion();
447         }
448 
449         return version;
450     }
451 
452     public String getPackaging() {
453         return getModel().getPackaging();
454     }
455 
456     public void setPackaging(String packaging) {
457         getModel().setPackaging(packaging);
458     }
459 
460     public void setInceptionYear(String inceptionYear) {
461         getModel().setInceptionYear(inceptionYear);
462     }
463 
464     public String getInceptionYear() {
465         return getModel().getInceptionYear();
466     }
467 
468     public void setUrl(String url) {
469         getModel().setUrl(url);
470     }
471 
472     public String getUrl() {
473         return getModel().getUrl();
474     }
475 
476     public Prerequisites getPrerequisites() {
477         return getModel().getPrerequisites();
478     }
479 
480     public void setIssueManagement(IssueManagement issueManagement) {
481         getModel().setIssueManagement(issueManagement);
482     }
483 
484     public CiManagement getCiManagement() {
485         return getModel().getCiManagement();
486     }
487 
488     public void setCiManagement(CiManagement ciManagement) {
489         getModel().setCiManagement(ciManagement);
490     }
491 
492     public IssueManagement getIssueManagement() {
493         return getModel().getIssueManagement();
494     }
495 
496     public void setDistributionManagement(DistributionManagement distributionManagement) {
497         getModel().setDistributionManagement(distributionManagement);
498     }
499 
500     public DistributionManagement getDistributionManagement() {
501         return getModel().getDistributionManagement();
502     }
503 
504     public void setDescription(String description) {
505         getModel().setDescription(description);
506     }
507 
508     public String getDescription() {
509         return getModel().getDescription();
510     }
511 
512     public void setOrganization(Organization organization) {
513         getModel().setOrganization(organization);
514     }
515 
516     public Organization getOrganization() {
517         return getModel().getOrganization();
518     }
519 
520     public void setScm(Scm scm) {
521         getModel().setScm(scm);
522     }
523 
524     public Scm getScm() {
525         return getModel().getScm();
526     }
527 
528     public void setMailingLists(List<MailingList> mailingLists) {
529         getModel().setMailingLists(mailingLists);
530     }
531 
532     public List<MailingList> getMailingLists() {
533         return getModel().getMailingLists();
534     }
535 
536     public void addMailingList(MailingList mailingList) {
537         getModel().addMailingList(mailingList);
538     }
539 
540     public void setDevelopers(List<Developer> developers) {
541         getModel().setDevelopers(developers);
542     }
543 
544     public List<Developer> getDevelopers() {
545         return getModel().getDevelopers();
546     }
547 
548     public void addDeveloper(Developer developer) {
549         getModel().addDeveloper(developer);
550     }
551 
552     public void setContributors(List<Contributor> contributors) {
553         getModel().setContributors(contributors);
554     }
555 
556     public List<Contributor> getContributors() {
557         return getModel().getContributors();
558     }
559 
560     public void addContributor(Contributor contributor) {
561         getModel().addContributor(contributor);
562     }
563 
564     public void setBuild(Build build) {
565         getModel().setBuild(build);
566     }
567 
568     public Build getBuild() {
569         return getModelBuild();
570     }
571 
572     public List<Resource> getResources() {
573         return getBuild().getResources();
574     }
575 
576     public List<Resource> getTestResources() {
577         return getBuild().getTestResources();
578     }
579 
580     public void addResource(Resource resource) {
581         getBuild().addResource(resource);
582     }
583 
584     public void addTestResource(Resource testResource) {
585         getBuild().addTestResource(testResource);
586     }
587 
588     public void setLicenses(List<License> licenses) {
589         getModel().setLicenses(licenses);
590     }
591 
592     public List<License> getLicenses() {
593         return getModel().getLicenses();
594     }
595 
596     public void addLicense(License license) {
597         getModel().addLicense(license);
598     }
599 
600     public void setArtifacts(Set<Artifact> artifacts) {
601         this.artifacts = artifacts;
602 
603         // flush the calculated artifactMap
604         artifactMap = null;
605     }
606 
607     /**
608      * All dependencies that this project has, including transitive ones. Contents are lazily populated, so depending on
609      * what phases have run dependencies in some scopes won't be included. e.g. if only compile phase has run,
610      * dependencies with scope test won't be included.
611      *
612      * @return {@link Set} &lt; {@link Artifact} &gt;
613      * @see #getDependencyArtifacts() to get only direct dependencies
614      */
615     public Set<Artifact> getArtifacts() {
616         if (artifacts == null) {
617             if (artifactFilter == null || resolvedArtifacts == null) {
618                 artifacts = new LinkedHashSet<>();
619             } else {
620                 artifacts = new LinkedHashSet<>(resolvedArtifacts.size() * 2);
621                 for (Artifact artifact : resolvedArtifacts) {
622                     if (artifactFilter.include(artifact)) {
623                         artifacts.add(artifact);
624                     }
625                 }
626             }
627         }
628         return artifacts;
629     }
630 
631     public Map<String, Artifact> getArtifactMap() {
632         if (artifactMap == null) {
633             artifactMap = ArtifactUtils.artifactMapByVersionlessId(getArtifacts());
634         }
635         return artifactMap;
636     }
637 
638     public void setPluginArtifacts(Set<Artifact> pluginArtifacts) {
639         this.pluginArtifacts = pluginArtifacts;
640 
641         this.pluginArtifactMap = null;
642     }
643 
644     public Set<Artifact> getPluginArtifacts() {
645         return pluginArtifacts;
646     }
647 
648     public Map<String, Artifact> getPluginArtifactMap() {
649         if (pluginArtifactMap == null) {
650             pluginArtifactMap = ArtifactUtils.artifactMapByVersionlessId(getPluginArtifacts());
651         }
652 
653         return pluginArtifactMap;
654     }
655 
656     public void setParentArtifact(Artifact parentArtifact) {
657         this.parentArtifact = parentArtifact;
658     }
659 
660     public Artifact getParentArtifact() {
661         return parentArtifact;
662     }
663 
664     public List<Repository> getRepositories() {
665         return getModel().getRepositories();
666     }
667 
668     // ----------------------------------------------------------------------
669     // Plugins
670     // ----------------------------------------------------------------------
671 
672     public List<Plugin> getBuildPlugins() {
673         if (getModel().getBuild() == null) {
674             return Collections.emptyList();
675         }
676         return Collections.unmodifiableList(getModel().getBuild().getPlugins());
677     }
678 
679     public List<String> getModules() {
680         return getModel().getModules();
681     }
682 
683     public PluginManagement getPluginManagement() {
684         PluginManagement pluginMgmt = null;
685 
686         Build build = getModel().getBuild();
687         if (build != null) {
688             pluginMgmt = build.getPluginManagement();
689         }
690 
691         return pluginMgmt;
692     }
693 
694     private Build getModelBuild() {
695         Build build = getModel().getBuild();
696 
697         if (build == null) {
698             build = new Build();
699 
700             getModel().setBuild(build);
701         }
702 
703         return build;
704     }
705 
706     public void setRemoteArtifactRepositories(List<ArtifactRepository> remoteArtifactRepositories) {
707         this.remoteArtifactRepositories = remoteArtifactRepositories;
708         this.remoteProjectRepositories = RepositoryUtils.toRepos(getRemoteArtifactRepositories());
709     }
710 
711     public List<ArtifactRepository> getRemoteArtifactRepositories() {
712         if (remoteArtifactRepositories == null) {
713             remoteArtifactRepositories = new ArrayList<>();
714         }
715 
716         return remoteArtifactRepositories;
717     }
718 
719     public void setPluginArtifactRepositories(List<ArtifactRepository> pluginArtifactRepositories) {
720         this.pluginArtifactRepositories = pluginArtifactRepositories;
721         this.remotePluginRepositories = RepositoryUtils.toRepos(getPluginArtifactRepositories());
722     }
723 
724     /**
725      * @return a list of ArtifactRepository objects constructed from the Repository objects returned by
726      *         getPluginRepositories.
727      */
728     public List<ArtifactRepository> getPluginArtifactRepositories() {
729         if (pluginArtifactRepositories == null) {
730             pluginArtifactRepositories = new ArrayList<>();
731         }
732 
733         return pluginArtifactRepositories;
734     }
735 
736     public ArtifactRepository getDistributionManagementArtifactRepository() {
737         return getArtifact().isSnapshot() && (getSnapshotArtifactRepository() != null)
738                 ? getSnapshotArtifactRepository()
739                 : getReleaseArtifactRepository();
740     }
741 
742     public List<Repository> getPluginRepositories() {
743         return getModel().getPluginRepositories();
744     }
745 
746     public List<RemoteRepository> getRemoteProjectRepositories() {
747         return remoteProjectRepositories;
748     }
749 
750     public List<RemoteRepository> getRemotePluginRepositories() {
751         return remotePluginRepositories;
752     }
753 
754     public void setActiveProfiles(List<Profile> activeProfiles) {
755         this.activeProfiles = activeProfiles;
756     }
757 
758     public List<Profile> getActiveProfiles() {
759         return activeProfiles;
760     }
761 
762     public void setInjectedProfileIds(String source, List<String> injectedProfileIds) {
763         if (injectedProfileIds != null) {
764             this.injectedProfileIds.put(source, new ArrayList<>(injectedProfileIds));
765         } else {
766             this.injectedProfileIds.remove(source);
767         }
768     }
769 
770     /**
771      * Gets the identifiers of all profiles that contributed to this project's effective model. This includes active
772      * profiles from the project's POM and all its parent POMs as well as from external sources like the
773      * {@code settings.xml}. The profile identifiers are grouped by the identifier of their source, e.g.
774      * {@code <groupId>:<artifactId>:<version>} for a POM profile or {@code external} for profiles from the
775      * {@code settings.xml}.
776      *
777      * @return The identifiers of all injected profiles, indexed by the source from which the profiles originated, never
778      *         {@code null}.
779      */
780     public Map<String, List<String>> getInjectedProfileIds() {
781         return this.injectedProfileIds;
782     }
783 
784     /**
785      * Add or replace an artifact. This method is now deprecated. Use the @{MavenProjectHelper} to attach artifacts to a
786      * project. In spite of the 'throws' declaration on this API, this method has never thrown an exception since Maven
787      * 3.0.x. Historically, it logged and ignored a second addition of the same g/a/v/c/t. Now it replaces the file for
788      * the artifact, so that plugins (e.g. shade) can change the pathname of the file for a particular set of
789      * coordinates.
790      *
791      * @param artifact the artifact to add or replace.
792      * @deprecated Please use {@link MavenProjectHelper}
793      * @throws DuplicateArtifactAttachmentException will never happen but leave it for backward compatibility
794      */
795     public void addAttachedArtifact(Artifact artifact) throws DuplicateArtifactAttachmentException {
796         // if already there we remove it and add again
797         int index = attachedArtifacts.indexOf(artifact);
798         if (index >= 0) {
799             LOGGER.warn("artifact '{}' already attached, replacing previous instance", artifact);
800             attachedArtifacts.set(index, artifact);
801         } else {
802             attachedArtifacts.add(artifact);
803         }
804     }
805 
806     /**
807      * Returns a read-only list of the attached artifacts to this project.
808      *
809      * @return the attached artifacts of this project
810      */
811     public List<Artifact> getAttachedArtifacts() {
812         if (attachedArtifacts == null) {
813             attachedArtifacts = new ArrayList<>();
814         }
815         return Collections.unmodifiableList(attachedArtifacts);
816     }
817 
818     public Xpp3Dom getGoalConfiguration(
819             String pluginGroupId, String pluginArtifactId, String executionId, String goalId) {
820         Xpp3Dom dom = null;
821 
822         if (getBuildPlugins() != null) {
823             for (Plugin plugin : getBuildPlugins()) {
824                 if (pluginGroupId.equals(plugin.getGroupId()) && pluginArtifactId.equals(plugin.getArtifactId())) {
825                     dom = (Xpp3Dom) plugin.getConfiguration();
826 
827                     if (executionId != null) {
828                         for (PluginExecution execution : plugin.getExecutions()) {
829                             if (executionId.equals(execution.getId())) {
830                                 // NOTE: The PluginConfigurationExpander already merged the plugin-level config in
831                                 dom = (Xpp3Dom) execution.getConfiguration();
832                                 break;
833                             }
834                         }
835                     }
836                     break;
837                 }
838             }
839         }
840 
841         if (dom != null) {
842             // make a copy so the original in the POM doesn't get messed with
843             dom = new Xpp3Dom(dom);
844         }
845 
846         return dom;
847     }
848 
849     public MavenProject getExecutionProject() {
850         return (executionProject == null ? this : executionProject);
851     }
852 
853     public void setExecutionProject(MavenProject executionProject) {
854         this.executionProject = executionProject;
855     }
856 
857     public List<MavenProject> getCollectedProjects() {
858         return collectedProjects;
859     }
860 
861     public void setCollectedProjects(List<MavenProject> collectedProjects) {
862         this.collectedProjects = collectedProjects;
863     }
864 
865     /**
866      * Direct dependencies that this project has.
867      *
868      * @return {@link Set} &lt; {@link Artifact} &gt;
869      * @see #getArtifacts() to get all transitive dependencies
870      */
871     @Deprecated
872     public Set<Artifact> getDependencyArtifacts() {
873         return dependencyArtifacts;
874     }
875 
876     @Deprecated
877     public void setDependencyArtifacts(Set<Artifact> dependencyArtifacts) {
878         this.dependencyArtifacts = dependencyArtifacts;
879     }
880 
881     public void setReleaseArtifactRepository(ArtifactRepository releaseArtifactRepository) {
882         this.releaseArtifactRepository = releaseArtifactRepository;
883     }
884 
885     public void setSnapshotArtifactRepository(ArtifactRepository snapshotArtifactRepository) {
886         this.snapshotArtifactRepository = snapshotArtifactRepository;
887     }
888 
889     public void setOriginalModel(Model originalModel) {
890         this.originalModel = originalModel;
891     }
892 
893     public Model getOriginalModel() {
894         return originalModel;
895     }
896 
897     public void setManagedVersionMap(Map<String, Artifact> map) {
898         managedVersionMap = map;
899     }
900 
901     public Map<String, Artifact> getManagedVersionMap() {
902         return managedVersionMap;
903     }
904 
905     @Override
906     public boolean equals(Object other) {
907         if (other == this) {
908             return true;
909         } else if (!(other instanceof MavenProject)) {
910             return false;
911         }
912 
913         MavenProject that = (MavenProject) other;
914 
915         return Objects.equals(getArtifactId(), that.getArtifactId())
916                 && Objects.equals(getGroupId(), that.getGroupId())
917                 && Objects.equals(getVersion(), that.getVersion());
918     }
919 
920     @Override
921     public int hashCode() {
922         return Objects.hash(getGroupId(), getArtifactId(), getVersion());
923     }
924 
925     public List<Extension> getBuildExtensions() {
926         Build build = getBuild();
927         if ((build == null) || (build.getExtensions() == null)) {
928             return Collections.emptyList();
929         } else {
930             return Collections.unmodifiableList(build.getExtensions());
931         }
932     }
933 
934     public void addProjectReference(MavenProject project) {
935         projectReferences.put(
936                 getProjectReferenceId(project.getGroupId(), project.getArtifactId(), project.getVersion()), project);
937     }
938 
939     public Properties getProperties() {
940         return getModel().getProperties();
941     }
942 
943     public List<String> getFilters() {
944         return getBuild().getFilters();
945     }
946 
947     public Map<String, MavenProject> getProjectReferences() {
948         return projectReferences;
949     }
950 
951     public boolean isExecutionRoot() {
952         return executionRoot;
953     }
954 
955     public void setExecutionRoot(boolean executionRoot) {
956         this.executionRoot = executionRoot;
957     }
958 
959     public String getDefaultGoal() {
960         return getBuild() != null ? getBuild().getDefaultGoal() : null;
961     }
962 
963     public Plugin getPlugin(String pluginKey) {
964         return getBuild().getPluginsAsMap().get(pluginKey);
965     }
966 
967     /**
968      * Default toString
969      */
970     @Override
971     public String toString() {
972         StringBuilder sb = new StringBuilder(128);
973         sb.append("MavenProject: ");
974         sb.append(getGroupId());
975         sb.append(':');
976         sb.append(getArtifactId());
977         sb.append(':');
978         sb.append(getVersion());
979         if (getFile() != null) {
980             sb.append(" @ ");
981             sb.append(getFile().getPath());
982         }
983 
984         return sb.toString();
985     }
986 
987     /**
988      * @since 2.0.9
989      */
990     @Override
991     public MavenProject clone() {
992         MavenProject clone;
993         try {
994             clone = (MavenProject) super.clone();
995         } catch (CloneNotSupportedException e) {
996             throw new UnsupportedOperationException(e);
997         }
998 
999         clone.deepCopy(this);
1000 
1001         return clone;
1002     }
1003 
1004     public void setModel(Model model) {
1005         this.model = model;
1006     }
1007 
1008     protected void setAttachedArtifacts(List<Artifact> attachedArtifacts) {
1009         this.attachedArtifacts = attachedArtifacts;
1010     }
1011 
1012     protected void setCompileSourceRoots(List<String> compileSourceRoots) {
1013         this.compileSourceRoots = compileSourceRoots;
1014     }
1015 
1016     protected void setTestCompileSourceRoots(List<String> testCompileSourceRoots) {
1017         this.testCompileSourceRoots = testCompileSourceRoots;
1018     }
1019 
1020     protected ArtifactRepository getReleaseArtifactRepository() {
1021         return releaseArtifactRepository;
1022     }
1023 
1024     protected ArtifactRepository getSnapshotArtifactRepository() {
1025         return snapshotArtifactRepository;
1026     }
1027 
1028     private void deepCopy(MavenProject project) {
1029         // disown the parent
1030 
1031         // copy fields
1032         file = project.file;
1033         basedir = project.basedir;
1034 
1035         // don't need a deep copy, they don't get modified or added/removed to/from - but make them unmodifiable to be
1036         // sure!
1037         if (project.getDependencyArtifacts() != null) {
1038             setDependencyArtifacts(Collections.unmodifiableSet(project.getDependencyArtifacts()));
1039         }
1040 
1041         if (project.getArtifacts() != null) {
1042             setArtifacts(Collections.unmodifiableSet(project.getArtifacts()));
1043         }
1044 
1045         if (project.getParentFile() != null) {
1046             parentFile = new File(project.getParentFile().getAbsolutePath());
1047         }
1048 
1049         if (project.getPluginArtifacts() != null) {
1050             setPluginArtifacts(Collections.unmodifiableSet(project.getPluginArtifacts()));
1051         }
1052 
1053         if (project.getReportArtifacts() != null) {
1054             setReportArtifacts(Collections.unmodifiableSet(project.getReportArtifacts()));
1055         }
1056 
1057         if (project.getExtensionArtifacts() != null) {
1058             setExtensionArtifacts(Collections.unmodifiableSet(project.getExtensionArtifacts()));
1059         }
1060 
1061         setParentArtifact((project.getParentArtifact()));
1062 
1063         if (project.getRemoteArtifactRepositories() != null) {
1064             setRemoteArtifactRepositories(Collections.unmodifiableList(project.getRemoteArtifactRepositories()));
1065         }
1066 
1067         if (project.getPluginArtifactRepositories() != null) {
1068             setPluginArtifactRepositories(Collections.unmodifiableList(project.getPluginArtifactRepositories()));
1069         }
1070 
1071         if (project.getActiveProfiles() != null) {
1072             setActiveProfiles((Collections.unmodifiableList(project.getActiveProfiles())));
1073         }
1074 
1075         if (project.getAttachedArtifacts() != null) {
1076             // clone properties modifiable by plugins in a forked lifecycle
1077             setAttachedArtifacts(new ArrayList<>(project.getAttachedArtifacts()));
1078         }
1079 
1080         if (project.getCompileSourceRoots() != null) {
1081             // clone source roots
1082             setCompileSourceRoots((new ArrayList<>(project.getCompileSourceRoots())));
1083         }
1084 
1085         if (project.getTestCompileSourceRoots() != null) {
1086             setTestCompileSourceRoots((new ArrayList<>(project.getTestCompileSourceRoots())));
1087         }
1088 
1089         if (project.getScriptSourceRoots() != null) {
1090             setScriptSourceRoots((new ArrayList<>(project.getScriptSourceRoots())));
1091         }
1092 
1093         if (project.getModel() != null) {
1094             setModel(project.getModel().clone());
1095         }
1096 
1097         if (project.getOriginalModel() != null) {
1098             setOriginalModel(project.getOriginalModel());
1099         }
1100 
1101         setExecutionRoot(project.isExecutionRoot());
1102 
1103         if (project.getArtifact() != null) {
1104             setArtifact(ArtifactUtils.copyArtifact(project.getArtifact()));
1105         }
1106 
1107         if (project.getManagedVersionMap() != null) {
1108             setManagedVersionMap(project.getManagedVersionMap());
1109         }
1110 
1111         lifecyclePhases.addAll(project.lifecyclePhases);
1112     }
1113 
1114     private void addArtifactPath(Artifact artifact, List<String> classpath) {
1115         File file = artifact.getFile();
1116         if (file != null) {
1117             classpath.add(file.getPath());
1118         }
1119     }
1120 
1121     private static String getProjectReferenceId(String groupId, String artifactId, String version) {
1122         StringBuilder buffer = new StringBuilder(128);
1123         buffer.append(groupId).append(':').append(artifactId).append(':').append(version);
1124         return buffer.toString();
1125     }
1126 
1127     /**
1128      * Sets the value of the context value of this project identified by the given key. If the supplied value is
1129      * <code>null</code>, the context value is removed from this project. Context values are intended to allow core
1130      * extensions to associate derived state with project instances.
1131      */
1132     public void setContextValue(String key, Object value) {
1133         if (context == null) {
1134             context = new HashMap<>();
1135         }
1136         if (value != null) {
1137             context.put(key, value);
1138         } else {
1139             context.remove(key);
1140         }
1141     }
1142 
1143     /**
1144      * Returns context value of this project associated with the given key or null if this project has no such value.
1145      */
1146     public Object getContextValue(String key) {
1147         if (context == null) {
1148             return null;
1149         }
1150         return context.get(key);
1151     }
1152 
1153     /**
1154      * Sets the project's class realm. <strong>Warning:</strong> This is an internal utility method that is only public
1155      * for technical reasons, it is not part of the public API. In particular, this method can be changed or deleted
1156      * without prior notice and must not be used by plugins.
1157      *
1158      * @param classRealm The class realm hosting the build extensions of this project, may be {@code null}.
1159      */
1160     public void setClassRealm(ClassRealm classRealm) {
1161         this.classRealm = classRealm;
1162     }
1163 
1164     /**
1165      * Gets the project's class realm. This class realm hosts the build extensions of the project.
1166      * <strong>Warning:</strong> This is an internal utility method that is only public for technical reasons, it is not
1167      * part of the public API. In particular, this method can be changed or deleted without prior notice and must not be
1168      * used by plugins.
1169      *
1170      * @return The project's class realm or {@code null}.
1171      */
1172     public ClassRealm getClassRealm() {
1173         return classRealm;
1174     }
1175 
1176     /**
1177      * Sets the artifact filter used to exclude shared extension artifacts from plugin realms. <strong>Warning:</strong>
1178      * This is an internal utility method that is only public for technical reasons, it is not part of the public API.
1179      * In particular, this method can be changed or deleted without prior notice and must not be used by plugins.
1180      *
1181      * @param extensionDependencyFilter The dependency filter to apply to plugins, may be {@code null}.
1182      */
1183     public void setExtensionDependencyFilter(DependencyFilter extensionDependencyFilter) {
1184         this.extensionDependencyFilter = extensionDependencyFilter;
1185     }
1186 
1187     /**
1188      * Gets the dependency filter used to exclude shared extension artifacts from plugin realms.
1189      * <strong>Warning:</strong> This is an internal utility method that is only public for technical reasons, it is not
1190      * part of the public API. In particular, this method can be changed or deleted without prior notice and must not be
1191      * used by plugins.
1192      *
1193      * @return The dependency filter or {@code null}.
1194      */
1195     public DependencyFilter getExtensionDependencyFilter() {
1196         return extensionDependencyFilter;
1197     }
1198 
1199     /**
1200      * Sets the transitive dependency artifacts that have been resolved/collected for this project.
1201      * <strong>Warning:</strong> This is an internal utility method that is only public for technical reasons, it is not
1202      * part of the public API. In particular, this method can be changed or deleted without prior notice and must not be
1203      * used by plugins.
1204      *
1205      * @param artifacts The set of artifacts, may be {@code null}.
1206      */
1207     public void setResolvedArtifacts(Set<Artifact> artifacts) {
1208         this.resolvedArtifacts = (artifacts != null) ? artifacts : Collections.<Artifact>emptySet();
1209         this.artifacts = null;
1210         this.artifactMap = null;
1211     }
1212 
1213     /**
1214      * Sets the scope filter to select the artifacts being exposed to the currently executed mojo.
1215      * <strong>Warning:</strong> This is an internal utility method that is only public for technical reasons, it is not
1216      * part of the public API. In particular, this method can be changed or deleted without prior notice and must not be
1217      * used by plugins.
1218      *
1219      * @param artifactFilter The artifact filter, may be {@code null} to exclude all artifacts.
1220      */
1221     public void setArtifactFilter(ArtifactFilter artifactFilter) {
1222         this.artifactFilter = artifactFilter;
1223         this.artifacts = null;
1224         this.artifactMap = null;
1225     }
1226 
1227     /**
1228      * <strong>Warning:</strong> This is an internal utility method that is only public for technical reasons, it is not
1229      * part of the public API. In particular, this method can be changed or deleted without prior notice and must not be
1230      * used by plugins.
1231      *
1232      * @param phase The phase to check for, must not be {@code null}.
1233      * @return {@code true} if the phase has been seen.
1234      */
1235     public boolean hasLifecyclePhase(String phase) {
1236         return lifecyclePhases.contains(phase);
1237     }
1238 
1239     /**
1240      * <strong>Warning:</strong> This is an internal utility method that is only public for technical reasons, it is not
1241      * part of the public API. In particular, this method can be changed or deleted without prior notice and must not be
1242      * used by plugins.
1243      *
1244      * @param lifecyclePhase The lifecycle phase to add, must not be {@code null}.
1245      */
1246     public void addLifecyclePhase(String lifecyclePhase) {
1247         lifecyclePhases.add(lifecyclePhase);
1248     }
1249 
1250     // ----------------------------------------------------------------------------------------------------------------
1251     //
1252     //
1253     // D E P R E C A T E D
1254     //
1255     //
1256     // ----------------------------------------------------------------------------------------------------------------
1257     //
1258     // Everything below will be removed for Maven 4.0.0
1259     //
1260     // ----------------------------------------------------------------------------------------------------------------
1261 
1262     private ProjectBuildingRequest projectBuilderConfiguration;
1263 
1264     private Map<String, String> moduleAdjustments;
1265 
1266     @Deprecated // This appears only to be used in test code
1267     public String getModulePathAdjustment(MavenProject moduleProject) throws IOException {
1268         // FIXME: This is hacky. What if module directory doesn't match artifactid, and parent
1269         // is coming from the repository??
1270         String module = moduleProject.getArtifactId();
1271 
1272         File moduleFile = moduleProject.getFile();
1273 
1274         if (moduleFile != null) {
1275             File moduleDir = moduleFile.getCanonicalFile().getParentFile();
1276 
1277             module = moduleDir.getName();
1278         }
1279 
1280         if (moduleAdjustments == null) {
1281             moduleAdjustments = new HashMap<>();
1282 
1283             List<String> modules = getModules();
1284             if (modules != null) {
1285                 for (String modulePath : modules) {
1286                     String moduleName = modulePath;
1287 
1288                     if (moduleName.endsWith("/") || moduleName.endsWith("\\")) {
1289                         moduleName = moduleName.substring(0, moduleName.length() - 1);
1290                     }
1291 
1292                     int lastSlash = moduleName.lastIndexOf('/');
1293 
1294                     if (lastSlash < 0) {
1295                         lastSlash = moduleName.lastIndexOf('\\');
1296                     }
1297 
1298                     String adjustment = null;
1299 
1300                     if (lastSlash > -1) {
1301                         moduleName = moduleName.substring(lastSlash + 1);
1302                         adjustment = modulePath.substring(0, lastSlash);
1303                     }
1304 
1305                     moduleAdjustments.put(moduleName, adjustment);
1306                 }
1307             }
1308         }
1309 
1310         return moduleAdjustments.get(module);
1311     }
1312 
1313     @Deprecated
1314     public Set<Artifact> createArtifacts(ArtifactFactory artifactFactory, String inheritedScope, ArtifactFilter filter)
1315             throws InvalidDependencyVersionException {
1316         return DefaultProjectArtifactFactory.createArtifacts(
1317                 artifactFactory, getModel().getDependencies(), inheritedScope, filter, this);
1318     }
1319 
1320     @Deprecated
1321     protected void setScriptSourceRoots(List<String> scriptSourceRoots) {
1322         this.scriptSourceRoots = scriptSourceRoots;
1323     }
1324 
1325     @Deprecated
1326     public void addScriptSourceRoot(String path) {
1327         if (path != null) {
1328             path = path.trim();
1329             if (path.length() != 0) {
1330                 if (!getScriptSourceRoots().contains(path)) {
1331                     getScriptSourceRoots().add(path);
1332                 }
1333             }
1334         }
1335     }
1336 
1337     @Deprecated
1338     public List<String> getScriptSourceRoots() {
1339         return scriptSourceRoots;
1340     }
1341 
1342     @Deprecated
1343     public List<Artifact> getCompileArtifacts() {
1344         List<Artifact> list = new ArrayList<>(getArtifacts().size());
1345 
1346         for (Artifact a : getArtifacts()) {
1347             // TODO classpath check doesn't belong here - that's the other method
1348             if (a.getArtifactHandler().isAddedToClasspath()) {
1349                 // TODO let the scope handler deal with this
1350                 if (Artifact.SCOPE_COMPILE.equals(a.getScope())
1351                         || Artifact.SCOPE_PROVIDED.equals(a.getScope())
1352                         || Artifact.SCOPE_SYSTEM.equals(a.getScope())) {
1353                     list.add(a);
1354                 }
1355             }
1356         }
1357         return list;
1358     }
1359 
1360     @Deprecated
1361     public List<Dependency> getCompileDependencies() {
1362         Set<Artifact> artifacts = getArtifacts();
1363 
1364         if ((artifacts == null) || artifacts.isEmpty()) {
1365             return Collections.emptyList();
1366         }
1367 
1368         List<Dependency> list = new ArrayList<>(artifacts.size());
1369 
1370         for (Artifact a : getArtifacts()) {
1371             // TODO let the scope handler deal with this
1372             if (Artifact.SCOPE_COMPILE.equals(a.getScope())
1373                     || Artifact.SCOPE_PROVIDED.equals(a.getScope())
1374                     || Artifact.SCOPE_SYSTEM.equals(a.getScope())) {
1375                 Dependency dependency = new Dependency();
1376 
1377                 dependency.setArtifactId(a.getArtifactId());
1378                 dependency.setGroupId(a.getGroupId());
1379                 dependency.setVersion(a.getVersion());
1380                 dependency.setScope(a.getScope());
1381                 dependency.setType(a.getType());
1382                 dependency.setClassifier(a.getClassifier());
1383 
1384                 list.add(dependency);
1385             }
1386         }
1387         return Collections.unmodifiableList(list);
1388     }
1389 
1390     @Deprecated
1391     public List<Artifact> getTestArtifacts() {
1392         List<Artifact> list = new ArrayList<>(getArtifacts().size());
1393 
1394         for (Artifact a : getArtifacts()) {
1395             // TODO classpath check doesn't belong here - that's the other method
1396             if (a.getArtifactHandler().isAddedToClasspath()) {
1397                 list.add(a);
1398             }
1399         }
1400         return list;
1401     }
1402 
1403     @Deprecated
1404     public List<Dependency> getTestDependencies() {
1405         Set<Artifact> artifacts = getArtifacts();
1406 
1407         if ((artifacts == null) || artifacts.isEmpty()) {
1408             return Collections.emptyList();
1409         }
1410 
1411         List<Dependency> list = new ArrayList<>(artifacts.size());
1412 
1413         for (Artifact a : getArtifacts()) {
1414             Dependency dependency = new Dependency();
1415 
1416             dependency.setArtifactId(a.getArtifactId());
1417             dependency.setGroupId(a.getGroupId());
1418             dependency.setVersion(a.getVersion());
1419             dependency.setScope(a.getScope());
1420             dependency.setType(a.getType());
1421             dependency.setClassifier(a.getClassifier());
1422 
1423             list.add(dependency);
1424         }
1425         return Collections.unmodifiableList(list);
1426     }
1427 
1428     @Deprecated // used by the Maven ITs
1429     public List<Dependency> getRuntimeDependencies() {
1430         Set<Artifact> artifacts = getArtifacts();
1431 
1432         if ((artifacts == null) || artifacts.isEmpty()) {
1433             return Collections.emptyList();
1434         }
1435 
1436         List<Dependency> list = new ArrayList<>(artifacts.size());
1437 
1438         for (Artifact a : getArtifacts()) {
1439             // TODO let the scope handler deal with this
1440             if (Artifact.SCOPE_COMPILE.equals(a.getScope()) || Artifact.SCOPE_RUNTIME.equals(a.getScope())) {
1441                 Dependency dependency = new Dependency();
1442 
1443                 dependency.setArtifactId(a.getArtifactId());
1444                 dependency.setGroupId(a.getGroupId());
1445                 dependency.setVersion(a.getVersion());
1446                 dependency.setScope(a.getScope());
1447                 dependency.setType(a.getType());
1448                 dependency.setClassifier(a.getClassifier());
1449 
1450                 list.add(dependency);
1451             }
1452         }
1453         return Collections.unmodifiableList(list);
1454     }
1455 
1456     @Deprecated
1457     public List<Artifact> getRuntimeArtifacts() {
1458         List<Artifact> list = new ArrayList<>(getArtifacts().size());
1459 
1460         for (Artifact a : getArtifacts()) {
1461             // TODO classpath check doesn't belong here - that's the other method
1462             if (a.getArtifactHandler().isAddedToClasspath()
1463                     // TODO let the scope handler deal with this
1464                     && (Artifact.SCOPE_COMPILE.equals(a.getScope()) || Artifact.SCOPE_RUNTIME.equals(a.getScope()))) {
1465                 list.add(a);
1466             }
1467         }
1468         return list;
1469     }
1470 
1471     @Deprecated
1472     public List<String> getSystemClasspathElements() throws DependencyResolutionRequiredException {
1473         List<String> list = new ArrayList<>(getArtifacts().size());
1474 
1475         String d = getBuild().getOutputDirectory();
1476         if (d != null) {
1477             list.add(d);
1478         }
1479 
1480         for (Artifact a : getArtifacts()) {
1481             if (a.getArtifactHandler().isAddedToClasspath()) {
1482                 // TODO let the scope handler deal with this
1483                 if (Artifact.SCOPE_SYSTEM.equals(a.getScope())) {
1484                     addArtifactPath(a, list);
1485                 }
1486             }
1487         }
1488         return list;
1489     }
1490 
1491     @Deprecated
1492     public List<Artifact> getSystemArtifacts() {
1493         List<Artifact> list = new ArrayList<>(getArtifacts().size());
1494 
1495         for (Artifact a : getArtifacts()) {
1496             // TODO classpath check doesn't belong here - that's the other method
1497             if (a.getArtifactHandler().isAddedToClasspath()) {
1498                 // TODO let the scope handler deal with this
1499                 if (Artifact.SCOPE_SYSTEM.equals(a.getScope())) {
1500                     list.add(a);
1501                 }
1502             }
1503         }
1504         return list;
1505     }
1506 
1507     @Deprecated
1508     public List<Dependency> getSystemDependencies() {
1509         Set<Artifact> artifacts = getArtifacts();
1510 
1511         if ((artifacts == null) || artifacts.isEmpty()) {
1512             return Collections.emptyList();
1513         }
1514 
1515         List<Dependency> list = new ArrayList<>(artifacts.size());
1516 
1517         for (Artifact a : getArtifacts()) {
1518             // TODO let the scope handler deal with this
1519             if (Artifact.SCOPE_SYSTEM.equals(a.getScope())) {
1520                 Dependency dependency = new Dependency();
1521 
1522                 dependency.setArtifactId(a.getArtifactId());
1523                 dependency.setGroupId(a.getGroupId());
1524                 dependency.setVersion(a.getVersion());
1525                 dependency.setScope(a.getScope());
1526                 dependency.setType(a.getType());
1527                 dependency.setClassifier(a.getClassifier());
1528 
1529                 list.add(dependency);
1530             }
1531         }
1532         return Collections.unmodifiableList(list);
1533     }
1534 
1535     @Deprecated
1536     public void setReporting(Reporting reporting) {
1537         getModel().setReporting(reporting);
1538     }
1539 
1540     @Deprecated
1541     public Reporting getReporting() {
1542         return getModel().getReporting();
1543     }
1544 
1545     @Deprecated
1546     public void setReportArtifacts(Set<Artifact> reportArtifacts) {
1547         this.reportArtifacts = reportArtifacts;
1548 
1549         reportArtifactMap = null;
1550     }
1551 
1552     @Deprecated
1553     public Set<Artifact> getReportArtifacts() {
1554         return reportArtifacts;
1555     }
1556 
1557     @Deprecated
1558     public Map<String, Artifact> getReportArtifactMap() {
1559         if (reportArtifactMap == null) {
1560             reportArtifactMap = ArtifactUtils.artifactMapByVersionlessId(getReportArtifacts());
1561         }
1562 
1563         return reportArtifactMap;
1564     }
1565 
1566     @Deprecated
1567     public void setExtensionArtifacts(Set<Artifact> extensionArtifacts) {
1568         this.extensionArtifacts = extensionArtifacts;
1569 
1570         extensionArtifactMap = null;
1571     }
1572 
1573     @Deprecated
1574     public Set<Artifact> getExtensionArtifacts() {
1575         return extensionArtifacts;
1576     }
1577 
1578     @Deprecated
1579     public Map<String, Artifact> getExtensionArtifactMap() {
1580         if (extensionArtifactMap == null) {
1581             extensionArtifactMap = ArtifactUtils.artifactMapByVersionlessId(getExtensionArtifacts());
1582         }
1583 
1584         return extensionArtifactMap;
1585     }
1586 
1587     @Deprecated
1588     public List<ReportPlugin> getReportPlugins() {
1589         if (getModel().getReporting() == null) {
1590             return Collections.emptyList();
1591         }
1592         return Collections.unmodifiableList(getModel().getReporting().getPlugins());
1593     }
1594 
1595     @Deprecated
1596     public Xpp3Dom getReportConfiguration(String pluginGroupId, String pluginArtifactId, String reportSetId) {
1597         Xpp3Dom dom = null;
1598 
1599         // ----------------------------------------------------------------------
1600         // I would like to be able to look up the Mojo object using a key but
1601         // we have a limitation in modello that will be remedied shortly. So
1602         // for now I have to iterate through and see what we have.
1603         // ----------------------------------------------------------------------
1604 
1605         if (getReportPlugins() != null) {
1606             for (ReportPlugin plugin : getReportPlugins()) {
1607                 if (pluginGroupId.equals(plugin.getGroupId()) && pluginArtifactId.equals(plugin.getArtifactId())) {
1608                     dom = (Xpp3Dom) plugin.getConfiguration();
1609 
1610                     if (reportSetId != null) {
1611                         ReportSet reportSet = plugin.getReportSetsAsMap().get(reportSetId);
1612                         if (reportSet != null) {
1613                             Xpp3Dom executionConfiguration = (Xpp3Dom) reportSet.getConfiguration();
1614                             if (executionConfiguration != null) {
1615                                 Xpp3Dom newDom = new Xpp3Dom(executionConfiguration);
1616                                 dom = Xpp3Dom.mergeXpp3Dom(newDom, dom);
1617                             }
1618                         }
1619                     }
1620                     break;
1621                 }
1622             }
1623         }
1624 
1625         if (dom != null) {
1626             // make a copy so the original in the POM doesn't get messed with
1627             dom = new Xpp3Dom(dom);
1628         }
1629 
1630         return dom;
1631     }
1632 
1633     /**
1634      * @deprecated Use MavenProjectHelper.attachArtifact(..) instead.
1635      */
1636     @Deprecated
1637     public void attachArtifact(String type, String classifier, File file) {}
1638 
1639     /**
1640      * @deprecated Use {@link org.apache.maven.model.io.ModelWriter}.
1641      */
1642     @Deprecated
1643     public void writeModel(Writer writer) throws IOException {
1644         MavenXpp3Writer pomWriter = new MavenXpp3Writer();
1645         pomWriter.write(writer, getModel());
1646     }
1647 
1648     /**
1649      * @deprecated Use {@link org.apache.maven.model.io.ModelWriter}.
1650      */
1651     @Deprecated
1652     public void writeOriginalModel(Writer writer) throws IOException {
1653         MavenXpp3Writer pomWriter = new MavenXpp3Writer();
1654         pomWriter.write(writer, getOriginalModel());
1655     }
1656 
1657     @Deprecated
1658     public Artifact replaceWithActiveArtifact(Artifact pluginArtifact) {
1659         return pluginArtifact;
1660     }
1661 
1662     /**
1663      * Gets the project building request from which this project instance was created. <strong>Warning:</strong> This is
1664      * a utility method that is meant to assist integrators of Maven, it must not be used by Maven plugins.
1665      *
1666      * @return The project building request or {@code null}.
1667      * @since 2.1
1668      */
1669     @Deprecated
1670     public ProjectBuildingRequest getProjectBuildingRequest() {
1671         return projectBuilderConfiguration;
1672     }
1673 
1674     /**
1675      * Sets the project building request from which this project instance was created. <strong>Warning:</strong> This is
1676      * a utility method that is meant to assist integrators of Maven, it must not be used by Maven plugins.
1677      *
1678      * @param projectBuildingRequest The project building request, may be {@code null}.
1679      * @since 2.1
1680      */
1681     // used by maven-dependency-tree
1682     @Deprecated
1683     public void setProjectBuildingRequest(ProjectBuildingRequest projectBuildingRequest) {
1684         this.projectBuilderConfiguration = projectBuildingRequest;
1685     }
1686 
1687     /**
1688      * @since 4.0.0
1689      * @return the rootDirectory for this project
1690      * @throws IllegalStateException if the rootDirectory cannot be found
1691      */
1692     public Path getRootDirectory() {
1693         if (rootDirectory == null) {
1694             throw new IllegalStateException(RootLocator.UNABLE_TO_FIND_ROOT_PROJECT_MESSAGE);
1695         }
1696         return rootDirectory;
1697     }
1698 
1699     public void setRootDirectory(Path rootDirectory) {
1700         this.rootDirectory = rootDirectory;
1701     }
1702 }