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