All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.codehaus.mojo.license.AbstractAddThirdPartyMojo Maven / Gradle / Ivy

There is a newer version: 1.6.3
Show newest version
/**
 * Copyright 2010-2012 The Kuali Foundation
 *
 * Licensed under the Educational Community 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.opensource.org/licenses/ecl2.php
 *
 * 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 org.codehaus.mojo.license;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.ProjectBuildingException;
import org.codehaus.mojo.license.model.LicenseMap;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;

/**
 * Abstract mojo for all third-party mojos.
 *
 * @author tchemit 
 * @since 1.0
 */
public abstract class AbstractAddThirdPartyMojo extends AbstractLicenseMojo {

    /**
     * Directory where to generate files.
     *
     * @parameter expression="${license.outputDirectory}"
     *            default-value="${project.build.directory}/generated-sources/license"
     * @required
     * @since 1.0
     */
    protected File outputDirectory;

    /**
     * File where to wirte the third-party file.
     *
     * @parameter expression="${license.thirdPartyFilename}" default-value="THIRD-PARTY.txt"
     * @required
     * @since 1.0
     */
    protected String thirdPartyFilename;

    /**
     * A flag to use the missing licenses file to consolidate the THID-PARTY file.
     *
     * @parameter expression="${license.useMissingFile}" default-value="false"
     * @since 1.0
     */
    protected boolean useMissingFile;

    /**
     * The file where to fill the license for dependencies with unknown license.
     *
     * @parameter expression="${license.missingFile}" default-value="src/license/THIRD-PARTY.properties"
     * @since 1.0
     */
    protected File missingFile;

    /**
     * Location of a properties file mapping artifacts that are published with no license to the license that should be
     * used for them. This supports classpath notation and any other type of URL Spring 3.1 resource loading can
     * understand.
     *
     * @parameter expression="${license.artifactLicenseMapping}" default-value="THIRD-PARTY.properties"
     * @since 1.0
     */
    protected String artifactLicenseMapping;

    /**
     * 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>
     *
     * @parameter
     * @since 1.0
     */
    protected List licenseMerges;

