1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.basepom.mojo.dvc.dependency;
16
17 import static com.google.common.base.Preconditions.checkNotNull;
18 import static com.google.common.collect.ImmutableSet.toImmutableSet;
19
20 import org.basepom.mojo.dvc.Context;
21 import org.basepom.mojo.dvc.PluginLog;
22 import org.basepom.mojo.dvc.QualifiedName;
23
24 import java.util.Objects;
25
26 import com.google.common.base.Throwables;
27 import com.google.common.collect.ImmutableList;
28 import com.google.common.collect.ImmutableMap;
29 import com.google.common.collect.ImmutableSet;
30 import org.apache.maven.RepositoryUtils;
31 import org.apache.maven.project.DefaultDependencyResolutionRequest;
32 import org.apache.maven.project.DependencyResolutionException;
33 import org.apache.maven.project.DependencyResolutionRequest;
34 import org.apache.maven.project.DependencyResolutionResult;
35 import org.apache.maven.project.MavenProject;
36 import org.apache.maven.project.ProjectBuildingException;
37 import org.apache.maven.project.ProjectBuildingResult;
38 import org.eclipse.aether.artifact.Artifact;
39 import org.eclipse.aether.artifact.DefaultArtifact;
40 import org.eclipse.aether.graph.Dependency;
41 import org.eclipse.aether.graph.DependencyFilter;
42 import org.eclipse.aether.graph.DependencyNode;
43 import org.eclipse.aether.repository.RemoteRepository;
44 import org.eclipse.aether.transfer.ArtifactTransferException;
45 import org.eclipse.aether.transfer.NoRepositoryLayoutException;
46 import org.eclipse.aether.util.artifact.JavaScopes;
47
48
49
50
51 public final class DependencyMapBuilder {
52
53 private static final PluginLog LOG = new PluginLog(DependencyMapBuilder.class);
54
55 private final Context context;
56
57 public DependencyMapBuilder(final Context context) {
58 this.context = checkNotNull(context, "context is null");
59 }
60
61
62
63
64
65
66
67
68
69
70 public DependencyMap mapDependency(final DependencyNode dependencyNode,
71 final DependencyFilter projectScopeFilter)
72 throws DependencyResolutionException, ProjectBuildingException {
73 checkNotNull(dependencyNode, "dependencyNode is null");
74 checkNotNull(projectScopeFilter, "projectScopeFilter is null");
75
76
77 final ProjectBuildingResult result = context.getProjectBuilder()
78 .build(convertFromAetherDependency(dependencyNode), false, context.createProjectBuildingRequest());
79
80
81 final MavenProject project = result.getProject();
82 return mapProject(project, projectScopeFilter);
83 }
84
85
86
87
88
89
90
91
92
93 public DependencyMap mapProject(final MavenProject project,
94 final DependencyFilter scopeFilter)
95 throws DependencyResolutionException {
96 checkNotNull(project, "project is null");
97 checkNotNull(scopeFilter, "scopeFilter is null");
98
99 final DependencyResolutionRequest request = new DefaultDependencyResolutionRequest();
100 request.setRepositorySession(context.getRepositorySystemSession());
101 request.setMavenProject(project);
102 request.setResolutionFilter(scopeFilter);
103
104 DependencyResolutionResult result;
105
106 try {
107 result = context.getProjectDependenciesResolver().resolve(request);
108 } catch (DependencyResolutionException e) {
109 result = e.getResult();
110
111 final ImmutableSet<ProjectKey> reactorProjects = context.getReactorProjects().stream()
112 .map(ProjectKey::fromProject).collect(toImmutableSet());
113
114
115 final ImmutableSet<Dependency> reactorDependencies = result.getUnresolvedDependencies().stream()
116 .filter(d -> reactorProjects.contains(ProjectKey.fromDependency(d)))
117 .collect(toImmutableSet());
118
119 result.getUnresolvedDependencies().removeAll(reactorDependencies);
120 result.getResolvedDependencies().addAll(reactorDependencies);
121
122 if (!context.isUnresolvedSystemArtifactsFailBuild()) {
123 final ImmutableSet<Dependency> systemDependencies = result.getUnresolvedDependencies().stream()
124 .filter(d -> JavaScopes.SYSTEM.equals(d.getScope()))
125 .collect(toImmutableSet());
126
127 result.getUnresolvedDependencies().removeAll(systemDependencies);
128 result.getResolvedDependencies().addAll(systemDependencies);
129 }
130
131 if (!context.isOptionalDependenciesMustExist()) {
132 final ImmutableSet<Dependency> optionalDependencies = result.getUnresolvedDependencies().stream()
133 .filter(Dependency::isOptional)
134 .collect(toImmutableSet());
135
136 result.getUnresolvedDependencies().removeAll(optionalDependencies);
137 result.getResolvedDependencies().addAll(optionalDependencies);
138 }
139
140 if (!result.getUnresolvedDependencies().isEmpty()) {
141 final Throwable t = Throwables.getRootCause(e);
142 RemoteRepository repository = null;
143
144 if (t instanceof NoRepositoryLayoutException) {
145 repository = ((NoRepositoryLayoutException) t).getRepository();
146 } else if (t instanceof ArtifactTransferException) {
147 repository = ((ArtifactTransferException) t).getRepository();
148 }
149
150 if (repository != null && "legacy".equals(repository.getContentType())) {
151 LOG.warn("Could not access a legacy repository for artifacts: %s; Reason: %s", result.getUnresolvedDependencies(), t.getMessage());
152 } else {
153 throw e;
154 }
155 }
156 }
157
158 final DependencyNode graph = result.getDependencyGraph();
159 final ImmutableMap.Builder<QualifiedName, DependencyNode> dependencyCollector = ImmutableMap.builder();
160 final ImmutableMap<QualifiedName, DependencyNode> directDependencies = loadDependencyTree(graph, scopeFilter, dependencyCollector);
161 dependencyCollector.putAll(directDependencies);
162 return new DependencyMap(dependencyCollector.build(), directDependencies);
163 }
164
165 private ImmutableMap<QualifiedName, DependencyNode> loadDependencyTree(final DependencyNode node,
166 final DependencyFilter filter,
167 final ImmutableMap.Builder<QualifiedName, DependencyNode> allDependencyCollector) {
168 final ImmutableMap.Builder<QualifiedName, DependencyNode> builder = ImmutableMap.builder();
169 for (final DependencyNode dependencyNode : node.getChildren()) {
170 if (dependencyNode.getManagedBits() != 0) {
171 if ((dependencyNode.getManagedBits() & DependencyNode.MANAGED_VERSION) != 0) {
172 LOG.debug("%s -> Managed Version!", dependencyNode.getArtifact());
173 }
174 if ((dependencyNode.getManagedBits() & DependencyNode.MANAGED_SCOPE) != 0) {
175 LOG.debug("%s -> Managed Scope!", dependencyNode.getArtifact());
176 }
177 if ((dependencyNode.getManagedBits() & DependencyNode.MANAGED_OPTIONAL) != 0) {
178 LOG.debug("%s -> Managed Optional!", dependencyNode.getArtifact());
179 }
180 if ((dependencyNode.getManagedBits() & DependencyNode.MANAGED_PROPERTIES) != 0) {
181 LOG.debug("%s -> Managed Properties!", dependencyNode.getArtifact());
182 }
183 if ((dependencyNode.getManagedBits() & DependencyNode.MANAGED_EXCLUSIONS) != 0) {
184 LOG.debug("%s -> Managed Exclusions!", dependencyNode.getArtifact());
185 }
186 }
187
188 if (filter.accept(dependencyNode, ImmutableList.of(node))) {
189 final QualifiedName name = QualifiedName.fromDependencyNode(dependencyNode);
190 builder.put(name, dependencyNode);
191
192 allDependencyCollector.putAll(loadDependencyTree(dependencyNode, filter, allDependencyCollector));
193 }
194 }
195 return builder.build();
196 }
197
198 static org.apache.maven.artifact.Artifact convertFromAetherDependency(final DependencyNode dependencyNode) {
199 Artifact aetherArtifact = convertToPomArtifact(dependencyNode.getArtifact());
200
201 final org.apache.maven.artifact.Artifact mavenArtifact = RepositoryUtils.toArtifact(aetherArtifact);
202 mavenArtifact.setScope(dependencyNode.getDependency().getScope());
203 mavenArtifact.setOptional(dependencyNode.getDependency().isOptional());
204
205 return mavenArtifact;
206 }
207
208 static Artifact convertToPomArtifact(final Artifact artifact) {
209
210 if (artifact.getClassifier().isEmpty() && "pom".equals(artifact.getExtension())) {
211 return artifact;
212 }
213
214
215 return new DefaultArtifact(artifact.getGroupId(), artifact.getArtifactId(), "pom", artifact.getVersion());
216 }
217
218 private static final class ProjectKey {
219
220 private final String groupId;
221 private final String artifactId;
222 private final String version;
223
224 public static ProjectKey fromProject(final MavenProject project) {
225 checkNotNull(project, "project; is null");
226 return new ProjectKey(project.getGroupId(), project.getArtifactId(), project.getVersion());
227 }
228
229 public static ProjectKey fromDependency(final Dependency dependency) {
230 checkNotNull(dependency, "artifact; is null");
231 return new ProjectKey(dependency.getArtifact().getGroupId(),
232 dependency.getArtifact().getArtifactId(),
233 dependency.getArtifact().getVersion());
234 }
235
236 private ProjectKey(final String groupId, final String artifactId, final String version) {
237 this.groupId = checkNotNull(groupId, "groupId is null");
238 this.artifactId = checkNotNull(artifactId, "artifactId is null");
239 this.version = checkNotNull(version, "version is null");
240 }
241
242 @Override
243 public boolean equals(Object o) {
244 if (this == o) {
245 return true;
246 }
247 if (o == null || getClass() != o.getClass()) {
248 return false;
249 }
250 ProjectKey that = (ProjectKey) o;
251 return groupId.equals(that.groupId)
252 && artifactId.equals(that.artifactId)
253 && version.equals(that.version);
254 }
255
256 @Override
257 public int hashCode() {
258 return Objects.hash(groupId, artifactId, version);
259 }
260 }
261 }