diff --git a/src/it/it-display-dependency-updates-issue-318-dependencyExcludes/invoker.properties b/src/it/it-display-dependency-updates-issue-318-dependencyExcludes/invoker.properties
new file mode 100644
index 000000000..d06587396
--- /dev/null
+++ b/src/it/it-display-dependency-updates-issue-318-dependencyExcludes/invoker.properties
@@ -0,0 +1 @@
+invoker.goals=${project.groupId}:${project.artifactId}:${project.version}:display-dependency-updates
diff --git a/src/it/it-display-dependency-updates-issue-318-dependencyExcludes/pom.xml b/src/it/it-display-dependency-updates-issue-318-dependencyExcludes/pom.xml
new file mode 100644
index 000000000..bb408cf5d
--- /dev/null
+++ b/src/it/it-display-dependency-updates-issue-318-dependencyExcludes/pom.xml
@@ -0,0 +1,31 @@
+
+ 4.0.0
+ localhost
+ it-display-dependency-updates-issue-318-dependencyExcludes
+ 1.0
+ pom
+ it-display-dependency-updates-issue-318-dependencyExcludes
+ exclude a set of dependencies
+ http://localhost/
+
+
+ localhost
+ dummy-api
+ 1.0
+ provided
+
+
+ localhost
+ dummy-impl
+ 1.0
+
+
+ localhost
+ latest-versions-api
+ 2.0.8
+ test
+
+
+
diff --git a/src/it/it-display-dependency-updates-issue-318-dependencyExcludes/test.properties b/src/it/it-display-dependency-updates-issue-318-dependencyExcludes/test.properties
new file mode 100644
index 000000000..a60d6f77e
--- /dev/null
+++ b/src/it/it-display-dependency-updates-issue-318-dependencyExcludes/test.properties
@@ -0,0 +1 @@
+dependencyExcludes=*:*:*:*:*:compile,*:*:*:*:*:test
diff --git a/src/it/it-display-dependency-updates-issue-318-dependencyExcludes/verify.groovy b/src/it/it-display-dependency-updates-issue-318-dependencyExcludes/verify.groovy
new file mode 100644
index 000000000..aadb8bd46
--- /dev/null
+++ b/src/it/it-display-dependency-updates-issue-318-dependencyExcludes/verify.groovy
@@ -0,0 +1,10 @@
+def buildLog = new File( basedir, "build.log" )
+
+assert buildLog.text.contains( """
+[INFO] The following dependencies in Dependencies have newer versions:
+[INFO] localhost:dummy-api ....................................... 1.0 -> 3.0
+[INFO]
+[INFO] ------------------------------------------------------------------------
+""".replaceAll( "\n", System.lineSeparator() ) )
+
+return true
diff --git a/src/it/it-display-dependency-updates-issue-318-dependencyIncludes-multi/invoker.properties b/src/it/it-display-dependency-updates-issue-318-dependencyIncludes-multi/invoker.properties
new file mode 100644
index 000000000..d06587396
--- /dev/null
+++ b/src/it/it-display-dependency-updates-issue-318-dependencyIncludes-multi/invoker.properties
@@ -0,0 +1 @@
+invoker.goals=${project.groupId}:${project.artifactId}:${project.version}:display-dependency-updates
diff --git a/src/it/it-display-dependency-updates-issue-318-dependencyIncludes-multi/pom.xml b/src/it/it-display-dependency-updates-issue-318-dependencyIncludes-multi/pom.xml
new file mode 100644
index 000000000..e0dd9d954
--- /dev/null
+++ b/src/it/it-display-dependency-updates-issue-318-dependencyIncludes-multi/pom.xml
@@ -0,0 +1,31 @@
+
+ 4.0.0
+ localhost
+ it-display-dependency-updates-issue-318-dependencyIncludes-multi
+ 1.0
+ pom
+ it-display-dependency-updates-issue-318-dependencyIncludes-multi
+ include a set of dependencies using multiple filters
+ http://localhost/
+
+
+ localhost
+ dummy-api
+ 1.0
+
+
+ localhost
+ dummy-impl
+ 1.0
+ test
+
+
+ localhost
+ latest-versions-api
+ 2.0.8
+ provided
+
+
+
diff --git a/src/it/it-display-dependency-updates-issue-318-dependencyIncludes-multi/test.properties b/src/it/it-display-dependency-updates-issue-318-dependencyIncludes-multi/test.properties
new file mode 100644
index 000000000..e09c93220
--- /dev/null
+++ b/src/it/it-display-dependency-updates-issue-318-dependencyIncludes-multi/test.properties
@@ -0,0 +1 @@
+dependencyIncludes=*:dummy-api,*:dummy-impl
diff --git a/src/it/it-display-dependency-updates-issue-318-dependencyIncludes-multi/verify.groovy b/src/it/it-display-dependency-updates-issue-318-dependencyIncludes-multi/verify.groovy
new file mode 100644
index 000000000..4845c5558
--- /dev/null
+++ b/src/it/it-display-dependency-updates-issue-318-dependencyIncludes-multi/verify.groovy
@@ -0,0 +1,11 @@
+def buildLog = new File(basedir, "build.log")
+
+assert buildLog.text.contains("""
+[INFO] The following dependencies in Dependencies have newer versions:
+[INFO] localhost:dummy-api ....................................... 1.0 -> 3.0
+[INFO] localhost:dummy-impl ...................................... 1.0 -> 2.2
+[INFO]
+[INFO] ------------------------------------------------------------------------
+""".replaceAll( "\n", System.lineSeparator() ) )
+
+return true
diff --git a/src/it/it-display-dependency-updates-issue-318-dependencyIncludes/invoker.properties b/src/it/it-display-dependency-updates-issue-318-dependencyIncludes/invoker.properties
new file mode 100644
index 000000000..d06587396
--- /dev/null
+++ b/src/it/it-display-dependency-updates-issue-318-dependencyIncludes/invoker.properties
@@ -0,0 +1 @@
+invoker.goals=${project.groupId}:${project.artifactId}:${project.version}:display-dependency-updates
diff --git a/src/it/it-display-dependency-updates-issue-318-dependencyIncludes/pom.xml b/src/it/it-display-dependency-updates-issue-318-dependencyIncludes/pom.xml
new file mode 100644
index 000000000..6b893ec38
--- /dev/null
+++ b/src/it/it-display-dependency-updates-issue-318-dependencyIncludes/pom.xml
@@ -0,0 +1,31 @@
+
+ 4.0.0
+ localhost
+ it-display-dependency-updates-issue-318-dependencyIncludes
+ 1.0
+ pom
+ it-display-dependency-updates-issue-318-dependencyIncludes
+ include a set of dependencies
+ http://localhost/
+
+
+ localhost
+ dummy-api
+ 1.0
+
+
+ localhost
+ dummy-impl
+ 1.0
+ test
+
+
+ localhost
+ latest-versions-api
+ 2.0.8
+ provided
+
+
+
diff --git a/src/it/it-display-dependency-updates-issue-318-dependencyIncludes/test.properties b/src/it/it-display-dependency-updates-issue-318-dependencyIncludes/test.properties
new file mode 100644
index 000000000..7c76baa2c
--- /dev/null
+++ b/src/it/it-display-dependency-updates-issue-318-dependencyIncludes/test.properties
@@ -0,0 +1 @@
+dependencyIncludes=localhost:dummy-*:*:*:*:*
diff --git a/src/it/it-display-dependency-updates-issue-318-dependencyIncludes/verify.groovy b/src/it/it-display-dependency-updates-issue-318-dependencyIncludes/verify.groovy
new file mode 100644
index 000000000..4845c5558
--- /dev/null
+++ b/src/it/it-display-dependency-updates-issue-318-dependencyIncludes/verify.groovy
@@ -0,0 +1,11 @@
+def buildLog = new File(basedir, "build.log")
+
+assert buildLog.text.contains("""
+[INFO] The following dependencies in Dependencies have newer versions:
+[INFO] localhost:dummy-api ....................................... 1.0 -> 3.0
+[INFO] localhost:dummy-impl ...................................... 1.0 -> 2.2
+[INFO]
+[INFO] ------------------------------------------------------------------------
+""".replaceAll( "\n", System.lineSeparator() ) )
+
+return true
diff --git a/src/it/it-display-dependency-updates-issue-318-dependencyIncludesAndExcludes/invoker.properties b/src/it/it-display-dependency-updates-issue-318-dependencyIncludesAndExcludes/invoker.properties
new file mode 100644
index 000000000..d06587396
--- /dev/null
+++ b/src/it/it-display-dependency-updates-issue-318-dependencyIncludesAndExcludes/invoker.properties
@@ -0,0 +1 @@
+invoker.goals=${project.groupId}:${project.artifactId}:${project.version}:display-dependency-updates
diff --git a/src/it/it-display-dependency-updates-issue-318-dependencyIncludesAndExcludes/pom.xml b/src/it/it-display-dependency-updates-issue-318-dependencyIncludesAndExcludes/pom.xml
new file mode 100644
index 000000000..24b3d0d18
--- /dev/null
+++ b/src/it/it-display-dependency-updates-issue-318-dependencyIncludesAndExcludes/pom.xml
@@ -0,0 +1,31 @@
+
+ 4.0.0
+ localhost
+ it-display-dependency-updates-issue-318-dependencyIncludesAndExcludes
+ 1.0
+ pom
+ it-display-dependency-updates-issue-318-dependencyIncludesAndExcludes
+ combine dependency inclusion and exclusion
+ http://localhost/
+
+
+ localhost
+ dummy-api
+ 1.0
+
+
+ localhost
+ dummy-impl
+ 1.0
+ test
+
+
+ localhost
+ latest-versions-api
+ 2.0.8
+ provided
+
+
+
diff --git a/src/it/it-display-dependency-updates-issue-318-dependencyIncludesAndExcludes/test.properties b/src/it/it-display-dependency-updates-issue-318-dependencyIncludesAndExcludes/test.properties
new file mode 100644
index 000000000..4337c8a82
--- /dev/null
+++ b/src/it/it-display-dependency-updates-issue-318-dependencyIncludesAndExcludes/test.properties
@@ -0,0 +1,2 @@
+dependencyIncludes=localhost:dummy-*:*:*:*:*
+dependencyExcludes=*:dummy-impl:*:*:*
diff --git a/src/it/it-display-dependency-updates-issue-318-dependencyIncludesAndExcludes/verify.groovy b/src/it/it-display-dependency-updates-issue-318-dependencyIncludesAndExcludes/verify.groovy
new file mode 100644
index 000000000..347f310ae
--- /dev/null
+++ b/src/it/it-display-dependency-updates-issue-318-dependencyIncludesAndExcludes/verify.groovy
@@ -0,0 +1,10 @@
+def buildLog = new File(basedir, "build.log")
+
+assert buildLog.text.contains("""
+[INFO] The following dependencies in Dependencies have newer versions:
+[INFO] localhost:dummy-api ....................................... 1.0 -> 3.0
+[INFO]
+[INFO] ------------------------------------------------------------------------
+""".replaceAll( "\n", System.lineSeparator() ) )
+
+return true
diff --git a/src/it/it-display-dependency-updates-issue-318-dependencyManagementExcludes/invoker.properties b/src/it/it-display-dependency-updates-issue-318-dependencyManagementExcludes/invoker.properties
new file mode 100644
index 000000000..d06587396
--- /dev/null
+++ b/src/it/it-display-dependency-updates-issue-318-dependencyManagementExcludes/invoker.properties
@@ -0,0 +1 @@
+invoker.goals=${project.groupId}:${project.artifactId}:${project.version}:display-dependency-updates
diff --git a/src/it/it-display-dependency-updates-issue-318-dependencyManagementExcludes/pom.xml b/src/it/it-display-dependency-updates-issue-318-dependencyManagementExcludes/pom.xml
new file mode 100644
index 000000000..78561b399
--- /dev/null
+++ b/src/it/it-display-dependency-updates-issue-318-dependencyManagementExcludes/pom.xml
@@ -0,0 +1,57 @@
+
+ 4.0.0
+ localhost
+ it-display-dependency-updates-issue-318-dependencyManagementExcludes
+ 1.0
+ pom
+ it-display-dependency-updates-issue-318-dependencyManagementExcludes
+ exclude dependencies from dependencyManagement
+ http://localhost/
+
+
+ localhost
+ dummy-api
+ 2.0
+
+
+ localhost
+ dummy-impl
+ 2.0
+
+
+ localhost
+ latest-versions-api
+ 2.0.11
+
+
+
+
+
+ localhost
+ dummy-api
+ 1.0
+
+
+ localhost
+ dummy-impl
+ 1.0
+ test
+
+
+ localhost
+ latest-versions-api
+ 2.0.8
+ provided
+
+
+ localhost
+ dummy-api-impl-bom-pom
+ 1.0
+ pom
+ import
+
+
+
+
diff --git a/src/it/it-display-dependency-updates-issue-318-dependencyManagementExcludes/test.properties b/src/it/it-display-dependency-updates-issue-318-dependencyManagementExcludes/test.properties
new file mode 100644
index 000000000..6093047d1
--- /dev/null
+++ b/src/it/it-display-dependency-updates-issue-318-dependencyManagementExcludes/test.properties
@@ -0,0 +1,2 @@
+processDependencies=false
+dependencyManagementExcludes=*:*:*:*:*:provided,*:*:*:*:*:import
diff --git a/src/it/it-display-dependency-updates-issue-318-dependencyManagementExcludes/verify.groovy b/src/it/it-display-dependency-updates-issue-318-dependencyManagementExcludes/verify.groovy
new file mode 100644
index 000000000..df3e5a07e
--- /dev/null
+++ b/src/it/it-display-dependency-updates-issue-318-dependencyManagementExcludes/verify.groovy
@@ -0,0 +1,11 @@
+def buildLog = new File(basedir, "build.log")
+
+assert buildLog.text.contains("""
+[INFO] The following dependencies in Dependency Management have newer versions:
+[INFO] localhost:dummy-api ....................................... 1.0 -> 3.0
+[INFO] localhost:dummy-impl ...................................... 1.0 -> 2.2
+[INFO]
+[INFO] ------------------------------------------------------------------------
+""".replaceAll( "\n", System.lineSeparator() ) )
+
+return true
diff --git a/src/it/it-display-dependency-updates-issue-318-dependencyManagementIncludes/invoker.properties b/src/it/it-display-dependency-updates-issue-318-dependencyManagementIncludes/invoker.properties
new file mode 100644
index 000000000..d06587396
--- /dev/null
+++ b/src/it/it-display-dependency-updates-issue-318-dependencyManagementIncludes/invoker.properties
@@ -0,0 +1 @@
+invoker.goals=${project.groupId}:${project.artifactId}:${project.version}:display-dependency-updates
diff --git a/src/it/it-display-dependency-updates-issue-318-dependencyManagementIncludes/pom.xml b/src/it/it-display-dependency-updates-issue-318-dependencyManagementIncludes/pom.xml
new file mode 100644
index 000000000..50bd3430c
--- /dev/null
+++ b/src/it/it-display-dependency-updates-issue-318-dependencyManagementIncludes/pom.xml
@@ -0,0 +1,50 @@
+
+ 4.0.0
+ localhost
+ it-display-dependency-updates-issue-318-dependencyManagementIncludes
+ 1.0
+ pom
+ it-display-dependency-updates-issue-318-dependencyManagementIncludes
+ include dependencies from dependencyManagement
+ http://localhost/
+
+
+ localhost
+ dummy-api
+ 2.0
+
+
+ localhost
+ dummy-impl
+ 2.0
+
+
+ localhost
+ latest-versions-api
+ 2.0.11
+
+
+
+
+
+ localhost
+ dummy-api
+ 1.0
+
+
+ localhost
+ dummy-impl
+ 1.0
+ test
+
+
+ localhost
+ latest-versions-api
+ 2.0.8
+ provided
+
+
+
+
diff --git a/src/it/it-display-dependency-updates-issue-318-dependencyManagementIncludes/test.properties b/src/it/it-display-dependency-updates-issue-318-dependencyManagementIncludes/test.properties
new file mode 100644
index 000000000..04de1a195
--- /dev/null
+++ b/src/it/it-display-dependency-updates-issue-318-dependencyManagementIncludes/test.properties
@@ -0,0 +1,2 @@
+processDependencies=false
+dependencyManagementIncludes=*:*:*:*:*:null,*:*:*:*:*:test
diff --git a/src/it/it-display-dependency-updates-issue-318-dependencyManagementIncludes/verify.groovy b/src/it/it-display-dependency-updates-issue-318-dependencyManagementIncludes/verify.groovy
new file mode 100644
index 000000000..df3e5a07e
--- /dev/null
+++ b/src/it/it-display-dependency-updates-issue-318-dependencyManagementIncludes/verify.groovy
@@ -0,0 +1,11 @@
+def buildLog = new File(basedir, "build.log")
+
+assert buildLog.text.contains("""
+[INFO] The following dependencies in Dependency Management have newer versions:
+[INFO] localhost:dummy-api ....................................... 1.0 -> 3.0
+[INFO] localhost:dummy-impl ...................................... 1.0 -> 2.2
+[INFO]
+[INFO] ------------------------------------------------------------------------
+""".replaceAll( "\n", System.lineSeparator() ) )
+
+return true
diff --git a/src/main/java/org/codehaus/mojo/versions/DisplayDependencyUpdatesMojo.java b/src/main/java/org/codehaus/mojo/versions/DisplayDependencyUpdatesMojo.java
index c5ca6344c..a4009aee9 100644
--- a/src/main/java/org/codehaus/mojo/versions/DisplayDependencyUpdatesMojo.java
+++ b/src/main/java/org/codehaus/mojo/versions/DisplayDependencyUpdatesMojo.java
@@ -19,6 +19,16 @@
* under the License.
*/
+import javax.xml.stream.XMLStreamException;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.TreeSet;
+
import org.apache.maven.artifact.ArtifactUtils;
import org.apache.maven.artifact.metadata.ArtifactMetadataRetrievalException;
import org.apache.maven.artifact.versioning.ArtifactVersion;
@@ -34,20 +44,12 @@
import org.apache.maven.project.MavenProject;
import org.codehaus.mojo.versions.api.ArtifactVersions;
import org.codehaus.mojo.versions.api.UpdateScope;
+import org.codehaus.mojo.versions.filtering.DependencyFilter;
+import org.codehaus.mojo.versions.filtering.WildcardMatcher;
import org.codehaus.mojo.versions.rewriting.ModifiedPomXMLEventReader;
import org.codehaus.mojo.versions.utils.DependencyComparator;
import org.codehaus.plexus.util.StringUtils;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.TreeSet;
-
-import javax.xml.stream.XMLStreamException;
-
/**
* Displays all dependencies that have newer versions available.
* It will also display dependencies which are used by a plugin or
@@ -91,6 +93,50 @@ public class DisplayDependencyUpdatesMojo
@Parameter( property = "processDependencyManagementTransitive", defaultValue = "true" )
private boolean processDependencyManagementTransitive;
+ /**
+ * Only take these artifacts into consideration.
+ *
+ * Comma-separated list of extended GAV patterns.
+ *
+ *
+ * Extended GAV: groupId:artifactId:version:type:classifier:scope
+ *
+ *
+ * The wildcard "*" can be used as the only, first, last or both characters in each token.
+ * The version token does support version ranges.
+ *
+ *
+ *
+ * Example: "mygroup:artifact:*,*:*:*:*:*:compile"
+ *
+ *
+ * @since 2.12.0
+ */
+ @Parameter( property = "dependencyManagementIncludes", defaultValue = WildcardMatcher.WILDCARD )
+ private List dependencyManagementIncludes;
+
+ /**
+ * Exclude these artifacts from consideration.
+ *
+ * Comma-separated list of extended GAV patterns.
+ *
+ *
+ * Extended GAV: groupId:artifactId:version:type:classifier:scope
+ *
+ *
+ * The wildcard "*" can be used as the only, first, last or both characters in each token.
+ * The version token does support version ranges.
+ *
+ *
+ *
+ * Example: "mygroup:artifact:*,*:*:*:*:*:provided,*:*:*:*:*:system"
+ *
+ *
+ * @since 2.12.0
+ */
+ @Parameter( property = "dependencyManagementExcludes" )
+ private List dependencyManagementExcludes;
+
/**
* Whether to process the dependencies section of the project.
*
@@ -99,6 +145,50 @@ public class DisplayDependencyUpdatesMojo
@Parameter( property = "processDependencies", defaultValue = "true" )
private boolean processDependencies;
+ /**
+ * Only take these artifacts into consideration.
+ *
+ * Comma-separated list of extended GAV patterns.
+ *
+ *
+ * Extended GAV: groupId:artifactId:version:type:classifier:scope
+ *
+ *
+ * The wildcard "*" can be used as the only, first, last or both characters in each token.
+ * The version token does support version ranges.
+ *
+ *
+ *
+ * Example: "mygroup:artifact:*,*:*:*:*:*:compile"
+ *
+ *
+ * @since 2.12.0
+ */
+ @Parameter( property = "dependencyIncludes", defaultValue = WildcardMatcher.WILDCARD )
+ private List dependencyIncludes;
+
+ /**
+ * Exclude these artifacts from consideration.
+ *
+ * Comma-separated list of extended GAV patterns.
+ *
+ *
+ * Extended GAV: groupId:artifactId:version:type:classifier:scope
+ *
+ *
+ * The wildcard "*" can be used as the only, first, last or both characters in each token.
+ * The version token does support version ranges.
+ *
+ *
+ *
+ * Example: "mygroup:artifact:*,*:*:*:*:*:provided,*:*:*:*:*:system"
+ *
+ *
+ * @since 2.12.0
+ */
+ @Parameter( property = "dependencyExcludes" )
+ private List dependencyExcludes;
+
/**
* Whether to process the dependencies sections of plugins.
*
@@ -118,7 +208,7 @@ public class DisplayDependencyUpdatesMojo
/**
* Whether to allow the major version number to be changed.
* You need to set {@link #allowAnyUpdates} to false
to
- * get this configuration gets control.
+ * get this configuration gets control.
* @since 2.5
*/
@Parameter(property = "allowMajorUpdates", defaultValue = "true")
@@ -127,7 +217,7 @@ public class DisplayDependencyUpdatesMojo
/**
* Whether to allow the minor version number to be changed.
* You need to set {@link #allowMajorUpdates} to false
to
- * get this configuration gets control.
+ * get this configuration gets control.
*
* @since 2.5
*/
@@ -137,7 +227,7 @@ public class DisplayDependencyUpdatesMojo
/**
* Whether to allow the incremental version number to be changed.
* You need to set {@link #allowMinorUpdates} to false
to
- * get this configuration gets control.
+ * get this configuration gets control.
*
* @since 2.5
*/
@@ -292,6 +382,7 @@ public boolean isVerbose()
* @see org.codehaus.mojo.versions.AbstractVersionsUpdaterMojo#execute()
* @since 1.0-alpha-1
*/
+ @Override
public void execute()
throws MojoExecutionException, MojoFailureException
{
@@ -306,7 +397,7 @@ public void execute()
for ( Dependency dependency : dependenciesFromPom )
{
getLog().debug( "dependency from pom: " + dependency.getGroupId() + ":" + dependency.getArtifactId()
- + ":" + dependency.getVersion() );
+ + ":" + dependency.getVersion() + ":" + dependency.getScope() );
if ( dependency.getVersion() == null )
{
// get parent and get the information from there.
@@ -371,11 +462,15 @@ public void execute()
{
if ( isProcessingDependencyManagement() )
{
+ dependencyManagement = filterDependencyManagementIncludes( dependencyManagement );
+
logUpdates( getHelper().lookupDependenciesUpdates( dependencyManagement, false ),
"Dependency Management" );
}
if ( isProcessingDependencies() )
{
+ dependencies = filterDependencyIncludes( dependencies );
+
logUpdates( getHelper().lookupDependenciesUpdates( dependencies, false ), "Dependencies" );
}
if ( isProcessPluginDependenciesInDependencyManagement() )
@@ -394,6 +489,33 @@ public void execute()
}
}
+ private Set filterDependencyIncludes(Set dependencies) {
+ return filterDependencies(dependencies, dependencyIncludes, dependencyExcludes, "dependencies");
+ }
+
+ private Set filterDependencyManagementIncludes(Set dependencyManagement) {
+ return filterDependencies(dependencyManagement,
+ dependencyManagementIncludes, dependencyManagementExcludes, "dependecyManagement");
+ }
+
+ private Set filterDependencies(
+ Set dependencies,
+ List includes,
+ List excludes,
+ String section
+ ) {
+ DependencyFilter includeDeps = DependencyFilter.parseFrom(includes);
+ DependencyFilter excludeDeps = DependencyFilter.parseFrom(excludes);
+
+ getLog().debug(String.format("parsed includes in %s: %s -> %s", section, includes, includeDeps ));
+ getLog().debug(String.format("parsed excludes in %s: %s -> %s", section, excludes, excludeDeps ));
+
+ Set onlyIncludes = includeDeps.retainingIn(dependencies);
+ Set filtered = excludeDeps.removingFrom(onlyIncludes);
+
+ return filtered;
+ }
+
private DependencyManagement getProjectDependencyManagement(MavenProject project) {
if (processDependencyManagementTransitive) {
return project.getDependencyManagement();
@@ -493,9 +615,9 @@ private void logUpdates( Map updates, String secti
}
logLine( false, "" );
}
- }
-
-
+ }
+
+
if ( withUpdates.isEmpty() )
{
if ( !usingCurrent.isEmpty() )
@@ -524,6 +646,7 @@ private void logUpdates( Map updates, String secti
* @see org.codehaus.mojo.versions.AbstractVersionsUpdaterMojo#update(org.codehaus.mojo.versions.rewriting.ModifiedPomXMLEventReader)
* @since 1.0-alpha-1
*/
+ @Override
protected void update( ModifiedPomXMLEventReader pom )
throws MojoExecutionException, MojoFailureException, XMLStreamException
{
diff --git a/src/main/java/org/codehaus/mojo/versions/filtering/DependencyFilter.java b/src/main/java/org/codehaus/mojo/versions/filtering/DependencyFilter.java
new file mode 100644
index 000000000..af021add5
--- /dev/null
+++ b/src/main/java/org/codehaus/mojo/versions/filtering/DependencyFilter.java
@@ -0,0 +1,67 @@
+package org.codehaus.mojo.versions.filtering;
+
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+import org.apache.maven.model.Dependency;
+import org.codehaus.mojo.versions.utils.DependencyComparator;
+
+public class DependencyFilter
+{
+
+ private final String pattern;
+ private final List matchers;
+
+ DependencyFilter( String pattern, List matchers )
+ {
+ this.pattern = pattern;
+ this.matchers = matchers;
+ }
+
+ public static DependencyFilter parseFrom( List dependencies )
+ {
+ List matchers = dependencies.stream()
+ .map( TokenizedMatcher::parse )
+ .collect( Collectors.toList() );
+
+ String debugPattern = String.join( ",", dependencies );
+
+ return new DependencyFilter( debugPattern, matchers );
+ }
+
+ private static Predicate not( Predicate predicate )
+ {
+ return x -> !predicate.test( x );
+ }
+
+ @Override
+ public String toString()
+ {
+ return String.format( "%s{%s}", getClass().getSimpleName(), pattern );
+ }
+
+ public Set retainingIn( Set dependencies )
+ {
+ return filterBy( dependencies, this::matchersMatch );
+ }
+
+ public Set removingFrom( Set dependencies )
+ {
+ return filterBy( dependencies, not( this::matchersMatch ) );
+ }
+
+ private boolean matchersMatch( Dependency dependency )
+ {
+ return matchers.stream().anyMatch( m -> m.test( dependency ) );
+ }
+
+ private TreeSet filterBy( Set dependencies, Predicate predicate )
+ {
+ return dependencies.stream()
+ .filter( predicate )
+ .collect( Collectors.toCollection( () -> new TreeSet<>( new DependencyComparator() ) ) );
+ }
+}
diff --git a/src/main/java/org/codehaus/mojo/versions/filtering/NullAwareWildcardMatcher.java b/src/main/java/org/codehaus/mojo/versions/filtering/NullAwareWildcardMatcher.java
new file mode 100644
index 000000000..dfa8fef64
--- /dev/null
+++ b/src/main/java/org/codehaus/mojo/versions/filtering/NullAwareWildcardMatcher.java
@@ -0,0 +1,22 @@
+package org.codehaus.mojo.versions.filtering;
+
+public class NullAwareWildcardMatcher extends WildcardMatcher
+{
+ public static final String NULL_KEYWORD = "null";
+
+ public NullAwareWildcardMatcher( String pattern )
+ {
+ super( pattern );
+ }
+
+ @Override
+ public boolean test( String token )
+ {
+ if ( NULL_KEYWORD.equals( getPattern() ) )
+ {
+ return token == null;
+ }
+
+ return super.test( token );
+ }
+}
diff --git a/src/main/java/org/codehaus/mojo/versions/filtering/TokenizedMatcher.java b/src/main/java/org/codehaus/mojo/versions/filtering/TokenizedMatcher.java
new file mode 100644
index 000000000..336c9f7e8
--- /dev/null
+++ b/src/main/java/org/codehaus/mojo/versions/filtering/TokenizedMatcher.java
@@ -0,0 +1,107 @@
+package org.codehaus.mojo.versions.filtering;
+
+import java.util.Collections;
+import java.util.EnumMap;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.function.Predicate;
+
+import org.apache.maven.model.Dependency;
+
+public class TokenizedMatcher implements Predicate
+{
+ public enum Tokens
+ {
+ GROUP_ID( Dependency::getGroupId ),
+ ARTIFACT_ID( Dependency::getArtifactId ),
+ VERSION( Dependency::getVersion ),
+ TYPE( Dependency::getType ),
+ CLASSIFIER( Dependency::getClassifier ),
+ SCOPE( Dependency::getScope );
+
+ private final Function tokenExtractor;
+
+ Tokens( Function tokenExtractor )
+ {
+ this.tokenExtractor = tokenExtractor;
+ }
+
+ public Function getTokenExtractor()
+ {
+ return tokenExtractor;
+ }
+ }
+
+ private final Map> matchers;
+
+ private TokenizedMatcher( Map> matchers )
+ {
+ this.matchers = matchers;
+ }
+
+ @Override
+ public boolean test( Dependency dependency )
+ {
+ for ( Tokens token : Tokens.values() )
+ {
+ String tokenValue = token.getTokenExtractor().apply( dependency );
+
+ Predicate matcher = matchers.get( token );
+ boolean matches = matcher.test( tokenValue );
+
+ if ( !matches )
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public static TokenizedMatcher parse( String pattern )
+ {
+ EnumMap> matchers = new EnumMap<>( Tokens.class );
+
+ String[] split = pattern == null
+ ? new String[0]
+ : pattern.split( ":" );
+
+ String groupIdPattern = split.length >= 1
+ ? split[0]
+ : WildcardMatcher.WILDCARD;
+ matchers.put( Tokens.GROUP_ID, WildcardMatcher.parse( groupIdPattern ) );
+
+ String artifactIdPattern = split.length >= 2
+ ? split[1]
+ : WildcardMatcher.WILDCARD;
+ matchers.put( Tokens.ARTIFACT_ID, WildcardMatcher.parse( artifactIdPattern ) );
+
+ String versionPattern = split.length >= 3
+ ? split[2]
+ : WildcardMatcher.WILDCARD;
+ matchers.put( Tokens.VERSION, WildcardMatcher.parse( versionPattern ) );
+
+ String typePattern = split.length >= 4
+ ? split[3]
+ : WildcardMatcher.WILDCARD;
+ matchers.put( Tokens.TYPE, WildcardMatcher.parse( typePattern ) );
+
+ String classifierPattern = split.length >= 5
+ ? split[4]
+ : WildcardMatcher.WILDCARD;
+ matchers.put( Tokens.CLASSIFIER, new NullAwareWildcardMatcher( classifierPattern ) );
+
+ String scopePattern = split.length >= 6
+ ? split[5]
+ : WildcardMatcher.WILDCARD;
+ matchers.put( Tokens.SCOPE, new NullAwareWildcardMatcher( scopePattern ) );
+
+ return new TokenizedMatcher( Collections.unmodifiableMap( matchers ) );
+ }
+
+ @Override
+ public String toString()
+ {
+ return String.format( "%s{%s}", getClass().getSimpleName(), matchers );
+ }
+}
diff --git a/src/main/java/org/codehaus/mojo/versions/filtering/WildcardMatcher.java b/src/main/java/org/codehaus/mojo/versions/filtering/WildcardMatcher.java
new file mode 100644
index 000000000..f63f5e88b
--- /dev/null
+++ b/src/main/java/org/codehaus/mojo/versions/filtering/WildcardMatcher.java
@@ -0,0 +1,95 @@
+package org.codehaus.mojo.versions.filtering;
+
+import java.util.function.Predicate;
+
+import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
+import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
+import org.apache.maven.artifact.versioning.VersionRange;
+
+public class WildcardMatcher implements Predicate
+{
+ public static final String WILDCARD = "*";
+
+ private final String pattern;
+
+ protected WildcardMatcher( String pattern )
+ {
+ this.pattern = pattern;
+ }
+
+ public static WildcardMatcher parse( String pattern )
+ {
+ return new WildcardMatcher( pattern );
+ }
+
+ @Override
+ public boolean test( String token )
+ {
+ if ( token == null )
+ {
+ return WILDCARD.equals( pattern );
+ }
+
+ boolean matches;
+
+ // support full wildcard and implied wildcard
+ if ( WILDCARD.equals( pattern ) || pattern.isEmpty() )
+ {
+ matches = true;
+ }
+ // support contains wildcard
+ else if ( pattern.startsWith( WILDCARD ) && pattern.endsWith( WILDCARD ) )
+ {
+ String contains = pattern.substring( 1, pattern.length() - 1 );
+
+ matches = token.contains( contains );
+ }
+ // support leading wildcard
+ else if ( pattern.startsWith( WILDCARD ) )
+ {
+ matches = token.endsWith( pattern.substring( 1 ) );
+ }
+ // support trailing wildcard
+ else if ( pattern.endsWith( WILDCARD ) )
+ {
+ String prefix = pattern.substring( 0, pattern.length() - 1 );
+
+ matches = token.startsWith( prefix );
+ }
+ // support versions range
+ else if ( pattern.startsWith( "[" ) || pattern.startsWith( "(" ) )
+ {
+ matches = isVersionIncludedInRange( token, pattern );
+ }
+ // support exact match
+ else
+ {
+ matches = token.equals( pattern );
+ }
+
+ return matches;
+ }
+
+ private boolean isVersionIncludedInRange( final String version, final String range )
+ {
+ try
+ {
+ return VersionRange.createFromVersionSpec( range ).containsVersion( new DefaultArtifactVersion( version ) );
+ }
+ catch ( InvalidVersionSpecificationException e )
+ {
+ return false;
+ }
+ }
+
+ public String getPattern()
+ {
+ return pattern;
+ }
+
+ @Override
+ public String toString()
+ {
+ return String.format( "%s{%s}", getClass().getSimpleName(), pattern );
+ }
+}
diff --git a/src/test/java/org/codehaus/mojo/versions/DependencyBuilder.java b/src/test/java/org/codehaus/mojo/versions/DependencyBuilder.java
new file mode 100644
index 000000000..05bf3817b
--- /dev/null
+++ b/src/test/java/org/codehaus/mojo/versions/DependencyBuilder.java
@@ -0,0 +1,133 @@
+package org.codehaus.mojo.versions;
+
+import org.apache.maven.model.Dependency;
+
+public class DependencyBuilder
+{
+
+ public String getGroupId()
+ {
+ return groupId;
+ }
+
+ public DependencyBuilder withGroupId( String groupId )
+ {
+ this.groupId = groupId;
+ return this;
+ }
+
+ public String getArtifactId()
+ {
+ return artifactId;
+ }
+
+ public DependencyBuilder withArtifactId( String artifactId )
+ {
+ this.artifactId = artifactId;
+ return this;
+ }
+
+ public String getVersion()
+ {
+ return version;
+ }
+
+ public DependencyBuilder withVersion( String version )
+ {
+ this.version = version;
+ return this;
+ }
+
+ public String getType()
+ {
+ return type;
+ }
+
+ public DependencyBuilder withType( String type )
+ {
+ this.type = type;
+ return this;
+ }
+
+ public String getClassifier()
+ {
+ return classifier;
+ }
+
+ public DependencyBuilder withClassifier( String classifier )
+ {
+ this.classifier = classifier;
+ return this;
+ }
+
+ public String getScope()
+ {
+ return scope;
+ }
+
+ public DependencyBuilder withScope( String scope )
+ {
+ this.scope = scope;
+ return this;
+ }
+
+ private String groupId = null;
+ private String artifactId = null;
+ private String version = null;
+ private String type = null;
+ private String classifier = null;
+ private String scope = null;
+
+ public static DependencyBuilder newBuilder()
+ {
+ return new DependencyBuilder();
+ }
+
+ public static DependencyBuilder newBuilder( String groupId, String artifactId, String version, String type,
+ String classifier, String scope )
+ {
+ return newBuilder()
+ .withGroupId( groupId )
+ .withArtifactId( artifactId )
+ .withVersion( version )
+ .withType( type )
+ .withClassifier( classifier )
+ .withScope( scope );
+ }
+
+ public static DependencyBuilder newBuilder( String groupId, String artifactId, String version )
+ {
+ return newBuilder()
+ .withGroupId( groupId )
+ .withArtifactId( artifactId )
+ .withVersion( version );
+ }
+
+ public static Dependency dependencyWith( String groupId, String artifactId, String version )
+ {
+ return newBuilder( groupId, artifactId, version )
+ .build();
+ }
+
+ public static Dependency dependencyWith( String groupId, String artifactId, String version, String type,
+ String classifier, String scope )
+ {
+ return newBuilder( groupId, artifactId, version, type, classifier, scope )
+ .build();
+ }
+
+
+ public Dependency build()
+ {
+ Dependency dep = new Dependency();
+ dep.setGroupId( groupId );
+ dep.setArtifactId( artifactId );
+ dep.setVersion( version );
+ dep.setType( type );
+ dep.setClassifier( classifier );
+ dep.setScope( scope );
+
+ return dep;
+ }
+
+}
diff --git a/src/test/java/org/codehaus/mojo/versions/HasGAVMatcher.java b/src/test/java/org/codehaus/mojo/versions/HasGAVMatcher.java
new file mode 100644
index 000000000..dda261a64
--- /dev/null
+++ b/src/test/java/org/codehaus/mojo/versions/HasGAVMatcher.java
@@ -0,0 +1,50 @@
+package org.codehaus.mojo.versions;
+
+import java.util.Objects;
+
+import org.apache.maven.model.Dependency;
+import org.hamcrest.Description;
+import org.hamcrest.TypeSafeMatcher;
+
+/**
+ * Hamcrest-Matcher that matches a {@link Dependency} GAV
+ */
+public class HasGAVMatcher extends TypeSafeMatcher
+{
+ private final String groupId;
+ private final String artifactId;
+ private final String version;
+
+ public HasGAVMatcher( String groupId, String artifactId, String version )
+ {
+ this.groupId = groupId;
+ this.artifactId = artifactId;
+ this.version = version;
+ }
+
+ public static HasGAVMatcher hasGAVOf( Dependency dependency )
+ {
+ return hasGAV( dependency.getGroupId(), dependency.getArtifactId(), dependency.getVersion() );
+ }
+
+ public static HasGAVMatcher hasGAV( String groupId, String artifactId, String version )
+ {
+ return new HasGAVMatcher( groupId, artifactId, version );
+ }
+
+ @Override
+ protected boolean matchesSafely( Dependency item )
+ {
+ boolean result = Objects.equals( groupId, item.getGroupId() )
+ && Objects.equals( artifactId, item.getArtifactId() )
+ && Objects.equals( version, item.getVersion() );
+
+ return result;
+ }
+
+ @Override
+ public void describeTo( Description description )
+ {
+ description.appendText( String.format( "has GAV %s:%s:%s", groupId, artifactId, version ) );
+ }
+}
diff --git a/src/test/java/org/codehaus/mojo/versions/filtering/DependencyFilterTest.java b/src/test/java/org/codehaus/mojo/versions/filtering/DependencyFilterTest.java
new file mode 100644
index 000000000..5f3a6c69e
--- /dev/null
+++ b/src/test/java/org/codehaus/mojo/versions/filtering/DependencyFilterTest.java
@@ -0,0 +1,205 @@
+package org.codehaus.mojo.versions.filtering;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.maven.model.Dependency;
+import org.codehaus.mojo.versions.DependencyBuilder;
+import org.junit.jupiter.api.DisplayNameGeneration;
+import org.junit.jupiter.api.DisplayNameGenerator;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+
+import static java.util.Arrays.asList;
+import static org.codehaus.mojo.versions.HasGAVMatcher.hasGAV;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.containsInAnyOrder;
+import static org.hamcrest.Matchers.empty;
+
+@DisplayNameGeneration( DisplayNameGenerator.ReplaceUnderscores.class )
+class DependencyFilterTest
+{
+
+ @Nested
+ class RemoveFromTest
+ {
+ private final Set input = new HashSet<>( asList(
+ DependencyBuilder.dependencyWith( "foo", "bar", "1" ),
+ DependencyBuilder.dependencyWith( "localhost", "my-api", "2" ),
+ DependencyBuilder.dependencyWith( "localhost", "my-impl", "3" )
+ ) );
+
+ @Test
+ void removes_excluded_deps_with_exact_match()
+ {
+ DependencyFilter exclusions = DependencyFilter.parseFrom( asList( "localhost:my-impl:3" ) );
+
+ Set actual = exclusions.removingFrom( input );
+
+ assertThat(
+ actual,
+ containsInAnyOrder(
+ hasGAV( "foo", "bar", "1" ),
+ hasGAV( "localhost", "my-api", "2" )
+ )
+ );
+ }
+
+ @Test
+ void removes_excluded_deps_with_wildcard_in_version()
+ {
+ DependencyFilter exclusions = DependencyFilter.parseFrom( asList( "localhost:my-impl:*" ) );
+
+ Set actual = exclusions.removingFrom( input );
+
+ assertThat(
+ actual,
+ containsInAnyOrder(
+ hasGAV( "foo", "bar", "1" ),
+ hasGAV( "localhost", "my-api", "2" )
+ )
+ );
+ }
+
+ @Test
+ void removes_excluded_deps_with_wildcard_in_groupId()
+ {
+ DependencyFilter exclusions = DependencyFilter.parseFrom( asList( "localhost:*:*" ) );
+
+ Set actual = exclusions.removingFrom( input );
+
+ assertThat(
+ actual,
+ containsInAnyOrder(
+ hasGAV( "foo", "bar", "1" )
+ )
+ );
+ }
+
+ @Test
+ void removes_excluded_deps_with_all_wildcards()
+ {
+ DependencyFilter exclusions = DependencyFilter.parseFrom( asList( "*:*:*" ) );
+
+ Set actual = exclusions.removingFrom( input );
+
+ assertThat(
+ actual,
+ empty()
+ );
+ }
+
+ @Test
+ void removes_multiple_patterns()
+ {
+ DependencyFilter exclusions = DependencyFilter.parseFrom( asList(
+ "*:my-api",
+ "*:my-impl"
+ ) );
+
+ Set actual = exclusions.removingFrom( input );
+
+ assertThat(
+ actual,
+ containsInAnyOrder(
+ hasGAV( "foo", "bar", "1" )
+ )
+ );
+ }
+
+ }
+
+ @Nested
+ class RetainingInTest
+ {
+ private final Set input = new HashSet<>( asList(
+ DependencyBuilder.dependencyWith( "foo", "bar", "1" ),
+ DependencyBuilder.dependencyWith( "localhost", "my-api", "2" ),
+ DependencyBuilder.dependencyWith( "localhost", "my-impl", "3" )
+ ) );
+
+ @Test
+ void retains_only_deps_with_exact_match()
+ {
+ DependencyFilter exclusions = DependencyFilter.parseFrom( asList( "localhost:my-impl:3" ) );
+
+ Set actual = exclusions.retainingIn( input );
+
+ assertThat(
+ actual,
+ containsInAnyOrder(
+ hasGAV( "localhost", "my-impl", "3" )
+ )
+ );
+ }
+
+ @Test
+ void retains_only_deps_matching_wildcard_in_version()
+ {
+ DependencyFilter exclusions = DependencyFilter.parseFrom( asList( "localhost:my-api:*" ) );
+
+ Set actual = exclusions.retainingIn( input );
+
+ assertThat(
+ actual,
+ containsInAnyOrder(
+ hasGAV( "localhost", "my-api", "2" )
+ )
+ );
+ }
+
+ @Test
+ void retains_only_deps_with_multiple_wildcards()
+ {
+ DependencyFilter exclusions = DependencyFilter.parseFrom( asList( "localhost:my-*:*" ) );
+
+ Set actual = exclusions.retainingIn( input );
+
+ assertThat(
+ actual,
+ containsInAnyOrder(
+ hasGAV( "localhost", "my-api", "2" ),
+ hasGAV( "localhost", "my-impl", "3" )
+ )
+ );
+ }
+
+ @Test
+ void retains_all_on_all_wildcards()
+ {
+ DependencyFilter exclusions = DependencyFilter.parseFrom( asList( "*:*:*" ) );
+
+ Set actual = exclusions.retainingIn( input );
+
+ assertThat(
+ actual,
+ containsInAnyOrder(
+ hasGAV( "foo", "bar", "1" ),
+ hasGAV( "localhost", "my-api", "2" ),
+ hasGAV( "localhost", "my-impl", "3" )
+ )
+ );
+ }
+
+
+ @Test
+ void retains_multiple_patterns()
+ {
+ DependencyFilter exclusions = DependencyFilter.parseFrom( asList(
+ "*:my-api",
+ "*:my-impl"
+ ) );
+
+ Set actual = exclusions.retainingIn( input );
+
+ assertThat(
+ actual,
+ containsInAnyOrder(
+ hasGAV( "localhost", "my-api", "2" ),
+ hasGAV( "localhost", "my-impl", "3" )
+ )
+ );
+ }
+ }
+
+}
diff --git a/src/test/java/org/codehaus/mojo/versions/filtering/TokenizedMatcherTest.java b/src/test/java/org/codehaus/mojo/versions/filtering/TokenizedMatcherTest.java
new file mode 100644
index 000000000..02102d670
--- /dev/null
+++ b/src/test/java/org/codehaus/mojo/versions/filtering/TokenizedMatcherTest.java
@@ -0,0 +1,167 @@
+package org.codehaus.mojo.versions.filtering;
+
+import org.apache.maven.model.Dependency;
+import org.codehaus.mojo.versions.DependencyBuilder;
+import org.junit.jupiter.api.DisplayNameGeneration;
+import org.junit.jupiter.api.DisplayNameGenerator;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+@DisplayNameGeneration( DisplayNameGenerator.ReplaceUnderscores.class )
+class TokenizedMatcherTest
+{
+
+ @Nested
+ class ExactMatchPattern
+ {
+
+ private final TokenizedMatcher matcher = TokenizedMatcher
+ .parse( "group:artifact:1.0:jar:tests:compile" );
+
+
+ @Test
+ void accepts_exact_match()
+ {
+ Dependency input = DependencyBuilder.dependencyWith(
+ "group",
+ "artifact",
+ "1.0",
+ "jar",
+ "tests",
+ "compile" );
+
+ boolean actual = matcher.test( input );
+
+ assertTrue( actual );
+ }
+
+
+ @ParameterizedTest
+ @CsvSource( {
+ "xxxxx, artifact, 1.0, jar, tests, compile",
+ "group, xxxxxxxx, 1.0, jar, tests, compile",
+ "group, artifact, xxx, jar, tests, compile",
+ "group, artifact, 1.0, xxx, tests, compile",
+ "group, artifact, 1.0, jar, xxxxx, compile",
+ "group, artifact, 1.0, jar, tests, xxxxxxx",
+ } )
+ void rejects_differing_fields(
+ String group, String artifact, String version, String type, String classifier, String scope
+ )
+ {
+
+ Dependency input = DependencyBuilder.dependencyWith(
+ group,
+ artifact,
+ version,
+ type,
+ classifier,
+ scope );
+
+ boolean actual = matcher.test( input );
+
+ assertFalse( actual );
+ }
+ }
+
+ @Nested
+ class WildcardPattern
+ {
+
+ @Test
+ void accepts_wildcards()
+ {
+ Dependency input = DependencyBuilder.dependencyWith(
+ "foo",
+ "my-api",
+ "foo",
+ "foo",
+ "foo",
+ "foo" );
+
+ TokenizedMatcher matcher = TokenizedMatcher
+ .parse( "*:my-api" );
+
+ boolean actual = matcher.test( input );
+
+ assertTrue( actual );
+ }
+
+ @Nested
+ class NullClassifier
+ {
+ private final DependencyBuilder depBuilder = DependencyBuilder.newBuilder(
+ "foo",
+ "foo",
+ "foo",
+ "foo",
+ "foo",
+ "foo" );
+
+ private final TokenizedMatcher matcher = TokenizedMatcher
+ .parse( "*:*:*:*:null:*" );
+
+ @Test
+ void accepts_null_scope()
+ {
+ Dependency input = depBuilder.withClassifier( null ).build();
+
+ boolean actual = matcher.test( input );
+
+ assertTrue( actual );
+ }
+
+ @Test
+ void rejects_nonnull_scope()
+ {
+ Dependency input = depBuilder.withClassifier( "tests" ).build();
+
+ boolean actual = matcher.test( input );
+
+ assertFalse( actual );
+ }
+ }
+
+ @Nested
+ class NullScope
+ {
+ private final DependencyBuilder depBuilder = DependencyBuilder.newBuilder(
+ "foo",
+ "foo",
+ "foo",
+ "foo",
+ "foo",
+ "foo" );
+
+ private final TokenizedMatcher matcher = TokenizedMatcher
+ .parse( "*:*:*:*:*:null" );
+
+ @Test
+ void accepts_null_scope()
+ {
+ Dependency input = depBuilder.withScope( null ).build();
+
+ boolean actual = matcher.test( input );
+
+ assertTrue( actual );
+ }
+
+ @Test
+ void rejects_nonnull_scope()
+ {
+ Dependency input = depBuilder.withScope( "compile" ).build();
+
+ boolean actual = matcher.test( input );
+
+ assertFalse( actual );
+ }
+ }
+
+ }
+
+}
diff --git a/src/test/java/org/codehaus/mojo/versions/filtering/WildcardMatcherTest.java b/src/test/java/org/codehaus/mojo/versions/filtering/WildcardMatcherTest.java
new file mode 100644
index 000000000..655316b73
--- /dev/null
+++ b/src/test/java/org/codehaus/mojo/versions/filtering/WildcardMatcherTest.java
@@ -0,0 +1,267 @@
+package org.codehaus.mojo.versions.filtering;
+
+import org.junit.jupiter.api.DisplayNameGeneration;
+import org.junit.jupiter.api.DisplayNameGenerator;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+@DisplayNameGeneration( DisplayNameGenerator.ReplaceUnderscores.class )
+class WildcardMatcherTest
+{
+ @Nested
+ class ExactValueTest
+ {
+ private final WildcardMatcher matcher = WildcardMatcher.parse( "asdf" );
+
+ @Test
+ void matches_the_exact_input()
+ {
+ boolean actual = matcher.test( "asdf" );
+
+ assertTrue( actual );
+ }
+
+ @Test
+ void rejects_null()
+ {
+ boolean actual = matcher.test( null );
+
+ assertFalse( actual );
+ }
+
+ @ParameterizedTest
+ @ValueSource( strings = {
+ "",
+ " ",
+ "a",
+ "as",
+ "asf",
+ "asXf",
+ "asdfx",
+ } )
+ void rejects_different_input( String input )
+ {
+ boolean actual = matcher.test( input );
+
+ assertFalse( actual );
+ }
+ }
+
+ @Nested
+ class WildcardOnlyPattern
+ {
+ private final WildcardMatcher matcher = WildcardMatcher.parse( "*" );
+
+ @Test
+ void accepts_null()
+ {
+ boolean actual = matcher.test( null );
+
+ assertTrue( actual );
+ }
+
+
+ @ParameterizedTest
+ @ValueSource( strings = {
+ "",
+ " ",
+ "a",
+ "asdfx",
+ } )
+ void accepts( String input )
+ {
+ boolean actual = matcher.test( input );
+
+ assertTrue( actual );
+ }
+
+ }
+
+
+ @Nested
+ class PatternWithWildcardAtStartAndEnd
+ {
+ private final WildcardMatcher matcher = WildcardMatcher.parse( "*asdf*" );
+
+ @Test
+ void rejects_null()
+ {
+ boolean actual = matcher.test( null );
+
+ assertFalse( actual );
+ }
+
+
+ @ParameterizedTest
+ @ValueSource( strings = {
+ "asdf",
+ "fooasdf",
+ "asdfbar",
+ "fooasdfbar",
+ " asdf",
+ "asdf ",
+ " asdf ",
+ } )
+ void accepts( String input )
+ {
+ boolean actual = matcher.test( input );
+
+ assertTrue( actual );
+ }
+
+ @ParameterizedTest
+ @ValueSource( strings = {
+ "",
+ " ",
+ "foo",
+ } )
+ void rejects( String input )
+ {
+ boolean actual = matcher.test( input );
+
+ assertFalse( actual );
+ }
+
+ }
+
+ @Nested
+ class PatternStartingWithWildcard
+ {
+ private final WildcardMatcher matcher = WildcardMatcher.parse( "*asdf" );
+
+ @Test
+ void rejects_null()
+ {
+ boolean actual = matcher.test( null );
+
+ assertFalse( actual );
+ }
+
+
+ @ParameterizedTest
+ @ValueSource( strings = {
+ "asdf",
+ "asdfasdf",
+ " asdf",
+ "Xasdf",
+ "99999999asdf",
+ } )
+ void accepts( String input )
+ {
+ boolean actual = matcher.test( input );
+
+ assertTrue( actual );
+ }
+
+ @ParameterizedTest
+ @ValueSource( strings = {
+ "",
+ " ",
+ "asdf ",
+ "asdfx",
+ "asdfbanana",
+ } )
+ void rejects( String input )
+ {
+ boolean actual = matcher.test( input );
+
+ assertFalse( actual );
+ }
+
+ }
+
+ @Nested
+ class PatternEndingWithWildcard
+ {
+ private final WildcardMatcher matcher = WildcardMatcher.parse( "asdf*" );
+
+ @Test
+ void rejects_null()
+ {
+ boolean actual = matcher.test( null );
+
+ assertFalse( actual );
+ }
+
+
+ @ParameterizedTest
+ @ValueSource( strings = {
+ "asdf",
+ "asdfasdf",
+ "asdf ",
+ "asdfx",
+ "asdfbanana",
+ } )
+ void accepts( String input )
+ {
+ boolean actual = matcher.test( input );
+
+ assertTrue( actual );
+ }
+
+ @ParameterizedTest
+ @ValueSource( strings = {
+ "",
+ " ",
+ " asdf",
+ "Xasdf",
+ "99999999asdf",
+ } )
+ void rejects( String input )
+ {
+ boolean actual = matcher.test( input );
+
+ assertFalse( actual );
+ }
+
+ }
+
+ @Nested
+ class PatternWithVersionRange
+ {
+ private final WildcardMatcher matcher = WildcardMatcher.parse( "[2.0,3.0]" );
+
+ @Test
+ void rejects_null()
+ {
+ boolean actual = matcher.test( null );
+
+ assertFalse( actual );
+ }
+
+
+ @ParameterizedTest
+ @ValueSource( strings = {
+ "2.0",
+ "2.1",
+ "3.0",
+ } )
+ void accepts( String input )
+ {
+ boolean actual = matcher.test( input );
+
+ assertTrue( actual );
+ }
+
+ @ParameterizedTest
+ @ValueSource( strings = {
+ "",
+ " ",
+ "1.0",
+ "2.0-SNAPSHOT",
+ "4.0",
+ } )
+ void rejects( String input )
+ {
+ boolean actual = matcher.test( input );
+
+ assertFalse( actual );
+ }
+
+ }
+
+}