1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.repository.internal;
20
21 import java.util.Objects;
22 import java.util.concurrent.ConcurrentHashMap;
23 import java.util.concurrent.ConcurrentMap;
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.RepositoryCache;
29 import org.eclipse.aether.RepositorySystemSession;
30
31 import static java.util.Objects.requireNonNull;
32
33
34
35
36
37
38 @Deprecated(since = "4.0.0")
39 public class DefaultModelCache implements ModelCache {
40 private static final String KEY = DefaultModelCache.class.getName();
41
42 @SuppressWarnings("unchecked")
43 public static ModelCache newInstance(RepositorySystemSession session) {
44 ConcurrentHashMap<Object, Supplier<?>> cache;
45 RepositoryCache repositoryCache = session.getCache();
46 if (repositoryCache == null) {
47 cache = new ConcurrentHashMap<>();
48 } else {
49 cache = (ConcurrentHashMap<Object, Supplier<?>>)
50 repositoryCache.computeIfAbsent(session, KEY, ConcurrentHashMap::new);
51 }
52 return new DefaultModelCache(cache);
53 }
54
55 private final ConcurrentMap<Object, Supplier<?>> cache;
56
57 private DefaultModelCache(ConcurrentMap<Object, Supplier<?>> cache) {
58 this.cache = requireNonNull(cache);
59 }
60
61 @Override
62 @SuppressWarnings({"unchecked"})
63 public <T> T computeIfAbsent(String groupId, String artifactId, String version, String tag, Supplier<T> data) {
64 return (T) computeIfAbsent(new GavCacheKey(groupId, artifactId, version, tag), data);
65 }
66
67 @Override
68 @SuppressWarnings({"unchecked"})
69 public <T> T computeIfAbsent(Source path, String tag, Supplier<T> data) {
70 return (T) computeIfAbsent(new SourceCacheKey(path, tag), data);
71 }
72
73 protected Object computeIfAbsent(Object key, Supplier<?> data) {
74 return cache.computeIfAbsent(key, k -> new CachingSupplier<>(data)).get();
75 }
76
77 static class GavCacheKey {
78
79 private final String gav;
80
81 private final String tag;
82
83 private final int hash;
84
85 GavCacheKey(String groupId, String artifactId, String version, String tag) {
86 this(gav(groupId, artifactId, version), tag);
87 }
88
89 GavCacheKey(String gav, String tag) {
90 this.gav = gav;
91 this.tag = tag;
92 this.hash = Objects.hash(gav, tag);
93 }
94
95 private static String gav(String groupId, String artifactId, String version) {
96 StringBuilder sb = new StringBuilder();
97 if (groupId != null) {
98 sb.append(groupId);
99 }
100 sb.append(":");
101 if (artifactId != null) {
102 sb.append(artifactId);
103 }
104 sb.append(":");
105 if (version != null) {
106 sb.append(version);
107 }
108 return sb.toString();
109 }
110
111 @Override
112 public boolean equals(Object obj) {
113 if (this == obj) {
114 return true;
115 }
116 if (null == obj || !getClass().equals(obj.getClass())) {
117 return false;
118 }
119 GavCacheKey that = (GavCacheKey) obj;
120 return Objects.equals(this.gav, that.gav) && Objects.equals(this.tag, that.tag);
121 }
122
123 @Override
124 public int hashCode() {
125 return hash;
126 }
127
128 @Override
129 public String toString() {
130 return "GavCacheKey{" + "gav='" + gav + '\'' + ", tag='" + tag + '\'' + '}';
131 }
132 }
133
134 private static final class SourceCacheKey {
135 private final Source source;
136
137 private final String tag;
138
139 private final int hash;
140
141 SourceCacheKey(Source source, String tag) {
142 this.source = source;
143 this.tag = tag;
144 this.hash = Objects.hash(source, tag);
145 }
146
147 @Override
148 public String toString() {
149 return "SourceCacheKey{" + "source=" + source + ", tag='" + tag + '\'' + '}';
150 }
151
152 @Override
153 public boolean equals(Object obj) {
154 if (this == obj) {
155 return true;
156 }
157 if (null == obj || !getClass().equals(obj.getClass())) {
158 return false;
159 }
160 SourceCacheKey that = (SourceCacheKey) obj;
161 return Objects.equals(this.source, that.source) && Objects.equals(this.tag, that.tag);
162 }
163
164 @Override
165 public int hashCode() {
166 return hash;
167 }
168 }
169
170 static class CachingSupplier<T> implements Supplier<T> {
171 final Supplier<T> supplier;
172 volatile Object value;
173
174 CachingSupplier(Supplier<T> supplier) {
175 this.supplier = supplier;
176 }
177
178 @Override
179 @SuppressWarnings({"unchecked", "checkstyle:InnerAssignment"})
180 public T get() {
181 Object v;
182 if ((v = value) == null) {
183 synchronized (this) {
184 if ((v = value) == null) {
185 try {
186 v = value = supplier.get();
187 } catch (Exception e) {
188 v = value = new AltRes(e);
189 }
190 }
191 }
192 }
193 if (v instanceof AltRes) {
194 uncheckedThrow(((AltRes) v).t);
195 }
196 return (T) v;
197 }
198
199 static class AltRes {
200 final Throwable t;
201
202 AltRes(Throwable t) {
203 this.t = t;
204 }
205 }
206 }
207
208 @SuppressWarnings("unchecked")
209 static <T extends Throwable> void uncheckedThrow(Throwable t) throws T {
210 throw (T) t;
211 }
212 }