org.codehaus.mojo.license.AbstractDownloadLicensesMojo Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of license-maven-plugin Show documentation
Show all versions of license-maven-plugin Show documentation
Maven plugin to download and collect license files from project dependencies.
package org.codehaus.mojo.license;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.model.License;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import org.apache.maven.settings.Proxy;
import org.codehaus.mojo.license.api.DependenciesTool;
import org.codehaus.mojo.license.api.MavenProjectDependenciesConfigurator;
import org.codehaus.mojo.license.model.ProjectLicenseInfo;
import org.codehaus.mojo.license.utils.FileUtil;
import org.codehaus.mojo.license.utils.LicenseDownloader;
import org.codehaus.mojo.license.utils.LicenseSummaryReader;
import org.codehaus.mojo.license.utils.LicenseSummaryWriter;
import org.codehaus.plexus.util.Base64;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
/**
* Created on 23/05/16.
*
* @author Tony Chemit - [email protected]
*/
public abstract class AbstractDownloadLicensesMojo
extends AbstractMojo
implements MavenProjectDependenciesConfigurator
{
// ----------------------------------------------------------------------
// Mojo Parameters
// ----------------------------------------------------------------------
/**
* Location of the local repository.
*
* @since 1.0
*/
@Parameter( defaultValue = "${localRepository}", readonly = true )
private ArtifactRepository localRepository;
/**
* List of Remote Repositories used by the resolver
*
* @since 1.0
*/
@Parameter( defaultValue = "${project.remoteArtifactRepositories}", readonly = true )
private List remoteRepositories;
/**
* Input file containing a mapping between each dependency and it's license information.
*
* @since 1.0
*/
@Parameter( property = "licensesConfigFile", defaultValue = "${project.basedir}/src/license/licenses.xml" )
private File licensesConfigFile;
/**
* The directory to which the dependency licenses should be written.
*
* @since 1.0
*/
@Parameter( property = "licensesOutputDirectory",
defaultValue = "${project.build.directory}/generated-resources/licenses" )
private File licensesOutputDirectory;
/**
* The output file containing a mapping between each dependency and it's license information.
*
* @since 1.0
*/
@Parameter( property = "licensesOutputFile",
defaultValue = "${project.build.directory}/generated-resources/licenses.xml" )
private File licensesOutputFile;
/**
* A filter to exclude some scopes.
*
* @since 1.0
*/
@Parameter( property = "license.excludedScopes", defaultValue = "system" )
private String excludedScopes;
/**
* A filter to include only some scopes, if let empty then all scopes will be used (no filter).
*
* @since 1.0
*/
@Parameter( property = "license.includedScopes", defaultValue = "" )
private String includedScopes;
/**
* Settings offline flag (will not download anything if setted to true).
*
* @since 1.0
*/
@Parameter( defaultValue = "${settings.offline}" )
private boolean offline;
/**
* Don't show warnings about bad or missing license files.
*
* @since 1.0
*/
@Parameter( defaultValue = "false" )
private boolean quiet;
/**
* Include transitive dependencies when downloading license files.
*
* @since 1.0
*/
@Parameter( defaultValue = "true" )
private boolean includeTransitiveDependencies;
/**
* Get declared proxies from the {@code settings.xml} file.
*
* @since 1.4
*/
@Parameter( defaultValue = "${settings.proxies}", readonly = true )
private List proxies;
/**
* A flag to organize the licenses by dependencies. When this is done, each dependency will
* get its full license file, even if already downloaded for another dependency.
*
* @since 1.9
*/
@Parameter( property = "license.organizeLicensesByDependencies", defaultValue = "false" )
protected boolean organizeLicensesByDependencies;
/**
* The Maven Project Object
*
* @since 1.0
*/
@Parameter( defaultValue = "${project}", readonly = true )
private MavenProject project;
// ----------------------------------------------------------------------
// Plexus Components
// ----------------------------------------------------------------------
/**
* Dependencies tool.
*
* @since 1.0
*/
@Component
private DependenciesTool dependenciesTool;
// ----------------------------------------------------------------------
// Private Fields
// ----------------------------------------------------------------------
/**
* Keeps a collection of the URLs of the licenses that have been downlaoded. This helps the plugin to avoid
* downloading the same license multiple times.
*/
private Set downloadedLicenseURLs = new HashSet();
/**
* Proxy Login/Password encoded(only if usgin a proxy with authentication).
*
* @since 1.4
*/
private String proxyLoginPasswordEncoded;
protected abstract boolean isSkip();
protected MavenProject getProject()
{
return project;
}
protected abstract Set getDependencies();
// ----------------------------------------------------------------------
// Mojo Implementation
// ----------------------------------------------------------------------
protected SortedMap getDependencies( MavenProject project )
{
return dependenciesTool.loadProjectDependencies( project, this, localRepository, remoteRepositories, null );
}
/**
* {@inheritDoc}
*/
public void execute()
throws MojoExecutionException
{
if ( offline )
{
getLog().warn( "Offline flag is on, download-licenses goal is skip." );
return;
}
if ( isSkip() )
{
getLog().info( "skip flag is on, will skip goal." );
return;
}
initDirectories();
initProxy();
Map configuredDepLicensesMap = new HashMap();
// License info from previous build
if ( licensesOutputFile.exists() )
{
loadLicenseInfo( configuredDepLicensesMap, licensesOutputFile, true );
}
// Manually configured license info, loaded second to override previously loaded info
if ( licensesConfigFile.exists() )
{
loadLicenseInfo( configuredDepLicensesMap, licensesConfigFile, false );
}
Set dependencies = getDependencies();
// The resulting list of licenses after dependency resolution
List depProjectLicenses = new ArrayList();
for ( MavenProject project : dependencies )
{
Artifact artifact = project.getArtifact();
getLog().debug( "Checking licenses for project " + artifact );
String artifactProjectId = getArtifactProjectId( artifact );
ProjectLicenseInfo depProject;
if ( configuredDepLicensesMap.containsKey( artifactProjectId ) )
{
depProject = configuredDepLicensesMap.get( artifactProjectId );
depProject.setVersion( artifact.getVersion() );
}
else
{
depProject = createDependencyProject( project );
}
downloadLicenses( depProject );
depProjectLicenses.add( depProject );
}
try
{
LicenseSummaryWriter.writeLicenseSummary( depProjectLicenses, licensesOutputFile );
}
catch ( Exception e )
{
throw new MojoExecutionException( "Unable to write license summary file: " + licensesOutputFile, e );
}
}
// ----------------------------------------------------------------------
// MavenProjectDependenciesConfigurator Implementation
// ----------------------------------------------------------------------
/**
* {@inheritDoc}
*/
public boolean isIncludeTransitiveDependencies()
{
return includeTransitiveDependencies;
}
/**
* {@inheritDoc}
*/
public List getExcludedScopes()
{
String[] split = excludedScopes == null ? new String[0] : excludedScopes.split( "," );
return Arrays.asList( split );
}
public void setExcludedScopes( String excludedScopes )
{
this.excludedScopes = excludedScopes;
}
/**
* {@inheritDoc}
*/
public List getIncludedScopes()
{
String[] split = includedScopes == null ? new String[0] : includedScopes.split( "," );
return Arrays.asList( split );
}
// not used at the moment
/**
* {@inheritDoc}
*/
public String getIncludedArtifacts()
{
return null;
}
// not used at the moment
/**
* {@inheritDoc}
*/
public String getIncludedGroups()
{
return null;
}
// not used at the moment
/**
* {@inheritDoc}
*/
public String getExcludedGroups()
{
return null;
}
// not used at the moment
/**
* {@inheritDoc}
*/
public String getExcludedArtifacts()
{
return null;
}
/**
* {@inheritDoc}
*/
public boolean isVerbose()
{
return getLog().isDebugEnabled();
}
// ----------------------------------------------------------------------
// Private Methods
// ----------------------------------------------------------------------
private void initDirectories()
throws MojoExecutionException
{
try
{
FileUtil.createDirectoryIfNecessary( licensesOutputDirectory );
FileUtil.createDirectoryIfNecessary( licensesOutputFile.getParentFile() );
}
catch ( IOException e )
{
throw new MojoExecutionException( "Unable to create a directory...", e );
}
}
private void initProxy()
throws MojoExecutionException
{
Proxy proxyToUse = null;
for ( Proxy proxy : proxies )
{
if ( proxy.isActive() && "http".equals( proxy.getProtocol() ) )
{
// found our proxy
proxyToUse = proxy;
break;
}
}
if ( proxyToUse != null )
{
System.getProperties().put( "proxySet", "true" );
System.setProperty( "proxyHost", proxyToUse.getHost() );
System.setProperty( "proxyPort", String.valueOf( proxyToUse.getPort() ) );
if ( proxyToUse.getNonProxyHosts() != null )
{
System.setProperty( "nonProxyHosts", proxyToUse.getNonProxyHosts() );
}
if ( proxyToUse.getUsername() != null )
{
String loginPassword = proxyToUse.getUsername() + ":" + proxyToUse.getPassword();
proxyLoginPasswordEncoded = new String( Base64.encodeBase64( loginPassword.getBytes() ) );
}
}
}
/**
* Load the license information contained in a file if it exists. Will overwrite existing license information in the
* map for dependencies with the same id. If the config file does not exist, the method does nothing.
*
* @param configuredDepLicensesMap A map between the dependencyId and the license info
* @param licenseConfigFile The license configuration file to load
* @param previouslyDownloaded Whether these licenses were already downloaded
* @throws MojoExecutionException if could not load license infos
*/
private void loadLicenseInfo( Map configuredDepLicensesMap, File licenseConfigFile,
boolean previouslyDownloaded )
throws MojoExecutionException
{
FileInputStream fis = null;
try
{
fis = new FileInputStream( licenseConfigFile );
List licensesList = LicenseSummaryReader.parseLicenseSummary( fis );
for ( ProjectLicenseInfo dep : licensesList )
{
configuredDepLicensesMap.put( dep.getId(), dep );
if ( previouslyDownloaded )
{
for ( License license : dep.getLicenses() )
{
// Save the URL so we don't download it again
downloadedLicenseURLs.add( license.getUrl() );
}
}
}
}
catch ( Exception e )
{
throw new MojoExecutionException( "Unable to parse license summary output file: " + licenseConfigFile, e );
}
finally
{
FileUtil.tryClose( fis );
}
}
/**
* Returns the project ID for the artifact
*
* @param artifact the artifact
* @return groupId:artifactId
*/
private String getArtifactProjectId( Artifact artifact )
{
return artifact.getGroupId() + ":" + artifact.getArtifactId();
}
/**
* Create a simple DependencyProject object containing the GAV and license info from the Maven Artifact
*
* @param depMavenProject the dependency maven project
* @return DependencyProject with artifact and license info
*/
private ProjectLicenseInfo createDependencyProject( MavenProject depMavenProject )
{
ProjectLicenseInfo dependencyProject =
new ProjectLicenseInfo( depMavenProject.getGroupId(), depMavenProject.getArtifactId(),
depMavenProject.getVersion() );
List> licenses = depMavenProject.getLicenses();
for ( Object license : licenses )
{
dependencyProject.addLicense( (License) license );
}
return dependencyProject;
}
/**
* Determine filename to use for downloaded license file. The file name is based on the configured name of the
* license (if available) and the remote filename of the license.
*
* @param depProject the project containing the license
* @param license the license
* @return A filename to be used for the downloaded license file
* @throws MalformedURLException if the license url is malformed
*/
private String getLicenseFileName( ProjectLicenseInfo depProject, License license )
throws MalformedURLException
{
String defaultExtension = ".txt";
URL licenseUrl = new URL( license.getUrl() );
File licenseUrlFile = new File( licenseUrl.getPath() );
String licenseFileName;
if ( organizeLicensesByDependencies )
{
licenseFileName = String.format( "%s.%s%s", depProject.getGroupId(), depProject.getArtifactId(),
license.getName() != null
? "_" + license.getName()
: "" ).toLowerCase().replaceAll( "\\s+", "_" );
}
else
{
licenseFileName = licenseUrlFile.getName();
if ( license.getName() != null )
{
licenseFileName = license.getName() + " - " + licenseUrlFile.getName();
}
// Check if the file has a valid file extention
int extensionIndex = licenseFileName.lastIndexOf( "." );
if ( extensionIndex == -1 || extensionIndex > ( licenseFileName.length() - 3 ) )
{
// This means it isn't a valid file extension, so append the default
licenseFileName = licenseFileName + defaultExtension;
}
// Force lower case so we don't end up with multiple copies of the same license
licenseFileName = licenseFileName.toLowerCase();
}
return licenseFileName;
}
/**
* Download the licenses associated with this project
*
* @param depProject The project which generated the dependency
*/
private void downloadLicenses( ProjectLicenseInfo depProject )
{
getLog().debug( "Downloading license(s) for project " + depProject );
List licenses = depProject.getLicenses();
if ( depProject.getLicenses() == null || depProject.getLicenses().isEmpty() )
{
if ( !quiet )
{
getLog().warn( "No license information available for: " + depProject );
}
return;
}
for ( License license : licenses )
{
try
{
String licenseFileName = getLicenseFileName( depProject, license );
File licenseOutputFile = new File( licensesOutputDirectory, licenseFileName );
if ( licenseOutputFile.exists() )
{
continue;
}
String licenseUrl = license.getUrl();
if ( !downloadedLicenseURLs.contains( licenseUrl ) || organizeLicensesByDependencies )
{
LicenseDownloader.downloadLicense( licenseUrl, proxyLoginPasswordEncoded, licenseOutputFile );
downloadedLicenseURLs.add( licenseUrl );
}
}
catch ( MalformedURLException e )
{
if ( !quiet )
{
getLog().warn( "POM for dependency " + depProject.toString() + " has an invalid license URL: " +
license.getUrl() );
}
}
catch ( FileNotFoundException e )
{
if ( !quiet )
{
getLog().warn( "POM for dependency " + depProject.toString() +
" has a license URL that returns file not found: " + license.getUrl() );
}
}
catch ( IOException e )
{
getLog().warn( "Unable to retrieve license for dependency: " + depProject.toString() );
getLog().warn( license.getUrl() );
getLog().warn( e.getMessage() );
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy