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.project;
20  
21  import java.nio.file.Files;
22  import java.nio.file.Path;
23  import java.util.Collections;
24  import java.util.HashMap;
25  import java.util.HashSet;
26  import java.util.Map;
27  import java.util.Objects;
28  import java.util.Set;
29  
30  import org.apache.maven.model.Model;
31  
32  /**
33   * Holds all Models that are known to the reactor. This allows the project builder to resolve imported Models from the
34   * reactor when building another project's effective model.
35   *
36   * @author Benjamin Bentmann
37   * @author Robert Scholte
38   */
39  class ReactorModelPool {
40      private final Map<GAKey, Set<Model>> modelsByGa = new HashMap<>();
41  
42      private final Map<Path, Model> modelsByPath = new HashMap<>();
43  
44      /**
45       * Get the model by its GAV or (since 4.0.0) by its GA if there is only one.
46       *
47       * @param groupId never {@code null}
48       * @param artifactId never {@code null}
49       * @param version can be {@code null}
50       * @return the matching model or {@code null}
51       * @throws IllegalStateException if version was null and multiple modules share the same groupId + artifactId
52       */
53      public Model get(String groupId, String artifactId, String version) {
54          return modelsByGa.getOrDefault(new GAKey(groupId, artifactId), Collections.emptySet()).stream()
55                  .filter(m -> version == null || version.equals(getVersion(m)))
56                  .reduce((a, b) -> {
57                      throw new IllegalStateException(
58                              "Multiple modules with key " + a.getGroupId() + ':' + a.getArtifactId());
59                  })
60                  .orElse(null);
61      }
62  
63      /**
64       * Find model by path, useful when location the parent by relativePath
65       *
66       * @param path
67       * @return the matching model or {@code null}
68       * @since 4.0.0
69       */
70      public Model get(Path path) {
71          final Path pomFile;
72          if (Files.isDirectory(path)) {
73              pomFile = path.resolve("pom.xml");
74          } else {
75              pomFile = path;
76          }
77          return modelsByPath.get(pomFile);
78      }
79  
80      private String getVersion(Model model) {
81          String version = model.getVersion();
82          if (version == null && model.getParent() != null) {
83              version = model.getParent().getVersion();
84          }
85          return version;
86      }
87  
88      static class Builder {
89          private ReactorModelPool pool = new ReactorModelPool();
90  
91          Builder put(Path pomFile, Model model) {
92              pool.modelsByPath.put(pomFile, model);
93              pool.modelsByGa
94                      .computeIfAbsent(new GAKey(getGroupId(model), model.getArtifactId()), k -> new HashSet<Model>())
95                      .add(model);
96              return this;
97          }
98  
99          ReactorModelPool build() {
100             return pool;
101         }
102 
103         private static String getGroupId(Model model) {
104             String groupId = model.getGroupId();
105             if (groupId == null && model.getParent() != null) {
106                 groupId = model.getParent().getGroupId();
107             }
108             return groupId;
109         }
110     }
111 
112     private static final class GAKey {
113 
114         private final String groupId;
115 
116         private final String artifactId;
117 
118         private final int hashCode;
119 
120         GAKey(String groupId, String artifactId) {
121             this.groupId = (groupId != null) ? groupId : "";
122             this.artifactId = (artifactId != null) ? artifactId : "";
123 
124             hashCode = Objects.hash(this.groupId, this.artifactId);
125         }
126 
127         @Override
128         public boolean equals(Object obj) {
129             if (this == obj) {
130                 return true;
131             }
132 
133             GAKey that = (GAKey) obj;
134 
135             return artifactId.equals(that.artifactId) && groupId.equals(that.groupId);
136         }
137 
138         @Override
139         public int hashCode() {
140             return hashCode;
141         }
142 
143         @Override
144         public String toString() {
145             StringBuilder buffer = new StringBuilder(128);
146             buffer.append(groupId).append(':').append(artifactId);
147             return buffer.toString();
148         }
149     }
150 }