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

org.codehaus.mojo.license.download.LicenseMatchers Maven / Gradle / Ivy

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

/*
 * #%L
 * License Maven Plugin
 * %%
 * Copyright (C) 2018 Codehaus
 * %%
 * 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 java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Pattern;

import org.apache.maven.plugin.MojoExecutionException;

/**
 * A collection of {@link DependencyMatcher}s to match and replace licenses in {@link ProjectLicenseInfo} instances.
 *
 * @author Peter Palaga
 * @since 1.18
 */
public class LicenseMatchers
{

    private static final Pattern MATCH_EMPTY_PATTERN = Pattern.compile( "" );
    private static final Pattern MATCH_ALL_PATTERN = Pattern.compile( ".*" );

    /**
     * @return a new {@link Builder}
     */
    public static Builder builder()
    {
        return new Builder();
    }

    /**
     * @param licenseMatchersFile
     * @return new {@link LicenseMatchers} configured from the given {@code licenseMatchersFile}
     * @throws MojoExecutionException
     */
    public static LicenseMatchers load( File licenseMatchersFile )
        throws MojoExecutionException
    {
        final List matchers = new ArrayList<>();
        try
        {
            if ( licenseMatchersFile != null && licenseMatchersFile.exists() )
            {
                final List replacements =
                    LicenseSummaryReader.parseLicenseSummary( licenseMatchersFile );

                for ( ProjectLicenseInfo dependency : replacements )
                {
                    matchers.add( DependencyMatcher.of( dependency ) );
                }
            }
        }
        catch ( Exception e )
        {
            throw new MojoExecutionException( "Could not parse licensesReplacementsFile " + licenseMatchersFile, e );
        }
        return new LicenseMatchers( matchers );
    }

    private static boolean match( Pattern pattern, String string )
    {
        return string == null ? pattern.matcher( "" ).matches() : pattern.matcher( string ).matches();
    }

    private static Pattern pattern( String string, boolean isPre118Match )
    {
        return string == null || string.isEmpty() ? MATCH_EMPTY_PATTERN
                        : isPre118Match ? Pattern.compile( Pattern.quote( string ) )
                                        : Pattern.compile( string, Pattern.CASE_INSENSITIVE );
    }

    private final List matchers;

    private LicenseMatchers( List matchers )
    {
        super();
        this.matchers = matchers;
    }

    /**
     * Replace matching licenses in the given {@code dependency}
     *
     * @param dependency
     */
    public void replaceMatches( ProjectLicenseInfo dependency )
    {
        for ( DependencyMatcher matcher : matchers )
        {
            if ( matcher.matches( dependency ) )
            {
                if ( matcher.isApproved() )
                {
                    /* do nothing */
                }
                else
                {
                    dependency.setLicenses( matcher.cloneLicenses() );
                }
                dependency.setApproved( true );
                dependency.getDownloaderMessages().clear();
            }
        }
    }

    /**
     * A {@link LicenseMatchers} builder
     */
    public static class Builder
    {
        private List matchers = new ArrayList<>();

        public Builder matcher( DependencyMatcher matcher )
        {
            matchers.add( matcher );
            return this;
        }

        public LicenseMatchers build()
        {
            final List ms = matchers;
            matchers = null;
            return new LicenseMatchers( ms );
        }
    }

    /**
     * A matcher for dependency nodes in a licenses.xml file
     *
     * @since 1.18
     */
    static class DependencyMatcher
    {

        public static DependencyMatcher of( ProjectLicenseInfo dependency )
        {
            final String version = dependency.getVersion();
            final boolean isPre118Match = !dependency.hasMatchLicenses();
            return new DependencyMatcher( pattern( dependency.getGroupId(), isPre118Match ),
                                          pattern( dependency.getArtifactId(), isPre118Match ),
                                          isPre118Match || version == null || version.isEmpty() ? MATCH_ALL_PATTERN
                                                          : Pattern.compile( version, Pattern.CASE_INSENSITIVE ),
                                          LicenseListMatcher.of( dependency ), dependency.cloneLicenses(),
                                          dependency.isApproved() );
        }

        private final Pattern artifactId;

        private final Pattern groupId;

