1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.internal.impl;
20
21 import java.io.IOException;
22 import java.nio.file.Files;
23 import java.nio.file.Path;
24 import java.util.ArrayList;
25 import java.util.Collections;
26 import java.util.LinkedHashMap;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.Optional;
30 import java.util.Set;
31 import java.util.function.Predicate;
32
33 import org.apache.maven.api.Dependency;
34 import org.apache.maven.api.JavaPathType;
35 import org.apache.maven.api.Node;
36 import org.apache.maven.api.PathType;
37 import org.apache.maven.api.services.DependencyResolverException;
38 import org.apache.maven.api.services.DependencyResolverRequest;
39 import org.apache.maven.api.services.DependencyResolverResult;
40
41
42
43
44
45
46
47
48
49
50
51
52
53 class DefaultDependencyResolverResult implements DependencyResolverResult {
54
55
56
57 private final List<Exception> exceptions;
58
59
60
61
62 private final Node root;
63
64
65
66
67 private final List<Node> nodes;
68
69
70
71
72 private final List<Path> paths;
73
74
75
76
77 private final Map<PathType, List<Path>> dispatchedPaths;
78
79
80
81
82 private final Map<Dependency, Path> dependencies;
83
84
85
86
87
88 private PathModularization outputModules;
89
90
91
92
93 private final PathModularizationCache cache;
94
95
96
97
98
99
100
101
102
103
104 DefaultDependencyResolverResult(PathModularizationCache cache, List<Exception> exceptions, Node root, int count) {
105 this.cache = cache;
106 this.exceptions = exceptions;
107 this.root = root;
108 nodes = new ArrayList<>(count);
109 paths = new ArrayList<>(count);
110 dispatchedPaths = new LinkedHashMap<>();
111 dependencies = new LinkedHashMap<>(count + count / 3);
112 }
113
114
115
116
117
118
119
120 private void addPathElement(PathType type, Path path) {
121 dispatchedPaths.computeIfAbsent(type, (t) -> new ArrayList<>()).add(path);
122 }
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159 void addOutputDirectory(Path main, Path test) throws IOException {
160 if (outputModules != null) {
161 throw new IllegalStateException("Output directories must be set first and only once.");
162 }
163 if (main != null) {
164 outputModules = cache.getModuleInfo(main);
165 addPathElement(outputModules.getPathType(), main);
166 } else {
167 outputModules = PathModularization.NONE;
168 }
169 if (test != null) {
170 boolean addToClasspath = true;
171 PathModularization testModules = cache.getModuleInfo(test);
172 boolean isModuleHierarchy = outputModules.isModuleHierarchy() || testModules.isModuleHierarchy();
173 for (String moduleName : outputModules.getModuleNames().values()) {
174 Path subdir = test;
175 if (isModuleHierarchy) {
176
177 Path path = test.resolve(moduleName);
178 if (!Files.isDirectory(path)) {
179
180 continue;
181 }
182 subdir = path;
183 }
184
185 addPathElement(JavaPathType.patchModule(moduleName), subdir);
186 addToClasspath = false;
187 }
188
189
190
191
192 for (Map.Entry<Path, String> entry : testModules.getModuleNames().entrySet()) {
193 if (!outputModules.containsModule(entry.getValue())) {
194 addPathElement(JavaPathType.MODULES, entry.getKey());
195 addToClasspath = false;
196 }
197 }
198 if (addToClasspath) {
199 addPathElement(JavaPathType.CLASSES, test);
200 }
201 }
202 }
203
204
205
206
207
208
209
210
211
212
213
214 void addDependency(Node node, Dependency dep, Predicate<PathType> filter, Path path) throws IOException {
215 nodes.add(node);
216 if (dep == null) {
217 return;
218 }
219 if (dependencies.put(dep, path) != null) {
220 throw new IllegalStateException("Duplicated key: " + dep);
221 }
222 if (path == null) {
223 return;
224 }
225 paths.add(path);
226
227
228
229
230
231
232
233 Set<PathType> pathTypes = dep.getType().getPathTypes();
234 if (containsPatches(pathTypes)) {
235 if (outputModules == null) {
236
237 outputModules = PathModularization.NONE;
238 }
239 PathType type = null;
240 for (Map.Entry<Path, String> info :
241 cache.getModuleInfo(path).getModuleNames().entrySet()) {
242 String moduleName = info.getValue();
243 type = JavaPathType.patchModule(moduleName);
244 if (!containsModule(moduleName)) {
245
246
247
248
249
250 type = cache.selectPathType(pathTypes, filter, path).orElse(type);
251 }
252 addPathElement(type, info.getKey());
253
254 }
255
256
257
258
259
260 if (type == null) {
261 Path main = findArtifactPath(dep.getGroupId(), dep.getArtifactId());
262 if (main != null) {
263 for (Map.Entry<Path, String> info :
264 cache.getModuleInfo(main).getModuleNames().entrySet()) {
265 type = JavaPathType.patchModule(info.getValue());
266 addPathElement(type, info.getKey());
267
268 }
269 }
270 }
271 if (type != null) {
272 return;
273 }
274 }
275 addPathElement(cache.selectPathType(pathTypes, filter, path).orElse(PathType.UNRESOLVED), path);
276 }
277
278
279
280
281 private boolean containsPatches(Set<PathType> types) {
282 for (PathType type : types) {
283 if (type instanceof JavaPathType.Modular) {
284 type = ((JavaPathType.Modular) type).rawType();
285 }
286 if (JavaPathType.PATCH_MODULE.equals(type)) {
287 return true;
288 }
289 }
290 return false;
291 }
292
293
294
295
296
297
298 private boolean containsModule(String moduleName) throws IOException {
299 for (Path path : dispatchedPaths.getOrDefault(JavaPathType.MODULES, Collections.emptyList())) {
300 if (cache.getModuleInfo(path).containsModule(moduleName)) {
301 return true;
302 }
303 }
304 return false;
305 }
306
307
308
309
310
311
312
313
314 private Path findArtifactPath(String group, String artifact) throws IOException {
315 for (Map.Entry<Dependency, Path> entry : dependencies.entrySet()) {
316 Dependency dep = entry.getKey();
317 if (group.equals(dep.getGroupId()) && artifact.equals(dep.getArtifactId())) {
318 return entry.getValue();
319 }
320 }
321 return null;
322 }
323
324 @Override
325 public List<Exception> getExceptions() {
326 return exceptions;
327 }
328
329 @Override
330 public Node getRoot() {
331 return root;
332 }
333
334 @Override
335 public List<Node> getNodes() {
336 return nodes;
337 }
338
339 @Override
340 public List<Path> getPaths() {
341 return paths;
342 }
343
344 @Override
345 public Map<PathType, List<Path>> getDispatchedPaths() {
346 return dispatchedPaths;
347 }
348
349 @Override
350 public Map<Dependency, Path> getDependencies() {
351 return dependencies;
352 }
353
354 @Override
355 public Optional<String> warningForFilenameBasedAutomodules() {
356 try {
357 return cache.warningForFilenameBasedAutomodules(dispatchedPaths.get(JavaPathType.MODULES));
358 } catch (IOException e) {
359 throw new DependencyResolverException("Cannot read module information.", e);
360 }
361 }
362 }