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.graph;
20  
21  import java.io.File;
22  import java.util.ArrayList;
23  import java.util.HashSet;
24  import java.util.LinkedHashSet;
25  import java.util.List;
26  import java.util.Optional;
27  import java.util.Set;
28  import org.apache.maven.MavenExecutionException;
29  import org.apache.maven.execution.MavenExecutionRequest;
30  import org.apache.maven.project.MavenProject;
31  import org.slf4j.Logger;
32  import org.slf4j.LoggerFactory;
33  
34  /**
35   * Utility class to extract {@link MavenProject} from the project graph during the execution phase based on optional or
36   * required selectors.
37   */
38  public final class ProjectSelector {
39      private static final Logger LOGGER = LoggerFactory.getLogger(ProjectSelector.class);
40  
41      public Set<MavenProject> getRequiredProjectsBySelectors(
42              MavenExecutionRequest request, List<MavenProject> projects, Set<String> projectSelectors)
43              throws MavenExecutionException {
44          Set<MavenProject> selectedProjects = new LinkedHashSet<>();
45          File baseDirectory = getBaseDirectoryFromRequest(request);
46          for (String selector : projectSelectors) {
47              Optional<MavenProject> optSelectedProject =
48                      findOptionalProjectBySelector(projects, baseDirectory, selector);
49              if (!optSelectedProject.isPresent()) {
50                  String message = "Could not find the selected project in the reactor: " + selector;
51                  throw new MavenExecutionException(message, request.getPom());
52              }
53  
54              MavenProject selectedProject = optSelectedProject.get();
55  
56              selectedProjects.add(selectedProject);
57              selectedProjects.addAll(getChildProjects(selectedProject, request));
58          }
59  
60          return selectedProjects;
61      }
62  
63      public Set<MavenProject> getOptionalProjectsBySelectors(
64              MavenExecutionRequest request, List<MavenProject> projects, Set<String> projectSelectors) {
65          Set<MavenProject> resolvedOptionalProjects = new LinkedHashSet<>();
66          Set<String> unresolvedOptionalSelectors = new HashSet<>();
67          File baseDirectory = getBaseDirectoryFromRequest(request);
68          for (String selector : projectSelectors) {
69              Optional<MavenProject> optSelectedProject =
70                      findOptionalProjectBySelector(projects, baseDirectory, selector);
71              if (optSelectedProject.isPresent()) {
72                  resolvedOptionalProjects.add(optSelectedProject.get());
73                  resolvedOptionalProjects.addAll(getChildProjects(optSelectedProject.get(), request));
74              } else {
75                  unresolvedOptionalSelectors.add(selector);
76              }
77          }
78  
79          if (!unresolvedOptionalSelectors.isEmpty()) {
80              LOGGER.info("The requested optional projects {} do not exist.", unresolvedOptionalSelectors);
81          }
82  
83          return resolvedOptionalProjects;
84      }
85  
86      private List<MavenProject> getChildProjects(MavenProject parent, MavenExecutionRequest request) {
87          final List<MavenProject> children = parent.getCollectedProjects();
88          if (children != null && request.isRecursive()) {
89              return children;
90          } else {
91              return new ArrayList<>();
92          }
93      }
94  
95      private Optional<MavenProject> findOptionalProjectBySelector(
96              List<MavenProject> projects, File reactorDirectory, String selector) {
97          return projects.stream()
98                  .filter(project -> isMatchingProject(project, selector, reactorDirectory))
99                  .findFirst();
100     }
101 
102     File getBaseDirectoryFromRequest(MavenExecutionRequest request) {
103         return request.getBaseDirectory() != null ? new File(request.getBaseDirectory()) : null;
104     }
105 
106     boolean isMatchingProject(MavenProject project, String selector, File reactorDirectory) {
107         // [groupId]:artifactId
108         if (selector.contains(":")) {
109             String id = ':' + project.getArtifactId();
110 
111             if (id.equals(selector)) {
112                 return true;
113             }
114 
115             id = project.getGroupId() + id;
116 
117             return id.equals(selector);
118         }
119 
120         // relative path, e.g. "sub", "../sub" or "."
121         else if (reactorDirectory != null) {
122             File selectedProject =
123                     new File(new File(reactorDirectory, selector).toURI().normalize());
124 
125             if (selectedProject.isFile()) {
126                 return selectedProject.equals(project.getFile());
127             } else if (selectedProject.isDirectory()) {
128                 return selectedProject.equals(project.getBasedir());
129             }
130         }
131 
132         return false;
133     }
134 }