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.AbstractList;
26  import java.util.ArrayList;
27  import java.util.Collection;
28  import java.util.Collections;
29  import java.util.HashMap;
30  import java.util.Iterator;
31  import java.util.LinkedHashMap;
32  import java.util.LinkedHashSet;
33  import java.util.List;
34  import java.util.ListIterator;
35  import java.util.Map;
36  import java.util.Objects;
37  import java.util.Properties;
38  import java.util.Set;
39  
40  import org.apache.maven.RepositoryUtils;
41  import org.apache.maven.artifact.Artifact;
42  import org.apache.maven.artifact.ArtifactUtils;
43  import org.apache.maven.artifact.DependencyResolutionRequiredException;
44  import org.apache.maven.artifact.factory.ArtifactFactory;
45  import org.apache.maven.artifact.repository.ArtifactRepository;
46  import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
47  import org.apache.maven.model.Build;
48  import org.apache.maven.model.CiManagement;
49  import org.apache.maven.model.Contributor;
50  import org.apache.maven.model.Dependency;
51  import org.apache.maven.model.DependencyManagement;
52  import org.apache.maven.model.Developer;
53  import org.apache.maven.model.DistributionManagement;
54  import org.apache.maven.model.Extension;
55  import org.apache.maven.model.IssueManagement;
56  import org.apache.maven.model.License;
57  import org.apache.maven.model.MailingList;
58  import org.apache.maven.model.Model;
59  import org.apache.maven.model.Organization;
60  import org.apache.maven.model.Plugin;
61  import org.apache.maven.model.PluginExecution;
62  import org.apache.maven.model.PluginManagement;
63  import org.apache.maven.model.Prerequisites;
64  import org.apache.maven.model.Profile;
65  import org.apache.maven.model.ReportPlugin;
66  import org.apache.maven.model.ReportSet;
67  import org.apache.maven.model.Reporting;
68  import org.apache.maven.model.Repository;
69  import org.apache.maven.model.Resource;
70  import org.apache.maven.model.Scm;
71  import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
72  import org.apache.maven.model.root.RootLocator;
73  import org.apache.maven.project.artifact.InvalidDependencyVersionException;
74  import org.apache.maven.project.artifact.MavenMetadataSource;
75  import org.codehaus.plexus.classworlds.realm.ClassRealm;
76  import org.codehaus.plexus.util.xml.Xpp3Dom;
77  import org.eclipse.aether.graph.DependencyFilter;
78  import org.eclipse.aether.repository.RemoteRepository;
79  import org.slf4j.Logger;
80  import org.slf4j.LoggerFactory;
81  
82  /**
83   * The concern of the project is provide runtime values based on the model.
84   * <p>
85   * The values in the model remain untouched but during the process of building a project notions like inheritance and
86   * interpolation can be added. This allows to have an entity which is useful in a runtime while preserving the model so
87   * that it can be marshalled and unmarshalled without being tainted by runtime requirements.
88   * </p>
89   * <p>
90   * With changes during 3.2.2 release MavenProject is closer to being immutable after construction with the removal of
91   * all components from this class, and the upfront construction taken care of entirely by the {@link ProjectBuilder}.
92   * There is still the issue of having to run the lifecycle in order to find all the compile source roots and resource
93   * directories but I hope to take care of this during the Maven 4.0 release (jvz).
94   * </p>
95   */
96  public class MavenProject implements Cloneable {
97  
98      private static final Logger LOGGER = LoggerFactory.getLogger(MavenProject.class);
99  
100     public static final String EMPTY_PROJECT_GROUP_ID = "unknown";
101 
102     public static final String EMPTY_PROJECT_ARTIFACT_ID = "empty-project";
103 
104     public static final String EMPTY_PROJECT_VERSION = "0";
105 
106     private Model model;
107 
108     private MavenProject parent;
109 
110     private File file;
111 
112     private File basedir;
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<String>());
186 
187     private Path rootDirectory;
188 
189     public MavenProject() {
190         Model model = new Model();
191 
192         model.setGroupId(EMPTY_PROJECT_GROUP_ID);
193         model.setArtifactId(EMPTY_PROJECT_ARTIFACT_ID);
194         model.setVersion(EMPTY_PROJECT_VERSION);
195 
196         setModel(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 sourceroots.
285     // ----------------------------------------------------------------------
286 
287     /**
288      * Sanitizes a path by trimming it and converting it to an absolute path.
289      *
290      * @param path the path to sanitize
291      * @return the sanitized path, or null if the input path is null, empty, or consists only of whitespace
292      */
293     private String sanitizePath(String path) {
294         if (path == null) {
295             return null;
296         }
297         path = path.trim();
298         if (path.isEmpty()) {
299             return null;
300         }
301         File file = new File(path);
302         if (file.isAbsolute()) {
303             return file.getAbsolutePath();
304         } else if (".".equals(path)) {
305             return getBasedir().getAbsolutePath();
306         } else {
307             return new File(getBasedir(), path).getAbsolutePath();
308         }
309     }
310 
311     private void addPath(List<String> paths, String path) {
312         String sanitizedPath = sanitizePath(path);
313         if (sanitizedPath != null && !paths.contains(sanitizedPath)) {
314             paths.add(sanitizedPath);
315         }
316     }
317 
318     private void removePath(List<String> paths, String path) {
319         String sanitizedPath = sanitizePath(path);
320         if (sanitizedPath != null) {
321             paths.remove(sanitizedPath);
322         }
323     }
324 
325     /**
326      * Adds the specified path to the list of compile source roots for this project.
327      *
328      * @param path the source root to add
329      */
330     public void addCompileSourceRoot(String path) {
331         addPath(compileSourceRoots, path);
332     }
333 
334     /**
335      * Removes the specified path from the list of compile source roots.
336      *
337      * @param path the source root to remove
338      * @since 3.9.10
339      */
340     public void removeCompileSourceRoot(String path) {
341         removePath(compileSourceRoots, path);
342     }
343 
344     /**
345      * Adds the specified path to the list of test compile source roots for this project.
346      *
347      * @param path the test source root to add
348      */
349     public void addTestCompileSourceRoot(String path) {
350         addPath(testCompileSourceRoots, path);
351     }
352 
353     /**
354      * Removes the specified path from the list of test compile source roots.
355      *
356      * @param path the test source root to remove
357      * @since 3.9.10
358      */
359     public void removeTestCompileSourceRoot(String path) {
360         removePath(testCompileSourceRoots, path);
361     }
362 
363     /**
364      * Gets the list of compile source roots for this project.
365      * <p>
366      * <strong>Note:</strong> The collection returned by this method should not be modified directly.
367      * Use {@link #addCompileSourceRoot(String)} and {@link #removeCompileSourceRoot(String)} methods instead.
368      *
369      * @return a list of compile source roots
370      */
371     public List<String> getCompileSourceRoots() {
372         return new LoggingList<>(compileSourceRoots, "compileSourceRoots");
373     }
374 
375     /**
376      * Gets the list of test compile source roots for this project.
377      * <p>
378      * <strong>Note:</strong> The collection returned by this method should not be modified directly.
379      * Use {@link #addTestCompileSourceRoot(String)} and {@link #removeTestCompileSourceRoot(String)} methods instead.
380      *
381      * @return a list of test compile source roots
382      */
383     public List<String> getTestCompileSourceRoots() {
384         return new LoggingList<>(testCompileSourceRoots, "testCompileSourceRoots");
385     }
386 
387     public List<String> getCompileClasspathElements() throws DependencyResolutionRequiredException {
388         List<String> list = new ArrayList<>(getArtifacts().size() + 1);
389 
390         String d = getBuild().getOutputDirectory();
391         if (d != null) {
392             list.add(d);
393         }
394 
395         for (Artifact a : getArtifacts()) {
396             if (a.getArtifactHandler().isAddedToClasspath()) {
397                 // TODO let the scope handler deal with this
398                 if (Artifact.SCOPE_COMPILE.equals(a.getScope())
399                         || Artifact.SCOPE_PROVIDED.equals(a.getScope())
400                         || Artifact.SCOPE_SYSTEM.equals(a.getScope())) {
401                     addArtifactPath(a, list);
402                 }
403             }
404         }
405 
406         return list;
407     }
408 
409     // TODO this checking for file == null happens because the resolver has been confused about the root
410     // artifact or not. things like the stupid dummy artifact coming from surefire.
411     public List<String> getTestClasspathElements() throws DependencyResolutionRequiredException {
412         List<String> list = new ArrayList<>(getArtifacts().size() + 2);
413 
414         String d = getBuild().getTestOutputDirectory();
415         if (d != null) {
416             list.add(d);
417         }
418 
419         d = getBuild().getOutputDirectory();
420         if (d != null) {
421             list.add(d);
422         }
423 
424         for (Artifact a : getArtifacts()) {
425             if (a.getArtifactHandler().isAddedToClasspath()) {
426                 addArtifactPath(a, list);
427             }
428         }
429 
430         return list;
431     }
432 
433     public List<String> getRuntimeClasspathElements() throws DependencyResolutionRequiredException {
434         List<String> list = new ArrayList<>(getArtifacts().size() + 1);
435 
436         String d = getBuild().getOutputDirectory();
437         if (d != null) {
438             list.add(d);
439         }
440 
441         for (Artifact a : getArtifacts()) {
442             if (a.getArtifactHandler().isAddedToClasspath()
443                     // TODO let the scope handler deal with this
444                     && (Artifact.SCOPE_COMPILE.equals(a.getScope()) || Artifact.SCOPE_RUNTIME.equals(a.getScope()))) {
445                 addArtifactPath(a, list);
446             }
447         }
448         return list;
449     }
450 
451     // ----------------------------------------------------------------------
452     // Delegate to the model
453     // ----------------------------------------------------------------------
454 
455     public void setModelVersion(String pomVersion) {
456         getModel().setModelVersion(pomVersion);
457     }
458 
459     public String getModelVersion() {
460         return getModel().getModelVersion();
461     }
462 
463     public String getId() {
464         return getModel().getId();
465     }
466 
467     public void setGroupId(String groupId) {
468         getModel().setGroupId(groupId);
469     }
470 
471     public String getGroupId() {
472         String groupId = getModel().getGroupId();
473 
474         if ((groupId == null) && (getModel().getParent() != null)) {
475             groupId = getModel().getParent().getGroupId();
476         }
477 
478         return groupId;
479     }
480 
481     public void setArtifactId(String artifactId) {
482         getModel().setArtifactId(artifactId);
483     }
484 
485     public String getArtifactId() {
486         return getModel().getArtifactId();
487     }
488 
489     public void setName(String name) {
490         getModel().setName(name);
491     }
492 
493     public String getName() {
494         if (getModel().getName() != null) {
495             return getModel().getName();
496         } else {
497             return getArtifactId();
498         }
499     }
500 
501     public void setVersion(String version) {
502         getModel().setVersion(version);
503     }
504 
505     public String getVersion() {
506         String version = getModel().getVersion();
507 
508         if ((version == null) && (getModel().getParent() != null)) {
509             version = getModel().getParent().getVersion();
510         }
511 
512         return version;
513     }
514 
515     public String getPackaging() {
516         return getModel().getPackaging();
517     }
518 
519     public void setPackaging(String packaging) {
520         getModel().setPackaging(packaging);
521     }
522 
523     public void setInceptionYear(String inceptionYear) {
524         getModel().setInceptionYear(inceptionYear);
525     }
526 
527     public String getInceptionYear() {
528         return getModel().getInceptionYear();
529     }
530 
531     public void setUrl(String url) {
532         getModel().setUrl(url);
533     }
534 
535     public String getUrl() {
536         return getModel().getUrl();
537     }
538 
539     public Prerequisites getPrerequisites() {
540         return getModel().getPrerequisites();
541     }
542 
543     public void setIssueManagement(IssueManagement issueManagement) {
544         getModel().setIssueManagement(issueManagement);
545     }
546 
547     public CiManagement getCiManagement() {
548         return getModel().getCiManagement();
549     }
550 
551     public void setCiManagement(CiManagement ciManagement) {
552         getModel().setCiManagement(ciManagement);
553     }
554 
555     public IssueManagement getIssueManagement() {
556         return getModel().getIssueManagement();
557     }
558 
559     public void setDistributionManagement(DistributionManagement distributionManagement) {
560         getModel().setDistributionManagement(distributionManagement);
561     }
562 
563     public DistributionManagement getDistributionManagement() {
564         return getModel().getDistributionManagement();
565     }
566 
567     public void setDescription(String description) {
568         getModel().setDescription(description);
569     }
570 
571     public String getDescription() {
572         return getModel().getDescription();
573     }
574 
575     public void setOrganization(Organization organization) {
576         getModel().setOrganization(organization);
577     }
578 
579     public Organization getOrganization() {
580         return getModel().getOrganization();
581     }
582 
583     public void setScm(Scm scm) {
584         getModel().setScm(scm);
585     }
586 
587     public Scm getScm() {
588         return getModel().getScm();
589     }
590 
591     public void setMailingLists(List<MailingList> mailingLists) {
592         getModel().setMailingLists(mailingLists);
593     }
594 
595     public List<MailingList> getMailingLists() {
596         return getModel().getMailingLists();
597     }
598 
599     public void addMailingList(MailingList mailingList) {
600         getModel().addMailingList(mailingList);
601     }
602 
603     public void setDevelopers(List<Developer> developers) {
604         getModel().setDevelopers(developers);
605     }
606 
607     public List<Developer> getDevelopers() {
608         return getModel().getDevelopers();
609     }
610 
611     public void addDeveloper(Developer developer) {
612         getModel().addDeveloper(developer);
613     }
614 
615     public void setContributors(List<Contributor> contributors) {
616         getModel().setContributors(contributors);
617     }
618 
619     public List<Contributor> getContributors() {
620         return getModel().getContributors();
621     }
622 
623     public void addContributor(Contributor contributor) {
624         getModel().addContributor(contributor);
625     }
626 
627     public void setBuild(Build build) {
628         getModel().setBuild(build);
629     }
630 
631     public Build getBuild() {
632         return getModelBuild();
633     }
634 
635     public List<Resource> getResources() {
636         return getBuild().getResources();
637     }
638 
639     public List<Resource> getTestResources() {
640         return getBuild().getTestResources();
641     }
642 
643     public void addResource(Resource resource) {
644         getBuild().addResource(resource);
645     }
646 
647     public void addTestResource(Resource testResource) {
648         getBuild().addTestResource(testResource);
649     }
650 
651     public void setLicenses(List<License> licenses) {
652         getModel().setLicenses(licenses);
653     }
654 
655     public List<License> getLicenses() {
656         return getModel().getLicenses();
657     }
658 
659     public void addLicense(License license) {
660         getModel().addLicense(license);
661     }
662 
663     public void setArtifacts(Set<Artifact> artifacts) {
664         this.artifacts = artifacts;
665 
666         // flush the calculated artifactMap
667         artifactMap = null;
668     }
669 
670     /**
671      * All dependencies that this project has, including transitive ones. Contents are lazily populated, so depending on
672      * what phases have run dependencies in some scopes won't be included. eg. if only compile phase has run,
673      * dependencies with scope test won't be included.
674      *
675      * @return {@link Set} &lt; {@link Artifact} &gt;
676      * @see #getDependencyArtifacts() to get only direct dependencies
677      */
678     public Set<Artifact> getArtifacts() {
679         if (artifacts == null) {
680             if (artifactFilter == null || resolvedArtifacts == null) {
681                 artifacts = new LinkedHashSet<>();
682             } else {
683                 artifacts = new LinkedHashSet<>(resolvedArtifacts.size() * 2);
684                 for (Artifact artifact : resolvedArtifacts) {
685                     if (artifactFilter.include(artifact)) {
686                         artifacts.add(artifact);
687                     }
688                 }
689             }
690         }
691         return artifacts;
692     }
693 
694     public Map<String, Artifact> getArtifactMap() {
695         if (artifactMap == null) {
696             artifactMap = ArtifactUtils.artifactMapByVersionlessId(getArtifacts());
697         }
698         return artifactMap;
699     }
700 
701     public void setPluginArtifacts(Set<Artifact> pluginArtifacts) {
702         this.pluginArtifacts = pluginArtifacts;
703 
704         this.pluginArtifactMap = null;
705     }
706 
707     public Set<Artifact> getPluginArtifacts() {
708         return pluginArtifacts;
709     }
710 
711     public Map<String, Artifact> getPluginArtifactMap() {
712         if (pluginArtifactMap == null) {
713             pluginArtifactMap = ArtifactUtils.artifactMapByVersionlessId(getPluginArtifacts());
714         }
715 
716         return pluginArtifactMap;
717     }
718 
719     public void setParentArtifact(Artifact parentArtifact) {
720         this.parentArtifact = parentArtifact;
721     }
722 
723     public Artifact getParentArtifact() {
724         return parentArtifact;
725     }
726 
727     public List<Repository> getRepositories() {
728         return getModel().getRepositories();
729     }
730 
731     // ----------------------------------------------------------------------
732     // Plugins
733     // ----------------------------------------------------------------------
734 
735     public List<Plugin> getBuildPlugins() {
736         if (getModel().getBuild() == null) {
737             return Collections.emptyList();
738         }
739         return Collections.unmodifiableList(getModel().getBuild().getPlugins());
740     }
741 
742     public List<String> getModules() {
743         return getModel().getModules();
744     }
745 
746     public PluginManagement getPluginManagement() {
747         PluginManagement pluginMgmt = null;
748 
749         Build build = getModel().getBuild();
750         if (build != null) {
751             pluginMgmt = build.getPluginManagement();
752         }
753 
754         if (pluginMgmt == null) {
755             pluginMgmt = new PluginManagement();
756         }
757 
758         return pluginMgmt;
759     }
760 
761     private Build getModelBuild() {
762         Build build = getModel().getBuild();
763 
764         if (build == null) {
765             build = new Build();
766 
767             getModel().setBuild(build);
768         }
769 
770         return build;
771     }
772 
773     public void setRemoteArtifactRepositories(List<ArtifactRepository> remoteArtifactRepositories) {
774         this.remoteArtifactRepositories = remoteArtifactRepositories;
775         this.remoteProjectRepositories = RepositoryUtils.toRepos(getRemoteArtifactRepositories());
776     }
777 
778     public List<ArtifactRepository> getRemoteArtifactRepositories() {
779         if (remoteArtifactRepositories == null) {
780             remoteArtifactRepositories = new ArrayList<>();
781         }
782 
783         return remoteArtifactRepositories;
784     }
785 
786     public void setPluginArtifactRepositories(List<ArtifactRepository> pluginArtifactRepositories) {
787         this.pluginArtifactRepositories = pluginArtifactRepositories;
788         this.remotePluginRepositories = RepositoryUtils.toRepos(getPluginArtifactRepositories());
789     }
790 
791     /**
792      * @return a list of ArtifactRepository objects constructed from the Repository objects returned by
793      *         getPluginRepositories.
794      */
795     public List<ArtifactRepository> getPluginArtifactRepositories() {
796         if (pluginArtifactRepositories == null) {
797             pluginArtifactRepositories = new ArrayList<>();
798         }
799 
800         return pluginArtifactRepositories;
801     }
802 
803     public ArtifactRepository getDistributionManagementArtifactRepository() {
804         return getArtifact().isSnapshot() && (getSnapshotArtifactRepository() != null)
805                 ? getSnapshotArtifactRepository()
806                 : getReleaseArtifactRepository();
807     }
808 
809     public List<Repository> getPluginRepositories() {
810         return getModel().getPluginRepositories();
811     }
812 
813     public List<RemoteRepository> getRemoteProjectRepositories() {
814         return remoteProjectRepositories;
815     }
816 
817     public List<RemoteRepository> getRemotePluginRepositories() {
818         return remotePluginRepositories;
819     }
820 
821     public void setActiveProfiles(List<Profile> activeProfiles) {
822         this.activeProfiles = activeProfiles;
823     }
824 
825     public List<Profile> getActiveProfiles() {
826         return activeProfiles;
827     }
828 
829     public void setInjectedProfileIds(String source, List<String> injectedProfileIds) {
830         if (injectedProfileIds != null) {
831             this.injectedProfileIds.put(source, new ArrayList<>(injectedProfileIds));
832         } else {
833             this.injectedProfileIds.remove(source);
834         }
835     }
836 
837     /**
838      * Gets the identifiers of all profiles that contributed to this project's effective model. This includes active
839      * profiles from the project's POM and all its parent POMs as well as from external sources like the
840      * {@code settings.xml}. The profile identifiers are grouped by the identifier of their source, e.g.
841      * {@code <groupId>:<artifactId>:<version>} for a POM profile or {@code external} for profiles from the
842      * {@code settings.xml}.
843      *
844      * @return The identifiers of all injected profiles, indexed by the source from which the profiles originated, never
845      *         {@code null}.
846      */
847     public Map<String, List<String>> getInjectedProfileIds() {
848         return this.injectedProfileIds;
849     }
850 
851     /**
852      * Add or replace an artifact. This method is now deprecated. Use the @{MavenProjectHelper} to attach artifacts to a
853      * project. In spite of the 'throws' declaration on this API, this method has never thrown an exception since Maven
854      * 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
855      * the artifact, so that plugins (e.g. shade) can change the pathname of the file for a particular set of
856      * coordinates.
857      *
858      * @param artifact the artifact to add or replace.
859      * @deprecated Please use {@link MavenProjectHelper}
860      * @throws DuplicateArtifactAttachmentException will never happen but leave it for backward compatibility
861      */
862     public void addAttachedArtifact(Artifact artifact) throws DuplicateArtifactAttachmentException {
863         // if already there we remove it and add again
864         int index = attachedArtifacts.indexOf(artifact);
865         if (index >= 0) {
866             LOGGER.warn("artifact {} already attached, replace previous instance", artifact);
867             attachedArtifacts.set(index, artifact);
868         } else {
869             attachedArtifacts.add(artifact);
870         }
871     }
872 
873     /**
874      * Returns a mutable list of the attached artifacts to this project. It is highly advised <em>not</em>
875      * to modify this list, but rather use the {@link MavenProjectHelper}.
876      * <p>
877      * <strong>Note</strong>: This list will be made read-only in Maven 4.</p>
878      *
879      * @return the attached artifacts of this project
880      */
881     public List<Artifact> getAttachedArtifacts() {
882         if (attachedArtifacts == null) {
883             attachedArtifacts = new ArrayList<>();
884         }
885         return attachedArtifacts;
886     }
887 
888     public Xpp3Dom getGoalConfiguration(
889             String pluginGroupId, String pluginArtifactId, String executionId, String goalId) {
890         Xpp3Dom dom = null;
891 
892         if (getBuildPlugins() != null) {
893             for (Plugin plugin : getBuildPlugins()) {
894                 if (pluginGroupId.equals(plugin.getGroupId()) && pluginArtifactId.equals(plugin.getArtifactId())) {
895                     dom = (Xpp3Dom) plugin.getConfiguration();
896 
897                     if (executionId != null) {
898                         PluginExecution execution = plugin.getExecutionsAsMap().get(executionId);
899                         if (execution != null) {
900                             // NOTE: The PluginConfigurationExpander already merged the plugin-level config in
901                             dom = (Xpp3Dom) execution.getConfiguration();
902                         }
903                     }
904                     break;
905                 }
906             }
907         }
908 
909         if (dom != null) {
910             // make a copy so the original in the POM doesn't get messed with
911             dom = new Xpp3Dom(dom);
912         }
913 
914         return dom;
915     }
916 
917     public MavenProject getExecutionProject() {
918         return (executionProject == null ? this : executionProject);
919     }
920 
921     public void setExecutionProject(MavenProject executionProject) {
922         this.executionProject = executionProject;
923     }
924 
925     public List<MavenProject> getCollectedProjects() {
926         return collectedProjects;
927     }
928 
929     public void setCollectedProjects(List<MavenProject> collectedProjects) {
930         this.collectedProjects = collectedProjects;
931     }
932 
933     /**
934      * Direct dependencies that this project has.
935      *
936      * @return {@link Set} &lt; {@link Artifact} &gt;
937      * @see #getArtifacts() to get all transitive dependencies
938      */
939     @Deprecated
940     public Set<Artifact> getDependencyArtifacts() {
941         return dependencyArtifacts;
942     }
943 
944     @Deprecated
945     public void setDependencyArtifacts(Set<Artifact> dependencyArtifacts) {
946         this.dependencyArtifacts = dependencyArtifacts;
947     }
948 
949     public void setReleaseArtifactRepository(ArtifactRepository releaseArtifactRepository) {
950         this.releaseArtifactRepository = releaseArtifactRepository;
951     }
952 
953     public void setSnapshotArtifactRepository(ArtifactRepository snapshotArtifactRepository) {
954         this.snapshotArtifactRepository = snapshotArtifactRepository;
955     }
956 
957     public void setOriginalModel(Model originalModel) {
958         this.originalModel = originalModel;
959     }
960 
961     public Model getOriginalModel() {
962         return originalModel;
963     }
964 
965     public void setManagedVersionMap(Map<String, Artifact> map) {
966         managedVersionMap = map;
967     }
968 
969     public Map<String, Artifact> getManagedVersionMap() {
970         return managedVersionMap;
971     }
972 
973     @Override
974     public boolean equals(Object other) {
975         if (other == this) {
976             return true;
977         } else if (!(other instanceof MavenProject)) {
978             return false;
979         }
980 
981         MavenProject that = (MavenProject) other;
982 
983         return Objects.equals(getArtifactId(), that.getArtifactId())
984                 && Objects.equals(getGroupId(), that.getGroupId())
985                 && Objects.equals(getVersion(), that.getVersion());
986     }
987 
988     @Override
989     public int hashCode() {
990         return Objects.hash(getGroupId(), getArtifactId(), getVersion());
991     }
992 
993     public List<Extension> getBuildExtensions() {
994         Build build = getBuild();
995         if ((build == null) || (build.getExtensions() == null)) {
996             return Collections.emptyList();
997         } else {
998             return Collections.unmodifiableList(build.getExtensions());
999         }
1000     }
1001 
1002     public void addProjectReference(MavenProject project) {
1003         projectReferences.put(
1004                 getProjectReferenceId(project.getGroupId(), project.getArtifactId(), project.getVersion()), project);
1005     }
1006 
1007     public Properties getProperties() {
1008         return getModel().getProperties();
1009     }
1010 
1011     public List<String> getFilters() {
1012         return getBuild().getFilters();
1013     }
1014 
1015     public Map<String, MavenProject> getProjectReferences() {
1016         return projectReferences;
1017     }
1018 
1019     public boolean isExecutionRoot() {
1020         return executionRoot;
1021     }
1022 
1023     public void setExecutionRoot(boolean executionRoot) {
1024         this.executionRoot = executionRoot;
1025     }
1026 
1027     public String getDefaultGoal() {
1028         return getBuild() != null ? getBuild().getDefaultGoal() : null;
1029     }
1030 
1031     public Plugin getPlugin(String pluginKey) {
1032         return getBuild().getPluginsAsMap().get(pluginKey);
1033     }
1034 
1035     /**
1036      * Default toString
1037      */
1038     @Override
1039     public String toString() {
1040         StringBuilder sb = new StringBuilder(128);
1041         sb.append("MavenProject: ");
1042         sb.append(getGroupId());
1043         sb.append(':');
1044         sb.append(getArtifactId());
1045         sb.append(':');
1046         sb.append(getVersion());
1047         sb.append(" @ ");
1048 
1049         try {
1050             sb.append(getFile().getPath());
1051         } catch (NullPointerException e) {
1052             // don't log it.
1053         }
1054 
1055         return sb.toString();
1056     }
1057 
1058     /**
1059      * @since 2.0.9
1060      */
1061     @Override
1062     public MavenProject clone() {
1063         MavenProject clone;
1064         try {
1065             clone = (MavenProject) super.clone();
1066         } catch (CloneNotSupportedException e) {
1067             throw new UnsupportedOperationException(e);
1068         }
1069 
1070         clone.deepCopy(this);
1071 
1072         return clone;
1073     }
1074 
1075     public void setModel(Model model) {
1076         this.model = model;
1077     }
1078 
1079     protected void setAttachedArtifacts(List<Artifact> attachedArtifacts) {
1080         this.attachedArtifacts = attachedArtifacts;
1081     }
1082 
1083     protected void setCompileSourceRoots(List<String> compileSourceRoots) {
1084         this.compileSourceRoots = compileSourceRoots;
1085     }
1086 
1087     protected void setTestCompileSourceRoots(List<String> testCompileSourceRoots) {
1088         this.testCompileSourceRoots = testCompileSourceRoots;
1089     }
1090 
1091     protected ArtifactRepository getReleaseArtifactRepository() {
1092         return releaseArtifactRepository;
1093     }
1094 
1095     protected ArtifactRepository getSnapshotArtifactRepository() {
1096         return snapshotArtifactRepository;
1097     }
1098 
1099     private void deepCopy(MavenProject project) {
1100         // disown the parent
1101 
1102         // copy fields
1103         file = project.file;
1104         basedir = project.basedir;
1105 
1106         // don't need a deep copy, they don't get modified or added/removed to/from - but make them unmodifiable to be
1107         // sure!
1108         if (project.getDependencyArtifacts() != null) {
1109             setDependencyArtifacts(Collections.unmodifiableSet(project.getDependencyArtifacts()));
1110         }
1111 
1112         if (project.getArtifacts() != null) {
1113             setArtifacts(Collections.unmodifiableSet(project.getArtifacts()));
1114         }
1115 
1116         if (project.getParentFile() != null) {
1117             parentFile = new File(project.getParentFile().getAbsolutePath());
1118         }
1119 
1120         if (project.getPluginArtifacts() != null) {
1121             setPluginArtifacts(Collections.unmodifiableSet(project.getPluginArtifacts()));
1122         }
1123 
1124         if (project.getReportArtifacts() != null) {
1125             setReportArtifacts(Collections.unmodifiableSet(project.getReportArtifacts()));
1126         }
1127 
1128         if (project.getExtensionArtifacts() != null) {
1129             setExtensionArtifacts(Collections.unmodifiableSet(project.getExtensionArtifacts()));
1130         }
1131 
1132         setParentArtifact((project.getParentArtifact()));
1133 
1134         if (project.getRemoteArtifactRepositories() != null) {
1135             setRemoteArtifactRepositories(Collections.unmodifiableList(project.getRemoteArtifactRepositories()));
1136         }
1137 
1138         if (project.getPluginArtifactRepositories() != null) {
1139             setPluginArtifactRepositories(Collections.unmodifiableList(project.getPluginArtifactRepositories()));
1140         }
1141 
1142         if (project.getActiveProfiles() != null) {
1143             setActiveProfiles((Collections.unmodifiableList(project.getActiveProfiles())));
1144         }
1145 
1146         if (project.getAttachedArtifacts() != null) {
1147             // clone properties modifyable by plugins in a forked lifecycle
1148             setAttachedArtifacts(new ArrayList<>(project.getAttachedArtifacts()));
1149         }
1150 
1151         if (project.getCompileSourceRoots() != null) {
1152             // clone source roots
1153             setCompileSourceRoots((new ArrayList<>(project.getCompileSourceRoots())));
1154         }
1155 
1156         if (project.getTestCompileSourceRoots() != null) {
1157             setTestCompileSourceRoots((new ArrayList<>(project.getTestCompileSourceRoots())));
1158         }
1159 
1160         if (project.getScriptSourceRoots() != null) {
1161             setScriptSourceRoots((new ArrayList<>(project.getScriptSourceRoots())));
1162         }
1163 
1164         if (project.getModel() != null) {
1165             setModel(project.getModel().clone());
1166         }
1167 
1168         if (project.getOriginalModel() != null) {
1169             setOriginalModel(project.getOriginalModel());
1170         }
1171 
1172         setExecutionRoot(project.isExecutionRoot());
1173 
1174         if (project.getArtifact() != null) {
1175             setArtifact(ArtifactUtils.copyArtifact(project.getArtifact()));
1176         }
1177 
1178         if (project.getManagedVersionMap() != null) {
1179             setManagedVersionMap(project.getManagedVersionMap());
1180         }
1181 
1182         lifecyclePhases.addAll(project.lifecyclePhases);
1183     }
1184 
1185     private void addArtifactPath(Artifact artifact, List<String> classpath) {
1186         File file = artifact.getFile();
1187         if (file != null) {
1188             classpath.add(file.getPath());
1189         }
1190     }
1191 
1192     private static String getProjectReferenceId(String groupId, String artifactId, String version) {
1193         StringBuilder buffer = new StringBuilder(128);
1194         buffer.append(groupId).append(':').append(artifactId).append(':').append(version);
1195         return buffer.toString();
1196     }
1197 
1198     /**
1199      * A List implementation that logs warnings when modified directly instead of using the proper add/remove methods.
1200      * This is a wrapper that delegates all operations to the underlying list, so modifications to this list
1201      * will affect the original list.
1202      *
1203      * @param <E> the type of elements in the list
1204      * @since 3.9.10
1205      */
1206     private class LoggingList<E> extends AbstractList<E> {
1207         private static final String DISABLE_WARNINGS_PROPERTY = "maven.project.sourceRoots.warningsDisabled";
1208         private final List<E> delegate;
1209         private final String collectionName;
1210 
1211         LoggingList(List<E> delegate, String collectionName) {
1212             this.delegate = delegate;
1213             this.collectionName = collectionName;
1214         }
1215 
1216         private void logWarning(String method) {
1217             // Check if warnings are disabled
1218             String property = getProperties().getProperty(DISABLE_WARNINGS_PROPERTY);
1219             if (property == null) {
1220                 property = System.getProperty(DISABLE_WARNINGS_PROPERTY);
1221             }
1222             if (Boolean.parseBoolean(property)) {
1223                 return;
1224             }
1225 
1226             String specificMethods = getRecommendedMethods(collectionName);
1227             LOGGER.warn("Plugin is modifying " + collectionName + " through " + method
1228                     + "(), which will not work in Maven 4.0.0. "
1229                     + "Use " + specificMethods + " instead. "
1230                     + "If using a plugin, please upgrade to the latest version or report the issue to the plugin maintainer. "
1231                     + "To disable these warnings, set -D" + DISABLE_WARNINGS_PROPERTY + "=true on the command line, "
1232                     + "in the .mvn/maven.config file, or in project POM properties.");
1233             // Log a stack trace to help identify the caller
1234             if (LOGGER.isDebugEnabled()) {
1235                 LOGGER.debug("Stack trace for deprecated source root modification:", new Exception("Stack trace"));
1236             }
1237         }
1238 
1239         private String getRecommendedMethods(String collectionName) {
1240             switch (collectionName) {
1241                 case "compileSourceRoots":
1242                     return "MavenProject.addCompileSourceRoot()/removeCompileSourceRoot() methods";
1243                 case "testCompileSourceRoots":
1244                     return "MavenProject.addTestCompileSourceRoot()/removeTestCompileSourceRoot() methods";
1245                 default:
1246                     return "appropriate MavenProject add/remove methods";
1247             }
1248         }
1249 
1250         @Override
1251         public E get(int index) {
1252             return delegate.get(index);
1253         }
1254 
1255         @Override
1256         public int size() {
1257             return delegate.size();
1258         }
1259 
1260         @Override
1261         public E set(int index, E element) {
1262             logWarning("set");
1263             return delegate.set(index, element);
1264         }
1265 
1266         @Override
1267         public void add(int index, E element) {
1268             logWarning("add");
1269             delegate.add(index, element);
1270         }
1271 
1272         @Override
1273         public E remove(int index) {
1274             logWarning("remove");
1275             return delegate.remove(index);
1276         }
1277 
1278         @Override
1279         public void clear() {
1280             logWarning("clear");
1281             delegate.clear();
1282         }
1283 
1284         @Override
1285         public boolean addAll(int index, Collection<? extends E> c) {
1286             logWarning("addAll");
1287             return delegate.addAll(index, c);
1288         }
1289 
1290         @Override
1291         public Iterator<E> iterator() {
1292             return new Iterator<E>() {
1293                 private final Iterator<E> it = delegate.iterator();
1294 
1295                 @Override
1296                 public boolean hasNext() {
1297                     return it.hasNext();
1298                 }
1299 
1300                 @Override
1301                 public E next() {
1302                     return it.next();
1303                 }
1304 
1305                 @Override
1306                 public void remove() {
1307                     logWarning("iterator.remove");
1308                     it.remove();
1309                 }
1310             };
1311         }
1312 
1313         @Override
1314         public ListIterator<E> listIterator() {
1315             return listIterator(0);
1316         }
1317 
1318         @Override
1319         public ListIterator<E> listIterator(int index) {
1320             return new ListIterator<E>() {
1321                 private final ListIterator<E> it = delegate.listIterator(index);
1322 
1323                 @Override
1324                 public boolean hasNext() {
1325                     return it.hasNext();
1326                 }
1327 
1328                 @Override
1329                 public E next() {
1330                     return it.next();
1331                 }
1332 
1333                 @Override
1334                 public boolean hasPrevious() {
1335                     return it.hasPrevious();
1336                 }
1337 
1338                 @Override
1339                 public E previous() {
1340                     return it.previous();
1341                 }
1342 
1343                 @Override
1344                 public int nextIndex() {
1345                     return it.nextIndex();
1346                 }
1347 
1348                 @Override
1349                 public int previousIndex() {
1350                     return it.previousIndex();
1351                 }
1352 
1353                 @Override
1354                 public void remove() {
1355                     logWarning("listIterator.remove");
1356                     it.remove();
1357                 }
1358 
1359                 @Override
1360                 public void set(E e) {
1361                     logWarning("listIterator.set");
1362                     it.set(e);
1363                 }
1364 
1365                 @Override
1366                 public void add(E e) {
1367                     logWarning("listIterator.add");
1368                     it.add(e);
1369                 }
1370             };
1371         }
1372 
1373         @Override
1374         public List<E> subList(int fromIndex, int toIndex) {
1375             return new LoggingList<>(delegate.subList(fromIndex, toIndex), collectionName);
1376         }
1377 
1378         @Override
1379         public boolean equals(Object o) {
1380             return delegate.equals(o);
1381         }
1382 
1383         @Override
1384         public int hashCode() {
1385             return delegate.hashCode();
1386         }
1387 
1388         @Override
1389         public String toString() {
1390             return delegate.toString();
1391         }
1392     }
1393 
1394     /**
1395      * Sets the value of the context value of this project identified by the given key. If the supplied value is
1396      * <code>null</code>, the context value is removed from this project. Context values are intended to allow core
1397      * extensions to associate derived state with project instances.
1398      */
1399     public void setContextValue(String key, Object value) {
1400         if (context == null) {
1401             context = new HashMap<>();
1402         }
1403         if (value != null) {
1404             context.put(key, value);
1405         } else {
1406             context.remove(key);
1407         }
1408     }
1409 
1410     /**
1411      * Returns context value of this project associated with the given key or null if this project has no such value.
1412      */
1413     public Object getContextValue(String key) {
1414         if (context == null) {
1415             return null;
1416         }
1417         return context.get(key);
1418     }
1419 
1420     /**
1421      * Sets the project's class realm. <strong>Warning:</strong> This is an internal utility method that is only public
1422      * for technical reasons, it is not part of the public API. In particular, this method can be changed or deleted
1423      * without prior notice and must not be used by plugins.
1424      *
1425      * @param classRealm The class realm hosting the build extensions of this project, may be {@code null}.
1426      */
1427     public void setClassRealm(ClassRealm classRealm) {
1428         this.classRealm = classRealm;
1429     }
1430 
1431     /**
1432      * Gets the project's class realm. This class realm hosts the build extensions of the project.
1433      * <strong>Warning:</strong> This is an internal utility method that is only public for technical reasons, it is not
1434      * part of the public API. In particular, this method can be changed or deleted without prior notice and must not be
1435      * used by plugins.
1436      *
1437      * @return The project's class realm or {@code null}.
1438      */
1439     public ClassRealm getClassRealm() {
1440         return classRealm;
1441     }
1442 
1443     /**
1444      * Sets the artifact filter used to exclude shared extension artifacts from plugin realms. <strong>Warning:</strong>
1445      * This is an internal utility method that is only public for technical reasons, it is not part of the public API.
1446      * In particular, this method can be changed or deleted without prior notice and must not be used by plugins.
1447      *
1448      * @param extensionDependencyFilter The dependency filter to apply to plugins, may be {@code null}.
1449      */
1450     public void setExtensionDependencyFilter(DependencyFilter extensionDependencyFilter) {
1451         this.extensionDependencyFilter = extensionDependencyFilter;
1452     }
1453 
1454     /**
1455      * Gets the dependency filter used to exclude shared extension artifacts from plugin realms.
1456      * <strong>Warning:</strong> This is an internal utility method that is only public for technical reasons, it is not
1457      * part of the public API. In particular, this method can be changed or deleted without prior notice and must not be
1458      * used by plugins.
1459      *
1460      * @return The dependency filter or {@code null}.
1461      */
1462     public DependencyFilter getExtensionDependencyFilter() {
1463         return extensionDependencyFilter;
1464     }
1465 
1466     /**
1467      * Sets the transitive dependency artifacts that have been resolved/collected for this project.
1468      * <strong>Warning:</strong> This is an internal utility method that is only public for technical reasons, it is not
1469      * part of the public API. In particular, this method can be changed or deleted without prior notice and must not be
1470      * used by plugins.
1471      *
1472      * @param artifacts The set of artifacts, may be {@code null}.
1473      */
1474     public void setResolvedArtifacts(Set<Artifact> artifacts) {
1475         this.resolvedArtifacts = (artifacts != null) ? artifacts : Collections.<Artifact>emptySet();
1476         this.artifacts = null;
1477         this.artifactMap = null;
1478     }
1479 
1480     /**
1481      * Sets the scope filter to select the artifacts being exposed to the currently executed mojo.
1482      * <strong>Warning:</strong> This is an internal utility method that is only public for technical reasons, it is not
1483      * part of the public API. In particular, this method can be changed or deleted without prior notice and must not be
1484      * used by plugins.
1485      *
1486      * @param artifactFilter The artifact filter, may be {@code null} to exclude all artifacts.
1487      */
1488     public void setArtifactFilter(ArtifactFilter artifactFilter) {
1489         this.artifactFilter = artifactFilter;
1490         this.artifacts = null;
1491         this.artifactMap = null;
1492     }
1493 
1494     /**
1495      * <strong>Warning:</strong> This is an internal utility method that is only public for technical reasons, it is not
1496      * part of the public API. In particular, this method can be changed or deleted without prior notice and must not be
1497      * used by plugins.
1498      *
1499      * @param phase The phase to check for, must not be {@code null}.
1500      * @return {@code true} if the phase has been seen.
1501      */
1502     public boolean hasLifecyclePhase(String phase) {
1503         return lifecyclePhases.contains(phase);
1504     }
1505 
1506     /**
1507      * <strong>Warning:</strong> This is an internal utility method that is only public for technical reasons, it is not
1508      * part of the public API. In particular, this method can be changed or deleted without prior notice and must not be
1509      * used by plugins.
1510      *
1511      * @param lifecyclePhase The lifecycle phase to add, must not be {@code null}.
1512      */
1513     public void addLifecyclePhase(String lifecyclePhase) {
1514         lifecyclePhases.add(lifecyclePhase);
1515     }
1516 
1517     /**
1518      * Gets the root directory of the project, which is the parent directory
1519      * containing the {@code .mvn} directory.
1520      *
1521      * @return the root directory of the project
1522      * @throws IllegalStateException if the root directory could not be found
1523      * @see org.apache.maven.execution.MavenSession#getRootDirectory()
1524      *
1525      * @since 3.10.0
1526      */
1527     public Path getRootDirectory() {
1528         if (rootDirectory == null) {
1529             throw new IllegalStateException(RootLocator.UNABLE_TO_FIND_ROOT_PROJECT_MESSAGE);
1530         }
1531         return rootDirectory;
1532     }
1533 
1534     /**
1535      * @since 3.10.0
1536      */
1537     public void setRootDirectory(Path rootDirectory) {
1538         this.rootDirectory = rootDirectory;
1539     }
1540 
1541     // ----------------------------------------------------------------------------------------------------------------
1542     //
1543     //
1544     // D E P R E C A T E D
1545     //
1546     //
1547     // ----------------------------------------------------------------------------------------------------------------
1548     //
1549     // Everything below will be removed for Maven 4.0.0
1550     //
1551     // ----------------------------------------------------------------------------------------------------------------
1552 
1553     private ProjectBuildingRequest projectBuilderConfiguration;
1554 
1555     private Map<String, String> moduleAdjustments;
1556 
1557     @Deprecated // This appears only to be used in test code
1558     public String getModulePathAdjustment(MavenProject moduleProject) throws IOException {
1559         // FIXME: This is hacky. What if module directory doesn't match artifactid, and parent
1560         // is coming from the repository??
1561         String module = moduleProject.getArtifactId();
1562 
1563         File moduleFile = moduleProject.getFile();
1564 
1565         if (moduleFile != null) {
1566             File moduleDir = moduleFile.getCanonicalFile().getParentFile();
1567 
1568             module = moduleDir.getName();
1569         }
1570 
1571         if (moduleAdjustments == null) {
1572             moduleAdjustments = new HashMap<>();
1573 
1574             List<String> modules = getModules();
1575             if (modules != null) {
1576                 for (String modulePath : modules) {
1577                     String moduleName = modulePath;
1578 
1579                     if (moduleName.endsWith("/") || moduleName.endsWith("\\")) {
1580                         moduleName = moduleName.substring(0, moduleName.length() - 1);
1581                     }
1582 
1583                     int lastSlash = moduleName.lastIndexOf('/');
1584 
1585                     if (lastSlash < 0) {
1586                         lastSlash = moduleName.lastIndexOf('\\');
1587                     }
1588 
1589                     String adjustment = null;
1590 
1591                     if (lastSlash > -1) {
1592                         moduleName = moduleName.substring(lastSlash + 1);
1593                         adjustment = modulePath.substring(0, lastSlash);
1594                     }
1595 
1596                     moduleAdjustments.put(moduleName, adjustment);
1597                 }
1598             }
1599         }
1600 
1601         return moduleAdjustments.get(module);
1602     }
1603 
1604     @Deprecated
1605     public Set<Artifact> createArtifacts(ArtifactFactory artifactFactory, String inheritedScope, ArtifactFilter filter)
1606             throws InvalidDependencyVersionException {
1607         return MavenMetadataSource.createArtifacts(artifactFactory, getDependencies(), inheritedScope, filter, this);
1608     }
1609 
1610     @Deprecated
1611     protected void setScriptSourceRoots(List<String> scriptSourceRoots) {
1612         this.scriptSourceRoots = scriptSourceRoots;
1613     }
1614 
1615     @Deprecated
1616     public void addScriptSourceRoot(String path) {
1617         if (path != null) {
1618             path = path.trim();
1619             if (path.length() != 0) {
1620                 if (!getScriptSourceRoots().contains(path)) {
1621                     getScriptSourceRoots().add(path);
1622                 }
1623             }
1624         }
1625     }
1626 
1627     @Deprecated
1628     public List<String> getScriptSourceRoots() {
1629         return scriptSourceRoots;
1630     }
1631 
1632     @Deprecated
1633     public List<Artifact> getCompileArtifacts() {
1634         List<Artifact> list = new ArrayList<>(getArtifacts().size());
1635 
1636         for (Artifact a : getArtifacts()) {
1637             // TODO classpath check doesn't belong here - that's the other method
1638             if (a.getArtifactHandler().isAddedToClasspath()) {
1639                 // TODO let the scope handler deal with this
1640                 if (Artifact.SCOPE_COMPILE.equals(a.getScope())
1641                         || Artifact.SCOPE_PROVIDED.equals(a.getScope())
1642                         || Artifact.SCOPE_SYSTEM.equals(a.getScope())) {
1643                     list.add(a);
1644                 }
1645             }
1646         }
1647         return list;
1648     }
1649 
1650     @Deprecated
1651     public List<Dependency> getCompileDependencies() {
1652         Set<Artifact> artifacts = getArtifacts();
1653 
1654         if ((artifacts == null) || artifacts.isEmpty()) {
1655             return Collections.emptyList();
1656         }
1657 
1658         List<Dependency> list = new ArrayList<>(artifacts.size());
1659 
1660         for (Artifact a : getArtifacts()) {
1661             // TODO let the scope handler deal with this
1662             if (Artifact.SCOPE_COMPILE.equals(a.getScope())
1663                     || Artifact.SCOPE_PROVIDED.equals(a.getScope())
1664                     || Artifact.SCOPE_SYSTEM.equals(a.getScope())) {
1665                 Dependency dependency = new Dependency();
1666 
1667                 dependency.setArtifactId(a.getArtifactId());
1668                 dependency.setGroupId(a.getGroupId());
1669                 dependency.setVersion(a.getVersion());
1670                 dependency.setScope(a.getScope());
1671                 dependency.setType(a.getType());
1672                 dependency.setClassifier(a.getClassifier());
1673 
1674                 list.add(dependency);
1675             }
1676         }
1677         return Collections.unmodifiableList(list);
1678     }
1679 
1680     @Deprecated
1681     public List<Artifact> getTestArtifacts() {
1682         List<Artifact> list = new ArrayList<>(getArtifacts().size());
1683 
1684         for (Artifact a : getArtifacts()) {
1685             // TODO classpath check doesn't belong here - that's the other method
1686             if (a.getArtifactHandler().isAddedToClasspath()) {
1687                 list.add(a);
1688             }
1689         }
1690         return list;
1691     }
1692 
1693     @Deprecated
1694     public List<Dependency> getTestDependencies() {
1695         Set<Artifact> artifacts = getArtifacts();
1696 
1697         if ((artifacts == null) || artifacts.isEmpty()) {
1698             return Collections.emptyList();
1699         }
1700 
1701         List<Dependency> list = new ArrayList<>(artifacts.size());
1702 
1703         for (Artifact a : getArtifacts()) {
1704             Dependency dependency = new Dependency();
1705 
1706             dependency.setArtifactId(a.getArtifactId());
1707             dependency.setGroupId(a.getGroupId());
1708             dependency.setVersion(a.getVersion());
1709             dependency.setScope(a.getScope());
1710             dependency.setType(a.getType());
1711             dependency.setClassifier(a.getClassifier());
1712 
1713             list.add(dependency);
1714         }
1715         return Collections.unmodifiableList(list);
1716     }
1717 
1718     @Deprecated // used by the Maven ITs
1719     public List<Dependency> getRuntimeDependencies() {
1720         Set<Artifact> artifacts = getArtifacts();
1721 
1722         if ((artifacts == null) || artifacts.isEmpty()) {
1723             return Collections.emptyList();
1724         }
1725 
1726         List<Dependency> list = new ArrayList<>(artifacts.size());
1727 
1728         for (Artifact a : getArtifacts()) {
1729             // TODO let the scope handler deal with this
1730             if (Artifact.SCOPE_COMPILE.equals(a.getScope()) || Artifact.SCOPE_RUNTIME.equals(a.getScope())) {
1731                 Dependency dependency = new Dependency();
1732 
1733                 dependency.setArtifactId(a.getArtifactId());
1734                 dependency.setGroupId(a.getGroupId());
1735                 dependency.setVersion(a.getVersion());
1736                 dependency.setScope(a.getScope());
1737                 dependency.setType(a.getType());
1738                 dependency.setClassifier(a.getClassifier());
1739 
1740                 list.add(dependency);
1741             }
1742         }
1743         return Collections.unmodifiableList(list);
1744     }
1745 
1746     @Deprecated
1747     public List<Artifact> getRuntimeArtifacts() {
1748         List<Artifact> list = new ArrayList<>(getArtifacts().size());
1749 
1750         for (Artifact a : getArtifacts()) {
1751             // TODO classpath check doesn't belong here - that's the other method
1752             if (a.getArtifactHandler().isAddedToClasspath()
1753                     // TODO let the scope handler deal with this
1754                     && (Artifact.SCOPE_COMPILE.equals(a.getScope()) || Artifact.SCOPE_RUNTIME.equals(a.getScope()))) {
1755                 list.add(a);
1756             }
1757         }
1758         return list;
1759     }
1760 
1761     @Deprecated
1762     public List<String> getSystemClasspathElements() throws DependencyResolutionRequiredException {
1763         List<String> list = new ArrayList<>(getArtifacts().size());
1764 
1765         String d = getBuild().getOutputDirectory();
1766         if (d != null) {
1767             list.add(d);
1768         }
1769 
1770         for (Artifact a : getArtifacts()) {
1771             if (a.getArtifactHandler().isAddedToClasspath()) {
1772                 // TODO let the scope handler deal with this
1773                 if (Artifact.SCOPE_SYSTEM.equals(a.getScope())) {
1774                     addArtifactPath(a, list);
1775                 }
1776             }
1777         }
1778         return list;
1779     }
1780 
1781     @Deprecated
1782     public List<Artifact> getSystemArtifacts() {
1783         List<Artifact> list = new ArrayList<>(getArtifacts().size());
1784 
1785         for (Artifact a : getArtifacts()) {
1786             // TODO classpath check doesn't belong here - that's the other method
1787             if (a.getArtifactHandler().isAddedToClasspath()) {
1788                 // TODO let the scope handler deal with this
1789                 if (Artifact.SCOPE_SYSTEM.equals(a.getScope())) {
1790                     list.add(a);
1791                 }
1792             }
1793         }
1794         return list;
1795     }
1796 
1797     @Deprecated
1798     public List<Dependency> getSystemDependencies() {
1799         Set<Artifact> artifacts = getArtifacts();
1800 
1801         if ((artifacts == null) || artifacts.isEmpty()) {
1802             return Collections.emptyList();
1803         }
1804 
1805         List<Dependency> list = new ArrayList<>(artifacts.size());
1806 
1807         for (Artifact a : getArtifacts()) {
1808             // TODO let the scope handler deal with this
1809             if (Artifact.SCOPE_SYSTEM.equals(a.getScope())) {
1810                 Dependency dependency = new Dependency();
1811 
1812                 dependency.setArtifactId(a.getArtifactId());
1813                 dependency.setGroupId(a.getGroupId());
1814                 dependency.setVersion(a.getVersion());
1815                 dependency.setScope(a.getScope());
1816                 dependency.setType(a.getType());
1817                 dependency.setClassifier(a.getClassifier());
1818 
1819                 list.add(dependency);
1820             }
1821         }
1822         return Collections.unmodifiableList(list);
1823     }
1824 
1825     @Deprecated
1826     public void setReporting(Reporting reporting) {
1827         getModel().setReporting(reporting);
1828     }
1829 
1830     @Deprecated
1831     public Reporting getReporting() {
1832         return getModel().getReporting();
1833     }
1834 
1835     @Deprecated
1836     public void setReportArtifacts(Set<Artifact> reportArtifacts) {
1837         this.reportArtifacts = reportArtifacts;
1838 
1839         reportArtifactMap = null;
1840     }
1841 
1842     @Deprecated
1843     public Set<Artifact> getReportArtifacts() {
1844         return reportArtifacts;
1845     }
1846 
1847     @Deprecated
1848     public Map<String, Artifact> getReportArtifactMap() {
1849         if (reportArtifactMap == null) {
1850             reportArtifactMap = ArtifactUtils.artifactMapByVersionlessId(getReportArtifacts());
1851         }
1852 
1853         return reportArtifactMap;
1854     }
1855 
1856     @Deprecated
1857     public void setExtensionArtifacts(Set<Artifact> extensionArtifacts) {
1858         this.extensionArtifacts = extensionArtifacts;
1859 
1860         extensionArtifactMap = null;
1861     }
1862 
1863     @Deprecated
1864     public Set<Artifact> getExtensionArtifacts() {
1865         return extensionArtifacts;
1866     }
1867 
1868     @Deprecated
1869     public Map<String, Artifact> getExtensionArtifactMap() {
1870         if (extensionArtifactMap == null) {
1871             extensionArtifactMap = ArtifactUtils.artifactMapByVersionlessId(getExtensionArtifacts());
1872         }
1873 
1874         return extensionArtifactMap;
1875     }
1876 
1877     @Deprecated
1878     public List<ReportPlugin> getReportPlugins() {
1879         if (getModel().getReporting() == null) {
1880             return Collections.emptyList();
1881         }
1882         return Collections.unmodifiableList(getModel().getReporting().getPlugins());
1883     }
1884 
1885     @Deprecated
1886     public Xpp3Dom getReportConfiguration(String pluginGroupId, String pluginArtifactId, String reportSetId) {
1887         Xpp3Dom dom = null;
1888 
1889         // ----------------------------------------------------------------------
1890         // I would like to be able to lookup the Mojo object using a key but
1891         // we have a limitation in modello that will be remedied shortly. So
1892         // for now I have to iterate through and see what we have.
1893         // ----------------------------------------------------------------------
1894 
1895         if (getReportPlugins() != null) {
1896             for (ReportPlugin plugin : getReportPlugins()) {
1897                 if (pluginGroupId.equals(plugin.getGroupId()) && pluginArtifactId.equals(plugin.getArtifactId())) {
1898                     dom = (Xpp3Dom) plugin.getConfiguration();
1899 
1900                     if (reportSetId != null) {
1901                         ReportSet reportSet = plugin.getReportSetsAsMap().get(reportSetId);
1902                         if (reportSet != null) {
1903                             Xpp3Dom executionConfiguration = (Xpp3Dom) reportSet.getConfiguration();
1904                             if (executionConfiguration != null) {
1905                                 Xpp3Dom newDom = new Xpp3Dom(executionConfiguration);
1906                                 dom = Xpp3Dom.mergeXpp3Dom(newDom, dom);
1907                             }
1908                         }
1909                     }
1910                     break;
1911                 }
1912             }
1913         }
1914 
1915         if (dom != null) {
1916             // make a copy so the original in the POM doesn't get messed with
1917             dom = new Xpp3Dom(dom);
1918         }
1919 
1920         return dom;
1921     }
1922 
1923     /**
1924      * @deprecated Use MavenProjectHelper.attachArtifact(..) instead.
1925      */
1926     @Deprecated
1927     public void attachArtifact(String type, String classifier, File file) {}
1928 
1929     /**
1930      * @deprecated Use {@link org.apache.maven.model.io.ModelWriter}.
1931      */
1932     @Deprecated
1933     public void writeModel(Writer writer) throws IOException {
1934         MavenXpp3Writer pomWriter = new MavenXpp3Writer();
1935         pomWriter.write(writer, getModel());
1936     }
1937 
1938     /**
1939      * @deprecated Use {@link org.apache.maven.model.io.ModelWriter}.
1940      */
1941     @Deprecated
1942     public void writeOriginalModel(Writer writer) throws IOException {
1943         MavenXpp3Writer pomWriter = new MavenXpp3Writer();
1944         pomWriter.write(writer, getOriginalModel());
1945     }
1946 
1947     @Deprecated
1948     public Artifact replaceWithActiveArtifact(Artifact pluginArtifact) {
1949         return pluginArtifact;
1950     }
1951 
1952     /**
1953      * Gets the project building request from which this project instance was created. <strong>Warning:</strong> This is
1954      * an utility method that is meant to assist integrators of Maven, it must not be used by Maven plugins.
1955      *
1956      * @return The project building request or {@code null}.
1957      * @since 2.1
1958      */
1959     @Deprecated
1960     public ProjectBuildingRequest getProjectBuildingRequest() {
1961         return projectBuilderConfiguration;
1962     }
1963 
1964     /**
1965      * Sets the project building request from which this project instance was created. <strong>Warning:</strong> This is
1966      * an utility method that is meant to assist integrators of Maven, it must not be used by Maven plugins.
1967      *
1968      * @param projectBuildingRequest The project building request, may be {@code null}.
1969      * @since 2.1
1970      */
1971     // used by maven-dependency-tree
1972     @Deprecated
1973     public void setProjectBuildingRequest(ProjectBuildingRequest projectBuildingRequest) {
1974         this.projectBuilderConfiguration = projectBuildingRequest;
1975     }
1976 }