    /**
     * 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. * * @parameter expression="${license.bundleThirdPartyPath}" * default-value="META-INF/${project.artifactId}-THIRD-PARTY.txt" * @since 1.0 */ protected String bundleThirdPartyPath; /** * A flag to copy a bundled version of the third-party file. This is usefull to avoid for a final application * collision name of third party file. *

* The file will be copied at the {@link #bundleThirdPartyPath} location. * * @parameter expression="${license.generateBundle}" default-value="false" * @since 1.0 */ protected boolean generateBundle; /** * To force generation of the third-party file even if every thing is up to date. * * @parameter expression="${license.force}" default-value="false" * @since 1.0 */ protected boolean force; /** * A flag to fail the build if at least one dependency was detected without a license. * * @parameter expression="${license.failIfWarning}" default-value="false" * @since 1.0 */ protected boolean failIfWarning; /** * A flag to change the grouping of the generated THIRD-PARTY file. *

* By default, group by dependecies. *

* If sets to {@code true}, the it will group by license type. * * @parameter expression="${license.groupByLicense}" default-value="false" * @since 1.0 */ protected boolean groupByLicense; /** * A filter to exclude some scopes. * * @parameter expression="${license.excludedScopes}" default-value="system" * @since 1.0 */ protected String excludedScopes; /** * A filter to include only some scopes, if let empty then all scopes will be used (no filter). * * @parameter expression="${license.includedScopes}" default-value="" * @since 1.0 */ protected String includedScopes; /** * A filter to exclude some GroupIds * * @parameter expression="${license.excludedGroups}" default-value="" * @since 1.0 */ protected String excludedGroups; /** * A filter to include only some GroupIds * * @parameter expression="${license.includedGroups}" default-value="" * @since 1.0 */ protected String includedGroups; /** * A filter to exclude some ArtifactsIds * * @parameter expression="${license.excludedArtifacts}" default-value="" * @since 1.0 */ protected String excludedArtifacts; /** * A filter to include only some ArtifactsIds * * @parameter expression="${license.includedArtifacts}" default-value="" * @since 1.0 */ protected String includedArtifacts; /** * Include transitive dependencies when downloading license files. * * @parameter default-value="true" * @since 1.0 */ protected boolean includeTransitiveDependencies; /** * third party tool. * * @component * @readonly * @since 1.0 */ private ThirdPartyTool thridPartyTool; private SortedMap projectDependencies; private LicenseMap licenseMap; private SortedSet unsafeDependencies; private File thirdPartyFile; private SortedProperties unsafeMappings; private boolean doGenerate; private boolean doGenerateBundle; public static final String NO_DEPENDENCIES_MESSAGE = "the project has no dependencies."; private static SortedMap artifactCache; public static SortedMap getArtifactCache() { if (artifactCache == null) { artifactCache = new TreeMap(); } return artifactCache; } protected abstract SortedMap loadDependencies(); protected abstract SortedProperties createUnsafeMapping() throws ProjectBuildingException, IOException, ThirdPartyToolException; protected boolean exists(String location) { if (StringUtils.isBlank(location)) { return false; } ResourceLoader loader = new DefaultResourceLoader(); Resource resource = loader.getResource(location); return resource.exists(); } protected File copyToFileSystem(String location) { ResourceLoader loader = new DefaultResourceLoader(); Resource resource = loader.getResource(location); if (!resource.exists()) { throw new IllegalArgumentException("Can't locate " + location); } InputStream in = null; OutputStream out = null; try { in = resource.getInputStream(); File temp = new File(getProject().getBuild().getDirectory() + "/license/THIRD-PARTY.properties"); out = FileUtils.openOutputStream(temp); IOUtils.copy(in, out); getLog().debug("Created " + temp); return temp; } catch (IOException e) { throw new IllegalArgumentException(e); } finally { IOUtils.closeQuietly(in); IOUtils.closeQuietly(out); } } @Override protected void init() throws Exception { if (exists(getArtifactLicenseMapping())) { File propertiesFile = copyToFileSystem(getArtifactLicenseMapping()); setMissingFile(propertiesFile); } Log log = getLog(); if (log.isDebugEnabled()) { // always be verbose in debug mode setVerbose(true); } File file = new File(getOutputDirectory(), getThirdPartyFilename()); setThirdPartyFile(file); long buildTimestamp = getBuildTimestamp(); if (isVerbose()) { log.info("Build start at : " + buildTimestamp); log.info("third-party file : " + file.lastModified()); } setDoGenerate(isForce() || !file.exists() || buildTimestamp > file.lastModified()); if (isGenerateBundle()) { File bundleFile = FileUtil.getFile(getOutputDirectory(), getBundleThirdPartyPath()); if (isVerbose()) { log.info("bundle third-party file : " + bundleFile.lastModified()); } setDoGenerateBundle(isForce() || !bundleFile.exists() || buildTimestamp > bundleFile.lastModified()); } else { // not generating bundled file setDoGenerateBundle(false); } projectDependencies = loadDependencies(); licenseMap = createLicenseMap(projectDependencies); SortedSet unsafeDependencies = getThridPartyTool().getProjectsWithNoLicense(licenseMap, isVerbose()); setUnsafeDependencies(unsafeDependencies); if (!CollectionUtils.isEmpty(unsafeDependencies) && isUseMissingFile() && isDoGenerate()) { // load unsafeMapping unsafeMappings = createUnsafeMapping(); } if (!CollectionUtils.isEmpty(licenseMerges)) { // check where is not multi licenses merged main licenses (see OJO-1723) Map mergedLicenses = new HashMap(); for (String merge : licenseMerges) { merge = merge.trim(); String[] split = merge.split("\\|"); String mainLicense = split[0]; if (mergedLicenses.containsKey(mainLicense)) { // this license was already describe, fail the build... throw new MojoFailureException( "The merge main license " + mainLicense + " was already registred in the " + "configuration, please use only one such entry as describe in example " + "http://mojo.codehaus.org/license-maven-plugin/examples/example-thirdparty.html#Merge_licenses."); } mergedLicenses.put(mainLicense, split); } // merge licenses in license map for (String[] mergedLicense : mergedLicenses.values()) { if (isVerbose()) { getLog().info("Will merge " + Arrays.toString(mergedLicense) + ""); } thridPartyTool.mergeLicenses(licenseMap, mergedLicense); } } } protected LicenseMap createLicenseMap(SortedMap dependencies) { LicenseMap licenseMap = new LicenseMap(); for (MavenProject project : dependencies.values()) { thridPartyTool.addLicense(licenseMap, project, project.getLicenses()); } return licenseMap; } protected boolean checkUnsafeDependencies() { SortedSet unsafeDependencies = getUnsafeDependencies(); boolean unsafe = !CollectionUtils.isEmpty(unsafeDependencies); if (unsafe) { Log log = getLog(); log.debug("There is " + unsafeDependencies.size() + " dependencies with no license :"); for (MavenProject dep : unsafeDependencies) { // no license found for the dependency log.debug(" - " + MojoHelper.getArtifactId(dep.getArtifact())); } } return unsafe; } protected void writeThirdPartyFile() throws IOException { Log log = getLog(); LicenseMap licenseMap = getLicenseMap(); File target = getThirdPartyFile(); if (isDoGenerate()) { StringBuilder sb = new StringBuilder(); if (licenseMap.isEmpty()) { sb.append(NO_DEPENDENCIES_MESSAGE); } else { if (isGroupByLicense()) { // group by license sb.append("List of third-party dependencies grouped by " + "their license type."); for (String licenseName : licenseMap.keySet()) { SortedSet projects = licenseMap.get(licenseName); // Don't print the license if it isn't being used if (projects == null || projects.size() == 0) { continue; } sb.append("\n\n").append(licenseName).append(" : "); for (MavenProject mavenProject : projects) { String s = MojoHelper.getArtifactName(mavenProject); sb.append("\n * ").append(s); } } } else { // group by dependencies SortedMap map = licenseMap.toDependencyMap(); sb.append("List of ").append(map.size()).append(" third-party dependencies.\n"); List lines = new ArrayList(); for (Map.Entry entry : map.entrySet()) { String artifact = MojoHelper.getArtifactName(entry.getKey()); StringBuilder buffer = new StringBuilder(); for (String license : entry.getValue()) { buffer.append(" (").append(license).append(")"); } String licenses = buffer.toString(); String line = licenses + " " + artifact; lines.add(line); } Collections.sort(lines); for (String line : lines) { sb.append('\n').append(line); } lines.clear(); } } String content = sb.toString(); log.info("Writing third-party file to " + target); if (isVerbose()) { log.info(content); } FileUtil.writeString(target, content, getEncoding()); } if (isDoGenerateBundle()) { // creates the bundled license file File bundleTarget = FileUtil.getFile(getOutputDirectory(), getBundleThirdPartyPath()); log.info("Writing bundled third-party file to " + bundleTarget); FileUtil.copyFile(target, bundleTarget); } } public boolean isGroupByLicense() { return groupByLicense; } public void setGroupByLicense(boolean groupByLicense) { this.groupByLicense = groupByLicense; } public File getOutputDirectory() { return outputDirectory; } public String getThirdPartyFilename() { return thirdPartyFilename; } public String getBundleThirdPartyPath() { return bundleThirdPartyPath; } public boolean isGenerateBundle() { return generateBundle; } public boolean isFailIfWarning() { return failIfWarning; } public SortedMap getProjectDependencies() { return projectDependencies; } public SortedSet getUnsafeDependencies() { return unsafeDependencies; } public void setUnsafeDependencies(SortedSet unsafeDependencies) { this.unsafeDependencies = unsafeDependencies; } public File getThirdPartyFile() { return thirdPartyFile; } public LicenseMap getLicenseMap() { return licenseMap; } public void setOutputDirectory(File outputDirectory) { this.outputDirectory = outputDirectory; } public void setThirdPartyFilename(String thirdPartyFilename) { this.thirdPartyFilename = thirdPartyFilename; } public void setBundleThirdPartyPath(String bundleThirdPartyPath) { this.bundleThirdPartyPath = bundleThirdPartyPath; } public void setGenerateBundle(boolean generateBundle) { this.generateBundle = generateBundle; } public void setThirdPartyFile(File thirdPartyFile) { this.thirdPartyFile = thirdPartyFile; } public boolean isUseMissingFile() { return useMissingFile; } public File getMissingFile() { return missingFile; } public void setUseMissingFile(boolean useMissingFile) { this.useMissingFile = useMissingFile; } public void setMissingFile(File missingFile) { this.missingFile = missingFile; } public void setFailIfWarning(boolean failIfWarning) { this.failIfWarning = failIfWarning; } public SortedProperties getUnsafeMappings() { return unsafeMappings; } public boolean isForce() { return force; } public boolean isDoGenerate() { return doGenerate; } public void setForce(boolean force) { this.force = force; } public void setDoGenerate(boolean doGenerate) { this.doGenerate = doGenerate; } public boolean isDoGenerateBundle() { return doGenerateBundle; } public void setDoGenerateBundle(boolean doGenerateBundle) { this.doGenerateBundle = doGenerateBundle; } public List getExcludedScopes() { String[] split = excludedScopes == null ? new String[0] : excludedScopes.split(","); return Arrays.asList(split); } public void setExcludedScopes(String excludedScopes) { this.excludedScopes = excludedScopes; } public List getIncludedScopes() { String[] split = includedScopes == null ? new String[0] : includedScopes.split(","); return Arrays.asList(split); } public void setIncludedScopes(String includedScopes) { this.includedScopes = includedScopes; } public String getExcludedGroups() { return excludedGroups; } public void setExcludedGroups(String excludedGroups) { this.excludedGroups = excludedGroups; } public String getIncludedGroups() { return includedGroups; } public void setIncludedGroups(String includedGroups) { this.includedGroups = includedGroups; } public String getExcludedArtifacts() { return excludedArtifacts; } public void setExcludedArtifacts(String excludedArtifacts) { this.excludedArtifacts = excludedArtifacts; } public String getIncludedArtifacts() { return includedArtifacts; } public void setIncludedArtifacts(String includedArtifacts) { this.includedArtifacts = includedArtifacts; } public ThirdPartyTool getThridPartyTool() { return thridPartyTool; } public void setThridPartyTool(ThirdPartyTool thridPartyTool) { this.thridPartyTool = thridPartyTool; } public String getArtifactLicenseMapping() { return artifactLicenseMapping; } public void setArtifactLicenseMapping(String artifactLicenseMapping) { this.artifactLicenseMapping = artifactLicenseMapping; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy