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 }