1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.report.projectinfo.dependencies.renderer;
20
21 import java.util.Collections;
22 import java.util.Comparator;
23 import java.util.Iterator;
24 import java.util.List;
25 import java.util.Locale;
26 import java.util.Map;
27
28 import org.apache.maven.artifact.Artifact;
29 import org.apache.maven.artifact.metadata.ArtifactMetadataRetrievalException;
30 import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
31 import org.apache.maven.artifact.versioning.ArtifactVersion;
32 import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
33 import org.apache.maven.artifact.versioning.VersionRange;
34 import org.apache.maven.doxia.sink.Sink;
35 import org.apache.maven.model.Dependency;
36 import org.apache.maven.model.License;
37 import org.apache.maven.plugin.logging.Log;
38 import org.apache.maven.project.MavenProject;
39 import org.apache.maven.project.ProjectBuilder;
40 import org.apache.maven.project.ProjectBuildingException;
41 import org.apache.maven.project.ProjectBuildingRequest;
42 import org.apache.maven.report.projectinfo.AbstractProjectInfoRenderer;
43 import org.apache.maven.report.projectinfo.LicenseMapping;
44 import org.apache.maven.report.projectinfo.ProjectInfoReportUtils;
45 import org.apache.maven.report.projectinfo.dependencies.ManagementDependencies;
46 import org.apache.maven.report.projectinfo.dependencies.RepositoryUtils;
47 import org.apache.maven.repository.RepositorySystem;
48 import org.codehaus.plexus.i18n.I18N;
49 import org.codehaus.plexus.util.StringUtils;
50
51
52
53
54
55 public class DependencyManagementRenderer extends AbstractProjectInfoRenderer {
56 private final ManagementDependencies dependencies;
57
58 private final Log log;
59
60 private final ArtifactMetadataSource artifactMetadataSource;
61
62 private final RepositorySystem repositorySystem;
63
64 private final ProjectBuilder projectBuilder;
65
66 private final ProjectBuildingRequest buildingRequest;
67
68 private final RepositoryUtils repoUtils;
69
70 private final Map<String, String> licenseMappings;
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87 public DependencyManagementRenderer(
88 Sink sink,
89 Locale locale,
90 I18N i18n,
91 Log log,
92 ManagementDependencies dependencies,
93 ArtifactMetadataSource artifactMetadataSource,
94 RepositorySystem repositorySystem,
95 ProjectBuilder projectBuilder,
96 ProjectBuildingRequest buildingRequest,
97 RepositoryUtils repoUtils,
98 Map<String, String> licenseMappings) {
99 super(sink, i18n, locale);
100
101 this.log = log;
102 this.dependencies = dependencies;
103 this.artifactMetadataSource = artifactMetadataSource;
104 this.repositorySystem = repositorySystem;
105 this.projectBuilder = projectBuilder;
106 this.buildingRequest = buildingRequest;
107 this.repoUtils = repoUtils;
108 this.licenseMappings = licenseMappings;
109 }
110
111
112
113
114
115 @Override
116 protected String getI18Nsection() {
117 return "dependency-management";
118 }
119
120 @Override
121 protected void renderBody() {
122
123
124 if (!dependencies.hasDependencies()) {
125 startSection(getTitle());
126
127 paragraph(getI18nString("nolist"));
128
129 endSection();
130
131 return;
132 }
133
134
135 renderSectionProjectDependencies();
136 }
137
138
139
140
141
142 private void renderSectionProjectDependencies() {
143 startSection(getTitle());
144
145
146 Map<String, List<Dependency>> dependenciesByScope = dependencies.getManagementDependenciesByScope();
147
148 renderDependenciesForAllScopes(dependenciesByScope);
149
150 endSection();
151 }
152
153 private void renderDependenciesForAllScopes(Map<String, List<Dependency>> dependenciesByScope) {
154 renderDependenciesForScope(Artifact.SCOPE_COMPILE, dependenciesByScope.get(Artifact.SCOPE_COMPILE));
155 renderDependenciesForScope(Artifact.SCOPE_RUNTIME, dependenciesByScope.get(Artifact.SCOPE_RUNTIME));
156 renderDependenciesForScope(Artifact.SCOPE_TEST, dependenciesByScope.get(Artifact.SCOPE_TEST));
157 renderDependenciesForScope(Artifact.SCOPE_PROVIDED, dependenciesByScope.get(Artifact.SCOPE_PROVIDED));
158 renderDependenciesForScope(Artifact.SCOPE_SYSTEM, dependenciesByScope.get(Artifact.SCOPE_SYSTEM));
159 }
160
161 private String[] getDependencyTableHeader(boolean hasClassifier) {
162 String groupId = getI18nString("column.groupId");
163 String artifactId = getI18nString("column.artifactId");
164 String version = getI18nString("column.version");
165 String classifier = getI18nString("column.classifier");
166 String type = getI18nString("column.type");
167 String license = getI18nString("column.license");
168
169 if (hasClassifier) {
170 return new String[] {groupId, artifactId, version, classifier, type, license};
171 }
172
173 return new String[] {groupId, artifactId, version, type, license};
174 }
175
176 private void renderDependenciesForScope(String scope, List<Dependency> artifacts) {
177 if (artifacts != null) {
178
179 Collections.sort(artifacts, getDependencyComparator());
180
181 startSection(scope);
182
183 paragraph(getI18nString("intro." + scope));
184 startTable();
185
186 boolean hasClassifier = false;
187 for (Dependency dependency : artifacts) {
188 if (StringUtils.isNotEmpty(dependency.getClassifier())) {
189 hasClassifier = true;
190 break;
191 }
192 }
193
194 String[] tableHeader = getDependencyTableHeader(hasClassifier);
195 tableHeader(tableHeader);
196
197 for (Dependency dependency : artifacts) {
198 tableRow(getDependencyRow(dependency, hasClassifier));
199 }
200 endTable();
201
202 endSection();
203 }
204 }
205
206 @SuppressWarnings("unchecked")
207 private String[] getDependencyRow(Dependency dependency, boolean hasClassifier) {
208 Artifact artifact = repositorySystem.createArtifact(
209 dependency.getGroupId(),
210 dependency.getArtifactId(),
211 dependency.getVersion(),
212 dependency.getScope(),
213 dependency.getType());
214
215 StringBuilder licensesBuffer = new StringBuilder();
216 String url = null;
217 try {
218 VersionRange range = VersionRange.createFromVersionSpec(dependency.getVersion());
219
220 if (range.getRecommendedVersion() == null) {
221
222 log.debug("Resolving range for DependencyManagement on " + artifact.getId());
223
224 List<ArtifactVersion> versions = artifactMetadataSource.retrieveAvailableVersions(
225 artifact, buildingRequest.getLocalRepository(), buildingRequest.getRemoteRepositories());
226
227
228 for (Iterator<ArtifactVersion> iter = versions.iterator(); iter.hasNext(); ) {
229 if (!range.containsVersion(iter.next())) {
230 iter.remove();
231 }
232 }
233
234
235 if (!versions.isEmpty()) {
236 ArtifactVersion maxArtifactVersion = Collections.max(versions);
237
238 artifact.setVersion(maxArtifactVersion.toString());
239 log.debug("DependencyManagement resolved: " + artifact.getId());
240 }
241 }
242
243 url = ProjectInfoReportUtils.getArtifactUrl(repositorySystem, artifact, projectBuilder, buildingRequest);
244
245 MavenProject artifactProject = repoUtils.getMavenProjectFromRepository(artifact);
246
247 List<License> licenses = artifactProject.getLicenses();
248 for (License license : licenses) {
249 String name = license.getName();
250 if (licenseMappings != null && licenseMappings.containsKey(name)) {
251 name = licenseMappings.get(name);
252 }
253 String licenseCell = ProjectInfoReportUtils.getArtifactIdCell(name, license.getUrl());
254 if (licensesBuffer.length() > 0) {
255 licensesBuffer.append(", ");
256 }
257 licensesBuffer.append(licenseCell);
258 }
259 } catch (InvalidVersionSpecificationException e) {
260 log.warn("Unable to parse version for " + artifact.getId(), e);
261 } catch (ArtifactMetadataRetrievalException e) {
262 log.warn("Unable to retrieve versions for " + artifact.getId() + " from repository.", e);
263 } catch (ProjectBuildingException e) {
264 if (log.isDebugEnabled()) {
265 log.warn("Unable to create Maven project for " + artifact.getId() + " from repository.", e);
266 } else {
267 log.warn("Unable to create Maven project for " + artifact.getId() + " from repository.");
268 }
269 }
270
271 String artifactIdCell = ProjectInfoReportUtils.getArtifactIdCell(artifact.getArtifactId(), url);
272
273 if (hasClassifier) {
274 return new String[] {
275 dependency.getGroupId(),
276 artifactIdCell,
277 dependency.getVersion(),
278 dependency.getClassifier(),
279 dependency.getType(),
280 licensesBuffer.toString()
281 };
282 }
283
284 return new String[] {
285 dependency.getGroupId(),
286 artifactIdCell,
287 dependency.getVersion(),
288 dependency.getType(),
289 licensesBuffer.toString()
290 };
291 }
292
293 private Comparator<Dependency> getDependencyComparator() {
294 return new Comparator<Dependency>() {
295 public int compare(Dependency a1, Dependency a2) {
296 int result = a1.getGroupId().compareTo(a2.getGroupId());
297 if (result != 0) {
298 return result;
299 }
300
301 result = a1.getArtifactId().compareTo(a2.getArtifactId());
302 if (result != 0) {
303 return result;
304 }
305
306 result = a1.getType().compareTo(a2.getType());
307 if (result != 0) {
308 return result;
309 }
310
311 if (a1.getClassifier() == null) {
312 if (a2.getClassifier() != null) {
313 return 1;
314 }
315 } else {
316 if (a2.getClassifier() != null) {
317 result = a1.getClassifier().compareTo(a2.getClassifier());
318 } else {
319 return -1;
320 }
321 }
322
323 if (result != 0) {
324 return result;
325 }
326
327
328 return a1.getVersion().compareTo(a2.getVersion());
329 }
330 };
331 }
332 }