blob: e22083bd70c8193f8119db492606162b5c4876b2 [file] [log] [blame]
package org.apache.maven.report.projectinfo.dependencies.renderer;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.metadata.ArtifactMetadataRetrievalException;
import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
import org.apache.maven.artifact.versioning.ArtifactVersion;
import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
import org.apache.maven.artifact.versioning.VersionRange;
import org.apache.maven.doxia.sink.Sink;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.License;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.ProjectBuilder;
import org.apache.maven.project.ProjectBuildingException;
import org.apache.maven.project.ProjectBuildingRequest;
import org.apache.maven.report.projectinfo.AbstractProjectInfoRenderer;
import org.apache.maven.report.projectinfo.ProjectInfoReportUtils;
import org.apache.maven.report.projectinfo.dependencies.ManagementDependencies;
import org.apache.maven.report.projectinfo.dependencies.RepositoryUtils;
import org.apache.maven.repository.RepositorySystem;
import org.codehaus.plexus.i18n.I18N;
import org.codehaus.plexus.util.StringUtils;
/**
* @author Nick Stolwijk
* @since 2.1
*/
public class DependencyManagementRenderer
extends AbstractProjectInfoRenderer
{
private final ManagementDependencies dependencies;
private final Log log;
private final ArtifactMetadataSource artifactMetadataSource;
private final RepositorySystem repositorySystem;
private final ProjectBuilder projectBuilder;
private final ProjectBuildingRequest buildingRequest;
private final RepositoryUtils repoUtils;
/**
* Default constructor
*
* @param sink {@link Sink}
* @param locale {@link Locale}
* @param i18n {@link I18N}
* @param log {@link Log}
* @param dependencies {@link ManagementDependencies}
* @param artifactMetadataSource {@link ArtifactMetadataSource}
* @param repositorySystem {@link RepositorySystem}
* @param projectBuilder {@link ProjectBuilder}
* @param buildingRequest {@link ProjectBuildingRequest}
* @param repoUtils {@link RepositoryUtils}
*/
public DependencyManagementRenderer( Sink sink, Locale locale, I18N i18n, Log log,
ManagementDependencies dependencies,
ArtifactMetadataSource artifactMetadataSource,
RepositorySystem repositorySystem, ProjectBuilder projectBuilder,
ProjectBuildingRequest buildingRequest, RepositoryUtils repoUtils )
{
super( sink, i18n, locale );
this.log = log;
this.dependencies = dependencies;
this.artifactMetadataSource = artifactMetadataSource;
this.repositorySystem = repositorySystem;
this.projectBuilder = projectBuilder;
this.buildingRequest = buildingRequest;
this.repoUtils = repoUtils;
}
// ----------------------------------------------------------------------
// Public methods
// ----------------------------------------------------------------------
@Override
protected String getI18Nsection()
{
return "dependency-management";
}
@Override
public void renderBody()
{
// Dependencies report
if ( !dependencies.hasDependencies() )
{
startSection( getTitle() );
paragraph( getI18nString( "nolist" ) );
endSection();
return;
}
// === Section: Project Dependencies.
renderSectionProjectDependencies();
}
// ----------------------------------------------------------------------
// Private methods
// ----------------------------------------------------------------------
private void renderSectionProjectDependencies()
{
startSection( getTitle() );
// collect dependencies by scope
Map<String, List<Dependency>> dependenciesByScope = dependencies.getManagementDependenciesByScope();
renderDependenciesForAllScopes( dependenciesByScope );
endSection();
}
private void renderDependenciesForAllScopes( Map<String, List<Dependency>> dependenciesByScope )
{
renderDependenciesForScope( Artifact.SCOPE_COMPILE, dependenciesByScope.get( Artifact.SCOPE_COMPILE ) );
renderDependenciesForScope( Artifact.SCOPE_RUNTIME, dependenciesByScope.get( Artifact.SCOPE_RUNTIME ) );
renderDependenciesForScope( Artifact.SCOPE_TEST, dependenciesByScope.get( Artifact.SCOPE_TEST ) );
renderDependenciesForScope( Artifact.SCOPE_PROVIDED, dependenciesByScope.get( Artifact.SCOPE_PROVIDED ) );
renderDependenciesForScope( Artifact.SCOPE_SYSTEM, dependenciesByScope.get( Artifact.SCOPE_SYSTEM ) );
}
private String[] getDependencyTableHeader( boolean hasClassifier )
{
String groupId = getI18nString( "column.groupId" );
String artifactId = getI18nString( "column.artifactId" );
String version = getI18nString( "column.version" );
String classifier = getI18nString( "column.classifier" );
String type = getI18nString( "column.type" );
String license = getI18nString( "column.license" );
if ( hasClassifier )
{
return new String[] { groupId, artifactId, version, classifier, type, license };
}
return new String[] { groupId, artifactId, version, type, license };
}
private void renderDependenciesForScope( String scope, List<Dependency> artifacts )
{
if ( artifacts != null )
{
// can't use straight artifact comparison because we want optional last
Collections.sort( artifacts, getDependencyComparator() );
startSection( scope );
paragraph( getI18nString( "intro." + scope ) );
startTable();
boolean hasClassifier = false;
for ( Dependency dependency : artifacts )
{
if ( StringUtils.isNotEmpty( dependency.getClassifier() ) )
{
hasClassifier = true;
break;
}
}
String[] tableHeader = getDependencyTableHeader( hasClassifier );
tableHeader( tableHeader );
for ( Dependency dependency : artifacts )
{
tableRow( getDependencyRow( dependency, hasClassifier ) );
}
endTable();
endSection();
}
}
@SuppressWarnings( "unchecked" )
private String[] getDependencyRow( Dependency dependency, boolean hasClassifier )
{
Artifact artifact =
repositorySystem.createArtifact( dependency.getGroupId(), dependency.getArtifactId(),
dependency.getVersion(), dependency.getScope(), dependency.getType() );
StringBuilder licensesBuffer = new StringBuilder();
String url = null;
try
{
VersionRange range = VersionRange.createFromVersionSpec( dependency.getVersion() );
if ( range.getRecommendedVersion() == null )
{
// MPIR-216: no direct version but version range: need to choose one precise version
log.debug( "Resolving range for DependencyManagement on " + artifact.getId() );
List<ArtifactVersion> versions =
artifactMetadataSource.retrieveAvailableVersions( artifact, buildingRequest.getLocalRepository(),
buildingRequest.getRemoteRepositories() );
// only use versions from range
for ( Iterator<ArtifactVersion> iter = versions.iterator(); iter.hasNext(); )
{
if ( ! range.containsVersion( iter.next() ) )
{
iter.remove();
}
}
// select latest, assuming pom information will be the most accurate
if ( !versions.isEmpty() )
{
ArtifactVersion maxArtifactVersion = Collections.max( versions );
artifact.setVersion( maxArtifactVersion.toString() );
log.debug( "DependencyManagement resolved: " + artifact.getId() );
}
}
url = ProjectInfoReportUtils.getArtifactUrl( repositorySystem, artifact, projectBuilder, buildingRequest );
MavenProject artifactProject = repoUtils.getMavenProjectFromRepository( artifact );
List<License> licenses = artifactProject.getLicenses();
for ( License license : licenses )
{
String licenseCell = ProjectInfoReportUtils.getArtifactIdCell( license.getName(), license.getUrl() );
if ( licensesBuffer.length() > 0 )
{
licensesBuffer.append( ", " );
}
licensesBuffer.append( licenseCell );
}
}
catch ( InvalidVersionSpecificationException e )
{
log.warn( "Unable to parse version for " + artifact.getId(), e );
}
catch ( ArtifactMetadataRetrievalException e )
{
log.warn( "Unable to retrieve versions for " + artifact.getId() + " from repository.", e );
}
catch ( ProjectBuildingException e )
{
log.warn( "Unable to create Maven project for " + artifact.getId() + " from repository.", e );
}
String artifactIdCell = ProjectInfoReportUtils.getArtifactIdCell( artifact.getArtifactId(), url );
if ( hasClassifier )
{
return new String[] { dependency.getGroupId(), artifactIdCell, dependency.getVersion(),
dependency.getClassifier(), dependency.getType(), licensesBuffer.toString() };
}
return new String[] { dependency.getGroupId(), artifactIdCell, dependency.getVersion(),
dependency.getType(), licensesBuffer.toString() };
}
private Comparator<Dependency> getDependencyComparator()
{
return new Comparator<Dependency>()
{
public int compare( Dependency a1, Dependency a2 )
{
int result = a1.getGroupId().compareTo( a2.getGroupId() );
if ( result != 0 )
{
return result;
}
result = a1.getArtifactId().compareTo( a2.getArtifactId() );
if ( result != 0 )
{
return result;
}
result = a1.getType().compareTo( a2.getType() );
if ( result != 0 )
{
return result;
}
if ( a1.getClassifier() == null )
{
if ( a2.getClassifier() != null )
{
return 1;
}
}
else
{
if ( a2.getClassifier() != null )
{
result = a1.getClassifier().compareTo( a2.getClassifier() );
}
else
{
return -1;
}
}
if ( result != 0 )
{
return result;
}
// We don't consider the version range in the comparison, just the resolved version
return a1.getVersion().compareTo( a2.getVersion() );
}
};
}
}