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.Path;
22  import java.util.Collections;
23  import java.util.HashSet;
24  import java.util.Map;
25  import java.util.Objects;
26  import java.util.Set;
27  import java.util.concurrent.ConcurrentHashMap;
28  
29  import org.apache.maven.api.model.Model;
30  
31  /**
32   * Holds all Models that are known to the reactor. This allows the project builder to resolve imported Models from the
33   * reactor when building another project's effective model.
34   *
35   */
36  class ReactorModelPool {
37      private final Map<GAKey, Set<Model>> modelsByGa = new ConcurrentHashMap<>();
38  
39      private final Map<Path, Model> modelsByPath = new ConcurrentHashMap<>();
40  
41      /**
42       * Get the model by its GAV or (since 4.0.0) by its GA if there is only one.
43       *
44       * @param groupId never {@code null}
45       * @param artifactId never {@code null}
46       * @param version can be {@code null}
47       * @return the matching model or {@code null}
48       * @throws IllegalStateException if version was null and multiple modules share the same groupId + artifactId
49       */
50      public Model get(String groupId, String artifactId, String version) {
51          return modelsByGa.getOrDefault(new GAKey(groupId, artifactId), Collections.emptySet()).stream()
52                  .filter(m -> version == null || version.equals(getVersion(m)))
53                  .reduce((a, b) -> {
54                      throw new IllegalStateException(
55                              "Multiple modules with key " + a.getGroupId() + ':' + a.getArtifactId());
56                  })
57                  .orElse(null);
58      }
59  
60      private String getVersion(Model model) {
61          String version = model.getVersion();
62          if (version == null && model.getParent() != null) {
63              version = model.getParent().getVersion();
64          }
65          return version;
66      }
67  
68      void put(Path pomFile, Model model) {
69          modelsByPath.put(pomFile, model);
70          modelsByGa
71                  .computeIfAbsent(new GAKey(getGroupId(model), model.getArtifactId()), k -> new HashSet<>())
72                  .add(model);
73      }
74  
75      private static String getGroupId(Model model) {
76          String groupId = model.getGroupId();
77          if (groupId == null && model.getParent() != null) {
78              groupId = model.getParent().getGroupId();
79          }
80          return groupId;
81      }
82  
83      private static final class GAKey {
84  
85          private final String groupId;
86  
87          private final String artifactId;
88  
89          private final int hashCode;
90  
91          GAKey(String groupId, String artifactId) {
92              this.groupId = (groupId != null) ? groupId : "";
93              this.artifactId = (artifactId != null) ? artifactId : "";
94  
95              hashCode = Objects.hash(this.groupId, this.artifactId);
96          }
97  
98          @Override
99          public boolean equals(Object obj) {
100             if (this == obj) {
101                 return true;
102             }
103             if (!(obj instanceof GAKey)) {
104                 return false;
105             }
106             GAKey that = (GAKey) obj;
107             return artifactId.equals(that.artifactId) && groupId.equals(that.groupId);
108         }
109 
110         @Override
111         public int hashCode() {
112             return hashCode;
113         }
114 
115         @Override
116         public String toString() {
117             return groupId + ':' + artifactId;
118         }
119     }
120 }