org.codehaus.mojo.license.AbstractAddThirdPartyMojo Maven / Gradle / Ivy
package org.codehaus.mojo.license;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
import org.apache.maven.artifact.resolver.ArtifactResolutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.ProjectBuildingException;
import org.codehaus.mojo.license.api.*;
import org.codehaus.mojo.license.model.Dependency;
import org.codehaus.mojo.license.model.LicenseMap;
import org.codehaus.mojo.license.utils.FileUtil;
import org.codehaus.mojo.license.utils.LicenseRegistryClient;
import org.codehaus.mojo.license.utils.MojoHelper;
import org.codehaus.mojo.license.utils.SortedProperties;
import org.codehaus.mojo.license.utils.StringToList;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;
/*
* #%L
* License Maven Plugin
* %%
* Copyright (C) 2008 - 2011 CodeLutin, Codehaus, Tony Chemit
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* .
* #L%
*/
/**
* Abstract mojo for all third-party mojos.
*
* @author tchemit [email protected]
* @since 1.0
*/
public abstract class AbstractAddThirdPartyMojo
extends AbstractLicenseMojo
{
protected static final String DEP_SEPARATOR = "--";
// ----------------------------------------------------------------------
// Mojo Parameters
// ----------------------------------------------------------------------
/**
* Directory where to generate files.
*
* @since 1.0
*/
@Parameter( property = "license.outputDirectory",
defaultValue = "${project.build.directory}/generated-resources/licenses", required = true )
private File outputDirectory;
/**
* Attach the 'missing' file as an additional artifact so that it is deployed in the deploy phase.
*
* @since 1.0
*/
@Parameter( property = "license.deployMissingFile", defaultValue = "true" )
boolean deployMissingFile;
/**
* Load files supplying information for missing third party licenses from repositories.
* The plugin looks for Maven artifacts with coordinates of the form G:A:V:properties:third-party, where
* the group, artifact, and version are those for dependencies of your project,
* while the type is 'properties' and the classifier is 'third-party'.
*
* @since 1.0
*/
@Parameter( property = "license.useRepositoryMissingFiles", defaultValue = "true" )
boolean useRepositoryMissingFiles;
/**
* To execute or not this mojo if project packaging is pom.
*
* Note: The default value is {@code false}.
*
* @since 1.1
*/
@Parameter( property = "license.acceptPomPackaging", defaultValue = "false" )
boolean acceptPomPackaging;
/**
* A filter to exclude some scopes.
*
* @since 1.1
*/
@Parameter( property = "license.excludedScopes", defaultValue = "system" )
String excludedScopes;
/**
* A filter to include only some scopes, if let empty then all scopes will be used (no filter).
*
* @since 1.1
*/
@Parameter( property = "license.includedScopes")
String includedScopes;
/**
* A filter to exclude some GroupIds
* This is a regular expression that is applied to groupIds (not an ant pattern).
*
* @since 1.1
*/
@Parameter( property = "license.excludedGroups")
String excludedGroups;
/**
* A filter to include only some GroupIds
* This is a regular expression applied to artifactIds.
*
* @since 1.1
*/
@Parameter( property = "license.includedGroups")
String includedGroups;
/**
* A filter to exclude some ArtifactsIds
* This is a regular expression applied to artifactIds.
*
* @since 1.1
*/
@Parameter( property = "license.excludedArtifacts")
String excludedArtifacts;
/**
* A filter to include only some ArtifactsIds
* This is a regular expression applied to artifactIds.
*
* @since 1.1
*/
@Parameter( property = "license.includedArtifacts")
String includedArtifacts;
/**
* Include transitive dependencies when checking for missing licenses and downloading license files.
* If this is false, then only direct dependencies are examined.
*
* @since 1.1
*/
@Parameter( property = "license.includeTransitiveDependencies", defaultValue = "true" )
boolean includeTransitiveDependencies;
/**
* Exclude transitive dependencies from excluded Artifacts
*
* @since 1.13
*/
@Parameter( property = "license.excludeTransitiveDependencies", defaultValue = "false" )
boolean excludeTransitiveDependencies;
/**
* File where to write the third-party file.
*
* @since 1.0
*/
@Parameter( property = "license.thirdPartyFilename", defaultValue = "THIRD-PARTY.txt", required = true )
String thirdPartyFilename;
@Parameter( property = "license.thirdPartyDepsFilename", defaultValue = "THIRD-PARTY-DEPS", required = true )
String thirdPartyDepsJsonFilename;
/**
* A flag to use the missing licenses file to consolidate the THID-PARTY file.
*
* @since 1.0
*/
@Parameter( property = "license.useMissingFile", defaultValue = "false" )
boolean useMissingFile;
/**
* The file to write with a license information template for dependencies with unknown license.
*
* @since 1.0
*/
@Parameter( property = "license.missingFile", defaultValue = "src/license/THIRD-PARTY.properties" )
File missingFile;
/**
* To resolve third party licenses from an artifact.
*
* @since 1.14
*/
@Parameter( property = "license.missingLicensesFileArtifact" )
String missingLicensesFileArtifact;
/**
* The file to write with a license information template for dependencies to override.
*
* @since 1.12
*/
@Parameter( property = "license.overrideFile", defaultValue = "src/license/override-THIRD-PARTY.properties" )
File overrideFile;
/**
* To merge licenses in final file.
*
* Each entry represents a merge (first license is main license to keep), licenses are separated by {@code |}.
*
* Example :
*
*
* <licenseMerges>
* <licenseMerge>The Apache Software License|Version 2.0,Apache License, Version 2.0</licenseMerge>
* </licenseMerges>
* </pre>
*
* @since 1.0
*/
@Parameter
List licenseMerges;
/**
* To specify some licenses to include.
*
* If this parameter is filled and a license is not in this {@code whitelist} then build will failed when property
* {@link #failIfWarning} is true.
*
* Since version {@code 1.4}, there is two ways to fill this parameter :
*
* - A simple string (separated by {@code |}), the way to use by property configuration:
*
<includedLicenses>licenseA|licenseB</includedLicenses>
or
* -Dlicense.includedLicenses=licenseA|licenseB
*
* - A list of string (can only be used in plugin configuration, not via property configuration)
*
* <includedLicenses>
* <includedLicense>licenseA</includedLicense>
* <includedLicenses>licenseB</includedLicense>
* </includedLicenses>
*
*
*
* @since 1.1
*/
@Parameter( property = "license.includedLicenses")
IncludedLicenses includedLicenses;
@Parameter( property = "license.hiddenLicenses")
HiddenLicenses hiddenLicenses;
Map> includedDependencies = new HashMap<>();
Set listedDependencies;
/**
* To specify some licenses to exclude.
*
* If a such license is found then build will failed when property
* {@link #failIfWarning} is true.
*
* Since version {@code 1.4}, there is two ways to fill this parameter :
*
* - A simple string (separated by {@code |}), the way to use by property configuration:
*
<excludedLicenses>licenseA|licenseB</excludedLicenses>
or
* -Dlicense.excludedLicenses=licenseA|licenseB
*
* - A list of string (can only be used in plugin configuration, not via property configuration)
*
* <excludedLicenses>
* <excludedLicense>licenseA</excludedLicense>
* <excludedLicense>licenseB</excludedLicense>
* </excludedLicenses>
*
*
*
* @since 1.1
*/
@Parameter( property = "license.excludedLicenses")
ExcludedLicenses excludedLicenses;
/**
* The path of the bundled third party file to produce when
* {@link #generateBundle} is on.
*
* Note: This option is not available for {@code pom} module types.
*
* @since 1.0
*/
@Parameter( property = "license.bundleThirdPartyPath",
defaultValue = "META-INF/${project.artifactId}-THIRD-PARTY.txt" )
String bundleThirdPartyPath;
/**
* A flag to copy a bundled version of the third-party file. This is useful
* to avoid for a final application collision name of third party file.
*
* The file will be copied at the {@link #bundleThirdPartyPath} location.
*
* @since 1.0
*/
@Parameter( property = "license.generateBundle", defaultValue = "false" )
boolean generateBundle;
/**
* To force generation of the third-party file even if everything is up to date.
*
* @since 1.0
*/
@Parameter( property = "license.force", defaultValue = "false" )
boolean force;
/**
* A flag to fail the build if at least one dependency was detected without a license.
*
* @since 1.0
* @deprecated since 1.14, use now {@link #failOnMissing} or {@link #failOnBlacklist}.
*/
@Deprecated
@Parameter( property = "license.failIfWarning", defaultValue = "false" )
boolean failIfWarning;
/**
* A flag to fail the build if at least one dependency was detected without a license.
*
* @since 1.14
*/
@Parameter( property = "license.failOnMissing", defaultValue = "false" )
boolean failOnMissing;
/**
* A flag to fail the build if at least one dependency was blacklisted.
*
* @since 1.14
*/
@Parameter( property = "license.failOnBlacklist", defaultValue = "false" )
boolean failOnBlacklist;
@Parameter(property = "license.failOnNotWhitelistedDependency", defaultValue = "false")
boolean failOnNotWhitelistedDependency;
/**
* A flag to sort artifact by name in the generated third-party file.
*
* If not then artifacts are sorted by
groupId:artifactId:version
*
* @since 1.6
*/
@Parameter( property = "license.sortArtifactByName", defaultValue = "false" )
boolean sortArtifactByName;
@Parameter(property = "license.includedDependenciesWhitelist")
private String includedDependenciesWhitelist;
/**
* Template used to build the third-party file.
*
* (This template uses freemarker).
*
* Note: This property can either point to a file or a resource on
* the classpath. In case it points to a file and this plugin is used within
* a sub-module as part of a multi-module build, you need to make this path
* resolvable, e.g. by prepending {@code basedir}.
*
* @since 1.1
*/
@Parameter( property = "license.fileTemplate", defaultValue = "/org/codehaus/mojo/license/third-party-file.ftl" )
String fileTemplate;
/**
* Local Repository.
*
* @since 1.0.0
*/
@Parameter( property = "localRepository", required = true, readonly = true )
ArtifactRepository localRepository;
/**
* Remote repositories used for the project.
*
* @since 1.0.0
*/
@Parameter( property = "project.remoteArtifactRepositories", required = true, readonly = true )
List remoteRepositories;
/**
* The set of dependencies for the current project, used to locate license databases.
*/
@Parameter( property = "project.artifacts", required = true, readonly = true )
Set dependencies;
// ----------------------------------------------------------------------
// Plexus components
// ----------------------------------------------------------------------
/**
* Third party tool (much of the logic of these mojos is implemented here).
*
* @since 1.0
*/
@Component
private ThirdPartyTool thirdPartyTool;
/**
* Dependencies tool. (pluggable component to find dependencies that match up with
* criteria).
*
* @since 1.1
*/
@Component
DependenciesTool dependenciesTool;
// ----------------------------------------------------------------------
// Private fields
// ----------------------------------------------------------------------
/**
* Third-party helper (high level tool with common code for mojo and report).
*/
private ThirdPartyHelper helper;
private SortedMap projectDependencies;
LicenseMap licenseMap;
SortedSet unsafeDependencies;
private File thirdPartyFile;
SortedProperties unsafeMappings;
/**
* Flag computed in the {@link #init()} method to know if there is something has to be generated.
*/
private boolean doGenerate;
/**
* Flag computed in the {@link #init()} method to know if a bundle version has to be generated.
*/
private boolean doGenerateBundle;
/**
* Map from G/A/V as string to license key, obtained from global dependencies of type=.ld.properties.
* This could probably be refactored to have more in common with the classifier-based loader.
*
* @since 1.4
*/
private Map globalKnownLicenses;
// ----------------------------------------------------------------------
// Abstract Methods
// ----------------------------------------------------------------------
/**
* Loads the dependencies of the project (as {@link MavenProject}, indexed by their gav.
*
* @return the map of dependencies of the maven project indexed by their gav.
*/
protected abstract SortedMap loadDependencies();
/**
* Creates the unsafe mapping (says dependencies with no license given by their pom).
*
* Can come from loaded missing file or from dependencies with no license at all.
*
* @return the map of usafe mapping indexed by their gav.
* @throws ProjectBuildingException if could not create maven porject for some dependencies
* @throws IOException if could not load missing file
* @throws ThirdPartyToolException for third party tool error
*/
protected abstract SortedProperties createUnsafeMapping()
throws ProjectBuildingException, IOException, ThirdPartyToolException;
// ----------------------------------------------------------------------
// AbstractLicenseMojo Implementaton
// ----------------------------------------------------------------------
/**
* {@inheritDoc}
*/
@Override
protected void init()
throws Exception
{
Log log = getLog();
if ( log.isDebugEnabled() )
{
// always be verbose in debug mode
setVerbose( true );
}
getLog().info("Loading WHITE licenses: licenses-whitelist.txt");
final LicenseRegistryClient licenseRegistryClient = LicenseRegistryClient.getInstance();
this.includedLicenses = new IncludedLicenses(licenseRegistryClient.getFileContent("licenses-whitelist.txt"));
getLog().info("Loading HIDDEN licenses: licenses-hidden.txt");
this.hiddenLicenses = new HiddenLicenses(licenseRegistryClient.getFileContent("licenses-hidden.txt"));
if (StringUtils.isNotBlank(includedDependenciesWhitelist)) {
getLog().info(String.format("Loading Dependencies Whitelist: %s", includedDependenciesWhitelist));
includedDependencies.putAll(new ObjectMapper().readValue(licenseRegistryClient.getFileContent(includedDependenciesWhitelist), new TypeReference