![JAR search and dependency download from the Maven repository](/logo.png)
com.puresoltechnologies.maven.plugins.license.ValidatorMojo 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
This is a license checker plugin for Maven.
/*
* Copyright 2013 PureSol Technologies
*
* Licensed 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.
*/
package com.puresoltechnologies.maven.plugins.license;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import java.util.regex.Pattern;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.model.License;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.plugins.annotations.Execute;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
import com.puresoltechnologies.maven.plugins.license.internal.ArtifactUtilities;
import com.puresoltechnologies.maven.plugins.license.internal.DependencyTree;
import com.puresoltechnologies.maven.plugins.license.internal.IOUtilities;
import com.puresoltechnologies.maven.plugins.license.parameter.ArtifactInformation;
import com.puresoltechnologies.maven.plugins.license.parameter.KnownLicense;
import com.puresoltechnologies.maven.plugins.license.parameter.ValidationResult;
/**
* This class is a Maven Mojo to check the validity of licenses specified in the
* dependencies of a maven module.
*
* Used to configure injection of Plexus components by
* MavenPluginManager.getConfiguredMojo(...) and special Maven objects as well:
*
* mojoExecution org.apache.maven.plugin.MojoExecution project
* org.apache.maven.project.MavenProject session
* org.apache.maven.execution.MavenSession settings
* org.apache.maven.settings.Settings plugin (Maven-3 only)
* org.apache.maven.plugin.descriptor.PluginDescriptor
*
* @author Rick-Rainer Ludwig
*/
@Mojo(//
name = "validate", //
requiresDirectInvocation = false, //
requiresProject = true, //
requiresReports = false, //
requiresOnline = false, //
inheritByDefault = true, //
threadSafe = true,//
requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME,//
requiresDependencyCollection = ResolutionScope.COMPILE_PLUS_RUNTIME//
)
@Execute(//
goal = "validate",//
phase = LifecyclePhase.VALIDATE//
)
public class ValidatorMojo extends AbstractValidationMojo {
private static final String TEST_SCOPE_NAME = "test";
@Parameter(alias = "knownLicenses", required = true)
private Set knownLicenses;
@Parameter(alias = "outputDirectory", required = false, defaultValue = "${project.build.directory}/licenses")
private File outputDirectory;
/**
* This parameter contains whether this Mojo shall fail fast (with first
* occurrence of an invalid license) or should do all the work first before
* failing. Default value is false.
*/
@Parameter(alias = "failFast", required = false, defaultValue = "false")
private boolean failFast;
/**
* This parameter contains whether or not the dependency should be checked
* recursively or not. Default is true.
*/
@Parameter(alias = "recursive", required = false, defaultValue = "true")
private boolean recursive;
/**
* Specifies whether or not the dependencies in test scope should be
* skipped. Default is false.
*/
@Parameter(alias = "skipTestScope", required = false, defaultValue = "true")
private boolean skipTestScope;
/**
* Specifies whether or not the dependencies in provided scope should be
* skipped. Default is false.
*/
@Parameter(alias = "skipProvidedScope", required = false, defaultValue = "true")
private boolean skipProvidedScope;
/**
* Specified whether or not to skip archetypes with optional flag.
*/
@Parameter(alias = "skipOptionals", required = false, defaultValue = "true")
private boolean skipOptionals;
/**
* This field contains the writer for the validation result file.
*/
private OutputStreamWriter writer;
@Override
public void execute() throws MojoExecutionException, MojoFailureException {
storeSettings();
DependencyTree dependencyTree = loadArtifacts(recursive, skipTestScope,
skipProvidedScope, skipOptionals);
validateArtifacts(dependencyTree);
}
private void storeSettings() throws MojoExecutionException {
File file = IOUtilities
.createNewSettingsFile(getLog(), outputDirectory);
try (FileOutputStream fileOutputStream = new FileOutputStream(file);
OutputStreamWriter propertiesWriter = new OutputStreamWriter(
fileOutputStream, Charset.defaultCharset())) {
Properties properties = new Properties();
properties.setProperty("recursive", Boolean.toString(recursive));
properties.setProperty("skipTestScope",
Boolean.toString(skipTestScope));
properties.setProperty("skipProvidedScope",
Boolean.toString(skipProvidedScope));
properties.setProperty("skipOptionals",
Boolean.toString(skipOptionals));
properties
.store(propertiesWriter, "license-maven-plugin settings.");
} catch (IOException e) {
throw new MojoExecutionException(
"Could not write settings.properties.", e);
}
}
/**
* This method checks a set of artifacts for validity.
*
* @param dependencies
* is a {@link Set} of {@link Artifact} which is to be checked
* for validity.
* @throws MojoExecutionException
* is throw if the execution was faulty.
* @throws MojoFailureException
* is thrown if an invalid license is found.
*/
private void validateArtifacts(DependencyTree dependencyTree)
throws MojoExecutionException, MojoFailureException {
File licenseResultsFile = IOUtilities.createNewResultsFile(getLog(),
outputDirectory);
try (FileOutputStream outputStream = new FileOutputStream(
licenseResultsFile)) {
writer = new OutputStreamWriter(outputStream,
Charset.defaultCharset());
try {
boolean valid = true;
List checkedArtifact = new ArrayList<>();
for (DependencyTree dependency : dependencyTree) {
Artifact artifact = dependency.getArtifact();
if (artifact == getMavenProject().getArtifact()) {
// skip self, it is not needed to be evaluated
continue;
}
String artifactIdentifier = ArtifactUtilities
.toString(artifact);
if (checkedArtifact.contains(artifactIdentifier)) {
continue;
}
checkedArtifact.add(artifactIdentifier);
if (!isArtifactValid(dependency)) {
if (failFast) {
throw new MojoFailureException(
"Invalid license(s) was/were found!");
}
valid = false;
}
}
if (!valid) {
throw new MojoFailureException(
"Invalid license(s) was/were found!");
}
} finally {
try {
writer.close();
} finally {
writer = null;
}
}
} catch (IOException e) {
throw new MojoExecutionException(
"Could not write validation result to '"
+ licenseResultsFile + "'.", e);
}
}
/**
* This method checks the validity of a single artifact.
*
* @param artifact
* is the {@link Artifact} to be checked for validity.
* @return true
is returned if the license is valid.
* false
is returned otherwise.
* @throws MojoFailureException
* is thrown if {@link #failFast} is set to true
* and the license is invalid to enforce the fail fast behavior
* requested.
* @throws MojoExecutionException
* is thrown in case of a faulty Maven run.
*/
private boolean isArtifactValid(DependencyTree dependency)
throws MojoFailureException, MojoExecutionException {
Artifact artifact = dependency.getArtifact();
ArtifactInformation artifactInformation = new ArtifactInformation(
artifact);
if (skipTestScope) {
if (TEST_SCOPE_NAME.equals(artifact.getScope())) {
ValidationResult result = new ValidationResult(
artifactInformation, null, null, null, "test scope",
true);
logArtifactResult(result);
return true;
}
}
List licenses = dependency.getLicenses();
if (licenses.size() == 0) {
KnownLicense knownLicense = findKnownLicense(artifactInformation);
if (knownLicense != null) {
ValidationResult result = new ValidationResult(
artifactInformation, knownLicense, null, null,
"no license found, but dependency is approved", true);
logArtifactResult(result);
return true;
} else {
ValidationResult result = new ValidationResult(
artifactInformation, null, null, null,
"no license found and artifact is not approved", false);
logArtifactResult(result);
return false;
}
}
boolean valid = true;
for (License license : licenses) {
String licenseName = license.getName();
URL licenseURL;
try {
licenseURL = new URL(license.getUrl());
} catch (MalformedURLException e) {
licenseURL = null;
}
KnownLicense knownLicense = findKnownLicense(artifactInformation);
if (knownLicense != null) {
ValidationResult result = new ValidationResult(
artifactInformation, knownLicense, licenseName,
licenseURL, "license is approved by artifact", true);
logArtifactResult(result);
} else {
knownLicense = findKnownLicense(artifactInformation, license);
if (knownLicense != null) {
ValidationResult result = new ValidationResult(
artifactInformation, knownLicense, licenseName,
licenseURL, "license is approved", true);
logArtifactResult(result);
} else {
ValidationResult result = new ValidationResult(
artifactInformation, null, licenseName, licenseURL,
"license is not approved", false);
logArtifactResult(result);
valid = false;
}
}
}
return valid;
}
/**
* This method returns the normalized name of the license.
*
* @param artifactInformation
*
* @param license
* is the {@link License} object which is to be looked up.
* @return A {@link KnownLicense} is returned containing the known license.
* @throws MojoFailureException
* is thrown if the normalized name cannot be looked up due to
* missing configuration.
*/
private KnownLicense findKnownLicense(
ArtifactInformation artifactInformation, License license)
throws MojoFailureException {
for (KnownLicense knownLicense : knownLicenses) {
if (knownLicense.getName().equals(license.getName())) {
return knownLicense;
}
for (String alias : knownLicense.getAliases()) {
if ((alias == null) || (alias.isEmpty())) {
throw new MojoFailureException(
"An alias was found without identifier.");
}
if (alias.equals(license.getName())) {
return knownLicense;
}
}
}
return null;
}
private KnownLicense findKnownLicense(
ArtifactInformation artifactInformation)
throws MojoFailureException {
for (KnownLicense knownLicense : knownLicenses) {
for (String approvedDependency : knownLicense
.getApprovedDependencies()) {
if ((approvedDependency == null)
|| (approvedDependency.isEmpty())) {
throw new MojoFailureException(
"An approved dependency was found without identifier.");
}
if (Pattern.matches(approvedDependency,
artifactInformation.getIdentifier())) {
return knownLicense;
}
}
}
return null;
}
/**
* This method is used to log results with Maven log {@link Log}.
*
* @param artifact
* is the {@link Artifact} which was checked for validity.
* @param validationResult
* is the {@link ValidationResult} of the check.
* @param licenseOrApprovalMessage
* is the message to be printed containing the license or the
* appoval message.
* @param knownLicense
* @throws MojoExecutionException
* @throws IOException
* @throws MojoFailureException
*/
private void logArtifactResult(ValidationResult validationResult)
throws MojoExecutionException, MojoFailureException {
StringBuffer buffer = new StringBuffer();
buffer.append("License ");
String originalLicenseName = validationResult.getOriginalLicenseName();
if (originalLicenseName != null) {
buffer.append("'");
buffer.append(originalLicenseName);
buffer.append("' ");
URL originalLicenseURL = validationResult.getOriginalLicenseURL();
if (originalLicenseURL != null) {
buffer.append("(");
buffer.append(originalLicenseURL.toString());
buffer.append(") ");
}
}
buffer.append("checked for artifact '");
ArtifactInformation artifactInformation = validationResult
.getArtifactInformation();
buffer.append(artifactInformation.getIdentifier());
buffer.append("': \n >> ");
if (validationResult.isValid()) {
buffer.append("valid as '");
KnownLicense license = validationResult.getLicense();
buffer.append(license.getName());
buffer.append("' (");
buffer.append(validationResult.getComment());
buffer.append(")");
getLog().info(buffer.toString());
} else {
buffer.append("invalid (");
buffer.append(validationResult.getComment());
buffer.append(")");
getLog().error(buffer.toString());
}
IOUtilities.writeResult(writer, validationResult);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy