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