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.repository.internal;
20  
21  import java.util.Map;
22  import java.util.Objects;
23  import java.util.concurrent.ConcurrentHashMap;
24  import java.util.function.Supplier;
25  
26  import org.apache.maven.building.Source;
27  import org.apache.maven.model.building.ModelCache;
28  import org.eclipse.aether.RepositorySystemSession;
29  
30  /**
31   * A model builder cache backed by the repository system cache.
32   *
33   */
34  public class DefaultModelCache implements ModelCache {
35  
36      private static final String KEY = DefaultModelCache.class.getName();
37  
38      private final Map<Object, Supplier<?>> cache;
39  
40      public static ModelCache newInstance(RepositorySystemSession session) {
41          Map<Object, Supplier<?>> cache;
42          if (session.getCache() == null) {
43              cache = new ConcurrentHashMap<>();
44          } else {
45              cache = (Map) session.getCache().get(session, KEY);
46              if (cache == null) {
47                  cache = new ConcurrentHashMap<>();
48                  session.getCache().put(session, KEY, cache);
49              }
50          }
51          return new DefaultModelCache(cache);
52      }
53  
54      private DefaultModelCache(Map<Object, Supplier<?>> cache) {
55          this.cache = cache;
56      }
57  
58      public Object get(Source path, String tag) {
59          return get(new SourceCacheKey(path, tag));
60      }
61  
62      public void put(Source path, String tag, Object data) {
63          put(new SourceCacheKey(path, tag), data);
64      }
65  
66      @Override
67      public Object get(String groupId, String artifactId, String version, String tag) {
68          return get(new GavCacheKey(groupId, artifactId, version, tag));
69      }
70  
71      @Override
72      public void put(String groupId, String artifactId, String version, String tag, Object data) {
73          put(new GavCacheKey(groupId, artifactId, version, tag), data);
74      }
75  
76      protected Object get(Object key) {
77          Supplier<?> s = cache.get(key);
78          return s != null ? s.get() : null;
79      }
80  
81      protected void put(Object key, Object data) {
82          cache.put(key, () -> data);
83      }
84  
85      @Override
86      public Object computeIfAbsent(
87              String groupId, String artifactId, String version, String tag, Supplier<Supplier<?>> data) {
88          return computeIfAbsent(new GavCacheKey(groupId, artifactId, version, tag), data);
89      }
90  
91      @Override
92      public Object computeIfAbsent(Source path, String tag, Supplier<Supplier<?>> data) {
93          return computeIfAbsent(new SourceCacheKey(path, tag), data);
94      }
95  
96      protected Object computeIfAbsent(Object key, Supplier<Supplier<?>> data) {
97          Supplier<?> s = cache.computeIfAbsent(key, k -> data.get());
98          return s != null ? s.get() : null;
99      }
100 
101     static class GavCacheKey {
102 
103         private final String gav;
104 
105         private final String tag;
106 
107         private final int hash;
108 
109         GavCacheKey(String groupId, String artifactId, String version, String tag) {
110             this(gav(groupId, artifactId, version), tag);
111         }
112 
113         GavCacheKey(String gav, String tag) {
114             this.gav = gav;
115             this.tag = tag;
116             this.hash = Objects.hash(gav, tag);
117         }
118 
119         private static String gav(String groupId, String artifactId, String version) {
120             StringBuilder sb = new StringBuilder();
121             if (groupId != null) {
122                 sb.append(groupId);
123             }
124             sb.append(":");
125             if (artifactId != null) {
126                 sb.append(artifactId);
127             }
128             sb.append(":");
129             if (version != null) {
130                 sb.append(version);
131             }
132             return sb.toString();
133         }
134 
135         @Override
136         public boolean equals(Object obj) {
137             if (this == obj) {
138                 return true;
139             }
140             if (null == obj || !getClass().equals(obj.getClass())) {
141                 return false;
142             }
143             GavCacheKey that = (GavCacheKey) obj;
144             return Objects.equals(this.gav, that.gav) && Objects.equals(this.tag, that.tag);
145         }
146 
147         @Override
148         public int hashCode() {
149             return hash;
150         }
151 
152         @Override
153         public String toString() {
154             return "GavCacheKey{" + "gav='" + gav + '\'' + ", tag='" + tag + '\'' + '}';
155         }
156     }
157 
158     private static final class SourceCacheKey {
159         private final Source source;
160 
161         private final String tag;
162 
163         private final int hash;
164 
165         SourceCacheKey(Source source, String tag) {
166             this.source = source;
167             this.tag = tag;
168             this.hash = Objects.hash(source, tag);
169         }
170 
171         @Override
172         public String toString() {
173             return "SourceCacheKey{" + "source=" + source + ", tag='" + tag + '\'' + '}';
174         }
175 
176         @Override
177         public boolean equals(Object obj) {
178             if (this == obj) {
179                 return true;
180             }
181             if (null == obj || !getClass().equals(obj.getClass())) {
182                 return false;
183             }
184             SourceCacheKey that = (SourceCacheKey) obj;
185             return Objects.equals(this.source, that.source) && Objects.equals(this.tag, that.tag);
186         }
187 
188         @Override
189         public int hashCode() {
190             return hash;
191         }
192     }
193 }