View Javadoc

1   package org.apache.maven.report.projectinfo.dependencies.renderer;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.util.Collections;
23  import java.util.Comparator;
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.factory.ArtifactFactory;
30  import org.apache.maven.artifact.metadata.ArtifactMetadataRetrievalException;
31  import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
32  import org.apache.maven.artifact.repository.ArtifactRepository;
33  import org.apache.maven.artifact.versioning.ArtifactVersion;
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.MavenProjectBuilder;
40  import org.apache.maven.project.ProjectBuildingException;
41  import org.apache.maven.report.projectinfo.AbstractProjectInfoRenderer;
42  import org.apache.maven.report.projectinfo.ProjectInfoReportUtils;
43  import org.apache.maven.report.projectinfo.dependencies.ManagementDependencies;
44  import org.apache.maven.report.projectinfo.dependencies.RepositoryUtils;
45  import org.codehaus.plexus.i18n.I18N;
46  import org.codehaus.plexus.util.StringUtils;
47  
48  /**
49   * @author Nick Stolwijk
50   * @version $Id: DependencyManagementRenderer.java 1100828 2011-05-08 22:34:59Z hboutemy $
51   * @since 2.1
52   */
53  public class DependencyManagementRenderer
54      extends AbstractProjectInfoRenderer
55  {
56      private final ManagementDependencies dependencies;
57  
58      private final Log log;
59  
60      private final ArtifactMetadataSource artifactMetadataSource;
61  
62      private final ArtifactFactory artifactFactory;
63  
64      private final MavenProjectBuilder mavenProjectBuilder;
65  
66      private final List<ArtifactRepository> remoteRepositories;
67  
68      private final ArtifactRepository localRepository;
69  
70      private final RepositoryUtils repoUtils;
71  
72      /**
73       * Default constructor
74       *
75       * @param sink
76       * @param locale
77       * @param i18n
78       * @param log
79       * @param artifactFactory
80       * @param dependencies
81       * @param mavenProjectBuilder
82       * @param remoteRepositories
83       * @param localRepository
84       * @param repoUtils
85       */
86      public DependencyManagementRenderer( Sink sink, Locale locale, I18N i18n, Log log,
87                                           ManagementDependencies dependencies,
88                                           ArtifactMetadataSource artifactMetadataSource,
89                                           ArtifactFactory artifactFactory, MavenProjectBuilder mavenProjectBuilder,
90                                           List<ArtifactRepository> remoteRepositories,
91                                           ArtifactRepository localRepository, RepositoryUtils repoUtils )
92      {
93          super( sink, i18n, locale );
94  
95          this.log = log;
96          this.dependencies = dependencies;
97          this.artifactMetadataSource = artifactMetadataSource;
98          this.artifactFactory = artifactFactory;
99          this.mavenProjectBuilder = mavenProjectBuilder;
100         this.remoteRepositories = remoteRepositories;
101         this.localRepository = localRepository;
102         this.repoUtils = repoUtils;
103     }
104 
105     // ----------------------------------------------------------------------
106     // Public methods
107     // ----------------------------------------------------------------------
108 
109     @Override
110     protected String getI18Nsection()
111     {
112         return "dependencyManagement";
113     }
114 
115     @Override
116     public void renderBody()
117     {
118         // Dependencies report
119 
120         if ( !dependencies.hasDependencies() )
121         {
122             startSection( getTitle() );
123 
124             paragraph( getI18nString( "nolist" ) );
125 
126             endSection();
127 
128             return;
129         }
130 
131         // === Section: Project Dependencies.
132         renderSectionProjectDependencies();
133     }
134 
135     // ----------------------------------------------------------------------
136     // Private methods
137     // ----------------------------------------------------------------------
138 
139     private void renderSectionProjectDependencies()
140     {
141         startSection( getTitle() );
142 
143         // collect dependencies by scope
144         Map<String, List<Dependency>> dependenciesByScope = dependencies.getManagementDependenciesByScope();
145 
146         renderDependenciesForAllScopes( dependenciesByScope );
147 
148         endSection();
149     }
150 
151     private void renderDependenciesForAllScopes( Map<String, List<Dependency>> dependenciesByScope )
152     {
153         renderDependenciesForScope( Artifact.SCOPE_COMPILE, dependenciesByScope.get( Artifact.SCOPE_COMPILE ) );
154         renderDependenciesForScope( Artifact.SCOPE_RUNTIME, dependenciesByScope.get( Artifact.SCOPE_RUNTIME ) );
155         renderDependenciesForScope( Artifact.SCOPE_TEST, dependenciesByScope.get( Artifact.SCOPE_TEST ) );
156         renderDependenciesForScope( Artifact.SCOPE_PROVIDED, dependenciesByScope.get( Artifact.SCOPE_PROVIDED ) );
157         renderDependenciesForScope( Artifact.SCOPE_SYSTEM, dependenciesByScope.get( Artifact.SCOPE_SYSTEM ) );
158     }
159 
160     private String[] getDependencyTableHeader( boolean hasClassifier )
161     {
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         {
171             return new String[] { groupId, artifactId, version, classifier, type, license };
172         }
173 
174         return new String[] { groupId, artifactId, version, type, license };
175     }
176 
177     private void renderDependenciesForScope( String scope, List<Dependency> artifacts )
178     {
179         if ( artifacts != null )
180         {
181             // can't use straight artifact comparison because we want optional last
182             Collections.sort( artifacts, getDependencyComparator() );
183 
184             startSection( scope );
185 
186             paragraph( getI18nString( "intro." + scope ) );
187             startTable();
188 
189             boolean hasClassifier = false;
190             for ( Dependency dependency : artifacts )
191             {
192                 if ( StringUtils.isNotEmpty( dependency.getClassifier() ) )
193                 {
194                     hasClassifier = true;
195                     break;
196                 }
197             }
198 
199             String[] tableHeader = getDependencyTableHeader( hasClassifier );
200             tableHeader( tableHeader );
201 
202             for ( Dependency dependency : artifacts )
203             {
204                 tableRow( getDependencyRow( dependency, hasClassifier ) );
205             }
206             endTable();
207 
208             endSection();
209         }
210     }
211 
212     @SuppressWarnings( "unchecked" )
213     private String[] getDependencyRow( Dependency dependency, boolean hasClassifier )
214     {
215         Artifact artifact =
216             artifactFactory.createProjectArtifact( dependency.getGroupId(), dependency.getArtifactId(),
217                                                    dependency.getVersion() );
218 
219         StringBuffer licensesBuffer = new StringBuffer();
220         String url = null;
221         try
222         {
223             List<ArtifactVersion> versions =
224                 artifactMetadataSource.retrieveAvailableVersions( artifact, localRepository, remoteRepositories );
225 
226             if ( versions.size() > 0 )
227             {
228                 Collections.sort( versions );
229                 
230                 artifact.setVersion( versions.get( versions.size() - 1 ).toString() );
231             }
232 
233             url =
234                 ProjectInfoReportUtils.getArtifactUrl( artifactFactory, artifact, mavenProjectBuilder,
235                                                        remoteRepositories, localRepository );
236 
237             MavenProject artifactProject = repoUtils.getMavenProjectFromRepository( artifact );
238 
239             List<License> licenses = artifactProject.getLicenses();
240             for ( License license : licenses )
241             {
242                 String licenseCell = ProjectInfoReportUtils.getArtifactIdCell( license.getName(), license.getUrl() );
243                 if ( licensesBuffer.length() > 0 )
244                 {
245                     licensesBuffer.append( ", " );
246                 }
247                 licensesBuffer.append( licenseCell );
248             }
249         }
250         catch ( ArtifactMetadataRetrievalException e )
251         {
252             log.warn( "Unable to retrieve versions for " + artifact.getId() + " from repository.", e );
253         }
254         catch ( ProjectBuildingException e )
255         {
256             log.warn( "Unable to create Maven project for " + artifact.getId() + " from repository.", e );
257         }
258 
259         String artifactIdCell = ProjectInfoReportUtils.getArtifactIdCell( artifact.getArtifactId(), url );
260 
261         if ( hasClassifier )
262         {
263             return new String[] { dependency.getGroupId(), artifactIdCell, dependency.getVersion(),
264                 dependency.getClassifier(), dependency.getType(), licensesBuffer.toString() };
265         }
266 
267         return new String[] { dependency.getGroupId(), artifactIdCell, dependency.getVersion(),
268             dependency.getType(), licensesBuffer.toString() };
269     }
270 
271     private Comparator<Dependency> getDependencyComparator()
272     {
273         return new Comparator<Dependency>()
274         {
275             public int compare( Dependency a1, Dependency a2 )
276             {
277                 int result = a1.getGroupId().compareTo( a2.getGroupId() );
278                 if ( result != 0 )
279                 {
280                     return result;
281                 }
282 
283                 result = a1.getArtifactId().compareTo( a2.getArtifactId() );
284                 if ( result != 0 )
285                 {
286                     return result;
287                 }
288 
289                 result = a1.getType().compareTo( a2.getType() );
290                 if ( result != 0 )
291                 {
292                     return result;
293                 }
294 
295                 if ( a1.getClassifier() == null )
296                 {
297                     if ( a2.getClassifier() != null )
298                     {
299                         return 1;
300                     }
301                 }
302                 else
303                 {
304                     if ( a2.getClassifier() != null )
305                     {
306                         result = a1.getClassifier().compareTo( a2.getClassifier() );
307                     }
308                     else
309                     {
310                         return -1;
311                     }
312                 }
313 
314                 if ( result != 0 )
315                 {
316                     return result;
317                 }
318 
319                 // We don't consider the version range in the comparison, just the resolved version
320                 return a1.getVersion().compareTo( a2.getVersion() );
321             }
322         };
323     }
324 }