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