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