diff --git a/src/it/download-licenses-force/postbuild.groovy b/src/it/download-licenses-force/postbuild.groovy
index db2917e85..7294695c5 100644
--- a/src/it/download-licenses-force/postbuild.groovy
+++ b/src/it/download-licenses-force/postbuild.groovy
@@ -44,4 +44,4 @@ assert expectedLicensesErrorsXml.text.equals(licensesErrorsXml.text)
final Path log = basePath.resolve('build.log')
assert Files.exists(log)
-assert log.text.contains('There were 1 download errors - check ')
+assert log.text.contains('There were 2 download errors - check ')
diff --git a/src/main/java/org/codehaus/mojo/license/AbstractDownloadLicensesMojo.java b/src/main/java/org/codehaus/mojo/license/AbstractDownloadLicensesMojo.java
index 1db78e16b..7f1904e10 100644
--- a/src/main/java/org/codehaus/mojo/license/AbstractDownloadLicensesMojo.java
+++ b/src/main/java/org/codehaus/mojo/license/AbstractDownloadLicensesMojo.java
@@ -46,13 +46,14 @@
import org.codehaus.mojo.license.download.ProjectLicense;
import org.codehaus.mojo.license.download.ProjectLicenseInfo;
import org.codehaus.mojo.license.download.LicenseDownloader.LicenseDownloadResult;
+import org.codehaus.mojo.license.download.LicenseMatchers;
import org.codehaus.mojo.license.utils.FileUtil;
import org.codehaus.mojo.license.utils.MojoHelper;
import java.io.File;
-import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
+import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
@@ -61,8 +62,8 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
-import java.util.HashMap;
import java.util.Iterator;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -100,13 +101,95 @@ public abstract class AbstractDownloadLicensesMojo
@Parameter( defaultValue = "${project.remoteArtifactRepositories}", readonly = true )
private List remoteRepositories;
+ // CHECKSTYLE_OFF: LineLength
/**
- * Input file containing a mapping between each dependency and it's license information.
+ * A file containing the license data (most notably license names and license URLs) missing in
+ * {@code pom.xml} files of the dependencies.
+ *
+ * Note that since 1.18, if you set {@link #errorRemedy} to {@code xmlOutput} the format of
+ * {@link #licensesErrorsFile} is the same as the one of {@link #licensesConfigFile}. So you can use
+ * {@link #licensesErrorsFile} as a base for {@link #licensesConfigFile}.
+ *
+ * Since 1.18, the format of the file is as follows:
+ *
+ * {@code
+ *
+ *
+ *
+ * \Qaopalliance\E
+ * \Qaopalliance\E
+ *
+ *
+ * \QPublic Domain\E
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ * \Qasm\E
+ * \Qasm\E
+ *
+ *
+ *
+ *
+ *
+ *
+ * BSD 3-Clause ASM
+ * https://gitlab.ow2.org/asm/asm/raw/ASM_3_1_MVN/LICENSE.txt
+ *
+ *
+ *
+ *
+ * \Qca.uhn.hapi\E
+ * .*
+ *
+ *
+ *
+ * \QHAPI is dual licensed (MPL, GPL)\E
+ * \QHAPI is dual licensed under both the Mozilla Public License and the GNU General Public License.\E\s+\QWhat this means is that you may choose to use HAPI under the terms of either license.\E\s+\QYou are both permitted and encouraged to use HAPI, royalty-free, within your applications,\E\s+\Qwhether they are free/open-source or commercial/closed-source, provided you abide by the\E\s+\Qterms of one of the licenses below.\E\s+\QYou are under no obligations to inform the HAPI project about what you are doing with\E\s+\QHAPI, but we would love to hear about it anyway!\E
+ *
+ *
+ * \QMozilla Public License 1.1\E
+ * \Qhttp://www.mozilla.org/MPL/MPL-1.1.txt\E
+ * \Qmozilla public license 1.1 - index.0c5913925d40.txt\E
+ *
+ *
+ * \QGNU General Public License\E
+ * \Qhttp://www.gnu.org/licenses/gpl.txt\E
+ * \Qgnu general public license - gpl.txt\E
+ *
+ *
+ *
+ *
+ *
+ *
+ * }
+ *
+ *
+ * Before 1.18 the format was the same as the one of {@link #licensesOutputFile} and the groupIds and artifactIds
+ * were matched as plain text rather than regular expressions. No other elements (incl. versions) were matched at
+ * all. Since 1.18 the backwards compatibility is achieved by falling back to plain text matching of groupIds
+ * and artifactIds if the given {@code } does not contain the {@code } element.
+ *
+ * Relationship to other parameters:
+ *
+ * - License names and license URLs {@link #licensesConfigFile} is applied before
+ * {@link #licenseUrlReplacements}
+ * - {@link #licenseUrlReplacements} are applied before {@link #licenseUrlFileNames}
+ * - {@link #licenseUrlFileNames} have higher precedence than {@code } elements in
+ * {@link #licensesConfigFile}
+ * - {@link #licenseUrlFileNames} are ignored when {@link #organizeLicensesByDependencies} is {@code true}
+ *
*
* @since 1.0
*/
@Parameter( property = "licensesConfigFile", defaultValue = "${project.basedir}/src/license/licenses.xml" )
- private File licensesConfigFile;
+ protected File licensesConfigFile;
+ // CHECKSTYLE_ON: LineLength
/**
* The directory to which the dependency licenses should be written.
@@ -115,7 +198,7 @@ public abstract class AbstractDownloadLicensesMojo
*/
@Parameter( property = "licensesOutputDirectory",
defaultValue = "${project.build.directory}/generated-resources/licenses" )
- private File licensesOutputDirectory;
+ protected File licensesOutputDirectory;
/**
* If {@code true}, the mojo will delete all files from {@link #licensesOutputDirectory} and then download them all
@@ -247,7 +330,7 @@ public abstract class AbstractDownloadLicensesMojo
* @since 1.18
*/
@Parameter( property = "license.errorRemedy", defaultValue = "warn" )
- private ErrorRemedy errorRemedy;
+ protected ErrorRemedy errorRemedy;
/**
* If {@code true}, all encountered dependency license URLs are downloaded, no matter what is there in
@@ -373,11 +456,21 @@ public abstract class AbstractDownloadLicensesMojo
*
* }
*
+ *
+ * Relationship to other parameters:
+ *
+ * - License names and license URLs {@link #licensesConfigFile} is applied before
+ * {@link #licenseUrlReplacements}
+ * - {@link #licenseUrlReplacements} are applied before {@link #licenseUrlFileNames}
+ * - {@link #licenseUrlFileNames} have higher precedence than {@code } elements in
+ * {@link #licensesConfigFile}
+ * - {@link #licenseUrlFileNames} are ignored when {@link #organizeLicensesByDependencies} is {@code true}
+ *
*
* @since 1.17
*/
@Parameter
- private List licenseUrlReplacements;
+ protected List licenseUrlReplacements;
/**
* A map that helps to select local files names for the content downloaded from license URLs.
@@ -420,6 +513,8 @@ public abstract class AbstractDownloadLicensesMojo
*
* Relationship to other parameters:
*
+ * - License names and license URLs {@link #licensesConfigFile} is applied before
+ * {@link #licenseUrlReplacements}
* - {@link #licenseUrlReplacements} are applied before {@link #licenseUrlFileNames}
* - {@link #licenseUrlFileNames} have higher precedence than {@code } elements in
* {@link #licensesConfigFile}
@@ -429,7 +524,7 @@ public abstract class AbstractDownloadLicensesMojo
* @since 1.18
*/
@Parameter
- private Map licenseUrlFileNames;
+ protected Map licenseUrlFileNames;
/**
* If {@code true}, {@link #licensesOutputFile} and {@link #licensesErrorsFile} will contain {@code }
@@ -509,24 +604,12 @@ public void execute()
initDirectories();
- Map configuredDepLicensesMap = new HashMap<>();
+ final LicenseMatchers matchers = LicenseMatchers.load( licensesConfigFile );
- // License info from previous build
- if ( !forceDownload && licensesOutputFile.exists() )
- {
- loadLicenseInfo( configuredDepLicensesMap, licensesOutputFile, true );
- }
-
- // Manually configured license info, loaded second to override previously loaded info
- if ( licensesConfigFile.exists() )
- {
- loadLicenseInfo( configuredDepLicensesMap, licensesConfigFile, false );
- }
-
- Set dependencies = getDependencies();
+ final Set dependencies = getDependencies();
// The resulting list of licenses after dependency resolution
- List depProjectLicenses = new ArrayList<>();
+ final List depProjectLicenses = new ArrayList<>();
try ( LicenseDownloader licenseDownloader = new LicenseDownloader( findActiveProxy() ) )
{
@@ -534,17 +617,8 @@ public void execute()
{
Artifact artifact = project.getArtifact();
getLog().debug( "Checking licenses for project " + artifact );
- String artifactProjectId = getArtifactProjectId( artifact );
- ProjectLicenseInfo depProject;
- if ( configuredDepLicensesMap.containsKey( artifactProjectId ) )
- {
- depProject = configuredDepLicensesMap.get( artifactProjectId );
- depProject.setVersion( artifact.getVersion() );
- }
- else
- {
- depProject = createDependencyProject( project );
- }
+ final ProjectLicenseInfo depProject = createDependencyProject( project );
+ matchers.replaceMatches( depProject );
depProjectLicenses.add( depProject );
}
if ( !offline )
@@ -574,7 +648,7 @@ public void execute()
{
if ( sortByGroupIdAndArtifactId )
{
- depProjectLicenses = sortByGroupIdAndArtifactId( depProjectLicenses );
+ sortByGroupIdAndArtifactId( depProjectLicenses );
}
if ( licensesOutputFileEncoding == null )
@@ -664,9 +738,8 @@ private static ErrorRemedy getEffectiveErrorRemedy( boolean quiet, ErrorRemedy e
}
}
- private List sortByGroupIdAndArtifactId( List depProjectLicenses )
+ private void sortByGroupIdAndArtifactId( List depProjectLicenses )
{
- List sorted = new ArrayList<>( depProjectLicenses );
Comparator comparator = new Comparator()
{
public int compare( ProjectLicenseInfo info1, ProjectLicenseInfo info2 )
@@ -676,8 +749,7 @@ public int compare( ProjectLicenseInfo info1, ProjectLicenseInfo info2 )
+ "+" + info2.getArtifactId() );
}
};
- Collections.sort( sorted, comparator );
- return sorted;
+ Collections.sort( depProjectLicenses, comparator );
}
// ----------------------------------------------------------------------
@@ -840,71 +912,61 @@ private Proxy findActiveProxy()
* @param previouslyDownloaded Whether these licenses were already downloaded
* @throws MojoExecutionException if could not load license infos
*/
- private void loadLicenseInfo( Map configuredDepLicensesMap, File licenseConfigFile,
+ private Map loadLicenseInfo( File licenseConfigFile,
boolean previouslyDownloaded )
throws MojoExecutionException
{
- FileInputStream fis = null;
- try
+ final Map configuredDepLicensesMap = new LinkedHashMap<>();
+ if ( licenseConfigFile.exists() )
{
- fis = new FileInputStream( licenseConfigFile );
- List licensesList = LicenseSummaryReader.parseLicenseSummary( fis );
- for ( ProjectLicenseInfo dep : licensesList )
+ try ( InputStream fis = Files.newInputStream( licenseConfigFile.toPath() ) )
{
- configuredDepLicensesMap.put( dep.getId(), dep );
- if ( previouslyDownloaded )
+ final List licensesList = LicenseSummaryReader.parseLicenseSummary( fis );
+ for ( ProjectLicenseInfo dep : licensesList )
{
- for ( ProjectLicense license : dep.getLicenses() )
+ configuredDepLicensesMap.put( dep.getId(), dep );
+ if ( previouslyDownloaded )
{
- final String url = license.getUrl();
- if ( url != null )
+ for ( ProjectLicense license : dep.getLicenses() )
{
- final String licenseUrl = rewriteLicenseUrlIfNecessary( url );
- final FileNameEntry fileNameEntry =
- getLicenseFileName( dep, licenseUrl, license.getName(), license.getFile() );
- final File licenseFile = fileNameEntry.getFile();
- if ( !forceDownload && licenseFile.exists() )
+ final String url = license.getUrl();
+ if ( url != null )
{
- final String actualSha1 = FileUtil.sha1( licenseFile.toPath() );
- if ( fileNameEntry.getSha1() != null && !actualSha1.equals( fileNameEntry.getSha1() ) )
+ final String licenseUrl = rewriteLicenseUrlIfNecessary( url );
+ final FileNameEntry fileNameEntry =
+ getLicenseFileName( dep, licenseUrl, license.getName(), license.getFile() );
+ final File licenseFile = fileNameEntry.getFile();
+ if ( !forceDownload && licenseFile.exists() )
{
- throw new MojoFailureException( "Unexpected sha1 checksum for file '"
+ final String actualSha1 = FileUtil.sha1( licenseFile.toPath() );
+ if ( fileNameEntry.getSha1() != null
+ && !actualSha1.equals( fileNameEntry.getSha1() ) )
+ {
+ throw new MojoFailureException( "Unexpected sha1 checksum for file '"
+ licenseFile.getAbsolutePath() + "': '" + actualSha1 + "'; expected '"
+ fileNameEntry.getSha1() + "'. You may want to (a) re-run the current mojo"
+ " with -Dlicense.forceDownload=true or (b) change the expected sha1 in"
- + " the licenseUrlFileNames entry '"
- + fileNameEntry.getFile().getName() + "' or (c) split the entry so that"
+ + " the licenseUrlFileNames entry '" + fileNameEntry.getFile().getName()
+ + "' or (c) split the entry so that"
+ " its URLs return content with different sha1 sums." );
+ }
+ // Save the URL so we don't download it again
+ cache.put( license.getUrl(), LicenseDownloadResult.success( licenseFile,
+ actualSha1,
+ fileNameEntry.isPreferred() ) );
}
- // Save the URL so we don't download it again
- cache.put( license.getUrl(), LicenseDownloadResult.success( licenseFile,
- actualSha1,
- fileNameEntry.isPreferred() ) );
}
}
}
}
}
+ catch ( Exception e )
+ {
+ throw new MojoExecutionException( "Unable to parse license summary output file: " + licenseConfigFile,
+ e );
+ }
}
- catch ( Exception e )
- {
- throw new MojoExecutionException( "Unable to parse license summary output file: " + licenseConfigFile, e );
- }
- finally
- {
- FileUtil.tryClose( fis );
- }
- }
-
- /**
- * Returns the project ID for the artifact
- *
- * @param artifact the artifact
- * @return groupId:artifactId
- */
- private String getArtifactProjectId( Artifact artifact )
- {
- return artifact.getGroupId() + ":" + artifact.getArtifactId();
+ return configuredDepLicensesMap;
}
/**
@@ -918,10 +980,11 @@ private ProjectLicenseInfo createDependencyProject( MavenProject depMavenProject
ProjectLicenseInfo dependencyProject =
new ProjectLicenseInfo( depMavenProject.getGroupId(), depMavenProject.getArtifactId(),
depMavenProject.getVersion() );
- List> licenses = depMavenProject.getLicenses();
- for ( Object license : licenses )
+ @SuppressWarnings( "unchecked" )
+ List licenses = depMavenProject.getLicenses();
+ for ( License license : licenses )
{
- dependencyProject.addLicense( new ProjectLicense( (License) license ) );
+ dependencyProject.addLicense( new ProjectLicense( license ) );
}
return dependencyProject;
}
@@ -1148,25 +1211,32 @@ private void handleResult( String licenseUrl, LicenseDownloadResult result, Proj
private void handleError( ProjectLicenseInfo depProject, String msg ) throws MojoFailureException
{
- switch ( errorRemedy )
+ if ( depProject.isApproved() )
{
- case ignore:
- /* do nothing */
- break;
- case warn:
- getLog().warn( msg );
- break;
- case failFast:
- throw new MojoFailureException( msg );
- case xmlOutput:
- getLog().debug( msg );
- depProject.addDownloaderMessage( msg );
- break;
- default:
- throw new IllegalStateException( "Unexpected value of " + ErrorRemedy.class.getName() + ": "
- + errorRemedy );
+ getLog().debug( "Supressing manually approved license issue: " + msg );
+ }
+ else
+ {
+ switch ( errorRemedy )
+ {
+ case ignore:
+ /* do nothing */
+ break;
+ case warn:
+ getLog().warn( msg );
+ break;
+ case failFast:
+ throw new MojoFailureException( msg );
+ case xmlOutput:
+ getLog().debug( msg );
+ depProject.addDownloaderMessage( msg );
+ break;
+ default:
+ throw new IllegalStateException( "Unexpected value of " + ErrorRemedy.class.getName() + ": "
+ + errorRemedy );
+ }
+ downloadErrorCount++;
}
- downloadErrorCount++;
}
private String rewriteLicenseUrlIfNecessary( final String originalLicenseUrl )
diff --git a/src/main/java/org/codehaus/mojo/license/AggregateDownloadLicensesMojo.java b/src/main/java/org/codehaus/mojo/license/AggregateDownloadLicensesMojo.java
index 7df49e607..351eb408b 100644
--- a/src/main/java/org/codehaus/mojo/license/AggregateDownloadLicensesMojo.java
+++ b/src/main/java/org/codehaus/mojo/license/AggregateDownloadLicensesMojo.java
@@ -36,6 +36,19 @@
/**
* Download the license files of all aggregated dependencies of the current project, and generate a summary file
* containing a list of all dependencies and their licenses.
+ *
+ * The license files will be downloaded to {@link AbstractDownloadLicensesMojo#licensesOutputDirectory} to be included
+ * in the final packaging of the project if desired. The licenses are downloaded from the url field of the dependency
+ * POM.
+ *
+ * If the license information (license name and license URL) is missing or otherwise broken in a dependency POM, this
+ * mojo offers several fallback options:
+ *
+ * - {@link AbstractDownloadLicensesMojo#licensesConfigFile}
+ * - {@link AbstractDownloadLicensesMojo#errorRemedy}
+ * - {@link AbstractDownloadLicensesMojo#licenseUrlReplacements}
+ * - {@link AbstractDownloadLicensesMojo#licenseUrlFileNames}
+ *
*
* Created on 23/05/16.
*
diff --git a/src/main/java/org/codehaus/mojo/license/DownloadLicensesMojo.java b/src/main/java/org/codehaus/mojo/license/DownloadLicensesMojo.java
index b5ad8c859..4edc11b21 100644
--- a/src/main/java/org/codehaus/mojo/license/DownloadLicensesMojo.java
+++ b/src/main/java/org/codehaus/mojo/license/DownloadLicensesMojo.java
@@ -35,6 +35,19 @@
/**
* Download the license files of all the current project's dependencies, and generate a summary file containing a list
* of all dependencies and their licenses.
+ *
+ * The license files will be downloaded to {@link AbstractDownloadLicensesMojo#licensesOutputDirectory} to be included
+ * in the final packaging of the project if desired. The licenses are downloaded from the url field of the dependency
+ * POM.
+ *
+ * If the license information (license name and license URL) is missing or otherwise broken in a dependency POM, this
+ * mojo offers several fallback options:
+ *
+ * - {@link AbstractDownloadLicensesMojo#licensesConfigFile}
+ * - {@link AbstractDownloadLicensesMojo#errorRemedy}
+ * - {@link AbstractDownloadLicensesMojo#licenseUrlReplacements}
+ * - {@link AbstractDownloadLicensesMojo#licenseUrlFileNames}
+ *
*
* @author Paul Gier
* @since 1.0
diff --git a/src/main/java/org/codehaus/mojo/license/download/LicenseMatchers.java b/src/main/java/org/codehaus/mojo/license/download/LicenseMatchers.java
new file mode 100644
index 000000000..df003f47c
--- /dev/null
+++ b/src/main/java/org/codehaus/mojo/license/download/LicenseMatchers.java
@@ -0,0 +1,339 @@
+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 );
+ }
+ }
+ }
+
+ /**
+ * 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() );
+ }
+
+ }
+
+}
diff --git a/src/main/java/org/codehaus/mojo/license/download/LicenseSummaryReader.java b/src/main/java/org/codehaus/mojo/license/download/LicenseSummaryReader.java
index b1548e642..e057f3891 100644
--- a/src/main/java/org/codehaus/mojo/license/download/LicenseSummaryReader.java
+++ b/src/main/java/org/codehaus/mojo/license/download/LicenseSummaryReader.java
@@ -31,10 +31,16 @@
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
+
+import java.io.File;
import java.io.IOException;
import java.io.InputStream;
+import java.nio.file.Files;
+import java.util.AbstractMap;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
+import java.util.Map;
/**
* A LicenseSummaryReader.
@@ -46,6 +52,19 @@
public class LicenseSummaryReader
{
+ public static List parseLicenseSummary( File licSummaryFile )
+ throws IOException, ParserConfigurationException, SAXException
+ {
+ if ( licSummaryFile.exists() )
+ {
+ try ( InputStream in = Files.newInputStream( licSummaryFile.toPath() ) )
+ {
+ return parseLicenseSummary( in );
+ }
+ }
+ return Collections.emptyList();
+ }
+
/**
* Read a component-info.xml from an input stream into a ComponentInfo object.
*
@@ -106,19 +125,39 @@ else if ( node.getNodeName().equals( "version" ) )
}
else if ( node.getNodeName().equals( "licenses" ) )
{
- NodeList licensesChildNodes = node.getChildNodes();
- for ( int j = 0; j < licensesChildNodes.getLength(); ++j )
+ Map.Entry> entry = parseLicenses( node );
+ dependency.setLicenses( entry.getValue() );
+ dependency.setApproved( entry.getKey() );
+ }
+ else if ( node.getNodeName().equals( "matchLicenses" ) )
+ {
+ dependency.setHasMatchLicenses( true );
+ dependency.setMatchLicenses( parseLicenses( node ).getValue() );
+ }
+ }
+ return dependency;
+ }
+
+ private static Map.Entry> parseLicenses( Node node )
+ {
+ final List result = new ArrayList();
+ final NodeList licensesChildNodes = node.getChildNodes();
+ final Node approvedNode = node.getAttributes().getNamedItem( "approved" );
+ boolean approved = Boolean.parseBoolean( approvedNode != null ? approvedNode.getNodeValue() : "false" );
+ for ( int j = 0; j < licensesChildNodes.getLength(); ++j )
+ {
+ final Node licensesChildNode = licensesChildNodes.item( j );
+ final String nodeName = licensesChildNode.getNodeName();
+ if ( nodeName.equals( "license" ) )
+ {
+ if ( approved )
{
- Node licensesChildNode = licensesChildNodes.item( j );
- if ( licensesChildNode.getNodeName().equals( "license" ) )
- {
- ProjectLicense license = parseLicense( licensesChildNode );
- dependency.addLicense( license );
- }
+ throw new IllegalStateException( "Cannot combine approved=\"true\" with elements" );
}
+ result.add( parseLicense( licensesChildNode ) );
}
}
- return dependency;
+ return new AbstractMap.SimpleImmutableEntry>( approved, result );
}
private static ProjectLicense parseLicense( Node licenseNode )
diff --git a/src/main/java/org/codehaus/mojo/license/download/LicenseSummaryWriter.java b/src/main/java/org/codehaus/mojo/license/download/LicenseSummaryWriter.java
index 8462ccdd3..6238ab3f9 100644
--- a/src/main/java/org/codehaus/mojo/license/download/LicenseSummaryWriter.java
+++ b/src/main/java/org/codehaus/mojo/license/download/LicenseSummaryWriter.java
@@ -41,6 +41,8 @@
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
/**
* A LicenseSummaryWriter.
@@ -87,39 +89,69 @@ public static void writeLicenseSummary( List dependencies, F
public static Node createDependencyNode( Document doc, ProjectLicenseInfo dep, boolean writeVersions )
{
- Node depNode = doc.createElement( "dependency" );
+ final List messages = dep.getDownloaderMessages();
+ final boolean hasDownloaderMessages = messages != null && !messages.isEmpty();
+
+ final Node depNode = doc.createElement( "dependency" );
- Node groupIdNode = doc.createElement( "groupId" );
- groupIdNode.appendChild( doc.createTextNode( dep.getGroupId() ) );
+ final Node groupIdNode = doc.createElement( "groupId" );
+ groupIdNode.appendChild( doc.createTextNode( patternOrText( dep.getGroupId(), hasDownloaderMessages ) ) );
depNode.appendChild( groupIdNode );
- Node artifactIdNode = doc.createElement( "artifactId" );
- artifactIdNode.appendChild( doc.createTextNode( dep.getArtifactId() ) );
+ final Node artifactIdNode = doc.createElement( "artifactId" );
+ artifactIdNode.appendChild( doc.createTextNode( patternOrText( dep.getArtifactId(), hasDownloaderMessages ) ) );
depNode.appendChild( artifactIdNode );
if ( writeVersions )
{
- Node versionNode = doc.createElement( "version" );
- versionNode.appendChild( doc.createTextNode( dep.getVersion() ) );
+ final Node versionNode = doc.createElement( "version" );
+ versionNode.appendChild( doc.createTextNode( patternOrText( dep.getVersion(), hasDownloaderMessages ) ) );
depNode.appendChild( versionNode );
}
+ else if ( hasDownloaderMessages )
+ {
+ depNode.appendChild( doc.createComment( " " + dep.getVersion() + " " ) );
+ }
+
+ if ( hasDownloaderMessages )
+ {
+ Node matchLicensesNode = doc.createElement( "matchLicenses" );
+ if ( dep.getLicenses() == null || dep.getLicenses().size() == 0 )
+ {
+ matchLicensesNode.appendChild( doc.createComment( " Match dependency with no licenses " ) );
+ }
+ else
+ {
+ for ( ProjectLicense lic : dep.getLicenses() )
+ {
+ matchLicensesNode.appendChild( createLicenseNode( doc, lic, true ) );
+ }
+ }
+ depNode.appendChild( matchLicensesNode );
+ }
+
Node licensesNode = doc.createElement( "licenses" );
if ( dep.getLicenses() == null || dep.getLicenses().size() == 0 )
{
- licensesNode.appendChild( doc.createComment( "No license information available. " ) );
+ final String comment =
+ hasDownloaderMessages ? " Manually add license elements here: " : " No license information available. ";
+ licensesNode.appendChild( doc.createComment( comment ) );
}
else
{
+ if ( hasDownloaderMessages )
+ {
+ licensesNode.appendChild( doc.createComment( " Manually fix the existing license nodes: " ) );
+ }
for ( ProjectLicense lic : dep.getLicenses() )
{
- licensesNode.appendChild( createLicenseNode( doc, lic ) );
+ licensesNode.appendChild( createLicenseNode( doc, lic, false ) );
}
}
depNode.appendChild( licensesNode );
- final List messages = dep.getDownloaderMessages();
- if ( messages != null && !messages.isEmpty() )
+ if ( hasDownloaderMessages )
{
final Node downloaderMessagesNode = doc.createElement( "downloaderMessages" );
for ( String msg : messages )
@@ -135,46 +167,76 @@ public static Node createDependencyNode( Document doc, ProjectLicenseInfo dep, b
}
- public static Node createLicenseNode( Document doc, ProjectLicense lic )
+ public static Node createLicenseNode( Document doc, ProjectLicense lic, boolean isMatcher )
{
Node licenseNode = doc.createElement( "license" );
if ( lic.getName() != null )
{
Node licNameNode = doc.createElement( "name" );
- licNameNode.appendChild( doc.createTextNode( lic.getName() ) );
+ licNameNode.appendChild( doc.createTextNode( patternOrText( lic.getName(), isMatcher ) ) );
licenseNode.appendChild( licNameNode );
}
if ( lic.getUrl() != null )
{
Node licUrlNode = doc.createElement( "url" );
- licUrlNode.appendChild( doc.createTextNode( lic.getUrl() ) );
+ licUrlNode.appendChild( doc.createTextNode( patternOrText( lic.getUrl(), isMatcher ) ) );
licenseNode.appendChild( licUrlNode );
}
if ( lic.getDistribution() != null )
{
Node licDistNode = doc.createElement( "distribution" );
- licDistNode.appendChild( doc.createTextNode( lic.getDistribution() ) );
+ licDistNode.appendChild( doc.createTextNode( patternOrText( lic.getDistribution(), isMatcher ) ) );
licenseNode.appendChild( licDistNode );
}
if ( lic.getFile() != null )
{
Node licFileNode = doc.createElement( "file" );
- licFileNode.appendChild( doc.createTextNode( lic.getFile() ) );
+ licFileNode.appendChild( doc.createTextNode( patternOrText( lic.getFile(), isMatcher ) ) );
licenseNode.appendChild( licFileNode );
}
if ( lic.getComments() != null )
{
Node licCommentsNode = doc.createElement( "comments" );
- licCommentsNode.appendChild( doc.createTextNode( lic.getComments() ) );
+ licCommentsNode.appendChild( doc.createTextNode( patternOrText( lic.getComments(), isMatcher ) ) );
licenseNode.appendChild( licCommentsNode );
}
return licenseNode;
}
+ private static final Pattern WHITESPACE_PATTERN = Pattern.compile( "\\s{2,}" );
+
+ static String patternOrText( String value, boolean isMatcher )
+ {
+ if ( value != null && !value.isEmpty() && isMatcher )
+ {
+ final StringBuilder result = new StringBuilder();
+ final Matcher m = WHITESPACE_PATTERN.matcher( value );
+ int offset = 0;
+ while ( m.find() )
+ {
+ if ( m.start() > offset )
+ {
+ result.append( Pattern.quote( value.substring( offset, m.start() ) ) );
+ }
+ result.append( "\\s+" );
+ offset = m.end();
+ }
+ if ( offset < value.length() )
+ {
+ result.append( Pattern.quote( value.substring( offset ) ) );
+ }
+ return result.toString();
+ }
+ else
+ {
+ return value;
+ }
+ }
+
}
diff --git a/src/main/java/org/codehaus/mojo/license/download/ProjectLicense.java b/src/main/java/org/codehaus/mojo/license/download/ProjectLicense.java
index 8cdb162f9..f9c3e5826 100644
--- a/src/main/java/org/codehaus/mojo/license/download/ProjectLicense.java
+++ b/src/main/java/org/codehaus/mojo/license/download/ProjectLicense.java
@@ -29,7 +29,7 @@
*
* @since 1.17
*/
-public class ProjectLicense
+public class ProjectLicense implements Cloneable
{
@@ -226,4 +226,74 @@ public void setFile( String file )
this.file = file;
}
+ @Override
+ public ProjectLicense clone()
+ throws CloneNotSupportedException
+ {
+ return (ProjectLicense) super.clone();
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ( ( comments == null ) ? 0 : comments.hashCode() );
+ result = prime * result + ( ( distribution == null ) ? 0 : distribution.hashCode() );
+ result = prime * result + ( ( file == null ) ? 0 : file.hashCode() );
+ result = prime * result + ( ( name == null ) ? 0 : name.hashCode() );
+ result = prime * result + ( ( url == null ) ? 0 : url.hashCode() );
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ // CHECKSTYLE_OFF: NeedBraces
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ ProjectLicense other = (ProjectLicense) obj;
+ if ( comments == null )
+ {
+ if ( other.comments != null )
+ return false;
+ }
+ else if ( !comments.equals( other.comments ) )
+ return false;
+ if ( distribution == null )
+ {
+ if ( other.distribution != null )
+ return false;
+ }
+ else if ( !distribution.equals( other.distribution ) )
+ return false;
+ if ( file == null )
+ {
+ if ( other.file != null )
+ return false;
+ }
+ else if ( !file.equals( other.file ) )
+ return false;
+ if ( name == null )
+ {
+ if ( other.name != null )
+ return false;
+ }
+ else if ( !name.equals( other.name ) )
+ return false;
+ if ( url == null )
+ {
+ if ( other.url != null )
+ return false;
+ }
+ else if ( !url.equals( other.url ) )
+ return false;
+ return true;
+ // CHECKSTYLE_ON: NeedBraces
+ }
+
}
diff --git a/src/main/java/org/codehaus/mojo/license/download/ProjectLicenseInfo.java b/src/main/java/org/codehaus/mojo/license/download/ProjectLicenseInfo.java
index d6a2433af..b4ac186cf 100644
--- a/src/main/java/org/codehaus/mojo/license/download/ProjectLicenseInfo.java
+++ b/src/main/java/org/codehaus/mojo/license/download/ProjectLicenseInfo.java
@@ -26,6 +26,7 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
/**
* Contains the license information for a single project/dependency
@@ -43,8 +44,13 @@ public class ProjectLicenseInfo
private List licenses = new ArrayList<>();
+ private List matchLicenses = new ArrayList<>();
+ private boolean hasMatchLicenses = false;
+
private List downloaderMessages = new ArrayList<>();
+ private boolean approved;
+
/**
* Default constructor.
*/
@@ -60,6 +66,14 @@ public ProjectLicenseInfo( String groupId, String artifactId, String version )
this.version = version;
}
+ public ProjectLicenseInfo( String groupId, String artifactId, String version, boolean hasMatchLicenses )
+ {
+ this.groupId = groupId;
+ this.artifactId = artifactId;
+ this.version = version;
+ this.hasMatchLicenses = hasMatchLicenses;
+ }
+
public String getGroupId()
{
return groupId;
@@ -105,6 +119,31 @@ public void addLicense( ProjectLicense license )
licenses.add( license );
}
+ public List getMatchLicenses()
+ {
+ return matchLicenses;
+ }
+
+ public void setMatchLicenses( List matchLicenses )
+ {
+ this.matchLicenses = matchLicenses;
+ }
+
+ public void addMatchLicense( ProjectLicense license )
+ {
+ matchLicenses.add( license );
+ }
+
+ public boolean hasMatchLicenses()
+ {
+ return hasMatchLicenses;
+ }
+
+ public void setHasMatchLicenses( boolean hasMatchLicenses )
+ {
+ this.hasMatchLicenses = hasMatchLicenses;
+ }
+
/**
* The unique ID for the project
*
@@ -159,6 +198,14 @@ public boolean equals( Object compareTo )
return false;
}
+ public boolean deepEquals( ProjectLicenseInfo other )
+ {
+ return Objects.equals( groupId, other.groupId ) && Objects.equals( artifactId, other.artifactId )
+ && Objects.equals( version, other.version ) && Objects.equals( licenses, other.licenses )
+ && Objects.equals( matchLicenses, other.matchLicenses )
+ && Objects.equals( downloaderMessages, other.downloaderMessages );
+ }
+
/**
* {@inheritDoc}
*/
@@ -168,4 +215,38 @@ public int hashCode()
return getId().hashCode();
}
+
+ /**
+ * @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 void setApproved( boolean approved )
+ {
+ this.approved = approved;
+ }
+
+ public boolean isApproved()
+ {
+ return approved;
+ }
+
}
diff --git a/src/site/apt/examples/example-download-licenses.apt.vm b/src/site/apt/examples/example-download-licenses.apt.vm
index a17c16e14..1a3a625d3 100644
--- a/src/site/apt/examples/example-download-licenses.apt.vm
+++ b/src/site/apt/examples/example-download-licenses.apt.vm
@@ -36,10 +36,8 @@ Download Licenses Examples
based on the url field of the dependency POM.
After downloading the license files, the plugin will create a summary file in XML format which describes
- the license(s) associated with each dependency. Note that subsequent runs of the plugin will attempt
- to use the existing summary file if found instead of re-downloading the licenses every build.
- If the license summary file is found, only the licenses of new dependencies not in the file will
- be downloaded.
+ the license(s) associated with each dependency. Note that subsequent runs of the plugin will avoid downloading
+ the licenses unless the local file exists or forceDownload is set to true.
* Basic Example
diff --git a/src/test/java/org/codehaus/mojo/license/download/LicenseMatchersTest.java b/src/test/java/org/codehaus/mojo/license/download/LicenseMatchersTest.java
new file mode 100644
index 000000000..f0a67d16a
--- /dev/null
+++ b/src/test/java/org/codehaus/mojo/license/download/LicenseMatchersTest.java
@@ -0,0 +1,160 @@
+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.util.ArrayList;
+import java.util.List;
+
+import org.codehaus.mojo.license.download.LicenseMatchers.DependencyMatcher;
+import org.codehaus.mojo.license.download.LicenseMatchers.LicenseMatcher;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class LicenseMatchersTest
+{
+ @Test
+ public void licenseMatches()
+ {
+ final LicenseMatcher lm1 = new LicenseMatcher( "my license", "http://some.com", null, "important comment" );
+ final ProjectLicense lic =
+ new ProjectLicense( "my license", "http://some.com", null, "important comment", null );
+
+ Assert.assertTrue( lm1.matches( lic ) );
+ lic.setName( "other license" );
+ Assert.assertFalse( lm1.matches( lic ) );
+
+ final LicenseMatcher lm2 = new LicenseMatcher( "other.*", "http://some.com", null, "important comment" );
+ Assert.assertTrue( lm2.matches( lic ) );
+ lic.setUrl( "http://other.org" );
+ Assert.assertFalse( lm2.matches( lic ) );
+
+ final LicenseMatcher lm3 = new LicenseMatcher( "other.*", "http://other\\..*", null, "important comment" );
+ Assert.assertTrue( lm3.matches( lic ) );
+ lic.setComments( "other comment" );
+ Assert.assertFalse( lm3.matches( lic ) );
+
+ final LicenseMatcher lm4 = new LicenseMatcher( "other.*", "http://other\\..*", null, ".*comment" );
+ Assert.assertTrue( lm4.matches( lic ) );
+
+
+ lic.setComments( null );
+ lic.setDistribution( null );
+ lic.setFile( null );
+ lic.setName( null );
+ lic.setUrl( null );
+ final LicenseMatcher lm5 = new LicenseMatcher( (String) null, (String) null, (String) null, (String) null );
+ Assert.assertTrue( lm5.matches( lic ) );
+
+ lic.setComments( "" );
+ lic.setDistribution( "" );
+ lic.setFile( "" );
+ lic.setName( "" );
+ lic.setUrl( "" );
+ Assert.assertTrue( lm5.matches( lic ) );
+
+ }
+
+ @Test
+ public void replaceMatchesLegacy()
+ {
+ final ProjectLicenseInfo dep = new ProjectLicenseInfo( "myGroup", "myArtifact", "1a2.3" );
+ final ProjectLicenseInfo pli1 = new ProjectLicenseInfo( "myGroup", "myArtifact", "1.2.3", false );
+ final ProjectLicense lic2 = new ProjectLicense("lic2", "http://other.org", null, "other comment", null);
+ pli1.addLicense( lic2 );
+ final DependencyMatcher m1 = DependencyMatcher.of( pli1 );
+ Assert.assertTrue( m1.matches( dep ) ); // legacy mode disregards the version
+ dep.setVersion( "1.2.3" );
+ Assert.assertTrue( m1.matches( dep ) );
+
+ dep.addLicense( new ProjectLicense( "lic1", "http://some.org", null, "comment", null ) );
+ Assert.assertTrue( m1.matches( dep ) );
+ final LicenseMatchers matchers1 = LicenseMatchers.builder().matcher( m1 ).build();
+ matchers1.replaceMatches( dep );
+ Assert.assertEquals( 1, dep.getLicenses().size() );
+ Assert.assertEquals( lic2, dep.getLicenses().get( 0 ) );
+ Assert.assertNotSame( lic2, dep.getLicenses().get( 0 ) );
+ }
+
+ @Test
+ public void replaceMatches()
+ {
+
+ final ProjectLicenseInfo dep = new ProjectLicenseInfo( "myGroup", "myArtifact", "1.2.3" );
+ final DependencyMatcher m0 =
+ DependencyMatcher.of( new ProjectLicenseInfo( "myGroup", "myArtifact", null, true ) );
+ Assert.assertTrue( m0.matches( dep ) );
+
+ final DependencyMatcher m1 =
+ DependencyMatcher.of( new ProjectLicenseInfo( "myGroup", "myArtifact", "1\\.2\\.3", true ) );
+ Assert.assertTrue( m1.matches( dep ) );
+ dep.setGroupId( "otherGroup" );
+ Assert.assertFalse( m1.matches( dep ) );
+
+ final DependencyMatcher m2 =
+ DependencyMatcher.of( new ProjectLicenseInfo( "other.*", "myArtifact", "1\\.2\\.3", true ) );
+ Assert.assertTrue( m2.matches( dep ) );
+ dep.setArtifactId( "otherArtifact" );
+ Assert.assertFalse( m2.matches( dep ) );
+
+ final DependencyMatcher m3 =
+ DependencyMatcher.of( new ProjectLicenseInfo( "other.*", ".*Artifact", "1\\.2\\.3", true ) );
+ Assert.assertTrue( m3.matches( dep ) );
+ dep.setVersion( "2.2.2" );
+ Assert.assertFalse( m3.matches( dep ) );
+
+ final DependencyMatcher m4 =
+ DependencyMatcher.of( new ProjectLicenseInfo( "other.*", ".*Artifact", "2\\.2\\..*", true ) );
+ Assert.assertTrue( m4.matches( dep ) );
+
+ final LicenseMatchers matchers1 = LicenseMatchers.builder().matcher( m1 ).build();
+
+ final List oldLics = dep.cloneLicenses();
+ matchers1.replaceMatches( dep );
+ Assert.assertEquals( oldLics, dep.getLicenses() );
+
+ dep.addLicense( new ProjectLicense( "lic1", "http://some.org", null, "comment", null ) );
+ Assert.assertFalse( m1.matches( dep ) );
+
+ final ProjectLicenseInfo dep11 = new ProjectLicenseInfo( "myGroup", "myArtifact", "1.2.3" );
+ dep11.addLicense( new ProjectLicense( "lic1", "http://some.org", null, "comment", null ) );
+ final List oldLics11 = dep.cloneLicenses();
+ final ProjectLicenseInfo pli11 = new ProjectLicenseInfo( "myGroup", "myArtifact", "1\\.2\\.3", true );
+ pli11.addMatchLicense( new ProjectLicense( "lic1", "http://some\\.org", null, "comment", null ) );
+ pli11.addLicense( new ProjectLicense( "lic2", "http://other.org", null, "other comment", null ) );
+ final DependencyMatcher m11 = DependencyMatcher.of( pli11 );
+ Assert.assertTrue( m11.matches( dep11 ) );
+
+ Assert.assertEquals( oldLics11, dep11.getLicenses() );
+
+ final LicenseMatchers matchers11 = LicenseMatchers.builder().matcher( m11 ).build();
+ matchers11.replaceMatches( dep11 );
+
+ Assert.assertNotEquals( oldLics11, dep11.getLicenses() );
+
+ final List newLics = dep11.getLicenses();
+ Assert.assertEquals( 1, newLics.size() );
+ Assert.assertEquals( 1, newLics.size() );
+
+ }
+
+}
diff --git a/src/test/java/org/codehaus/mojo/license/download/LicenseSummaryTest.java b/src/test/java/org/codehaus/mojo/license/download/LicenseSummaryTest.java
index 262591e74..058e922f2 100644
--- a/src/test/java/org/codehaus/mojo/license/download/LicenseSummaryTest.java
+++ b/src/test/java/org/codehaus/mojo/license/download/LicenseSummaryTest.java
@@ -131,4 +131,14 @@ public void testWriteReadLicenseSummary()
}
}
+
+ @Test
+ public void patternOrText()
+ {
+ Assert.assertEquals( "\\Qsimple\\E", LicenseSummaryWriter.patternOrText( "simple", true ) );
+ Assert.assertEquals( "\\Qone two\\E", LicenseSummaryWriter.patternOrText( "one two", true ) );
+ Assert.assertEquals( "\\Qone\\E\\s+\\Qtwo\\E", LicenseSummaryWriter.patternOrText( "one two", true ) );
+ Assert.assertEquals( "\\Qone\ntwo\\E", LicenseSummaryWriter.patternOrText( "one\ntwo", true ) );
+ Assert.assertEquals( "\\Qone\\E\\s+\\Qtwo\\E", LicenseSummaryWriter.patternOrText( "one\n\t\ttwo", true ) );
+ }
}