View Javadoc
1   package org.apache.maven.project;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.nio.file.Files;
23  import java.nio.file.Path;
24  import java.util.Collections;
25  import java.util.HashMap;
26  import java.util.HashSet;
27  import java.util.Map;
28  import java.util.Objects;
29  import java.util.Set;
30  
31  import org.apache.maven.model.Model;
32  
33  /**
34   * Holds all Models that are known to the reactor. This allows the project builder to resolve imported Models from the
35   * reactor when building another project's effective model.
36   *
37   * @author Benjamin Bentmann
38   * @author Robert Scholte
39   */
40  class ReactorModelPool
41  {
42      private final Map<GAKey, Set<Model>> modelsByGa = new HashMap<>();
43  
44      private final Map<Path, Model> modelsByPath = new HashMap<>();
45  
46      /**
47       * Get the model by its GAV or (since 4.0.0) by its GA if there is only one.
48       *
49       * @param groupId never {@code null}
50       * @param artifactId never {@code null}
51       * @param version can be {@code null}
52       * @return the matching model or {@code null}
53       * @throws IllegalStateException if version was null and multiple modules share the same groupId + artifactId
54       */
55      public Model get( String groupId, String artifactId, String version )
56      {
57          return modelsByGa.getOrDefault( new GAKey( groupId, artifactId ), Collections.emptySet() ).stream()
58                          .filter( m -> version == null || version.equals( getVersion( m ) ) )
59                          .reduce( ( a, b ) ->
60                          {
61                              throw new IllegalStateException( "Multiple modules with key "
62                                  + a.getGroupId() + ':' + a.getArtifactId() );
63                          } ).orElse( null );
64      }
65  
66      /**
67       * Find model by path, useful when location the parent by relativePath
68       *
69       * @param path
70       * @return the matching model or {@code null}
71       * @since 4.0.0
72       */
73      public Model get( Path path )
74      {
75          final Path pomFile;
76          if ( Files.isDirectory( path ) )
77          {
78              pomFile = path.resolve( "pom.xml" );
79          }
80          else
81          {
82              pomFile = path;
83          }
84          return modelsByPath.get( pomFile );
85      }
86  
87      private String getVersion( Model model )
88      {
89          String version = model.getVersion();
90          if ( version == null && model.getParent() != null )
91          {
92              version = model.getParent().getVersion();
93          }
94          return version;
95      }
96  
97      static class Builder
98      {
99          private ReactorModelPool pool = new ReactorModelPool();
100 
101         Builder put( Path pomFile, Model model )
102         {
103             pool.modelsByPath.put( pomFile, model );
104             pool.modelsByGa.computeIfAbsent( new GAKey( getGroupId( model ), model.getArtifactId() ),
105                                              k -> new HashSet<Model>() ).add( model );
106             return this;
107         }
108 
109         ReactorModelPool build()
110         {
111             return pool;
112         }
113 
114         private static String getGroupId( Model model )
115         {
116             String groupId = model.getGroupId();
117             if ( groupId == null && model.getParent() != null )
118             {
119                 groupId = model.getParent().getGroupId();
120             }
121             return groupId;
122         }
123     }
124 
125     private static final class GAKey
126     {
127 
128         private final String groupId;
129 
130         private final String artifactId;
131 
132         private final int hashCode;
133 
134         GAKey( String groupId, String artifactId )
135         {
136             this.groupId = ( groupId != null ) ? groupId : "";
137             this.artifactId = ( artifactId != null ) ? artifactId : "";
138 
139             hashCode = Objects.hash( this.groupId, this.artifactId );
140         }
141 
142         @Override
143         public boolean equals( Object obj )
144         {
145             if ( this == obj )
146             {
147                 return true;
148             }
149 
150             GAKey that = (GAKey) obj;
151 
152             return artifactId.equals( that.artifactId ) && groupId.equals( that.groupId );
153         }
154 
155         @Override
156         public int hashCode()
157         {
158             return hashCode;
159         }
160 
161         @Override
162         public String toString()
163         {
164             StringBuilder buffer = new StringBuilder( 128 );
165             buffer.append( groupId ).append( ':' ).append( artifactId );
166             return buffer.toString();
167         }
168     }
169 
170 }