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

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

There is a newer version: 2.4.0
Show newest version
package org.codehaus.mojo.license;

/*
 * #%L
 * License Maven Plugin
 * %%
 * Copyright (C) 2012 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%
 */

import org.apache.commons.collections.CollectionUtils;
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.doxia.siterenderer.Renderer;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
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.apache.maven.project.artifact.InvalidDependencyVersionException;
import org.apache.maven.reporting.AbstractMavenReport;
import org.apache.maven.reporting.MavenReportException;
import org.codehaus.mojo.license.api.ArtifactFilters;
import org.codehaus.mojo.license.api.DefaultThirdPartyDetails;
import org.codehaus.mojo.license.api.DefaultThirdPartyHelper;
import org.codehaus.mojo.license.api.DependenciesTool;
import org.codehaus.mojo.license.api.DependenciesToolException;
import org.codehaus.mojo.license.api.MavenProjectDependenciesConfigurator;
import org.codehaus.mojo.license.api.ThirdPartyDetails;
import org.codehaus.mojo.license.api.ThirdPartyHelper;
import org.codehaus.mojo.license.api.ThirdPartyTool;
import org.codehaus.mojo.license.api.ThirdPartyToolException;
import org.codehaus.mojo.license.model.LicenseMap;
import org.codehaus.mojo.license.utils.MojoHelper;
import org.codehaus.mojo.license.utils.UrlRequester;
import org.codehaus.plexus.i18n.I18N;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeSet;
import org.codehaus.mojo.license.api.ResolvedProjectDependencies;

/**
 * Base class for third-party reports.
 *
 * @author tchemit [email protected]
 * @since 1.1
 */
