com.google.code.mojo.license.AbstractLicenseMojo Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of maven-license-plugin Show documentation
Show all versions of maven-license-plugin Show documentation
Maven 2 plugin to check and update license headers in source files
/**
* Copyright (C) 2008 http://code.google.com/p/maven-license-plugin/
*
* 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.google.code.mojo.license;
import com.google.code.mojo.license.document.Document;
import com.google.code.mojo.license.document.DocumentFactory;
import com.google.code.mojo.license.document.DocumentType;
import com.google.code.mojo.license.header.AdditionalHeaderDefinition;
import com.google.code.mojo.license.header.Header;
import com.google.code.mojo.license.header.HeaderDefinition;
import com.google.code.mojo.license.header.HeaderType;
import com.google.code.mojo.license.util.Selection;
import com.google.code.mojo.license.util.resource.ResourceFinder;
import com.mycila.xmltool.XMLDoc;
import org.apache.maven.artifact.DependencyResolutionRequiredException;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.project.MavenProject;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import static com.google.code.mojo.license.document.DocumentType.*;
import static java.lang.String.*;
import static java.util.Arrays.*;
/**
* Date: 18-Feb-2008
Author: Mathieu Carbou ([email protected])
*/
public abstract class AbstractLicenseMojo extends AbstractMojo {
/**
* The base directory, in which to search for files.
*
* @parameter expression="${license.basedir}" default-value="${basedir}"
* @required
*/
protected File basedir;
/**
* The text document containing the license header to check or use for reformatting
*
* @parameter expression="${license.header}"
*/
protected String header;
/**
* Specifies additional header files to use when checking for the presence of a valid header in your sources.
*
* When using format goal, this property will be used to detect all valid headers that don't need formatting.
*
* When using remove goal, this property will be used to detect all valid headers that also must be removed.
*
* @parameter
*/
protected String[] validHeaders = new String[0];
/**
* Allows the use of external header definitions files. These files are properties like.
*
* @parameter
*/
protected String[] headerDefinitions = new String[0];
/**
* The properties to use when reading the header, to replace tokens
*
* @parameter
*/
protected Map properties = new HashMap();
/**
* Specifies files, which are included in the check. By default, all files are included.
*
* @parameter
*/
protected String[] includes = new String[0];
/**
* Specifies files, which are excluded in the check. By default, no files are excluded.
*
* @parameter
*/
protected String[] excludes = new String[0];
/**
* Specify the list of keywords to use to detect a header. A header must include all keywords to be valid.
* By default, the word 'copyright' is used. Detection is done case insensitive.
*
* @parameter
*/
protected String[] keywords = new String[]{"copyright"};
/**
* Whether to use the default excludes when scanning for files.
*
* @parameter expression="${license.useDefaultExcludes}" default-value="true"
*/
protected boolean useDefaultExcludes = true;
/**
* Wheter to treat multi-modules projects as only one project (true) or treat multi-module projects separately
* (false, by default)
*
* @parameter expression="${license.aggregate}" default-value="false"
*/
protected boolean aggregate = false;
/**
* Set mapping between document mapping and a supported type to use
*
* @parameter
*/
protected Map mapping = new HashMap();
/**
* Whether to use the default mapping between fiel extensions and comments to use, or only the one your provide
*
* @parameter expression="${license.useDefaultMapping}" default-value="true"
*/
protected boolean useDefaultMapping = true;
/**
* Maven license plugin uses concurrency to check license headers. This factor is used to control the number
* of threads used to check. The rule is:
*
* {@code = * concurrencyFactor}
*
* The default is 1.5.
*
* @parameter expression="${license.concurrencyFactor}" default-value="1.5"
*/
protected float concurrencyFactor = 1.5f;
/**
* Whether to skip the plugin execution
*
* @parameter expression="${license.skip}" default-value="false"
*/
protected boolean skip = false;
/**
* Set this to "true" to cause no output
*
* @parameter expression="${license.quiet}" default-value="false"
*/
protected boolean quiet = false;
/**
* Set to true if you need a strict check against the headers. By default, the existence of
* a header is verified by taking the top portion of a file and checking if it contains the
* headers text, not considering special characters (spaces, tabs, ...)
*
* We highly recommend to set this option to true. It is by default set to false for
* backward compatibility
*
* @parameter expression="${license.strictCheck}" default-value="false"
*/
protected boolean strictCheck = false;
/**
* Set the charcter encoding for files
*
* @parameter expression="${license.encoding}" default-value="${file.encoding}"
*/
protected String encoding = System.getProperty("file.encoding");
/**
* @parameter default-value="${project}"
* @required
* @readonly
*/
protected MavenProject project = new MavenProject();
private ResourceFinder finder;
@SuppressWarnings({"unchecked"})
protected final void execute(final Callback callback) throws MojoExecutionException, MojoFailureException {
if (!skip) {
if (header == null) {
warn("No header file specified to check for license");
return;
}
if (!strictCheck) {
warn("Property 'strictChecking' is not enabled. Please consider adding true in your pom.xml file.");
warn("See http://code.google.com/p/maven-license-plugin/wiki/Configuration for more information.");
}
finder = new ResourceFinder(basedir);
try {
finder.setCompileClassPath(project.getCompileClasspathElements());
} catch (DependencyResolutionRequiredException e) {
throw new MojoExecutionException(e.getMessage(), e);
}
finder.setPluginClassPath(getClass().getClassLoader());
final Header h = new Header(finder.findResource(this.header), mergeProperties());
debug("Header %s:\n%s", h.getLocation(), h);
if (this.validHeaders == null) this.validHeaders = new String[0];
final List validHeaders = new ArrayList(this.validHeaders.length);
for (String validHeader : this.validHeaders)
validHeaders.add(new Header(finder.findResource(validHeader), mergeProperties()));
final DocumentFactory documentFactory = new DocumentFactory(basedir, buildMapping(), buildHeaderDefinitions(), encoding, keywords);
int nThreads = (int) (Runtime.getRuntime().availableProcessors() * concurrencyFactor);
ExecutorService executorService = Executors.newFixedThreadPool(nThreads);
CompletionService completionService = new ExecutorCompletionService(executorService);
int count = 0;
debug("Number of execution threads: %s", nThreads);
try {
for (final String file : listSelectedFiles()) {
completionService.submit(new Runnable() {
public void run() {
Document document = documentFactory.createDocuments(file);
debug("Selected file: %s [header style: %s]", document.getFile(), document.getHeaderDefinition());
if (document.isNotSupported()) {
warn("Unknown file extension: %s", document.getFile());
} else if (document.is(h)) {
debug("Skipping header file: %s", document.getFile());
} else if (document.hasHeader(h, strictCheck)) {
callback.onExistingHeader(document, h);
} else {
boolean headerFound = false;
for (Header validHeader : validHeaders) {
if (headerFound = document.hasHeader(validHeader, strictCheck)) {
callback.onExistingHeader(document, h);
break;
}
}
if (!headerFound)
callback.onHeaderNotFound(document, h);
}
}
}, null);
count++;
}
while (count-- > 0) {
try {
completionService.take().get();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (ExecutionException e) {
Throwable cause = e.getCause();
if (cause instanceof Error)
throw (Error) cause;
if (cause instanceof MojoExecutionException)
throw (MojoExecutionException) cause;
if (cause instanceof MojoFailureException)
throw (MojoFailureException) cause;
if (cause instanceof RuntimeException)
throw (RuntimeException) cause;
throw new RuntimeException(cause.getMessage(), cause);
}
}
} finally {
executorService.shutdownNow();
}
}
}
protected final Map mergeProperties() {
// first put systen environment
Map props = new HashMap(System.getenv());
// we override by properties in the POM
if (this.properties != null) {
props.putAll(this.properties);
}
// then we override by java system properties (command-line -D...)
for (Map.Entry