diff --git a/src/it/it-display-dependency-updates-issue-258-dependencyIncludesAndExcludes/invoker.properties b/src/it/it-display-dependency-updates-issue-258-dependencyIncludesAndExcludes/invoker.properties new file mode 100644 index 000000000..c9c201caf --- /dev/null +++ b/src/it/it-display-dependency-updates-issue-258-dependencyIncludesAndExcludes/invoker.properties @@ -0,0 +1,9 @@ +invoker.goals.1=${project.groupId}:${project.artifactId}:${project.version}:display-dependency-updates -Dverbose=true -Dversions.outputFile=./output1.txt -DoutputEncoding=UTF-8 -DprocessPluginDependenciesInPluginManagement=false -DpluginDependencyIncludes=localhost:dummy-api + +invoker.goals.2=${project.groupId}:${project.artifactId}:${project.version}:display-dependency-updates -Dverbose=true -Dversions.outputFile=./output2.txt -DoutputEncoding=UTF-8 -DprocessPluginDependenciesInPluginManagement=false -DpluginDependencyExcludes=localhost:dummy-api + +invoker.goals.3=${project.groupId}:${project.artifactId}:${project.version}:display-dependency-updates -Dverbose=true -Dversions.outputFile=./output3.txt -DoutputEncoding=UTF-8 -DprocessPluginDependencies=false -DpluginManagementDependencyIncludes=localhost:dummy-impl + +invoker.goals.4=${project.groupId}:${project.artifactId}:${project.version}:display-dependency-updates -Dverbose=true -Dversions.outputFile=./output4.txt -DoutputEncoding=UTF-8 -DprocessPluginDependencies=false -DpluginManagementDependencyExcludes=localhost:dummy-impl + +invoker.goals.5=${project.groupId}:${project.artifactId}:${project.version}:display-dependency-updates -Dverbose=true -Dversions.outputFile=./output5.txt -DoutputEncoding=UTF-8 -DprocessPluginDependencies=false -DpluginManagementDependencyExcludes=localhost \ No newline at end of file diff --git a/src/it/it-display-dependency-updates-issue-258-dependencyIncludesAndExcludes/pom.xml b/src/it/it-display-dependency-updates-issue-258-dependencyIncludesAndExcludes/pom.xml new file mode 100644 index 000000000..aebe5f65d --- /dev/null +++ b/src/it/it-display-dependency-updates-issue-258-dependencyIncludesAndExcludes/pom.xml @@ -0,0 +1,47 @@ + + 4.0.0 + localhost + it-display-dependency-updates-issue-258-dependencyIncludesAndExcludes + 1.0 + pom + + + + + localhost + dummy-maven-plugin + 1.0 + + + localhost + dummy-api + 1.0 + + + + + + + + localhost + dummy-maven-plugin + 1.0 + + + localhost + dummy-impl + 1.0 + + + localhost + dummy-parent2 + 1.0 + + + + + + + \ No newline at end of file diff --git a/src/it/it-display-dependency-updates-issue-258-dependencyIncludesAndExcludes/verify.groovy b/src/it/it-display-dependency-updates-issue-258-dependencyIncludesAndExcludes/verify.groovy new file mode 100644 index 000000000..cdce154d8 --- /dev/null +++ b/src/it/it-display-dependency-updates-issue-258-dependencyIncludesAndExcludes/verify.groovy @@ -0,0 +1,18 @@ +output = new File(basedir, "output1.txt").text +assert output =~ /localhost:dummy-api/ +assert output !=~ /localhost:dummy-impl/ + +output = new File(basedir, "output2.txt").text +assert output !=~ /localhost:dummy-api/ +assert output =~ /localhost:dummy-impl/ + +output = new File(basedir, "output3.txt").text +assert output =~ /localhost:dummy-impl/ +assert output !=~ /localhost:dummy-parent2/ + +output = new File(basedir, "output4.txt").text +assert output !=~ /localhost:dummy-impl/ +assert output =~ /localhost:dummy-parent2/ + +output = new File(basedir, "output5.txt") +assert !output.exists( ) 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 index aadb8bd46..d2db90cc1 100644 --- a/src/it/it-display-dependency-updates-issue-318-dependencyExcludes/verify.groovy +++ b/src/it/it-display-dependency-updates-issue-318-dependencyExcludes/verify.groovy @@ -4,7 +4,6 @@ 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/verify.groovy b/src/it/it-display-dependency-updates-issue-318-dependencyIncludes-multi/verify.groovy index 4845c5558..9441f237e 100644 --- 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 @@ -5,7 +5,6 @@ assert buildLog.text.contains(""" [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/verify.groovy b/src/it/it-display-dependency-updates-issue-318-dependencyIncludes/verify.groovy index 4845c5558..9441f237e 100644 --- a/src/it/it-display-dependency-updates-issue-318-dependencyIncludes/verify.groovy +++ b/src/it/it-display-dependency-updates-issue-318-dependencyIncludes/verify.groovy @@ -5,7 +5,6 @@ assert buildLog.text.contains(""" [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/verify.groovy b/src/it/it-display-dependency-updates-issue-318-dependencyIncludesAndExcludes/verify.groovy index 347f310ae..f324a4706 100644 --- a/src/it/it-display-dependency-updates-issue-318-dependencyIncludesAndExcludes/verify.groovy +++ b/src/it/it-display-dependency-updates-issue-318-dependencyIncludesAndExcludes/verify.groovy @@ -4,7 +4,6 @@ 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/verify.groovy b/src/it/it-display-dependency-updates-issue-318-dependencyManagementExcludes/verify.groovy index df3e5a07e..f6bbd04f7 100644 --- a/src/it/it-display-dependency-updates-issue-318-dependencyManagementExcludes/verify.groovy +++ b/src/it/it-display-dependency-updates-issue-318-dependencyManagementExcludes/verify.groovy @@ -5,7 +5,6 @@ assert buildLog.text.contains(""" [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/verify.groovy b/src/it/it-display-dependency-updates-issue-318-dependencyManagementIncludes/verify.groovy index df3e5a07e..f6bbd04f7 100644 --- a/src/it/it-display-dependency-updates-issue-318-dependencyManagementIncludes/verify.groovy +++ b/src/it/it-display-dependency-updates-issue-318-dependencyManagementIncludes/verify.groovy @@ -5,7 +5,6 @@ assert buildLog.text.contains(""" [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 f4cf8274b..73a4f353a 100644 --- a/src/main/java/org/codehaus/mojo/versions/DisplayDependencyUpdatesMojo.java +++ b/src/main/java/org/codehaus/mojo/versions/DisplayDependencyUpdatesMojo.java @@ -28,6 +28,7 @@ import java.util.Objects; import java.util.Set; import java.util.TreeSet; +import java.util.stream.Collectors; import org.apache.maven.artifact.ArtifactUtils; import org.apache.maven.artifact.metadata.ArtifactMetadataRetrievalException; @@ -49,6 +50,8 @@ import org.codehaus.mojo.versions.utils.DependencyComparator; import org.codehaus.plexus.util.StringUtils; +import static org.apache.commons.lang3.StringUtils.countMatches; + /** * Displays all dependencies that have newer versions available. * It will also display dependencies which are used by a plugin or @@ -107,7 +110,7 @@ public class DisplayDependencyUpdatesMojo *

* *

- * Example: "mygroup:artifact:*,*:*:*:*:*:compile" + * Example: {@code "mygroup:artifact:*,*:*:*:*:*:compile"} *

* * @since 2.12.0 @@ -129,7 +132,7 @@ public class DisplayDependencyUpdatesMojo *

* *

- * Example: "mygroup:artifact:*,*:*:*:*:*:provided,*:*:*:*:*:system" + * Example: {@code "mygroup:artifact:*,*:*:*:*:*:provided,*:*:*:*:*:system"} *

* * @since 2.12.0 @@ -159,7 +162,7 @@ public class DisplayDependencyUpdatesMojo *

* *

- * Example: "mygroup:artifact:*,*:*:*:*:*:compile" + * Example: {@code "mygroup:artifact:*,*:*:*:*:*:compile"} *

* * @since 2.12.0 @@ -181,7 +184,7 @@ public class DisplayDependencyUpdatesMojo *

* *

- * Example: "mygroup:artifact:*,*:*:*:*:*:provided,*:*:*:*:*:system" + * Example: {@code "mygroup:artifact:*,*:*:*:*:*:provided,*:*:*:*:*:system"} *

* * @since 2.12.0 @@ -257,6 +260,77 @@ public class DisplayDependencyUpdatesMojo @Parameter( property = "verbose", defaultValue = "false" ) private boolean verbose; + /** + *

Only take these artifacts into consideration:
+ * Comma-separated list of {@code groupId:[artifactId[:version]]} patterns

+ * + *

+ * The wildcard "*" can be used as the only, first, last or both characters in each token. + * The version token does support version ranges. + *

+ * + *

+ * Example: {@code "mygroup:artifact:*,othergroup:*,anothergroup"} + *

+ * + * @since 2.12.0 + */ + @Parameter( property = "pluginDependencyIncludes", defaultValue = WildcardMatcher.WILDCARD ) + private List pluginDependencyIncludes; + + /** + *

Exclude these artifacts into consideration:
+ * Comma-separated list of {@code groupId:[artifactId[:version]]} patterns

+ * + *

+ * The wildcard "*" can be used as the only, first, last or both characters in each token. + * The version token does support version ranges. + *

+ * + *

+ * Example: {@code "mygroup:artifact:*,othergroup:*,anothergroup"} + *

+ * + * @since 2.12.0 + */ + @Parameter( property = "pluginDependencyExcludes" ) + private List pluginDependencyExcludes; + + /** + *

Only take these artifacts into consideration:
+ * Comma-separated list of {@code groupId:[artifactId[:version]]} patterns

+ + * The wildcard "*" can be used as the only, first, last or both characters in each token. + * The version token does support version ranges. + *

+ * + *

+ * Example: {@code "mygroup:artifact:*,othergroup:*,anothergroup"} + *

+ * + * @since 2.12.0 + */ + @Parameter( property = "pluginManagementDependencyIncludes", defaultValue = WildcardMatcher.WILDCARD ) + private List pluginManagementDependencyIncludes; + + /** + *

Exclude these artifacts into consideration:
+ * Comma-separated list of {@code groupId:[artifactId[:version]]} patterns

+ * + *

+ * The wildcard "*" can be used as the only, first, last or both characters in each token. + * The version token does support version ranges. + *

+ * + *

+ * Example: {@code "mygroup:artifact:*,othergroup:*,anothergroup"} + *

+ * + * @since 2.12.0 + */ + @Parameter( property = "pluginManagementDependencyExcludes" ) + private List pluginManagementDependencyExcludes; + // --------------------- GETTER / SETTER METHODS --------------------- private static Set extractPluginDependenciesFromPluginsInPluginManagement( Build build ) @@ -392,6 +466,8 @@ public void execute() { logInit(); + validateInput(); + Set dependencyManagement = new TreeSet<>( new DependencyComparator() ); DependencyManagement projectDependencyManagement = getProjectDependencyManagement( getProject() ); if ( projectDependencyManagement != null ) @@ -480,11 +556,16 @@ public void execute() } if ( isProcessPluginDependenciesInDependencyManagement() ) { + pluginDependenciesInPluginManagement = + filterPluginManagementIncludes( pluginDependenciesInPluginManagement ); + logUpdates( getHelper().lookupDependenciesUpdates( pluginDependenciesInPluginManagement, false ), "pluginManagement of plugins" ); } if ( isProcessingPluginDependencies() ) { + pluginDependencies = filterPluginDependencyIncludes( pluginDependencies ); + logUpdates( getHelper().lookupDependenciesUpdates( pluginDependencies, false ), "Plugin Dependencies" ); } } @@ -494,15 +575,56 @@ public void execute() } } + private void validateInput() throws MojoExecutionException + { + validateGAVList( dependencyIncludes, 6, "dependencyIncludes" ); + validateGAVList( dependencyExcludes, 6, "dependencyExcludes" ); + validateGAVList( dependencyManagementIncludes, 6, "dependencyManagementIncludes" ); + validateGAVList( dependencyManagementIncludes, 6, "dependencyManagementExcludes" ); + validateGAVList( pluginDependencyIncludes, 3, "pluginDependencyIncludes" ); + validateGAVList( pluginDependencyExcludes, 3, "pluginDependencyExcludes" ); + validateGAVList( pluginManagementDependencyIncludes, 3, "pluginManagementDependencyIncludes" ); + validateGAVList( pluginManagementDependencyExcludes, 3, "pluginManagementDependencyExcludes" ); + } + + /** + * Validates a list of GAV strings + * @param gavList list of the input GAV strings + * @param numSections number of sections in the GAV to verify against + * @param argumentName argument name to indicate in the exception + * @throws MojoExecutionException if the argument is invalid + */ + static void validateGAVList( List gavList, int numSections, String argumentName ) + throws MojoExecutionException + { + if ( gavList != null && gavList.stream().anyMatch( gav -> countMatches( gav, ":" ) >= numSections ) ) + { + throw new MojoExecutionException( argumentName + " should not contain more than 6 segments" ); + } + } + private Set filterDependencyIncludes( Set dependencies ) { - return filterDependencies( dependencies, dependencyIncludes, dependencyExcludes, "dependencies" ); + return filterDependencies( dependencies, dependencyIncludes, dependencyExcludes, "Dependencies" ); } private Set filterDependencyManagementIncludes( Set dependencyManagement ) { return filterDependencies( dependencyManagement, - dependencyManagementIncludes, dependencyManagementExcludes, "dependecyManagement" ); + dependencyManagementIncludes, dependencyManagementExcludes, "Dependecy Management" ); + } + + private Set filterPluginDependencyIncludes( Set dependencies ) + { + return filterDependencies( dependencies, pluginDependencyIncludes, pluginDependencyExcludes, + "Plugin Dependencies" ); + } + + private Set filterPluginManagementIncludes( Set dependencyManagement ) + { + return filterDependencies( dependencyManagement, + pluginManagementDependencyIncludes, pluginManagementDependencyExcludes, + "Plugin Management Dependencies" ); } private Set filterDependencies( @@ -515,15 +637,26 @@ private Set filterDependencies( 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 filtered = includeDeps.retainingIn( dependencies ); + filtered = excludeDeps.removingFrom( filtered ); - Set onlyIncludes = includeDeps.retainingIn( dependencies ); - Set filtered = excludeDeps.removingFrom( onlyIncludes ); + if ( getLog().isDebugEnabled() ) + { + 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 ) ); + getLog().debug( String.format( "Unfiltered %s: ", section ) + output( dependencies ) ); + getLog().debug( String.format( "Filtered %s: ", section ) + output( filtered ) ); + } return filtered; } + private String output( Set dependencies ) + { + return dependencies.stream() + .map( d -> String.format( "%s:%s:%s", d.getGroupId(), d.getArtifactId(), d.getVersion() ) ) + .collect( Collectors.joining( ", " ) ); + } private DependencyManagement getProjectDependencyManagement( MavenProject project ) { if ( processDependencyManagementTransitive ) diff --git a/src/test/java/org/codehaus/mojo/versions/DisplayDependencyUpdatesMojoTest.java b/src/test/java/org/codehaus/mojo/versions/DisplayDependencyUpdatesMojoTest.java new file mode 100644 index 000000000..5e31adcb4 --- /dev/null +++ b/src/test/java/org/codehaus/mojo/versions/DisplayDependencyUpdatesMojoTest.java @@ -0,0 +1,47 @@ +package org.codehaus.mojo.versions; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.util.Arrays; + +import org.apache.maven.plugin.MojoExecutionException; +import org.junit.Test; + +/** + * Basic tests for {@linkplain DisplayDependencyUpdatesMojo}. + * + * @author Andrzej Jarmoniuk + */ +public class DisplayDependencyUpdatesMojoTest +{ + @Test + public void testValidateGAVListSuccessful() throws MojoExecutionException + { + DisplayDependencyUpdatesMojo.validateGAVList( Arrays.asList( "group", "group:artifact", + "group:artifact:version" ), 3, "" ); + } + + @Test( expected = MojoExecutionException.class ) + public void testValidateGAVListFailed() throws MojoExecutionException + { + DisplayDependencyUpdatesMojo.validateGAVList( Arrays.asList( "group:artifact:version", + "group:artifact:version:type" ), 3, "" ); + } +}