        private final LicenseListMatcher licenseListMatcher;

        private final boolean approved;
        private final List licenses;

        private final Pattern version;

        DependencyMatcher( Pattern groupId, Pattern artifactId, Pattern version, LicenseListMatcher licenseListMatcher,
                           List licenses, boolean approved )
        {
            super();
            this.groupId = groupId;
            this.artifactId = artifactId;
            this.version = version;
            this.licenseListMatcher = licenseListMatcher;
            this.licenses = licenses;
            this.approved = approved;
        }

        public List getLicenseMatchers()
        {
            return null;
        }

        /**
         * @return a deep clone of {@link #licenses}
         */
        public List cloneLicenses()
        {
            try
            {
                final ArrayList result = new ArrayList<>( licenses != null ? licenses.size() : 0 );
                if ( licenses != null )
                {
                    for ( ProjectLicense license : licenses )
                    {
                        result.add( license.clone() );
                    }
                }
                return result;
            }
            catch ( CloneNotSupportedException e )
            {
                throw new RuntimeException( e );
            }
        }

        public boolean matches( ProjectLicenseInfo dependency )
        {
            return match( groupId, dependency.getGroupId() ) && match( artifactId, dependency.getArtifactId() )
                && match( version, dependency.getVersion() ) && licenseListMatcher.matches( dependency.getLicenses() );
        }

        public boolean isApproved()
        {
            return approved;
        }

    }

    /**
     * A matcher for lists of {@link ProjectLicense}s.
     *
     * @since 1.18
     */
    static class LicenseListMatcher
    {
        private final List licenseMatchers;

        private static final LicenseListMatcher MATCHES_ALL_LICENSE_LIST_MATCHER = new LicenseListMatcher( null )
        {
            @Override
            public boolean matches( List licenses )
            {
                return true;
            }
        };

        public LicenseListMatcher( List licenseMatchers )
        {
            this.licenseMatchers = licenseMatchers;
        }

        public boolean matches( List licenses )
        {
            final int licsSize = licenses == null ? 0 : licenses.size();
            if ( licenseMatchers.size() != licsSize )
            {
                return false;
            }
            final Iterator matchersIt = licenseMatchers.iterator();
            final Iterator licsIt = licenses.iterator();
            while ( matchersIt.hasNext() )
            {
                if ( !matchersIt.next().matches( licsIt.next() ) )
                {
                    return false;
                }
            }
            return true;
        }

        public static LicenseListMatcher of( ProjectLicenseInfo dependency )
        {
            if ( !dependency.hasMatchLicenses() )
            {
                return MATCHES_ALL_LICENSE_LIST_MATCHER;
            }

            final List licenseMatchers;
            final List rawMatchers = dependency.getMatchLicenses();
            if ( rawMatchers == null || rawMatchers.isEmpty() )
            {
                licenseMatchers = Collections.emptyList();
            }
            else
            {
                licenseMatchers = new ArrayList<>();
                for ( ProjectLicense lic : rawMatchers )
                {
                    licenseMatchers.add( new LicenseMatcher( lic.getName(), lic.getUrl(), lic.getDistribution(),
                                                             lic.getComments() ) );
                }
            }
            return new LicenseListMatcher( licenseMatchers );
        }
    }

    /**
     * A matcher for single {@link ProjectLicense}s.
     *
     * @since 1.18
     */
    static class LicenseMatcher
    {

        private final Pattern comments;
        private final Pattern distribution;
        private final Pattern name;
        private final Pattern url;

        LicenseMatcher( Pattern name, Pattern url, Pattern distribution, Pattern comments )
        {
            super();
            this.name = name;
            this.url = url;
            this.distribution = distribution;
            this.comments = comments;
        }

        LicenseMatcher( String name, String url, String distribution, String comments )
        {
            super();
            this.name = pattern( name, false );
            this.url = pattern( url, false );
            this.distribution = pattern( distribution, false );
            this.comments = pattern( comments, false );
        }

        public boolean matches( ProjectLicense license )
        {
            return match( name, license.getName() ) && match( url, license.getUrl() )
                && match( distribution, license.getDistribution() ) && match( comments, license.getComments() );
        }

    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy