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