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 javax.inject.Inject;
22 import javax.inject.Named;
23 import javax.inject.Singleton;
24
25 import java.nio.file.Path;
26 import java.util.ArrayList;
27 import java.util.Collection;
28 import java.util.Collections;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.Objects;
32 import java.util.Set;
33 import java.util.stream.Collectors;
34
35 import org.apache.maven.RepositoryUtils;
36 import org.apache.maven.api.Artifact;
37 import org.apache.maven.api.ArtifactCoordinate;
38 import org.apache.maven.api.Node;
39 import org.apache.maven.api.Project;
40 import org.apache.maven.api.ResolutionScope;
41 import org.apache.maven.api.Scope;
42 import org.apache.maven.api.Session;
43 import org.apache.maven.api.services.*;
44 import org.apache.maven.lifecycle.LifecycleExecutionException;
45 import org.apache.maven.lifecycle.internal.LifecycleDependencyResolver;
46 import org.apache.maven.project.MavenProject;
47 import org.eclipse.aether.graph.Dependency;
48 import org.eclipse.aether.graph.DependencyFilter;
49 import org.eclipse.aether.graph.DependencyNode;
50 import org.eclipse.aether.graph.DependencyVisitor;
51 import org.eclipse.aether.util.graph.visitor.FilteringDependencyVisitor;
52 import org.eclipse.aether.util.graph.visitor.PreorderDependencyNodeConsumerVisitor;
53
54 import static org.apache.maven.internal.impl.Utils.cast;
55 import static org.apache.maven.internal.impl.Utils.map;
56 import static org.apache.maven.internal.impl.Utils.nonNull;
57
58 @Named
59 @Singleton
60 public class DefaultDependencyResolver implements DependencyResolver {
61
62 @Inject
63 public DefaultDependencyResolver() {}
64
65 @Override
66 public List<Node> flatten(Session s, Node node, ResolutionScope scope) throws DependencyResolverException {
67 InternalSession session = InternalSession.from(s);
68
69
70 DependencyNode root = cast(AbstractNode.class, node, "node").getDependencyNode();
71 List<DependencyNode> dependencies = new ArrayList<>();
72 DependencyVisitor builder = new PreorderDependencyNodeConsumerVisitor(dependencies::add);
73 DependencyFilter filter = getScopeDependencyFilter(scope);
74 DependencyVisitor visitor = new FilteringDependencyVisitor(builder, filter);
75 root.accept(visitor);
76 dependencies.remove(root);
77
78 return map(dependencies, session::getNode);
79 }
80
81 private static DependencyFilter getScopeDependencyFilter(ResolutionScope scope) {
82 Set<String> scopes = scope.scopes().stream().map(Scope::id).collect(Collectors.toSet());
83 return (n, p) -> {
84 Dependency d = n.getDependency();
85 return d == null || scopes.contains(d.getScope());
86 };
87 }
88
89 @Override
90 public DependencyResolverResult resolve(DependencyResolverRequest request)
91 throws DependencyCollectorException, DependencyResolverException, ArtifactResolverException {
92 nonNull(request, "request can not be null");
93 InternalSession session = InternalSession.from(request.getSession());
94
95 if (request.getProject().isPresent()) {
96 List<Artifact> artifacts = resolveDependencies(
97 request.getSession(), request.getProject().get(), request.getResolutionScope());
98 List<Path> paths = artifacts.stream()
99 .map(a -> request.getSession()
100 .getService(ArtifactManager.class)
101 .getPath(a)
102 .get())
103 .collect(Collectors.toList());
104 return new DefaultDependencyResolverResult(Collections.emptyList(), null, Collections.emptyList(), paths);
105 }
106
107 DependencyCollectorResult collectorResult =
108 session.getService(DependencyCollector.class).collect(request);
109 List<Node> dependencies = flatten(session, collectorResult.getRoot(), request.getResolutionScope());
110
111 List<ArtifactCoordinate> coordinates = dependencies.stream()
112 .map(Node::getDependency)
113 .filter(Objects::nonNull)
114 .map(Artifact::toCoordinate)
115 .collect(Collectors.toList());
116 Map<Artifact, Path> artifacts = session.resolveArtifacts(coordinates);
117 List<Path> paths = dependencies.stream()
118 .map(Node::getDependency)
119 .filter(Objects::nonNull)
120 .map(artifacts::get)
121 .filter(Objects::nonNull)
122 .collect(Collectors.toList());
123
124 return new DefaultDependencyResolverResult(
125 collectorResult.getExceptions(), collectorResult.getRoot(), dependencies, paths);
126 }
127
128 private List<Artifact> resolveDependencies(Session session, Project project, ResolutionScope scope) {
129 Collection<String> toResolve = toScopes(scope);
130 try {
131 LifecycleDependencyResolver lifecycleDependencyResolver =
132 session.getService(Lookup.class).lookup(LifecycleDependencyResolver.class);
133 Set<org.apache.maven.artifact.Artifact> artifacts = lifecycleDependencyResolver.resolveProjectArtifacts(
134 getMavenProject(project),
135 toResolve,
136 toResolve,
137 InternalSession.from(session).getMavenSession(),
138 false,
139 Collections.emptySet());
140 return map(artifacts, a -> InternalSession.from(session).getArtifact(RepositoryUtils.toArtifact(a)));
141 } catch (LifecycleExecutionException e) {
142 throw new DependencyResolverException("Unable to resolve project dependencies", e);
143 }
144 }
145
146 private MavenProject getMavenProject(Project project) {
147 return ((DefaultProject) project).getProject();
148 }
149
150 private Collection<String> toScopes(ResolutionScope scope) {
151 return map(scope.scopes(), Scope::id);
152 }
153
154 static class DefaultDependencyResolverResult implements DependencyResolverResult {
155 private final List<Exception> exceptions;
156 private final Node root;
157 private final List<Node> dependencies;
158 private final List<Path> paths;
159
160 DefaultDependencyResolverResult(
161 List<Exception> exceptions, Node root, List<Node> dependencies, List<Path> paths) {
162 this.exceptions = exceptions;
163 this.root = root;
164 this.dependencies = dependencies;
165 this.paths = paths;
166 }
167
168 @Override
169 public List<Exception> getExceptions() {
170 return exceptions;
171 }
172
173 @Override
174 public Node getRoot() {
175 return root;
176 }
177
178 @Override
179 public List<Node> getDependencies() {
180 return dependencies;
181 }
182
183 @Override
184 public List<Path> getPaths() {
185 return paths;
186 }
187 }
188 }