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