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.execution;
20  
21  import java.io.File;
22  import java.nio.file.Path;
23  import java.util.ArrayList;
24  import java.util.Arrays;
25  import java.util.Collections;
26  import java.util.Date;
27  import java.util.List;
28  import java.util.Map;
29  import java.util.Objects;
30  import java.util.Properties;
31  import java.util.concurrent.ConcurrentHashMap;
32  
33  import org.apache.maven.artifact.repository.ArtifactRepository;
34  import org.apache.maven.artifact.repository.RepositoryCache;
35  import org.apache.maven.model.building.ModelProblem;
36  import org.apache.maven.monitor.event.EventDispatcher;
37  import org.apache.maven.plugin.descriptor.PluginDescriptor;
38  import org.apache.maven.project.MavenProject;
39  import org.apache.maven.project.ProjectBuildingRequest;
40  import org.apache.maven.settings.Settings;
41  import org.codehaus.plexus.PlexusContainer;
42  import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
43  import org.eclipse.aether.RepositorySystemSession;
44  
45  /**
46   * A Maven execution session.
47   *
48   * @author Jason van Zyl
49   */
50  public class MavenSession implements Cloneable {
51      private MavenExecutionRequest request;
52  
53      private MavenExecutionResult result;
54  
55      private RepositorySystemSession repositorySession;
56  
57      private Properties executionProperties;
58  
59      private ThreadLocal<MavenProject> currentProject = new ThreadLocal<>();
60  
61      /**
62       * These projects have already been topologically sorted in the {@link org.apache.maven.Maven} component before
63       * being passed into the session. This is also the potentially constrained set of projects by using --projects
64       * on the command line.
65       */
66      private List<MavenProject> projects;
67  
68      /**
69       * The full set of projects before any potential constraining by --projects. Useful in the case where you want to
70       * build a smaller set of projects but perform other operations in the context of your reactor.
71       */
72      private List<MavenProject> allProjects;
73  
74      private MavenProject topLevelProject;
75  
76      private ProjectDependencyGraph projectDependencyGraph;
77  
78      private boolean parallel;
79  
80      private List<ModelProblem> modelProblems = Collections.emptyList();
81  
82      private final Map<String, Map<String, Map<String, Object>>> pluginContextsByProjectAndPluginKey =
83              new ConcurrentHashMap<>();
84  
85      public void setProjects(List<MavenProject> projects) {
86          if (!projects.isEmpty()) {
87              MavenProject first = projects.get(0);
88              this.currentProject = ThreadLocal.withInitial(() -> first);
89              this.topLevelProject = projects.stream()
90                      .filter(project -> project.isExecutionRoot())
91                      .findFirst()
92                      .orElse(first);
93          } else {
94              this.currentProject = new ThreadLocal<>();
95              this.topLevelProject = null;
96          }
97          this.projects = projects;
98      }
99  
100     public ArtifactRepository getLocalRepository() {
101         return request.getLocalRepository();
102     }
103 
104     public List<String> getGoals() {
105         return request.getGoals();
106     }
107 
108     /**
109      * Gets the user properties to use for interpolation and profile activation. The user properties have been
110      * configured directly by the user on his discretion, e.g. via the {@code -Dkey=value} parameter on the command
111      * line.
112      *
113      * @return The user properties, never {@code null}.
114      */
115     public Properties getUserProperties() {
116         return request.getUserProperties();
117     }
118 
119     /**
120      * Gets the system properties to use for interpolation and profile activation. The system properties are collected
121      * from the runtime environment like {@link System#getProperties()} and environment variables.
122      *
123      * @return The system properties, never {@code null}.
124      */
125     public Properties getSystemProperties() {
126         return request.getSystemProperties();
127     }
128 
129     public Settings getSettings() {
130         return settings;
131     }
132 
133     public List<MavenProject> getProjects() {
134         return projects;
135     }
136 
137     public String getExecutionRootDirectory() {
138         return request.getBaseDirectory();
139     }
140 
141     public MavenExecutionRequest getRequest() {
142         return request;
143     }
144 
145     public void setCurrentProject(MavenProject currentProject) {
146         this.currentProject.set(currentProject);
147     }
148 
149     public MavenProject getCurrentProject() {
150         return currentProject.get();
151     }
152 
153     public ProjectBuildingRequest getProjectBuildingRequest() {
154         return request.getProjectBuildingRequest().setRepositorySession(getRepositorySession());
155     }
156 
157     public List<String> getPluginGroups() {
158         return request.getPluginGroups();
159     }
160 
161     public boolean isOffline() {
162         return request.isOffline();
163     }
164 
165     public MavenProject getTopLevelProject() {
166         return topLevelProject;
167     }
168 
169     public MavenExecutionResult getResult() {
170         return result;
171     }
172 
173     /**
174      * Returns top directory if discovered or {@code null}.
175      * Top directory is directory where top level POM resides with respect of any reactor limiting or shaping like use
176      * of {@code -f} or alike CLI options.
177      *
178      * @since 3.10.0
179      */
180     public Path getTopDirectory() {
181         return request.getTopDirectory();
182     }
183 
184     /**
185      * Returns root directory if discovered or throws {@link IllegalStateException} if it could not be found.
186      * Root directory is detected, usually by the presence of {@code .mvn} directory, and is used to discover
187      * extensions and other configuration files. It usually represents the "project root" or "checkout root".
188      * Root directory may be equal to top directory or some parent of it (first directory where {@code .mvn} is found).
189      *
190      *  @throws IllegalStateException if the root directory could not be found
191      *
192      * @since 3.10.0
193      */
194     public Path getRootDirectory() {
195         return request.getRootDirectory();
196     }
197 
198     // Backward compat
199 
200     public Map<String, Object> getPluginContext(PluginDescriptor plugin, MavenProject project) {
201         String projectKey = project.getId();
202 
203         Map<String, Map<String, Object>> pluginContextsByKey = pluginContextsByProjectAndPluginKey.get(projectKey);
204 
205         if (pluginContextsByKey == null) {
206             pluginContextsByKey = new ConcurrentHashMap<>();
207 
208             pluginContextsByProjectAndPluginKey.put(projectKey, pluginContextsByKey);
209         }
210 
211         String pluginKey = plugin.getPluginLookupKey();
212 
213         Map<String, Object> pluginContext = pluginContextsByKey.get(pluginKey);
214 
215         if (pluginContext == null) {
216             pluginContext = new ConcurrentHashMap<>();
217 
218             pluginContextsByKey.put(pluginKey, pluginContext);
219         }
220 
221         return pluginContext;
222     }
223 
224     public ProjectDependencyGraph getProjectDependencyGraph() {
225         return projectDependencyGraph;
226     }
227 
228     public void setProjectDependencyGraph(ProjectDependencyGraph projectDependencyGraph) {
229         this.projectDependencyGraph = projectDependencyGraph;
230     }
231 
232     public String getReactorFailureBehavior() {
233         return request.getReactorFailureBehavior();
234     }
235 
236     @Override
237     public MavenSession clone() {
238         try {
239             MavenSession clone = (MavenSession) super.clone();
240             // the default must become the current project of the thread that clones this
241             MavenProject current = getCurrentProject();
242             // we replace the thread local of the clone to prevent write through and enforce the new default value
243             clone.currentProject = ThreadLocal.withInitial(() -> current);
244             return clone;
245         } catch (CloneNotSupportedException e) {
246             throw new RuntimeException("Bug", e);
247         }
248     }
249 
250     public Date getStartTime() {
251         return request.getStartTime();
252     }
253 
254     public boolean isParallel() {
255         return parallel;
256     }
257 
258     public void setParallel(boolean parallel) {
259         this.parallel = parallel;
260     }
261 
262     /**
263      * Returns the problems detected while building the Maven models.
264      *
265      * @return the model problems, never {@code null}
266      * @since 3.10.0
267      */
268     public List<ModelProblem> getModelProblems() {
269         return modelProblems;
270     }
271 
272     /**
273      * Records the problems detected while building the Maven models.
274      *
275      * @param modelProblems the model problems, must not be {@code null}
276      * @since 3.10.0
277      */
278     public void setModelProblems(List<ModelProblem> modelProblems) {
279         this.modelProblems = Collections.unmodifiableList(new ArrayList<>(Objects.requireNonNull(modelProblems)));
280     }
281 
282     public RepositorySystemSession getRepositorySession() {
283         return repositorySession;
284     }
285 
286     private Map<String, MavenProject> projectMap;
287 
288     public void setProjectMap(Map<String, MavenProject> projectMap) {
289         this.projectMap = projectMap;
290     }
291 
292     /** This is a provisional method and may be removed */
293     public List<MavenProject> getAllProjects() {
294         return allProjects;
295     }
296 
297     /** This is a provisional method and may be removed */
298     public void setAllProjects(List<MavenProject> allProjects) {
299         this.allProjects = allProjects;
300     }
301 
302     /*if_not[MAVEN4]*/
303 
304     //
305     // Deprecated
306     //
307 
308     private PlexusContainer container;
309 
310     private final Settings settings;
311 
312     @Deprecated
313     /** @deprecated This appears to only be used in the ReactorReader and we can do any processing required there */
314     public Map<String, MavenProject> getProjectMap() {
315         return projectMap;
316     }
317 
318     @Deprecated
319     public MavenSession(
320             PlexusContainer container,
321             RepositorySystemSession repositorySession,
322             MavenExecutionRequest request,
323             MavenExecutionResult result) {
324         this.container = container;
325         this.request = request;
326         this.result = result;
327         this.settings = new SettingsAdapter(request);
328         this.repositorySession = repositorySession;
329     }
330 
331     @Deprecated
332     public MavenSession(
333             PlexusContainer container,
334             MavenExecutionRequest request,
335             MavenExecutionResult result,
336             MavenProject project) {
337         this(container, request, result, Arrays.asList(new MavenProject[] {project}));
338     }
339 
340     @Deprecated
341     @SuppressWarnings("checkstyle:parameternumber")
342     public MavenSession(
343             PlexusContainer container,
344             Settings settings,
345             ArtifactRepository localRepository,
346             EventDispatcher eventDispatcher,
347             ReactorManager unused,
348             List<String> goals,
349             String executionRootDir,
350             Properties executionProperties,
351             Date startTime) {
352         this(
353                 container,
354                 settings,
355                 localRepository,
356                 eventDispatcher,
357                 unused,
358                 goals,
359                 executionRootDir,
360                 executionProperties,
361                 null,
362                 startTime);
363     }
364 
365     @Deprecated
366     @SuppressWarnings("checkstyle:parameternumber")
367     public MavenSession(
368             PlexusContainer container,
369             Settings settings,
370             ArtifactRepository localRepository,
371             EventDispatcher eventDispatcher,
372             ReactorManager unused,
373             List<String> goals,
374             String executionRootDir,
375             Properties executionProperties,
376             Properties userProperties,
377             Date startTime) {
378         this.container = container;
379         this.settings = settings;
380         this.executionProperties = executionProperties;
381         this.request = new DefaultMavenExecutionRequest();
382         this.request.setUserProperties(userProperties);
383         this.request.setLocalRepository(localRepository);
384         this.request.setGoals(goals);
385         this.request.setBaseDirectory((executionRootDir != null) ? new File(executionRootDir) : null);
386         this.request.setStartTime(startTime);
387     }
388 
389     @Deprecated
390     public MavenSession(
391             PlexusContainer container,
392             MavenExecutionRequest request,
393             MavenExecutionResult result,
394             List<MavenProject> projects) {
395         this.container = container;
396         this.request = request;
397         this.result = result;
398         this.settings = new SettingsAdapter(request);
399         setProjects(projects);
400     }
401 
402     @Deprecated
403     public List<MavenProject> getSortedProjects() {
404         return getProjects();
405     }
406 
407     @Deprecated
408     //
409     // Used by Tycho and will break users and force them to upgrade to Maven 3.1 so we should really leave
410     // this here, possibly indefinitely.
411     //
412     public RepositoryCache getRepositoryCache() {
413         return null;
414     }
415 
416     @Deprecated
417     public EventDispatcher getEventDispatcher() {
418         return null;
419     }
420 
421     @Deprecated
422     public boolean isUsingPOMsFromFilesystem() {
423         return request.isProjectPresent();
424     }
425 
426     /**
427      * @deprecated Use either {@link #getUserProperties()} or {@link #getSystemProperties()}.
428      */
429     @Deprecated
430     public Properties getExecutionProperties() {
431         if (executionProperties == null) {
432             executionProperties = new Properties();
433             executionProperties.putAll(request.getSystemProperties());
434             executionProperties.putAll(request.getUserProperties());
435         }
436 
437         return executionProperties;
438     }
439 
440     @Deprecated
441     public PlexusContainer getContainer() {
442         return container;
443     }
444 
445     @Deprecated
446     public Object lookup(String role) throws ComponentLookupException {
447         return container.lookup(role);
448     }
449 
450     @Deprecated
451     public Object lookup(String role, String roleHint) throws ComponentLookupException {
452         return container.lookup(role, roleHint);
453     }
454 
455     @Deprecated
456     public List<Object> lookupList(String role) throws ComponentLookupException {
457         return container.lookupList(role);
458     }
459 
460     @Deprecated
461     public Map<String, Object> lookupMap(String role) throws ComponentLookupException {
462         return container.lookupMap(role);
463     }
464 
465     /*end[MAVEN4]*/
466 }