Skip to content

Commit 6bde637

Browse files
committed
ProjectManager cleanup
1 parent 7b4a4bf commit 6bde637

File tree

2 files changed

+109
-53
lines changed

2 files changed

+109
-53
lines changed

api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectManager.java

Lines changed: 76 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
import java.util.Optional;
2626
import java.util.stream.Stream;
2727

28-
import org.apache.maven.api.Artifact;
2928
import org.apache.maven.api.Language;
3029
import org.apache.maven.api.ProducedArtifact;
3130
import org.apache.maven.api.Project;
@@ -39,53 +38,83 @@
3938
import org.apache.maven.api.annotations.Nullable;
4039

4140
/**
42-
* Interface to manage the project during its lifecycle.
41+
* Interface to manage the project state and artifacts during the Maven build lifecycle.
42+
* This service provides operations to:
43+
* <ul>
44+
* <li>Manage project artifacts (main and attached)</li>
45+
* <li>Handle source roots and resources</li>
46+
* <li>Access and modify project properties</li>
47+
* <li>Manage repository configurations</li>
48+
* <li>Handle project forking states</li>
49+
* </ul>
50+
*
51+
* The service maintains the mutable state of projects as they progress through
52+
* their build lifecycle, ensuring thread-safety and proper state management.
53+
* All implementations must be thread-safe as they may be accessed concurrently
54+
* during parallel builds.
4355
*
4456
* @since 4.0.0
57+
* @see org.apache.maven.api.services.ProjectBuilder
58+
* @see Project
4559
*/
4660
@Experimental
4761
public interface ProjectManager extends Service {
4862
/**
4963
* Returns the path to the built project artifact file, if the project has been built.
64+
* This path is only available after the artifact has been produced during the build lifecycle.
5065
*
51-
* @param project the project for which to get the path
52-
* @return the path of the built project artifact
66+
* @param project the project to get the artifact path for
67+
* @return an Optional containing the path to the built artifact if available,
68+
* or empty if the artifact hasn't been built yet
5369
*/
5470
@Nonnull
55-
Optional<Path> getPath(Project project);
71+
Optional<Path> getPath(@Nonnull Project project);
5672

5773
/**
58-
* {@return an immutable collection of attached artifacts for given project}.
74+
* Returns an immutable collection of attached artifacts for the given project.
75+
* Attached artifacts are secondary artifacts produced during the build (e.g., sources jar,
76+
* javadoc jar, test jars). These artifacts are created and attached during specific
77+
* lifecycle phases, so the collection contents depend on the build phase when this method
78+
* is called.
5979
*
60-
* @param project the project from which to get the attached artifacts
80+
* @param project the project to get attached artifacts for
81+
* @return an immutable collection of attached artifacts, may be empty if no artifacts
82+
* have been attached yet
83+
* @throws IllegalArgumentException if the project is null
84+
* @see #getAllArtifacts(Project)
6185
*/
6286
@Nonnull
63-
Collection<ProducedArtifact> getAttachedArtifacts(Project project);
87+
Collection<ProducedArtifact> getAttachedArtifacts(@Nonnull Project project);
6488

6589
/**
66-
* {@return project's all artifacts as immutable collection}. The list contains all artifacts, even the attached ones,
67-
* if any. Hence, the list returned by this method depends on which lifecycle step of the build was it invoked.
68-
* The head of returned list is result of {@link Project#getArtifacts()} method, so same applies here: the list can have
69-
* minimum of one element. The maximum number of elements is in turn dependent on build configuration and lifecycle
70-
* phase when this method was invoked (i.e. is javadoc jar built and attached, is sources jar built attached, are
71-
* all the artifact signed, etc.).
72-
* <p>
73-
* This method is shorthand for {@link Project#getArtifacts()} and {@link #getAttachedArtifacts(Project)} methods.
74-
*
75-
* @param project the project from which to get all artifacts
76-
*
77-
* @see org.apache.maven.api.services.ArtifactManager#getPath(Artifact)
90+
* Returns project's all artifacts as an immutable ordered collection. The collection contains:
91+
* <ul>
92+
* <li>The project's artifacts ({@link Project#getArtifacts()}):
93+
* <ul>
94+
* <li>The POM artifact (always present)</li>
95+
* <li>The main project artifact (if applicable based on packaging)</li>
96+
* </ul>
97+
* </li>
98+
* <li>All attached artifacts in the order they were attached</li>
99+
* </ul>
100+
* The contents depend on the current lifecycle phase when this method is called, as artifacts
101+
* are typically attached during specific phases (e.g., sources jar during package phase).
102+
*
103+
* @param project the project to get artifacts for
104+
* @return an immutable ordered collection of all project artifacts
105+
* @see #getAttachedArtifacts(Project)
78106
*/
79-
Collection<ProducedArtifact> getAllArtifacts(Project project);
107+
@Nonnull
108+
Collection<ProducedArtifact> getAllArtifacts(@Nonnull Project project);
80109

81110
/**
82111
* Attaches an artifact to the project using the given file path. The artifact type will be
83-
* determined from the file extension.
112+
* determined from the file extension. This method is thread-safe and ensures proper
113+
* synchronization of the project's artifact state.
84114
*
85115
* @param session the current build session
86116
* @param project the project to attach the artifact to
87117
* @param path the path to the artifact file
88-
* @throws IllegalArgumentException if the session, project or path is null
89118
*/
90119
default void attachArtifact(@Nonnull Session session, @Nonnull Project project, @Nonnull Path path) {
91120
String name = path.getFileName().toString();
@@ -103,8 +132,6 @@ default void attachArtifact(@Nonnull Session session, @Nonnull Project project,
103132
* @param project the project to attach the artifact to
104133
* @param type the type of the artifact (e.g., "jar", "war", "sources")
105134
* @param path the path to the artifact file
106-
* @throws IllegalArgumentException if the session, project, type or path is null
107-
*
108135
* @see org.apache.maven.api.Type
109136
*/
110137
default void attachArtifact(
@@ -121,7 +148,6 @@ default void attachArtifact(
121148
* @param project the project to attach the artifact to
122149
* @param artifact the produced artifact to attach
123150
* @param path the path to the artifact file
124-
* @throws IllegalArgumentException if the project, artifact or path is null
125151
*/
126152
void attachArtifact(@Nonnull Project project, @Nonnull ProducedArtifact artifact, @Nonnull Path path);
127153

@@ -154,7 +180,9 @@ default void attachArtifact(
154180
* @param scope the scope of the sources to return, or {@code null} for all scopes
155181
* @param language the language of the sources to return, or {@code null} for all languages
156182
*/
157-
Stream<SourceRoot> getEnabledSourceRoots(@Nonnull Project project, ProjectScope scope, Language language);
183+
@Nonnull
184+
Stream<SourceRoot> getEnabledSourceRoots(
185+
@Nonnull Project project, @Nullable ProjectScope scope, @Nullable Language language);
158186

159187
/**
160188
* Adds the given source to the given project.
@@ -189,17 +217,23 @@ void addSourceRoot(
189217
@Nonnull Project project, @Nonnull ProjectScope scope, @Nonnull Language language, @Nonnull Path directory);
190218

191219
/**
192-
* {@return an immutable list of project remote repositories} (directly specified or inherited).
220+
* Returns an immutable list of project remote repositories (directly specified or inherited).
221+
* The repositories are ordered by declaration order, with inherited repositories appearing
222+
* after directly specified ones.
193223
*
194224
* @param project the project
225+
* @return ordered list of remote repositories
195226
*/
196227
@Nonnull
197228
List<RemoteRepository> getRemoteProjectRepositories(@Nonnull Project project);
198229

199230
/**
200-
* {@return an immutable list of project remote plugin repositories} (directly specified or inherited).
231+
* Returns an immutable list of project plugin remote repositories (directly specified or inherited).
232+
* The repositories are ordered by declaration order, with inherited repositories appearing
233+
* after directly specified ones.
201234
*
202235
* @param project the project
236+
* @return ordered list of remote repositories
203237
*/
204238
@Nonnull
205239
List<RemoteRepository> getRemotePluginRepositories(@Nonnull Project project);
@@ -215,14 +249,26 @@ void addSourceRoot(
215249
Map<String, String> getProperties(@Nonnull Project project);
216250

217251
/**
218-
* Set a given project property.
252+
* Set a given project property. Properties set through this method are only valid
253+
* for the current build session and do not modify the underlying project model.
219254
*
220255
* @param project the project to modify
221256
* @param key they property's key
222257
* @param value the value or {@code null} to unset the property
223258
*/
224259
void setProperty(@Nonnull Project project, @Nonnull String key, @Nullable String value);
225260

261+
/**
262+
* Returns the original project being built when the input project is a forked project.
263+
* During certain lifecycle phases, particularly for aggregator mojos, Maven may create
264+
* a forked project (a copy of the original project) to execute a subset of the lifecycle.
265+
* This method allows retrieving the original project that initiated the build.
266+
*
267+
* @param project the potentially forked project
268+
* @return an Optional containing the original project if the input is a forked project,
269+
* or an empty Optional if the input is already the original project
270+
* @throws IllegalArgumentException if the project is null
271+
*/
226272
@Nonnull
227273
Optional<Project> getExecutionProject(@Nonnull Project project);
228274
}

impl/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectManager.java

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import org.apache.maven.api.di.SessionScoped;
4444
import org.apache.maven.api.services.ArtifactManager;
4545
import org.apache.maven.api.services.ProjectManager;
46+
import org.apache.maven.impl.InternalSession;
4647
import org.apache.maven.impl.MappedList;
4748
import org.apache.maven.impl.PropertiesAsMap;
4849
import org.apache.maven.project.MavenProject;
@@ -67,34 +68,35 @@ public DefaultProjectManager(InternalMavenSession session, ArtifactManager artif
6768

6869
@Nonnull
6970
@Override
70-
public Optional<Path> getPath(Project project) {
71+
public Optional<Path> getPath(@Nonnull Project project) {
72+
nonNull(project, "project");
7173
Optional<ProducedArtifact> mainArtifact = project.getMainArtifact();
72-
if (mainArtifact.isPresent()) {
73-
return artifactManager.getPath(mainArtifact.get());
74-
}
75-
return Optional.empty();
74+
return mainArtifact.flatMap(artifactManager::getPath);
7675
}
7776

7877
@Nonnull
7978
@Override
80-
public Collection<ProducedArtifact> getAttachedArtifacts(Project project) {
81-
InternalMavenSession session = ((DefaultProject) project).getSession();
82-
Collection<ProducedArtifact> attached = map(
83-
getMavenProject(project).getAttachedArtifacts(),
84-
a -> session.getArtifact(ProducedArtifact.class, RepositoryUtils.toArtifact(a)));
79+
public Collection<ProducedArtifact> getAttachedArtifacts(@Nonnull Project project) {
80+
nonNull(project, "project");
81+
Collection<ProducedArtifact> attached =
82+
map(getMavenProject(project).getAttachedArtifacts(), a -> getSession(project)
83+
.getArtifact(ProducedArtifact.class, RepositoryUtils.toArtifact(a)));
8584
return Collections.unmodifiableCollection(attached);
8685
}
8786

8887
@Override
89-
public Collection<ProducedArtifact> getAllArtifacts(Project project) {
88+
@Nonnull
89+
public Collection<ProducedArtifact> getAllArtifacts(@Nonnull Project project) {
90+
nonNull(project, "project");
9091
ArrayList<ProducedArtifact> result = new ArrayList<>(2);
9192
result.addAll(project.getArtifacts());
9293
result.addAll(getAttachedArtifacts(project));
9394
return Collections.unmodifiableCollection(result);
9495
}
9596

9697
@Override
97-
public void attachArtifact(Project project, ProducedArtifact artifact, Path path) {
98+
@SuppressWarnings("deprecation")
99+
public void attachArtifact(@Nonnull Project project, @Nonnull ProducedArtifact artifact, @Nonnull Path path) {
98100
nonNull(project, "project");
99101
nonNull(artifact, "artifact");
100102
nonNull(path, "path");
@@ -122,8 +124,8 @@ public void attachArtifact(Project project, ProducedArtifact artifact, Path path
122124
+ artifact.getBaseVersion());
123125
}
124126
getMavenProject(project)
125-
.addAttachedArtifact(RepositoryUtils.toArtifact(
126-
((DefaultProject) project).getSession().toArtifact(artifact)));
127+
.addAttachedArtifact(
128+
RepositoryUtils.toArtifact(getSession(project).toArtifact(artifact)));
127129
artifactManager.setPath(artifact, path);
128130
}
129131

@@ -158,19 +160,21 @@ public void addSourceRoot(
158160
}
159161

160162
@Override
161-
public List<RemoteRepository> getRemoteProjectRepositories(Project project) {
163+
@Nonnull
164+
public List<RemoteRepository> getRemoteProjectRepositories(@Nonnull Project project) {
162165
return Collections.unmodifiableList(new MappedList<>(
163-
((DefaultProject) project).getProject().getRemoteProjectRepositories(), session::getRemoteRepository));
166+
getMavenProject(project).getRemoteProjectRepositories(), session::getRemoteRepository));
164167
}
165168

166169
@Override
167-
public List<RemoteRepository> getRemotePluginRepositories(Project project) {
168-
return Collections.unmodifiableList(new MappedList<>(
169-
((DefaultProject) project).getProject().getRemotePluginRepositories(), session::getRemoteRepository));
170+
@Nonnull
171+
public List<RemoteRepository> getRemotePluginRepositories(@Nonnull Project project) {
172+
return Collections.unmodifiableList(
173+
new MappedList<>(getMavenProject(project).getRemotePluginRepositories(), session::getRemoteRepository));
170174
}
171175

172176
@Override
173-
public void setProperty(Project project, String key, String value) {
177+
public void setProperty(@Nonnull Project project, @Nonnull String key, String value) {
174178
Properties properties = getMavenProject(project).getProperties();
175179
if (value == null) {
176180
properties.remove(key);
@@ -180,13 +184,15 @@ public void setProperty(Project project, String key, String value) {
180184
}
181185

182186
@Override
183-
public Map<String, String> getProperties(Project project) {
187+
@Nonnull
188+
public Map<String, String> getProperties(@Nonnull Project project) {
184189
return Collections.unmodifiableMap(
185-
new PropertiesAsMap(((DefaultProject) project).getProject().getProperties()));
190+
new PropertiesAsMap(getMavenProject(project).getProperties()));
186191
}
187192

188193
@Override
189-
public Optional<Project> getExecutionProject(Project project) {
194+
@Nonnull
195+
public Optional<Project> getExecutionProject(@Nonnull Project project) {
190196
// Session keep tracks of the Project per project id,
191197
// so we cannot use session.getProject(p) for forked projects
192198
// which are temporary clones
@@ -197,4 +203,8 @@ public Optional<Project> getExecutionProject(Project project) {
197203
private MavenProject getMavenProject(Project project) {
198204
return ((DefaultProject) project).getProject();
199205
}
206+
207+
private static InternalSession getSession(Project project) {
208+
return ((DefaultProject) project).getSession();
209+
}
200210
}

0 commit comments

Comments
 (0)