1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.impl.cache;
20
21 import java.util.ArrayList;
22 import java.util.HashMap;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.function.Function;
26
27 import org.apache.maven.api.cache.BatchRequestException;
28 import org.apache.maven.api.cache.MavenExecutionException;
29 import org.apache.maven.api.cache.RequestCache;
30 import org.apache.maven.api.cache.RequestResult;
31 import org.apache.maven.api.services.Request;
32 import org.apache.maven.api.services.Result;
33
34
35
36
37
38
39
40
41
42
43
44 public abstract class AbstractRequestCache implements RequestCache {
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59 @Override
60 @SuppressWarnings("all")
61 public <REQ extends Request<?>, REP extends Result<REQ>> REP request(REQ req, Function<REQ, REP> supplier) {
62 CachingSupplier<REQ, REP> cs = doCache(req, supplier);
63 return cs.apply(req);
64 }
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84 @Override
85 @SuppressWarnings("unchecked")
86 public <REQ extends Request<?>, REP extends Result<REQ>> List<REP> requests(
87 List<REQ> reqs, Function<List<REQ>, List<REP>> supplier) {
88 final Map<REQ, Object> nonCachedResults = new HashMap<>();
89 List<RequestResult<REQ, REP>> allResults = new ArrayList<>(reqs.size());
90
91 Function<REQ, REP> individualSupplier = req -> {
92 synchronized (nonCachedResults) {
93 while (!nonCachedResults.containsKey(req)) {
94 try {
95 nonCachedResults.wait();
96 } catch (InterruptedException e) {
97 Thread.currentThread().interrupt();
98 throw new RuntimeException(e);
99 }
100 }
101 Object val = nonCachedResults.get(req);
102 if (val instanceof CachingSupplier.AltRes altRes) {
103 uncheckedThrow(altRes.throwable);
104 }
105 return (REP) val;
106 }
107 };
108
109 List<CachingSupplier<REQ, REP>> suppliers = new ArrayList<>(reqs.size());
110 List<REQ> nonCached = new ArrayList<>();
111 for (REQ req : reqs) {
112 CachingSupplier<REQ, REP> cs = doCache(req, individualSupplier);
113 suppliers.add(cs);
114 if (cs.getValue() == null) {
115 nonCached.add(req);
116 }
117 }
118
119 if (!nonCached.isEmpty()) {
120 synchronized (nonCachedResults) {
121 try {
122 List<REP> reps = supplier.apply(nonCached);
123 for (int i = 0; i < reps.size(); i++) {
124 nonCachedResults.put(nonCached.get(i), reps.get(i));
125 }
126 } catch (MavenExecutionException e) {
127
128 for (REQ req : nonCached) {
129 nonCachedResults.put(
130 req, new CachingSupplier.AltRes(e.getCause()));
131 }
132 } finally {
133 nonCachedResults.notifyAll();
134 }
135 }
136 }
137
138
139 boolean hasFailures = false;
140 for (int i = 0; i < reqs.size(); i++) {
141 REQ req = reqs.get(i);
142 CachingSupplier<REQ, REP> cs = suppliers.get(i);
143 try {
144 REP value = cs.apply(req);
145 allResults.add(new RequestResult<>(req, value, null));
146 } catch (Throwable t) {
147 hasFailures = true;
148 allResults.add(new RequestResult<>(req, null, t));
149 }
150 }
151
152 if (hasFailures) {
153 throw new BatchRequestException("One or more requests failed", allResults);
154 }
155
156 return allResults.stream().map(RequestResult::result).toList();
157 }
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172 protected abstract <REQ extends Request<?>, REP extends Result<REQ>> CachingSupplier<REQ, REP> doCache(
173 REQ req, Function<REQ, REP> supplier);
174
175 @SuppressWarnings("unchecked")
176 protected static <T extends Throwable> void uncheckedThrow(Throwable t) throws T {
177 throw (T) t;
178 }
179 }