public abstract class AbstractThirdPartyReportMojo extends AbstractMavenReport
    implements MavenProjectDependenciesConfigurator
{

    // ----------------------------------------------------------------------
    // Mojo Parameters
    // ----------------------------------------------------------------------

    /**
     * A filter to exclude some scopes.
     *
     * @since 1.1
     */
    @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.1
     */
    @Parameter( property = "license.includedScopes" )
    private String includedScopes;

    /**
     * A filter to exclude some types.
     *
     * @since 1.15
     */
    @Parameter( property = "license.excludedTypes" )
    private String excludedTypes;

    /**
     * A filter to include only some types, if let empty then all types will be used (no filter).
     *
     * @since 1.15
     */
    @Parameter( property = "license.includedTypes" )
    private String includedTypes;

    /**
     * A filter to exclude some GroupIds
     *
     * @since 1.1
     */
    @Parameter( property = "license.excludedGroups" )
    private String excludedGroups;

    /**
     * A filter to include only some GroupIds
     *
     * @since 1.1
     */
    @Parameter( property = "license.includedGroups" )
    private String includedGroups;

    /**
     * A filter to exclude some ArtifactsIds
     *
     * @since 1.1
     */
    @Parameter( property = "license.excludedArtifacts" )
    private String excludedArtifacts;

    /**
     * A filter to include only some ArtifactsIds
     *
     * @since 1.1
     */
    @Parameter( property = "license.includedArtifacts" )
    private String includedArtifacts;

    /**
     * Include transitive dependencies when looking for missing licenses and downloading license files.
     *
     * @since 1.1
     */
    @Parameter( property = "license.includeTransitiveDependencies", defaultValue = "true" )
    private boolean includeTransitiveDependencies;

    /**
     * A filter to exclude transitive dependencies from excluded artifacts.
     *
     * @since 1.13
     */
    @Parameter( property = "license.excludeTransitiveDependencies", defaultValue = "false" )
    private boolean excludeTransitiveDependencies;

    /**
     * If {@code true} both optional and non-optional dependencies will be included in the list of artifacts for
     * creating the license report; otherwise only non-optional dependencies will be considered.
     *
     * @since 1.19
     */
    @Parameter( property = "license.includeOptional", defaultValue = "true" )
    boolean includeOptional;

    /**
     * A flag to use the missing licenses file to consolidate the THID-PARTY file.
     *
     * @since 1.1
     */
    @Parameter( property = "license.useMissingFile", defaultValue = "false" )
    private boolean useMissingFile;

    /**
     * The file where to fill the license for dependencies with unknwon license.
     *
     * @since 1.1
     */
    @Parameter( property = "license.missingFile", defaultValue = "src/license/THIRD-PARTY.properties" )
    private File missingFile;

    /**
     * The Url that holds the missing license dependency entries. This is an extension to {@link #missingFile}.
     * If set then the entries that will be found at this URL will be added additionally to the entries of the
     * missing file.
*
* NOTE:
* the response of the URL endpoint must return content that matches the THIRD-PARTY.properties file! * * @since 1.15 */ @Parameter( property = "license.missingFileUrl" ) String missingFileUrl; /** * A file containing the override license information for dependencies. * Note: Specify either {@link #overrideUrl} (preferred) or {@link #overrideFile}. * If none of these is specified, then {@value LicenseMojoUtils#DEFAULT_OVERRIDE_THIRD_PARTY} resolved against * ${basedir} will be used if it exists. * * @since 1.11 * @deprecated Use {@link #overrideUrl} instead */ @Deprecated @Parameter( property = "license.overrideFile" ) private File overrideFile; /** * A URL pointing at a property file with the override license information for dependencies. * Note: Specify either {@link #overrideUrl} (preferred) or {@link #overrideFile}. * If none of these is specified, then {@value LicenseMojoUtils#DEFAULT_OVERRIDE_THIRD_PARTY} resolved against * ${basedir} will be used if it exists. *

* An example of the file content: *

     * org.jboss.xnio--xnio-api--3.3.6.Final=The Apache Software License, Version 2.0
     * 
* * @since 1.17 */ @Parameter( property = "license.overrideUrl" ) private String overrideUrl; /** * A {@link URL} prepared either our of {@link #overrideFile} or {@link #overrideUrl} or the default value. * * @see LicenseMojoUtils#prepareThirdPartyOverrideUrl(URL, File, String, File) */ String resolvedOverrideUrl; /** * Load from repositories third party missing files. * * @since 1.0 */ @Parameter( property = "license.useRepositoryMissingFiles", defaultValue = "true" ) private boolean useRepositoryMissingFiles; /** * 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>
     *
     * Note: This option will be overridden by {@link #licenseMergesUrl} if it is used by command line.
     * @since 1.0
     */
    @Parameter
    private List licenseMerges;

    /**
      * Location of file with the merge licenses in order to be used by command line.
      * Note: This option overrides {@link #licenseMerges}.
      *
      * @since 1.18
      */
     @Parameter( property = "license.licenseMergesUrl" )
     protected String licenseMergesUrl;

    /**
     * The output directory for the report. Note that this parameter is only evaluated if the goal is run directly from
     * the command line. If the goal is run indirectly as part of a site generation, the output directory configured in
     * the Maven Site Plugin is used instead.
     *
     * @since 1.1
     */
    @Parameter( defaultValue = "${project.reporting.outputDirectory}", required = true )
    private File outputDirectory;

    /**
     * Flag to activate verbose mode.
     * 

* Note: Verbose mode is always on if you starts a debug maven instance * (says via {@code -X}). * * @since 1.0 */ @Parameter( property = "license.verbose", defaultValue = "${maven.verbose}" ) private boolean verbose; /** * Encoding used to read and writes files. *

* Note: If nothing is filled here, we will use the system * property {@code file.encoding}. * * @since 1.0 */ @Parameter( property = "license.encoding", defaultValue = "${project.build.sourceEncoding}" ) private String encoding; /** * Local Repository. * * @since 1.1 */ @Parameter( property = "localRepository", required = true, readonly = true ) private ArtifactRepository localRepository; /** * The Maven Project. * * @since 1.1 */ @Parameter( defaultValue = "${project}", readonly = true ) private MavenProject project; // ---------------------------------------------------------------------- // Plexus Components // ---------------------------------------------------------------------- /** * Doxia Site Renderer component. * * @since 1.1 */ @Component private Renderer siteRenderer; /** * Internationalization component. * * @since 1.1 */ @Component private I18N i18n; /** * dependencies tool. * * @since 1.1 */ @Component private DependenciesTool dependenciesTool; /** * third party tool. * * @since 1.1 */ @Component private ThirdPartyTool thirdPartyTool; /** * A URL returning a plain text file that contains include/exclude artifact filters in the following format: *

     * {@code
     * # this is a comment
     * include gaPattern org\.my-org:my-artifact
     * include gaPattern org\.other-org:other-artifact
     * exclude gaPattern org\.yet-anther-org:.*
     * include scope compile
     * include scope test
     * exclude scope system
     * include type jar
     * exclude type war
     * }
* * @since 1.18 */ @Parameter( property = "license.artifactFiltersUrl" ) private String artifactFiltersUrl; private ArtifactFilters artifactFilters; // ---------------------------------------------------------------------- // Protected Abstract Methods // ---------------------------------------------------------------------- protected abstract Collection createThirdPartyDetails() throws IOException, ThirdPartyToolException, ProjectBuildingException, MojoFailureException, InvalidDependencyVersionException, ArtifactNotFoundException, ArtifactResolutionException, DependenciesToolException, MojoExecutionException; // ---------------------------------------------------------------------- // AbstractMavenReport Implementation // ---------------------------------------------------------------------- /** * Method to initialize the mojo before doing any concrete actions. * * Note: The method is invoked before the {@link #executeReport()} method. * @throws IOException */ protected void init() throws IOException { if ( licenseMergesUrl != null ) { getLog().warn( "" ); getLog().warn( "licenseMerges will be overridden by licenseMergesUrl." ); getLog().warn( "" ); if ( UrlRequester.isStringUrl( licenseMergesUrl ) ) { licenseMerges = Arrays.asList( UrlRequester.getFromUrl( licenseMergesUrl ).split( "[\n\r]+" ) ); } } } /** * {@inheritDoc} */ protected void executeReport( Locale locale ) throws MavenReportException { resolvedOverrideUrl = LicenseMojoUtils.prepareThirdPartyOverrideUrl( resolvedOverrideUrl, overrideFile, overrideUrl, project.getBasedir(), getLog() ); Collection details; try { init(); details = createThirdPartyDetails(); } catch ( IOException e ) { throw new MavenReportException( e.getMessage(), e ); } catch ( ThirdPartyToolException e ) { throw new MavenReportException( e.getMessage(), e ); } catch ( ProjectBuildingException e ) { throw new MavenReportException( e.getMessage(), e ); } catch ( InvalidDependencyVersionException e ) { throw new MavenReportException( e.getMessage(), e ); } catch ( ArtifactNotFoundException e ) { throw new MavenReportException( e.getMessage(), e ); } catch ( ArtifactResolutionException e ) { throw new MavenReportException( e.getMessage(), e ); } catch ( MojoFailureException e ) { throw new MavenReportException( e.getMessage(), e ); } catch ( DependenciesToolException e ) { throw new MavenReportException( e.getMessage(), e ); } catch ( MojoExecutionException e ) { throw new MavenReportException( e.getMessage(), e ); } ThirdPartyReportRenderer renderer = new ThirdPartyReportRenderer( getSink(), i18n, getOutputName(), locale, details ); renderer.render(); } /** * {@inheritDoc} */ protected MavenProject getProject() { return project; } /** * {@inheritDoc} */ protected String getOutputDirectory() { if ( !outputDirectory.isAbsolute() ) { outputDirectory = new File( project.getBasedir(), outputDirectory.getPath() ); } return outputDirectory.getAbsolutePath(); } /** * {@inheritDoc} */ protected Renderer getSiteRenderer() { return siteRenderer; } /** * {@inheritDoc} */ public String getDescription( Locale locale ) { return i18n.getString( getOutputName(), locale, "report.description" ); } /** * {@inheritDoc} */ public String getName( Locale locale ) { return i18n.getString( getOutputName(), locale, "report.title" ); } // ---------------------------------------------------------------------- // MavenProjectDependenciesConfigurator Implementation // ---------------------------------------------------------------------- /** * {@inheritDoc} */ public boolean isIncludeTransitiveDependencies() { return includeTransitiveDependencies; } /** * {@inheritDoc} */ public boolean isExcludeTransitiveDependencies() { return excludeTransitiveDependencies; } /** {@inheritDoc} */ public ArtifactFilters getArtifactFilters() { if ( artifactFilters == null ) { artifactFilters = ArtifactFilters.of( includedGroups, excludedGroups, includedArtifacts, excludedArtifacts, includedScopes, excludedScopes, includedTypes, excludedTypes, includeOptional, artifactFiltersUrl , getEncoding() ); } return artifactFilters; } /** * {@inheritDoc} */ public boolean isVerbose() { return verbose; } // ---------------------------------------------------------------------- // Protected Methods // ---------------------------------------------------------------------- Collection createThirdPartyDetails( MavenProject project, boolean loadArtifacts ) throws IOException, ThirdPartyToolException, ProjectBuildingException, MojoFailureException, DependenciesToolException, MojoExecutionException { ResolvedProjectDependencies loadedDependencies; if ( loadArtifacts ) { loadedDependencies = dependenciesTool.loadProjectArtifacts( localRepository, project.getRemoteArtifactRepositories(), project, null ); } else { loadedDependencies = new ResolvedProjectDependencies( getProject().getArtifacts(), getProject().getDependencyArtifacts() ); } ThirdPartyHelper thirdPartyHelper = new DefaultThirdPartyHelper( project, encoding, verbose, dependenciesTool, thirdPartyTool, localRepository, project.getRemoteArtifactRepositories(), getLog() ); // load dependencies of the project SortedMap projectDependencies = thirdPartyHelper.loadDependencies( this, loadedDependencies ); // create licenseMap from it LicenseMap licenseMap = thirdPartyHelper.createLicenseMap( projectDependencies ); // Get unsafe dependencies (dependencies with no license in pom) SortedSet dependenciesWithNoLicense = thirdPartyHelper.getProjectsWithNoLicense( licenseMap ); // compute safe dependencies (with pom licenses) Set dependenciesWithPomLicense = new TreeSet<>( MojoHelper.newMavenProjectComparator() ); dependenciesWithPomLicense.addAll( projectDependencies.values() ); if ( CollectionUtils.isNotEmpty( dependenciesWithNoLicense ) ) { // there is some unsafe dependencies, remove them from safe dependencies dependenciesWithPomLicense.removeAll( dependenciesWithNoLicense ); if ( useMissingFile ) { // Resolve unsafe dependencies using missing files, this will update licenseMap and unsafeDependencies thirdPartyHelper.createUnsafeMapping( licenseMap, missingFile, missingFileUrl, useRepositoryMissingFiles, dependenciesWithNoLicense, projectDependencies, loadedDependencies.getAllDependencies() ); } } // LicenseMap is now complete, let's merge licenses if necessary thirdPartyHelper.mergeLicenses( licenseMerges, licenseMap ); // Add override licenses thirdPartyTool.overrideLicenses( licenseMap, projectDependencies, encoding, resolvedOverrideUrl ); // let's build third party details for each dependencies Collection details = new ArrayList<>(); for ( Map.Entry entry : licenseMap.toDependencyMap().entrySet() ) { MavenProject dependency = entry.getKey(); String[] licenses = entry.getValue(); ThirdPartyDetails detail = new DefaultThirdPartyDetails( dependency ); details.add( detail ); if ( dependenciesWithPomLicense.contains( dependency ) ) { // this is a pom licenses detail.setPomLicenses( licenses ); } else if ( !dependenciesWithNoLicense.contains( dependency ) ) { // this is a third-party licenses detail.setThirdPartyLicenses( licenses ); } } return details; } /** {@inheritDoc} */ public String getArtifactFiltersUrl() { return artifactFiltersUrl; } /** {@inheritDoc} */ public String getEncoding() { return encoding; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy