From f47481966c143363572c8f6226a06ff541441f1e Mon Sep 17 00:00:00 2001 From: Christoph Linder Date: Mon, 27 Jun 2022 23:41:14 +0200 Subject: [PATCH] fixes #318 implement includes/excludes for dependencies fixes #318 implement includes/excludes for dependencies apply maven codestyle fixes #318 implement includes/excludes for dependencies bump @since 2.12.0 fixes #318 implement includes/excludes for dependencies make ITs work on windows fixes #318 implement includes/excludes for dependencies switch to List instead of splitting a list-style string myself fixes #318 implement includes/excludes for dependencies migrate ITs to test.properties since maven runner does some magic with "," in invoker.goals with no other workaround fix some descriptions fixes #318 implement includes/excludes for dependencies add IT for multiple comma-separated inclusion filters --- .../invoker.properties | 1 + .../pom.xml | 31 ++ .../test.properties | 1 + .../verify.groovy | 10 + .../invoker.properties | 1 + .../pom.xml | 31 ++ .../test.properties | 1 + .../verify.groovy | 11 + .../invoker.properties | 1 + .../pom.xml | 31 ++ .../test.properties | 1 + .../verify.groovy | 11 + .../invoker.properties | 1 + .../pom.xml | 31 ++ .../test.properties | 2 + .../verify.groovy | 10 + .../invoker.properties | 1 + .../pom.xml | 57 ++++ .../test.properties | 2 + .../verify.groovy | 11 + .../invoker.properties | 1 + .../pom.xml | 50 ++++ .../test.properties | 2 + .../verify.groovy | 11 + .../DisplayDependencyUpdatesMojo.java | 157 ++++++++-- .../versions/filtering/DependencyFilter.java | 67 +++++ .../filtering/NullAwareWildcardMatcher.java | 22 ++ .../versions/filtering/TokenizedMatcher.java | 107 +++++++ .../versions/filtering/WildcardMatcher.java | 95 +++++++ .../mojo/versions/DependencyBuilder.java | 133 +++++++++ .../codehaus/mojo/versions/HasGAVMatcher.java | 50 ++++ .../filtering/DependencyFilterTest.java | 205 ++++++++++++++ .../filtering/TokenizedMatcherTest.java | 167 +++++++++++ .../filtering/WildcardMatcherTest.java | 267 ++++++++++++++++++ 34 files changed, 1563 insertions(+), 17 deletions(-) create mode 100644 src/it/it-display-dependency-updates-issue-318-dependencyExcludes/invoker.properties create mode 100644 src/it/it-display-dependency-updates-issue-318-dependencyExcludes/pom.xml create mode 100644 src/it/it-display-dependency-updates-issue-318-dependencyExcludes/test.properties create mode 100644 src/it/it-display-dependency-updates-issue-318-dependencyExcludes/verify.groovy create mode 100644 src/it/it-display-dependency-updates-issue-318-dependencyIncludes-multi/invoker.properties create mode 100644 src/it/it-display-dependency-updates-issue-318-dependencyIncludes-multi/pom.xml create mode 100644 src/it/it-display-dependency-updates-issue-318-dependencyIncludes-multi/test.properties create mode 100644 src/it/it-display-dependency-updates-issue-318-dependencyIncludes-multi/verify.groovy create mode 100644 src/it/it-display-dependency-updates-issue-318-dependencyIncludes/invoker.properties create mode 100644 src/it/it-display-dependency-updates-issue-318-dependencyIncludes/pom.xml create mode 100644 src/it/it-display-dependency-updates-issue-318-dependencyIncludes/test.properties create mode 100644 src/it/it-display-dependency-updates-issue-318-dependencyIncludes/verify.groovy create mode 100644 src/it/it-display-dependency-updates-issue-318-dependencyIncludesAndExcludes/invoker.properties create mode 100644 src/it/it-display-dependency-updates-issue-318-dependencyIncludesAndExcludes/pom.xml create mode 100644 src/it/it-display-dependency-updates-issue-318-dependencyIncludesAndExcludes/test.properties create mode 100644 src/it/it-display-dependency-updates-issue-318-dependencyIncludesAndExcludes/verify.groovy create mode 100644 src/it/it-display-dependency-updates-issue-318-dependencyManagementExcludes/invoker.properties create mode 100644 src/it/it-display-dependency-updates-issue-318-dependencyManagementExcludes/pom.xml create mode 100644 src/it/it-display-dependency-updates-issue-318-dependencyManagementExcludes/test.properties create mode 100644 src/it/it-display-dependency-updates-issue-318-dependencyManagementExcludes/verify.groovy create mode 100644 src/it/it-display-dependency-updates-issue-318-dependencyManagementIncludes/invoker.properties create mode 100644 src/it/it-display-dependency-updates-issue-318-dependencyManagementIncludes/pom.xml create mode 100644 src/it/it-display-dependency-updates-issue-318-dependencyManagementIncludes/test.properties create mode 100644 src/it/it-display-dependency-updates-issue-318-dependencyManagementIncludes/verify.groovy create mode 100644 src/main/java/org/codehaus/mojo/versions/filtering/DependencyFilter.java create mode 100644 src/main/java/org/codehaus/mojo/versions/filtering/NullAwareWildcardMatcher.java create mode 100644 src/main/java/org/codehaus/mojo/versions/filtering/TokenizedMatcher.java create mode 100644 src/main/java/org/codehaus/mojo/versions/filtering/WildcardMatcher.java create mode 100644 src/test/java/org/codehaus/mojo/versions/DependencyBuilder.java create mode 100644 src/test/java/org/codehaus/mojo/versions/HasGAVMatcher.java create mode 100644 src/test/java/org/codehaus/mojo/versions/filtering/DependencyFilterTest.java create mode 100644 src/test/java/org/codehaus/mojo/versions/filtering/TokenizedMatcherTest.java create mode 100644 src/test/java/org/codehaus/mojo/versions/filtering/WildcardMatcherTest.java 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 6094d7cae..93358dde9 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; @@ -33,20 +43,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 @@ -90,6 +92,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. * @@ -98,6 +144,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. * @@ -117,7 +207,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") @@ -126,7 +216,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 */ @@ -136,7 +226,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 ); + } + + } + +}