updateScope, boolean includeS
*/
ArtifactVersion[] getAllUpdates( VersionRange versionRange, boolean includeSnapshots );
+ /**
+ * Returns a {@linkplain Restriction} object for computing version upgrades
+ * with the given segment allowing updates, with all more major segments locked in place.
+ * The resulting restriction could be thought of as one
+ * retaining the versions on positions up to the held position,
+ * the position right after the position held in place will be incremented by one,
+ * and on all positions which are more minor than that, the range would contain -∞
+ * for the bottom bound and +∞ for the above bound.
+ * This will allow matching the required versions while not matching versions which are considered
+ * inferior than the zeroth version, i.e. versions with a qualifier.
+ *
+ * @param scope most major segment where updates are allowed Optional.empty() for no restriction
+ * @return {@linkplain Restriction} object based on the arguments
+ */
+ Restriction restrictionFor( Optional scope ) throws InvalidSegmentException;
+
+
+ /**
+ * Returns the {@link Restriction} objects for a segemnt scope which is to be ignored.
+ *
+ * @param ignored most major segment where updates are to be ignored; Optional.empty() for no ignored segments
+ * @return {@linkplain Restriction} object based on the arguments
+ */
+ Restriction restrictionForIgnoreScope( Optional ignored );
}
diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/api/VersionsHelper.java b/versions-common/src/main/java/org/codehaus/mojo/versions/api/VersionsHelper.java
index 28a11879dd..729aef0889 100644
--- a/versions-common/src/main/java/org/codehaus/mojo/versions/api/VersionsHelper.java
+++ b/versions-common/src/main/java/org/codehaus/mojo/versions/api/VersionsHelper.java
@@ -414,14 +414,4 @@ public VersionPropertiesMapRequest build()
*/
void resolveArtifact( Artifact artifact, boolean usePluginRepositories )
throws ArtifactResolutionException, ArtifactNotFoundException;
-
- /**
- * Attempts to interpolate the version from model properties.
- *
- * @param dependency the dependency
- * @param project the maven project
- * @return the dependency with interpolated property (as far as possible)
- * @since 2.14.0
- */
- Dependency interpolateVersion( Dependency dependency, MavenProject project );
}
diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/filtering/DependencyFilter.java b/versions-common/src/main/java/org/codehaus/mojo/versions/filtering/DependencyFilter.java
index e31a0481a5..00f58cb00c 100644
--- a/versions-common/src/main/java/org/codehaus/mojo/versions/filtering/DependencyFilter.java
+++ b/versions-common/src/main/java/org/codehaus/mojo/versions/filtering/DependencyFilter.java
@@ -19,6 +19,7 @@
* under the License.
*/
+import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
@@ -26,6 +27,7 @@
import java.util.stream.Collectors;
import org.apache.maven.model.Dependency;
+import org.apache.maven.plugin.logging.Log;
import org.codehaus.mojo.versions.utils.DependencyComparator;
public class DependencyFilter
@@ -62,12 +64,12 @@ public String toString()
return String.format( "%s{%s}", getClass().getSimpleName(), pattern );
}
- public Set retainingIn( Set dependencies )
+ public Set retainingIn( Collection dependencies )
{
return filterBy( dependencies, this::matchersMatch );
}
- public Set removingFrom( Set dependencies )
+ public Set removingFrom( Collection dependencies )
{
return filterBy( dependencies, not( this::matchersMatch ) );
}
@@ -77,10 +79,51 @@ private boolean matchersMatch( Dependency dependency )
return matchers.stream().anyMatch( m -> m.test( dependency ) );
}
- private TreeSet filterBy( Set dependencies, Predicate predicate )
+ private TreeSet filterBy( Collection dependencies, Predicate predicate )
{
return dependencies.stream()
.filter( predicate )
.collect( Collectors.toCollection( () -> new TreeSet<>( DependencyComparator.INSTANCE ) ) );
}
+
+ /**
+ * Returns a set of dependencies filtered by the given include- and exclude filters.
+ * @param dependencies collection of dependencies to filter
+ * @param includes a list of dependency includes
+ * @param excludes a list of dependency excludes
+ * @param section if log is not null, dependency section name for the debug log
+ * @param log null or log to which debug information will be logged
+ * @return filtered set of dependencies
+ */
+ public static Set filterDependencies(
+ Collection dependencies,
+ List includes,
+ List excludes,
+ String section,
+ Log log
+ )
+ {
+ DependencyFilter includeDeps = DependencyFilter.parseFrom( includes );
+ DependencyFilter excludeDeps = DependencyFilter.parseFrom( excludes );
+
+ Set filtered = includeDeps.retainingIn( dependencies );
+ filtered = excludeDeps.removingFrom( filtered );
+
+ if ( log != null && log.isDebugEnabled() )
+ {
+ log.debug( String.format( "parsed includes in %s: %s -> %s", section, includes, includeDeps ) );
+ log.debug( String.format( "parsed excludes in %s: %s -> %s", section, excludes, excludeDeps ) );
+ log.debug( String.format( "Unfiltered %s: ", section ) + output( dependencies ) );
+ log.debug( String.format( "Filtered %s: ", section ) + output( filtered ) );
+ }
+
+ return filtered;
+ }
+
+ private static String output( Collection dependencies )
+ {
+ return dependencies.stream()
+ .map( d -> String.format( "%s:%s:%s", d.getGroupId(), d.getArtifactId(), d.getVersion() ) )
+ .collect( Collectors.joining( ", " ) );
+ }
}
diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/ordering/AbstractVersionComparator.java b/versions-common/src/main/java/org/codehaus/mojo/versions/ordering/AbstractVersionComparator.java
index 30a4835026..75b659e047 100644
--- a/versions-common/src/main/java/org/codehaus/mojo/versions/ordering/AbstractVersionComparator.java
+++ b/versions-common/src/main/java/org/codehaus/mojo/versions/ordering/AbstractVersionComparator.java
@@ -29,14 +29,10 @@
public abstract class AbstractVersionComparator
implements VersionComparator
{
- /**
- * {@inheritDoc}
- */
+ @Override
public abstract int compare( ArtifactVersion o1, ArtifactVersion o2 );
- /**
- * {@inheritDoc}
- */
+ @Override
public final int getSegmentCount( ArtifactVersion v )
{
if ( v == null )
@@ -58,6 +54,7 @@ public final int getSegmentCount( ArtifactVersion v )
*
* @return the hash code.
*/
+ @Override
public int hashCode()
{
return getClass().hashCode();
@@ -71,6 +68,7 @@ public int hashCode()
* @see #hashCode()
* @see java.util.Hashtable
*/
+ @Override
public boolean equals( Object obj )
{
return obj == this || ( obj != null && getClass().equals( obj.getClass() ) );
diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/ordering/VersionComparator.java b/versions-common/src/main/java/org/codehaus/mojo/versions/ordering/VersionComparator.java
index 91a40848c8..1ca3e6b075 100644
--- a/versions-common/src/main/java/org/codehaus/mojo/versions/ordering/VersionComparator.java
+++ b/versions-common/src/main/java/org/codehaus/mojo/versions/ordering/VersionComparator.java
@@ -20,14 +20,8 @@
*/
import java.util.Comparator;
-import java.util.Optional;
import org.apache.maven.artifact.versioning.ArtifactVersion;
-import org.apache.maven.artifact.versioning.Restriction;
-import org.codehaus.mojo.versions.api.Segment;
-
-import static org.codehaus.mojo.versions.api.Segment.MAJOR;
-import static org.codehaus.mojo.versions.api.Segment.SUBINCREMENTAL;
/**
* A rule for comparing and manipulating versions.
@@ -43,31 +37,4 @@ public interface VersionComparator
* @since 1.0-beta-1
*/
int getSegmentCount( ArtifactVersion artifactVersion );
-
- /**
- * Returns a {@linkplain Restriction} object for computing version upgrades
- * with the given segment allowing updates, with all more major segments locked in place.
- * The resulting restriction could be thought of as one
- * retaining the versions on positions up to the held position,
- * the position right after the position held in place will be incremented by one,
- * and on all positions which are more minor than that, the range would contain -∞
- * for the bottom bound and +∞ for the above bound.
- * This will allow matching the required versions while not matching versions which are considered
- * inferior than the zeroth version, i.e. versions with a qualifier.
- *
- * @param currentVersion The current version.
- * @param scope most major segment where updates are allowed Optional.empty() for no restriction
- * @return {@linkplain Restriction} object based on the arguments
- */
- default Restriction restrictionFor( ArtifactVersion currentVersion, Optional scope )
- throws InvalidSegmentException
- {
- ArtifactVersion nextVersion = scope.filter( s -> s.isMajorTo( SUBINCREMENTAL ) )
- .map( s -> (ArtifactVersion)
- new BoundArtifactVersion( currentVersion, Segment.of( s.value() + 1 ) ) )
- .orElse( currentVersion );
- return new Restriction( nextVersion, false, scope.filter( MAJOR::isMajorTo )
- .map( s -> (ArtifactVersion) new BoundArtifactVersion( currentVersion, s ) ).orElse( null ),
- false );
- }
}
diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/utils/MavenProjectUtils.java b/versions-common/src/main/java/org/codehaus/mojo/versions/utils/MavenProjectUtils.java
new file mode 100644
index 0000000000..fd51c9d37e
--- /dev/null
+++ b/versions-common/src/main/java/org/codehaus/mojo/versions/utils/MavenProjectUtils.java
@@ -0,0 +1,168 @@
+package org.codehaus.mojo.versions.utils;
+/*
+ * 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.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.apache.maven.model.Build;
+import org.apache.maven.model.Dependency;
+import org.apache.maven.model.DependencyManagement;
+import org.apache.maven.model.PluginManagement;
+import org.apache.maven.plugin.logging.Log;
+import org.apache.maven.project.MavenProject;
+import org.codehaus.mojo.versions.api.VersionRetrievalException;
+
+import static java.util.Collections.emptyList;
+import static java.util.Optional.ofNullable;
+
+/**
+ * Utility methods for extracting dependencies from a {@link org.apache.maven.project.MavenProject}
+ */
+public class MavenProjectUtils
+{
+ /**
+ * Retrieves dependencies from the plugins section
+ * @param project {@link MavenProject} instance
+ * @return set of {@link Dependency} objects
+ * or an empty set if none have been retrieveddependencies or an empty set if none have been retrieved
+ */
+ public static Set extractPluginDependenciesFromPluginsInPluginManagement( MavenProject project )
+ {
+ return ofNullable( project.getBuild() )
+ .map( Build::getPluginManagement )
+ .map( PluginManagement::getPlugins )
+ .orElse( emptyList() )
+ .stream()
+ .filter( plugin -> plugin.getDependencies() != null )
+ .flatMap( plugin -> plugin.getDependencies().stream() )
+ .collect( () -> new TreeSet<>( DependencyComparator.INSTANCE ), Set::add, Set::addAll );
+ }
+
+ /**
+ * Retrieves dependencies from plugin management
+ * @param project {@link MavenProject} instance
+ * @return set of {@link Dependency} objects
+ * or an empty set if none have been retrieveddependencies or an empty set if none have been retrieved
+ */
+ public static Set extractDependenciesFromPlugins( MavenProject project )
+ {
+ return project.getBuildPlugins().parallelStream()
+ .filter( plugin -> plugin.getDependencies() != null )
+ .flatMap( plugin -> plugin.getDependencies().stream() )
+ .collect( () -> new TreeSet<>( DependencyComparator.INSTANCE ), Set::add, Set::addAll );
+ }
+
+ /**
+ * Retrieves dependencies from the dependency management of the project
+ * as well as its immediate parent project.
+ *
+ * @param project {@link MavenProject} instance
+ * @param processDependencyManagementTransitive if {@code true}, the original model will be considered
+ * instead of the interpolated model, which does not contain
+ * imported dependencies
+ * @return set of {@link Dependency} objects
+ * or an empty set if none have been retrieveddependencies or an empty set if none have been retrieved
+ */
+ public static Set extractDependenciesFromDependencyManagement( MavenProject project,
+ boolean processDependencyManagementTransitive, Log log )
+ throws VersionRetrievalException
+ {
+ Set dependencyManagement = new TreeSet<>( DependencyComparator.INSTANCE );
+ DependencyManagement projectDependencyManagement = processDependencyManagementTransitive
+ ? project.getDependencyManagement()
+ : project.getOriginalModel().getDependencyManagement();
+ if ( projectDependencyManagement != null )
+ {
+
+ List dependenciesFromPom = projectDependencyManagement.getDependencies();
+ for ( Dependency dependency : dependenciesFromPom )
+ {
+ log.debug( "dependency from pom: " + dependency.getGroupId() + ":" + dependency.getArtifactId()
+ + ":" + dependency.getVersion() + ":" + dependency.getScope() );
+ if ( dependency.getVersion() == null )
+ {
+ // get parent and get the information from there.
+ if ( project.hasParent() )
+ {
+ log.debug( "Reading parent dependencyManagement information" );
+ DependencyManagement parentProjectDependencyManagement =
+ processDependencyManagementTransitive
+ ? project.getParent().getDependencyManagement()
+ : project.getParent().getOriginalModel().getDependencyManagement();
+ if ( parentProjectDependencyManagement != null )
+ {
+ List parentDeps = parentProjectDependencyManagement.getDependencies();
+ for ( Dependency parentDep : parentDeps )
+ {
+ // only groupId && artifactId needed cause version is null
+ if ( dependency.getGroupId().equals( parentDep.getGroupId() )
+ && dependency.getArtifactId().equals( parentDep.getArtifactId() )
+ && dependency.getType().equals( parentDep.getType() ) )
+ {
+ dependencyManagement.add( parentDep );
+ }
+ }
+ }
+ }
+ else
+ {
+ String message = "We can't get the version for the dependency " + dependency.getGroupId() + ":"
+ + dependency.getArtifactId() + " because there does not exist a parent.";
+ log.error( message );
+ // Throw error because we will not able to get a version for a dependency.
+ throw new VersionRetrievalException( message );
+ }
+ }
+ else
+ {
+ dependency = interpolateVersion( dependency, project );
+ dependencyManagement.add( dependency );
+ }
+ }
+ }
+ return dependencyManagement;
+ }
+
+ /**
+ * Attempts to interpolate the version from model properties.
+ *
+ * @param dependency the dependency
+ * @param project the maven project
+ * @return the dependency with interpolated property (as far as possible)
+ * @since 2.14.0
+ */
+ public static Dependency interpolateVersion( final Dependency dependency, final MavenProject project )
+ {
+
+ // resolve version from model properties if necessary (e.g. "${mycomponent.myversion}"
+ if ( dependency.getVersion().startsWith( "${" ) )
+ {
+ final String resolvedVersion = project.getOriginalModel()
+ .getProperties().getProperty(
+ dependency.getVersion().substring( 2, dependency.getVersion().length() - 1 ) );
+ if ( resolvedVersion != null && !resolvedVersion.isEmpty() )
+ {
+ dependency.setVersion( resolvedVersion );
+ }
+ }
+ return dependency;
+ }
+}
diff --git a/versions-common/src/test/java/org/codehaus/mojo/versions/api/ArtifactVersionsTest.java b/versions-common/src/test/java/org/codehaus/mojo/versions/api/ArtifactVersionsTest.java
index 1f4b3633e1..25913f0af8 100644
--- a/versions-common/src/test/java/org/codehaus/mojo/versions/api/ArtifactVersionsTest.java
+++ b/versions-common/src/test/java/org/codehaus/mojo/versions/api/ArtifactVersionsTest.java
@@ -25,6 +25,7 @@
import org.apache.maven.artifact.handler.DefaultArtifactHandler;
import org.apache.maven.artifact.versioning.ArtifactVersion;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
+import org.apache.maven.artifact.versioning.Restriction;
import org.apache.maven.artifact.versioning.VersionRange;
import org.codehaus.mojo.versions.ordering.InvalidSegmentException;
import org.codehaus.mojo.versions.ordering.MavenVersionComparator;
@@ -33,9 +34,12 @@
import static java.util.Optional.of;
import static org.codehaus.mojo.versions.api.Segment.INCREMENTAL;
+import static org.codehaus.mojo.versions.api.Segment.MAJOR;
+import static org.codehaus.mojo.versions.api.Segment.MINOR;
import static org.codehaus.mojo.versions.api.Segment.SUBINCREMENTAL;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.arrayContaining;
+import static org.hamcrest.Matchers.arrayWithSize;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
@@ -141,4 +145,63 @@ public void testGetNewerVersionsWithSnapshot() throws InvalidSegmentException
assertThat( instance.getNewerVersions( "1.0.0-SNAPSHOT", of( SUBINCREMENTAL ), false, false ),
arrayContaining( new DefaultArtifactVersion( "1.0.0" ) ) );
}
+
+ @Test
+ public void testAllVersionsForIgnoreScopeSubIncremental()
+ {
+ ArtifactVersion[] versions = versions( "1.0.0", "1.0.0-1", "1.0.1" );
+ ArtifactVersions instance =
+ new ArtifactVersions( new DefaultArtifact( "default-group", "dummy-api",
+ "1.0.0", "foo", "bar",
+ "jar", null ),
+ Arrays.asList( versions ), new MavenVersionComparator() );
+ Restriction restriction = instance.restrictionForIgnoreScope( of( SUBINCREMENTAL ) );
+ ArtifactVersion[] filteredVersions = instance.getVersions( restriction, false );
+ assertThat( filteredVersions, arrayWithSize( 1 ) );
+ assertThat( filteredVersions, arrayContaining( new DefaultArtifactVersion( "1.0.1" ) ) );
+ }
+
+ @Test
+ public void testAllVersionsForIgnoreScopeIncremental()
+ {
+ ArtifactVersion[] versions = versions( "1.0.0", "1.0.0-1", "1.0.1", "1.1.0" );
+ ArtifactVersions instance =
+ new ArtifactVersions( new DefaultArtifact( "default-group", "dummy-api",
+ "1.0.0", "foo", "bar",
+ "jar", null ),
+ Arrays.asList( versions ), new MavenVersionComparator() );
+ Restriction restriction = instance.restrictionForIgnoreScope( of( INCREMENTAL ) );
+ ArtifactVersion[] filteredVersions = instance.getVersions( restriction, false );
+ assertThat( filteredVersions, arrayWithSize( 1 ) );
+ assertThat( filteredVersions, arrayContaining( new DefaultArtifactVersion( "1.1.0" ) ) );
+ }
+
+ @Test
+ public void testAllVersionsForIgnoreScopeMinor()
+ {
+ ArtifactVersion[] versions = versions( "1.0.0", "1.0.0-1", "1.0.1", "1.1.0", "2.0.0" );
+ ArtifactVersions instance =
+ new ArtifactVersions( new DefaultArtifact( "default-group", "dummy-api",
+ "1.0.0", "foo", "bar",
+ "jar", null ),
+ Arrays.asList( versions ), new MavenVersionComparator() );
+ Restriction restriction = instance.restrictionForIgnoreScope( of( MINOR ) );
+ ArtifactVersion[] filteredVersions = instance.getVersions( restriction, false );
+ assertThat( filteredVersions, arrayWithSize( 1 ) );
+ assertThat( filteredVersions, arrayContaining( new DefaultArtifactVersion( "2.0.0" ) ) );
+ }
+
+ @Test
+ public void testAllVersionsForIgnoreScopeMajor()
+ {
+ ArtifactVersion[] versions = versions( "1.0.0", "1.0.0-1", "1.0.1", "1.1.0", "2.0.0" );
+ ArtifactVersions instance =
+ new ArtifactVersions( new DefaultArtifact( "default-group", "dummy-api",
+ "1.0.0", "foo", "bar",
+ "jar", null ),
+ Arrays.asList( versions ), new MavenVersionComparator() );
+ Restriction restriction = instance.restrictionForIgnoreScope( of( MAJOR ) );
+ ArtifactVersion[] filteredVersions = instance.getVersions( restriction, false );
+ assertThat( filteredVersions, arrayWithSize( 0 ) );
+ }
}
diff --git a/versions-common/src/test/java/org/codehaus/mojo/versions/utils/PropertiesVersionsFileReaderTest.java b/versions-common/src/test/java/org/codehaus/mojo/versions/utils/PropertiesVersionsFileReaderTest.java
index 2041c82e9c..4f68d71089 100644
--- a/versions-common/src/test/java/org/codehaus/mojo/versions/utils/PropertiesVersionsFileReaderTest.java
+++ b/versions-common/src/test/java/org/codehaus/mojo/versions/utils/PropertiesVersionsFileReaderTest.java
@@ -25,11 +25,9 @@
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
+import org.junit.Assert;
import org.junit.Test;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
public class PropertiesVersionsFileReaderTest
{
@@ -43,9 +41,9 @@ public void testRead() throws IOException
reader.read();
int numberOfPropertiesConfig = 3;
- assertTrue( equalsCvsUnordered( "booking-api.version,booking-lib.version,be-air-impl.version",
+ Assert.assertTrue( equalsCvsUnordered( "booking-api.version,booking-lib.version,be-air-impl.version",
reader.getProperties() ) );
- assertEquals( numberOfPropertiesConfig, reader.getPropertiesConfig().length );
+ Assert.assertEquals( numberOfPropertiesConfig, reader.getPropertiesConfig().length );
}
private boolean equalsCvsUnordered( String csvExpected, String csvActual )
diff --git a/versions-enforcer/pom.xml b/versions-enforcer/pom.xml
new file mode 100644
index 0000000000..1c4462b7f5
--- /dev/null
+++ b/versions-enforcer/pom.xml
@@ -0,0 +1,80 @@
+
+
+
+ versions
+ org.codehaus.mojo.versions
+ 2.14.0-SNAPSHOT
+
+ 4.0.0
+
+ versions-enforcer
+
+ Versions Enforcer
+ Enforcer rules using Versions Maven Plugin
+
+
+
+ org.codehaus.mojo.versions
+ versions-common
+ ${project.version}
+
+
+
+ org.codehaus.mojo.versions
+ versions-test
+ ${project.version}
+ test
+
+
+
+ org.apache.maven.enforcer
+ enforcer-api
+ provided
+
+
+ org.apache.maven
+ maven-compat
+ ${mavenVersion}
+ provided
+
+
+
+ org.junit.jupiter
+ junit-jupiter
+ test
+
+
+ org.junit.vintage
+ junit-vintage-engine
+ test
+
+
+ org.hamcrest
+ hamcrest-core
+
+
+
+
+ org.apache.maven.plugin-testing
+ maven-plugin-testing-harness
+ test
+
+
+ org.mockito
+ mockito-inline
+ test
+
+
+ org.hamcrest
+ hamcrest
+ test
+
+
+ org.slf4j
+ slf4j-simple
+ test
+
+
+
\ No newline at end of file
diff --git a/versions-enforcer/src/main/java/org/apache/maven/plugins/enforcer/MaxDependencyUpdates.java b/versions-enforcer/src/main/java/org/apache/maven/plugins/enforcer/MaxDependencyUpdates.java
new file mode 100644
index 0000000000..5007a24d36
--- /dev/null
+++ b/versions-enforcer/src/main/java/org/apache/maven/plugins/enforcer/MaxDependencyUpdates.java
@@ -0,0 +1,392 @@
+package org.apache.maven.plugins.enforcer;
+/*
+ * 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 java.util.List;
+import java.util.Optional;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.stream.Collectors;
+
+import org.apache.maven.artifact.manager.WagonManager;
+import org.apache.maven.artifact.repository.ArtifactRepository;
+import org.apache.maven.artifact.resolver.ArtifactResolver;
+import org.apache.maven.artifact.versioning.ArtifactVersion;
+import org.apache.maven.enforcer.rule.api.EnforcerRule;
+import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
+import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper;
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.model.Dependency;
+import org.apache.maven.plugin.MojoExecution;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.project.MavenProject;
+import org.apache.maven.repository.RepositorySystem;
+import org.apache.maven.settings.Settings;
+import org.codehaus.mojo.versions.api.ArtifactVersions;
+import org.codehaus.mojo.versions.api.DefaultVersionsHelper;
+import org.codehaus.mojo.versions.api.Segment;
+import org.codehaus.mojo.versions.api.VersionRetrievalException;
+import org.codehaus.mojo.versions.api.VersionsHelper;
+import org.codehaus.mojo.versions.model.RuleSet;
+import org.codehaus.mojo.versions.utils.DependencyComparator;
+import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException;
+import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
+
+import static java.util.Collections.emptyList;
+import static java.util.Collections.singletonList;
+import static java.util.Optional.empty;
+import static java.util.Optional.of;
+import static org.codehaus.mojo.versions.api.Segment.INCREMENTAL;
+import static org.codehaus.mojo.versions.api.Segment.MINOR;
+import static org.codehaus.mojo.versions.api.Segment.SUBINCREMENTAL;
+import static org.codehaus.mojo.versions.filtering.DependencyFilter.filterDependencies;
+import static org.codehaus.mojo.versions.filtering.WildcardMatcher.WILDCARD;
+import static org.codehaus.mojo.versions.utils.MavenProjectUtils.extractDependenciesFromDependencyManagement;
+import static org.codehaus.mojo.versions.utils.MavenProjectUtils.extractDependenciesFromPlugins;
+import static org.codehaus.mojo.versions.utils.MavenProjectUtils.extractPluginDependenciesFromPluginsInPluginManagement;
+
+public class MaxDependencyUpdates implements EnforcerRule
+{
+ /**
+ * Maximum allowed number of updates.
+ *
+ * @since 2.14.0
+ */
+ protected int maxUpdates = 0;
+
+ /**
+ * Whether to process the dependencies section of the project.
+ *
+ * @since 2.14.0
+ */
+ protected boolean processDependencies = true;
+
+ /**
+ * Whether to process the dependencyManagement section of the project.
+ *
+ * @since 1.2
+ */
+ protected boolean processDependencyManagement = true;
+
+ /**
+ * Whether to process the dependencyManagement part transitive or not.
+ * In case of type {@code pom} and scope {@code import}, this means
+ * by default to report also the imported dependencies.
+ * If the parameter is set to {@code false}, the report will only show
+ * updates of the imported pom itself.
+ *
+ * @since 2.14.0
+ */
+ protected boolean processDependencyManagementTransitive = true;
+
+ /**
+ * Whether to process the dependencies sections of plugins.
+ *
+ * @since 2.14.0
+ */
+ protected boolean processPluginDependencies = true;
+
+ /**
+ * Whether to process the dependencies sections of plugins which are defined in pluginManagement.
+ *
+ * @since 2.14.0
+ */
+ protected boolean processPluginDependenciesInPluginManagement = true;
+
+ /**
+ * Whether minor updates should be ignored. Default {@code false}.
+ *
+ * Note: when {@code true}, will also assume that {@link #ignoreIncrementalUpdates}
+ * and {@link #ignoreSubIncrementalUpdates} are {@code true}.
+ *
+ * @since 2.14.0
+ */
+ protected boolean ignoreMinorUpdates = false;
+
+ /**
+ * Whether incremental updates should be ignored. Default {@code false}.
+ *
+ * Note: when {@code true}, will also assume that
+ * {@link #ignoreSubIncrementalUpdates} is {@code true}.
+ *
+ * @since 2.14.0
+ */
+ protected boolean ignoreIncrementalUpdates = false;
+
+ /**
+ * Whether sub-incremental updates should be ignored. Default {@code false}.
+ *
+ * @since 2.14.0
+ */
+ protected boolean ignoreSubIncrementalUpdates = false;
+
+ /**
+ * List of dependency inclusion patterns.
+ * Only dependencies matching all the patterns will be considered.
+ * The wildcard "*" can be used as the only, first, last or both characters in each token.
+ * The version token does support version ranges.
+ *
+ * @since 2.14.0
+ */
+ protected List dependencyIncludes = singletonList( WILDCARD );
+
+ /**
+ * List of dependency exclusion patterns.
+ * Only dependencies matching none of the patterns will be considered.
+ * The wildcard "*" can be used as the only, first, last or both characters in each token.
+ * The version token does support version ranges.
+ *
+ * @since 2.14.0
+ */
+ protected List dependencyExcludes = emptyList();
+
+ /**
+ * List of dependency management inclusion patterns.
+ * Only dependencies matching all the patterns will be considered.
+ * The wildcard "*" can be used as the only, first, last or both characters in each token.
+ * The version token does support version ranges.
+ *
+ * @since 2.14.0
+ */
+ protected List dependencyManagementIncludes = singletonList( WILDCARD );
+
+ /**
+ * List of dependency management exclusion patterns.
+ * Only dependencies matching none of the patterns will be considered.
+ * The wildcard "*" can be used as the only, first, last or both characters in each token.
+ * The version token does support version ranges.
+ *
+ * @since 2.14.0
+ */
+ protected List dependencyManagementExcludes = emptyList();
+
+ /**
+ * List of plugin dependency inclusion patterns.
+ * Only dependencies matching all the patterns will be considered.
+ * The wildcard "*" can be used as the only, first, last or both characters in each token.
+ * The version token does support version ranges.
+ *
+ * @since 2.14.0
+ */
+ protected List pluginDependencyIncludes = singletonList( WILDCARD );
+
+ /**
+ * List of plugin dependency exclusion patterns.
+ * Only dependencies matching none of the patterns will be considered.
+ * The wildcard "*" can be used as the only, first, last or both characters in each token.
+ * The version token does support version ranges.
+ *
+ * @since 2.14.0
+ */
+ protected List pluginDependencyExcludes = emptyList();
+
+ /**
+ * List of plugin management dependency inclusion patterns.
+ * Only dependencies matching all the patterns will be considered.
+ * The wildcard "*" can be used as the only, first, last or both characters in each token.
+ * The version token does support version ranges.
+ *
+ * @since 2.14.0
+ */
+ protected List pluginManagementDependencyIncludes = singletonList( WILDCARD );
+
+ /**
+ * List of plugin dependency management exclusion patterns.
+ * Only dependencies matching none of the patterns will be considered.
+ * The wildcard "*" can be used as the only, first, last or both characters in each token.
+ * The version token does support version ranges.
+ *
+ * @since 2.14.0
+ */
+ protected List pluginManagementDependencyExcludes = emptyList();
+
+ /**
+ * settings.xml's server id for the URL. This is used when wagon needs extra authentication information.
+ *
+ * @since 2.14.0
+ */
+ private String serverId;
+
+ /**
+ * URI of a ruleSet file containing the rules that control how to compare
+ * version numbers. The URI could be either a Wagon URI or a classpath URI
+ * (e.g. classpath:///package/sub/package/rules.xml
).
+ *
+ * 2.14.0
+ */
+ private String rulesUri;
+
+ /**
+ * Allows specifying the {@linkplain RuleSet} object describing rules
+ * on artifact versions to ignore when considering updates.
+ *
+ * @see
+ * Using the ruleSet element in the POM
+ *
+ * @since 2.14.0
+ */
+ protected RuleSet ruleSet;
+
+ /**
+ * Retrieves the maven project from metadata
+ * @param ruleHelper EnforcerRuleHelper object
+ * @return maven project
+ */
+ private static MavenProject getMavenProject( EnforcerRuleHelper ruleHelper )
+ {
+ try
+ {
+ return (MavenProject) ruleHelper.evaluate( "${project}" );
+ }
+ catch ( ExpressionEvaluationException e )
+ {
+ throw new RuntimeException( "Cannot evaluate project metadata", e );
+ }
+ }
+
+ /**
+ * Creates the VersionsHelper object
+ * @param ruleHelper EnforcerRuleHelper object
+ * @return VersionsHelper object
+ */
+ @SuppressWarnings( "unchecked" )
+ private static VersionsHelper createVersionsHelper( EnforcerRuleHelper ruleHelper,
+ String serverId,
+ String rulesUri,
+ RuleSet ruleSet )
+ {
+ try
+ {
+ return new DefaultVersionsHelper.Builder()
+ .withRepositorySystem( ruleHelper.getComponent( RepositorySystem.class ) )
+ .withArtifactResolver( ruleHelper.getComponent( ArtifactResolver.class ) )
+ .withAetherRepositorySystem( ruleHelper.getComponent( org.eclipse.aether.RepositorySystem.class ) )
+ .withLocalRepository( (ArtifactRepository) ruleHelper.evaluate( "${localRepository}" ) )
+ .withWagonManager( ruleHelper.getComponent( WagonManager.class ) )
+ .withSettings( (Settings) ruleHelper.evaluate( "${settings}" ) )
+ .withServerId( serverId )
+ .withRulesUri( rulesUri )
+ .withRuleSet( ruleSet )
+ .withIgnoredVersions( null )
+ .withLog( ruleHelper.getLog() )
+ .withMavenSession( (MavenSession) ruleHelper.evaluate( "${session}" ) )
+ .withMojoExecution( (MojoExecution) ruleHelper.evaluate( "${mojoExecution}" ) )
+ .build();
+ }
+ catch ( ExpressionEvaluationException e )
+ {
+ throw new RuntimeException( "Cannot evaluate project metadata", e );
+ }
+ catch ( ComponentLookupException | MojoExecutionException e )
+ {
+ throw new RuntimeException( "Cannot resolve dependency", e );
+ }
+ }
+ @Override
+ public boolean isCacheable()
+ {
+ return false;
+ }
+
+ @Override
+ public boolean isResultValid( EnforcerRule enforcerRule )
+ {
+ return false;
+ }
+
+ @Override
+ public String getCacheId()
+ {
+ return "Does not matter as not cacheable";
+ }
+
+ @Override
+ public void execute( EnforcerRuleHelper ruleHelper ) throws EnforcerRuleException
+ {
+ VersionsHelper versionsHelper = createVersionsHelper( ruleHelper, serverId != null ? serverId : "serverId",
+ rulesUri, ruleSet );
+ MavenProject project = getMavenProject( ruleHelper );
+ Set dependencies = new TreeSet<>( DependencyComparator.INSTANCE );
+ if ( processDependencyManagement )
+ {
+ try
+ {
+ dependencies.addAll( filterDependencies( extractDependenciesFromDependencyManagement( project,
+ processDependencyManagementTransitive, ruleHelper.getLog() ),
+ dependencyManagementIncludes, dependencyManagementExcludes, "Dependency Management",
+ ruleHelper.getLog() ) );
+ }
+ catch ( VersionRetrievalException e )
+ {
+ throw new EnforcerRuleException( e.getMessage() );
+ }
+ }
+ if ( processPluginDependencies )
+ {
+ dependencies.addAll( filterDependencies( extractDependenciesFromPlugins( project ),
+ pluginDependencyIncludes, pluginDependencyExcludes,
+ "Plugin Dependencies", ruleHelper.getLog() ) );
+ }
+ if ( processPluginDependenciesInPluginManagement )
+ {
+ dependencies.addAll( filterDependencies(
+ extractPluginDependenciesFromPluginsInPluginManagement( project ),
+ pluginManagementDependencyIncludes, pluginManagementDependencyExcludes,
+ "Plugin Management Dependencies", ruleHelper.getLog() ) );
+ }
+ if ( processDependencies )
+ {
+ dependencies.addAll( filterDependencies( project.getDependencies(),
+ dependencyIncludes, dependencyExcludes, "Dependencies", ruleHelper.getLog() ) );
+ }
+ try
+ {
+ Optional ignoredSegment = ignoreSubIncrementalUpdates
+ ? of( SUBINCREMENTAL )
+ : ignoreIncrementalUpdates
+ ? of( INCREMENTAL )
+ : ignoreMinorUpdates
+ ? of( MINOR )
+ : empty();
+ List upgradable = versionsHelper
+ .lookupDependenciesUpdates( dependencies, false )
+ .values()
+ .parallelStream()
+ .filter( v ->
+ v.getVersions( v.restrictionForIgnoreScope( ignoredSegment ), true ).length > 0
+ )
+ .collect( Collectors.toList() );
+ if ( upgradable.size() > maxUpdates )
+ {
+ throw new EnforcerRuleException( "More than " + maxUpdates + " upgradable artifacts detected: "
+ + upgradable.stream().map( av -> av.getArtifact() + " -> ["
+ + Arrays.stream( av.getVersions() )
+ .map( ArtifactVersion::toString )
+ .collect( Collectors.joining( ", " ) )
+ + "]" )
+ .collect( Collectors.joining( ", " ) ) );
+ }
+ }
+ catch ( VersionRetrievalException e )
+ {
+ throw new RuntimeException( e.getMessage(), e );
+ }
+ }
+}
diff --git a/versions-enforcer/src/site/markdown/max-dependency-updates.md b/versions-enforcer/src/site/markdown/max-dependency-updates.md
new file mode 100644
index 0000000000..baa522154d
--- /dev/null
+++ b/versions-enforcer/src/site/markdown/max-dependency-updates.md
@@ -0,0 +1,113 @@
+
+title: Introduction
+author: Andrzej Jarmoniuk
+date: 2022-10-27
+
+
+
+# Max Dependency Updates
+
+This Maven Enforcer rule checks if the number of dependency updates does not exceed the given threshold.
+
+The following parameters are supported by this rule:
+
+| Parameter | Default | Description |
+|-----------------------------------------------|:----------:|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `maxUpdates` | `0` | The total maximum allowed number of dependency updates. |
+| `processDependencies` | `true` | Whether to process the dependencies section of the project. |
+| `processDependencyManagement` | `true` | Whether to process the dependencyManagement section of the project. |
+| `processDependencyManagementTransitive` | `true` | Whether to process the dependencyManagement part transitive or not. In case of *type* `pom` and *scope* `import`, this means by default to report also the imported dependencies. If the parameter is set to false the report will only show updates of the imported pom itself. |
+| `processPluginDependencies` | `true` | Whether to process the dependencies sections of plugins. |
+| `processPluginDependenciesInPluginManagement` | `true` | Whether to process the dependencies sections of plugins which are defined in pluginManagement. |
+| `ignoreMinorUpdates` | `false` | Whether minor updates should be ignored. Default `false`.
**Note:** when true, will also assume that `ignoreIncrementalUpdates` and `ignoreSubIncrementalUpdates` are also `true`. |
+| `ignoreIncrementalUpdates` | `false` | Whether incremental updates should be ignored. Default `false`.
**Note:** when true, will also assume that `ignoreSubIncrementalUpdates` is also `true`. |
+| `ignoreSubIncrementalUpdates` | `false` | Whether sub-incremental updates should be ignored. Default `false`. |
+| `dependencyIncludes` | `*` | List of dependency inclusion patterns. Only dependencies matching all the patterns will be considered.
The wildcard (`*`) can be used as the only, first, last or both characters in each token. The version token does support version ranges. |
+| `dependencyExcludes` | (empty) | List of dependency exclusion patterns. Only dependencies matching none of the patterns will be considered.
The wildcard (`*`) can be used as the only, first, last or both characters in each token. The version token does support version ranges. |
+| `dependencyManagementIncludes` | `*` | List of dependency management inclusion patterns. Only dependencies matching all the patterns will be considered.
The wildcard (`*`) can be used as the only, first, last or both characters in each token. The version token does support version ranges. |
+| `dependencyManagementExcludes` | (empty) | List of dependency management exclusion patterns. Only dependencies matching none of the patterns will be considered.
The wildcard (`*`) can be used as the only, first, last or both characters in each token. The version token does support version ranges. |
+| `pluginDependencyIncludes` | `*` | List of plugin dependency inclusion patterns. Only dependencies matching all the patterns will be considered.
The wildcard (`*`) can be used as the only, first, last or both characters in each token. The version token does support version ranges. |
+| `pluginDependencyExcludes` | (empty) | List of plugin dependency exclusion patterns. Only dependencies matching none of the patterns will be considered.
The wildcard (`*`) can be used as the only, first, last or both characters in each token. The version token does support version ranges. |
+| `pluginManagementDependencyIncludes` | `*` | List of plugin management dependency inclusion patterns. Only dependencies matching all the patterns will be considered.
The wildcard (`*`) can be used as the only, first, last or both characters in each token. The version token does support version ranges. |
+| `pluginManagementDependencyExcludes` | (empty) | List of plugin management dependency exclusion patterns. Only dependencies matching none of the patterns will be considered.
The wildcard (`*`) can be used as the only, first, last or both characters in each token. The version token does support version ranges. |
+| `serverId` | `serverId` | *settings.xml*'s server id for the URL. This is used when wagon needs extra authentication information. |
+| `rulesUri` | | URI of a ruleSet file containing the rules that control how to compare version numbers. The URI could be either a Wagon URI or a classpath URI (e.g. *classpath:\/\/\/package/sub/package/rules.xml*). |
+| `ruleSet` | | Allows specifying the `RuleSet` object describing rules on artifact versions to ignore when considering updates.
See: [Using the ruleSet element in the POM](../version-rules.html#Using_the_ruleSet_element_in_the_POM) |
+
+**Note:** Inclusion/exclusion parameters like `dependencyIncludes`, `dependencyExcludes`, etc. work the same way as parameters
+of the same name of the [versions:display-dependency-updates](../display-dependency-updates-mojo.html) goal
+of the plugin.
+
+The parameters accept a list of *extended GAV* patterns, meaning patterns of:
+
+`groupId:artifactId:version:type:classifier:scope`
+
+of which only `groupId` is obligatory. On top of that, all of the components can be replaced with the asterisk (`*`)
+character in which case it will match all values.
+
+So, e.g. both of the below patterns:
+- `org.codehaus.mojo`
+- `org.codehaus.mojo:*`
+
+will match all artifacts with groupId `org.codehaus.mojo`.
+
+### Sample Plugin Configuration
+
+Below a rundimentary example of using the enforcer rule. The example assumes that the versions of both
+the enforcer plugin as well as the versions plugin are set elsewhere (using dependencyManagement).
+
+The below example specifies a rule which will not allow any updates except for updates of `localhost:dummy-api`.
+It will also ignore all sub-incremental updates.
+
+```xml
+
+
+ ...
+
+
+
+ org.apache.maven.plugins
+ maven-enforcer-plugin
+
+ enforce
+
+
+
+
+ 0
+
+ localhost:dummy-api
+
+ true
+
+
+
+
+
+ org.codehaus.mojo.versions
+ versions-enforcer
+
+
+
+
+
+
+
+```
\ No newline at end of file
diff --git a/versions-enforcer/src/site/site.xml b/versions-enforcer/src/site/site.xml
new file mode 100644
index 0000000000..cfc81696d2
--- /dev/null
+++ b/versions-enforcer/src/site/site.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/versions-enforcer/src/test/java/org/apache/maven/plugins/enforcer/MaxDependencyUpdatesTest.java b/versions-enforcer/src/test/java/org/apache/maven/plugins/enforcer/MaxDependencyUpdatesTest.java
new file mode 100644
index 0000000000..7493bcce74
--- /dev/null
+++ b/versions-enforcer/src/test/java/org/apache/maven/plugins/enforcer/MaxDependencyUpdatesTest.java
@@ -0,0 +1,289 @@
+package org.apache.maven.plugins.enforcer;
+/*
+ * 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.HashMap;
+
+import org.apache.maven.artifact.resolver.ArtifactResolver;
+import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
+import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper;
+import org.apache.maven.plugin.MojoExecution;
+import org.apache.maven.plugin.testing.stubs.StubArtifactRepository;
+import org.apache.maven.project.MavenProject;
+import org.apache.maven.repository.RepositorySystem;
+import org.apache.maven.settings.Settings;
+import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException;
+import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
+import org.junit.Test;
+import org.mockito.ArgumentMatchers;
+
+import static java.util.Arrays.asList;
+import static java.util.Collections.singletonList;
+import static java.util.Collections.singletonMap;
+import static org.codehaus.mojo.versions.utils.DependencyBuilder.dependencyWith;
+import static org.codehaus.mojo.versions.utils.MockUtils.mockAetherRepositorySystem;
+import static org.codehaus.mojo.versions.utils.MockUtils.mockMavenSession;
+import static org.codehaus.mojo.versions.utils.MockUtils.mockRepositorySystem;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.containsString;
+import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class MaxDependencyUpdatesTest
+{
+ private static EnforcerRuleHelper mockRuleHelper( MavenProject mavenProject,
+ org.eclipse.aether.RepositorySystem aetherRepositorySystem )
+ throws ExpressionEvaluationException, ComponentLookupException
+ {
+ EnforcerRuleHelper ruleHelper = mock( EnforcerRuleHelper.class );
+ when( ruleHelper.evaluate( anyString() ) )
+ .then( ( a ) -> "${project}".equals( a.getArgument( 0 ) )
+ ? mavenProject
+ : "${localRepository}".equals( a.getArgument( 0 ) )
+ ? new StubArtifactRepository( "" )
+ : "${settings}".equals( a.getArgument( 0 ) )
+ ? new Settings()
+ : "${session}".equals( a.getArgument( 0 ) )
+ ? mockMavenSession()
+ : "${mojoExecution}".equals( a.getArgument( 0 ) )
+ ? mock( MojoExecution.class )
+ : null );
+ when( ruleHelper.getComponent( ArgumentMatchers.>any() ) )
+ .then( ( a ) -> a.getArgument( 0 ) == RepositorySystem.class
+ ? mockRepositorySystem()
+ : a.getArgument( 0 ) == ArtifactResolver.class
+ ? mock( ArtifactResolver.class )
+ : a.getArgument( 0 ) == org.eclipse.aether.RepositorySystem.class
+ ? aetherRepositorySystem
+ : null );
+ return ruleHelper;
+ }
+
+ @Test
+ public void testRuleFailsByMaxUpdatesExceeded()
+ throws ExpressionEvaluationException, ComponentLookupException
+ {
+ EnforcerRuleHelper ruleHelper = mockRuleHelper( new MavenProject()
+ {{
+ setDependencies( asList(
+ dependencyWith( "group", "artifactA", "1.0.0" ),
+ dependencyWith( "group", "artifactB", "1.0.0" ) ) );
+ }}, mockAetherRepositorySystem( new HashMap()
+ {{
+ put( "artifactA", new String[] { "1.0.0", "2.0.0" } );
+ put( "artifactB", new String[] { "1.0.0", "2.0.0" } );
+ }} ) );
+
+ try
+ {
+ new MaxDependencyUpdates()
+ {{
+ maxUpdates = 1;
+ }}.execute( ruleHelper );
+
+ fail( "EnforcerRuleException should have been thrown" );
+ }
+ catch ( EnforcerRuleException e )
+ {
+ assertThat( e.getMessage(), containsString( "More than 1 upgradable artifacts detected" ) );
+ }
+ }
+
+ @Test
+ public void testRulePassesByMaxUpdatesNotExceeded()
+ throws ExpressionEvaluationException, ComponentLookupException
+ {
+ EnforcerRuleHelper ruleHelper = mockRuleHelper( new MavenProject()
+ {{
+ setDependencies( singletonList(
+ dependencyWith( "group", "artifactA", "1.0.0" ) ) );
+ }}, mockAetherRepositorySystem( singletonMap( "artifactA", new String[] { "1.0.0", "2.0.0" } ) ) );
+
+ try
+ {
+ new MaxDependencyUpdates()
+ {{
+ maxUpdates = 1;
+ }}.execute( ruleHelper );
+ }
+ catch ( EnforcerRuleException e )
+ {
+ fail( "No EnforcerRuleException should have been thrown" );
+ }
+ }
+
+ @Test
+ public void testRulePassesByMaxUpdatesNotExceededDependencyIncludes()
+ throws ExpressionEvaluationException, ComponentLookupException
+ {
+ EnforcerRuleHelper ruleHelper = mockRuleHelper( new MavenProject()
+ {{
+ setDependencies( asList(
+ dependencyWith( "group", "artifactA", "1.0.0" ),
+ dependencyWith( "group", "artifactB", "1.0.0" ) ) );
+ }}, mockAetherRepositorySystem( new HashMap()
+ {{
+ put( "artifactA", new String[] { "1.0.0", "2.0.0" } );
+ put( "artifactB", new String[] { "1.0.0" } );
+ }} ) );
+
+ try
+ {
+ new MaxDependencyUpdates()
+ {{
+ dependencyIncludes = singletonList( "group:artifactB" );
+ }}.execute( ruleHelper );
+ }
+ catch ( EnforcerRuleException e )
+ {
+ fail( "No EnforcerRuleException should have been thrown" );
+ }
+ }
+
+ @Test
+ public void testRulePassesByMaxUpdatesNotExceededDependencyExcludes()
+ throws ExpressionEvaluationException, ComponentLookupException
+ {
+ EnforcerRuleHelper ruleHelper = mockRuleHelper( new MavenProject()
+ {{
+ setDependencies( asList(
+ dependencyWith( "group", "artifactA", "1.0.0" ),
+ dependencyWith( "group", "artifactB", "1.0.0" ) ) );
+ }}, mockAetherRepositorySystem( new HashMap()
+ {{
+ put( "artifactA", new String[] { "1.0.0", "2.0.0" } );
+ put( "artifactB", new String[] { "1.0.0" } );
+ }} ) );
+
+ try
+ {
+ new MaxDependencyUpdates()
+ {{
+ dependencyExcludes = singletonList( "group:artifactA" );
+ }}.execute( ruleHelper );
+ }
+ catch ( EnforcerRuleException e )
+ {
+ fail( "No EnforcerRuleException should have been thrown" );
+ }
+ }
+
+ @Test
+ public void testRulePassesByMaxUpdatesNotExceededDependencyIncludesExcludes()
+ throws ExpressionEvaluationException, ComponentLookupException
+ {
+ EnforcerRuleHelper ruleHelper = mockRuleHelper( new MavenProject()
+ {{
+ setDependencies( asList(
+ dependencyWith( "group", "artifactA", "1.0.0" ),
+ dependencyWith( "group", "artifactB", "1.0.0" ) ) );
+ }}, mockAetherRepositorySystem( new HashMap()
+ {{
+ put( "artifactA", new String[] { "1.0.0", "2.0.0" } );
+ put( "artifactB", new String[] { "1.0.0" } );
+ }} ) );
+
+ try
+ {
+ new MaxDependencyUpdates()
+ {{
+ dependencyIncludes = singletonList( "group:*" );
+ dependencyExcludes = singletonList( "group:artifactA" );
+ }}.execute( ruleHelper );
+ }
+ catch ( EnforcerRuleException e )
+ {
+ fail( "No EnforcerRuleException should have been thrown" );
+ }
+ }
+
+ @Test
+ public void testIgnoreSubIncrementalUpdates()
+ throws ExpressionEvaluationException, ComponentLookupException
+ {
+ EnforcerRuleHelper ruleHelper = mockRuleHelper( new MavenProject()
+ {{
+ setDependencies( singletonList(
+ dependencyWith( "group", "artifactA", "1.0.0" ) ) );
+ }}, mockAetherRepositorySystem( singletonMap( "artifactA",
+ new String[] { "1.0.0", "1.0.0-1" } ) ) );
+
+ try
+ {
+ new MaxDependencyUpdates()
+ {{
+ ignoreSubIncrementalUpdates = true;
+ }}.execute( ruleHelper );
+ }
+ catch ( EnforcerRuleException e )
+ {
+ fail( "No EnforcerRuleException should have been thrown" );
+ }
+ }
+
+ @Test
+ public void testIgnoreIncrementalUpdates()
+ throws ExpressionEvaluationException, ComponentLookupException
+ {
+ EnforcerRuleHelper ruleHelper = mockRuleHelper( new MavenProject()
+ {{
+ setDependencies( singletonList(
+ dependencyWith( "group", "artifactA", "1.0.0" ) ) );
+ }}, mockAetherRepositorySystem( singletonMap( "artifactA",
+ new String[] { "1.0.0", "1.0.0-1", "1.0.1" } ) ) );
+
+ try
+ {
+ new MaxDependencyUpdates()
+ {{
+ ignoreIncrementalUpdates = true;
+ }}.execute( ruleHelper );
+ }
+ catch ( EnforcerRuleException e )
+ {
+ fail( "No EnforcerRuleException should have been thrown" );
+ }
+ }
+
+ @Test
+ public void testIgnoreMinorUpdates()
+ throws ExpressionEvaluationException, ComponentLookupException
+ {
+ EnforcerRuleHelper ruleHelper = mockRuleHelper( new MavenProject()
+ {{
+ setDependencies( asList(
+ dependencyWith( "group", "artifactA", "1.0.0" ) ) );
+ }}, mockAetherRepositorySystem( singletonMap( "artifactA",
+ new String[] { "1.0.0", "1.0.0-1", "1.0.1", "1.1.0" } ) ) );
+
+ try
+ {
+ new MaxDependencyUpdates()
+ {{
+ ignoreMinorUpdates = true;
+ }}.execute( ruleHelper );
+ }
+ catch ( EnforcerRuleException e )
+ {
+ fail( "No EnforcerRuleException should have been thrown" );
+ }
+ }
+}
diff --git a/versions-maven-plugin/pom.xml b/versions-maven-plugin/pom.xml
index 71519af212..e586a8ba11 100644
--- a/versions-maven-plugin/pom.xml
+++ b/versions-maven-plugin/pom.xml
@@ -27,6 +27,13 @@
${project.version}
+
+ org.codehaus.mojo.versions
+ versions-test
+ ${project.version}
+ test
+
+
org.codehaus.mojo.versions
versions-common
@@ -38,7 +45,7 @@
maven-plugin-annotations
provided
-
+
org.apache.maven
maven-artifact
diff --git a/versions-maven-plugin/src/it/it-max-dependency-updates-001/invoker.properties b/versions-maven-plugin/src/it/it-max-dependency-updates-001/invoker.properties
new file mode 100644
index 0000000000..38b185e579
--- /dev/null
+++ b/versions-maven-plugin/src/it/it-max-dependency-updates-001/invoker.properties
@@ -0,0 +1,2 @@
+invoker.goals = enforcer:enforce
+invoker.buildResult = failure
diff --git a/versions-maven-plugin/src/it/it-max-dependency-updates-001/pom.xml b/versions-maven-plugin/src/it/it-max-dependency-updates-001/pom.xml
new file mode 100644
index 0000000000..bb5556fd98
--- /dev/null
+++ b/versions-maven-plugin/src/it/it-max-dependency-updates-001/pom.xml
@@ -0,0 +1,44 @@
+
+ 4.0.0
+ localhost
+ it-max-dependency-upgrades
+ 1.0
+ pom
+
+
+
+ localhost
+ dummy-api
+ 1.1
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-enforcer-plugin
+ @maven-enforcer-plugin.version@
+
+ enforce
+
+
+
+
+ 0
+
+
+
+
+
+ org.codehaus.mojo.versions
+ versions-enforcer
+ @project.version@
+
+
+
+
+
+
+
diff --git a/versions-maven-plugin/src/it/it-max-dependency-updates-002/invoker.properties b/versions-maven-plugin/src/it/it-max-dependency-updates-002/invoker.properties
new file mode 100644
index 0000000000..a30e3767bb
--- /dev/null
+++ b/versions-maven-plugin/src/it/it-max-dependency-updates-002/invoker.properties
@@ -0,0 +1,2 @@
+invoker.goals = enforcer:enforce
+invoker.buildResult = success
diff --git a/versions-maven-plugin/src/it/it-max-dependency-updates-002/pom.xml b/versions-maven-plugin/src/it/it-max-dependency-updates-002/pom.xml
new file mode 100644
index 0000000000..fbe9f0c7ce
--- /dev/null
+++ b/versions-maven-plugin/src/it/it-max-dependency-updates-002/pom.xml
@@ -0,0 +1,44 @@
+
+ 4.0.0
+ localhost
+ it-max-dependency-upgrades
+ 1.0
+ pom
+
+
+
+ localhost
+ dummy-api
+ 1.1
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-enforcer-plugin
+ @maven-enforcer-plugin.version@
+
+ enforce
+
+
+
+
+ 1
+
+
+
+
+
+ org.codehaus.mojo.versions
+ versions-enforcer
+ @project.version@
+
+
+
+
+
+
+
diff --git a/versions-maven-plugin/src/it/it-max-dependency-updates-003/invoker.properties b/versions-maven-plugin/src/it/it-max-dependency-updates-003/invoker.properties
new file mode 100644
index 0000000000..a30e3767bb
--- /dev/null
+++ b/versions-maven-plugin/src/it/it-max-dependency-updates-003/invoker.properties
@@ -0,0 +1,2 @@
+invoker.goals = enforcer:enforce
+invoker.buildResult = success
diff --git a/versions-maven-plugin/src/it/it-max-dependency-updates-003/pom.xml b/versions-maven-plugin/src/it/it-max-dependency-updates-003/pom.xml
new file mode 100644
index 0000000000..f9d43af726
--- /dev/null
+++ b/versions-maven-plugin/src/it/it-max-dependency-updates-003/pom.xml
@@ -0,0 +1,47 @@
+
+ 4.0.0
+ localhost
+ it-max-dependency-upgrades
+ 1.0
+ pom
+
+
+
+ localhost
+ dummy-api
+ 1.1
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-enforcer-plugin
+ @maven-enforcer-plugin.version@
+
+ enforce
+
+
+
+
+ 0
+
+ localhost:*
+
+
+
+
+
+
+ org.codehaus.mojo.versions
+ versions-enforcer
+ @project.version@
+
+
+
+
+
+
+
diff --git a/versions-maven-plugin/src/it/it-max-dependency-updates-004/invoker.properties b/versions-maven-plugin/src/it/it-max-dependency-updates-004/invoker.properties
new file mode 100644
index 0000000000..a30e3767bb
--- /dev/null
+++ b/versions-maven-plugin/src/it/it-max-dependency-updates-004/invoker.properties
@@ -0,0 +1,2 @@
+invoker.goals = enforcer:enforce
+invoker.buildResult = success
diff --git a/versions-maven-plugin/src/it/it-max-dependency-updates-004/pom.xml b/versions-maven-plugin/src/it/it-max-dependency-updates-004/pom.xml
new file mode 100644
index 0000000000..cd37c53bda
--- /dev/null
+++ b/versions-maven-plugin/src/it/it-max-dependency-updates-004/pom.xml
@@ -0,0 +1,45 @@
+
+ 4.0.0
+ localhost
+ it-max-dependency-upgrades
+ 1.0
+ pom
+
+
+
+ localhost
+ dummy-impl
+ 2.0
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-enforcer-plugin
+ @maven-enforcer-plugin.version@
+
+ enforce
+
+
+
+
+ 0
+ true
+
+
+
+
+
+ org.codehaus.mojo.versions
+ versions-enforcer
+ @project.version@
+
+
+
+
+
+
+
diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DependencyUpdatesReportMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DependencyUpdatesReportMojo.java
index 5ed1df38b9..fb6fe624b5 100644
--- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DependencyUpdatesReportMojo.java
+++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DependencyUpdatesReportMojo.java
@@ -51,6 +51,7 @@
import org.codehaus.plexus.i18n.I18N;
import static java.util.Collections.emptyMap;
+import static org.codehaus.mojo.versions.utils.MavenProjectUtils.interpolateVersion;
import static org.codehaus.mojo.versions.utils.MiscUtils.filter;
/**
@@ -174,7 +175,7 @@ && getProject().getOriginalModel().getDependencyManagement().getDependencies() !
// TODO: I'm not 100% sure if this will work correctly in all cases.
for ( Dependency dep : getProject().getOriginalModel().getDependencyManagement().getDependencies() )
{
- dep = getHelper().interpolateVersion( dep, getProject() );
+ dep = interpolateVersion( dep, getProject() );
getLog().debug( "Original Dpmg: " + dep.getGroupId() + ":" + dep.getArtifactId() + ":"
+ dep.getVersion() + ":" + dep.getType() + ":" + dep.getScope() );
diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayDependencyUpdatesMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayDependencyUpdatesMojo.java
index 02c7cc1b72..3d37aa60f4 100644
--- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayDependencyUpdatesMojo.java
+++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayDependencyUpdatesMojo.java
@@ -28,38 +28,37 @@
import java.util.Optional;
import java.util.Set;
import java.util.TreeSet;
-import java.util.stream.Collectors;
import org.apache.maven.artifact.ArtifactUtils;
import org.apache.maven.artifact.manager.WagonManager;
import org.apache.maven.artifact.resolver.ArtifactResolver;
import org.apache.maven.artifact.versioning.ArtifactVersion;
-import org.apache.maven.model.Build;
import org.apache.maven.model.Dependency;
-import org.apache.maven.model.DependencyManagement;
-import org.apache.maven.model.Plugin;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
-import org.apache.maven.project.MavenProject;
import org.apache.maven.project.MavenProjectBuilder;
import org.apache.maven.repository.RepositorySystem;
import org.codehaus.mojo.versions.api.ArtifactVersions;
import org.codehaus.mojo.versions.api.Segment;
import org.codehaus.mojo.versions.api.VersionRetrievalException;
import org.codehaus.mojo.versions.api.recording.ChangeRecorder;
-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.mojo.versions.utils.SegmentUtils;
import org.codehaus.plexus.util.StringUtils;
+import static java.util.Collections.emptySet;
import static java.util.Optional.empty;
import static java.util.Optional.of;
import static org.apache.commons.lang3.StringUtils.countMatches;
import static org.codehaus.mojo.versions.api.Segment.MAJOR;
+import static org.codehaus.mojo.versions.filtering.DependencyFilter.filterDependencies;
+import static org.codehaus.mojo.versions.utils.MavenProjectUtils.extractDependenciesFromDependencyManagement;
+import static org.codehaus.mojo.versions.utils.MavenProjectUtils.extractDependenciesFromPlugins;
+import static org.codehaus.mojo.versions.utils.MavenProjectUtils.extractPluginDependenciesFromPluginsInPluginManagement;
/**
* Displays all dependencies that have newer versions available.
@@ -357,68 +356,6 @@ public DisplayDependencyUpdatesMojo( RepositorySystem repositorySystem,
changeRecorders );
}
- private static Set extractPluginDependenciesFromPluginsInPluginManagement( Build build )
- {
- Set result = new TreeSet<>( DependencyComparator.INSTANCE );
- if ( build.getPluginManagement() != null )
- {
- for ( Plugin plugin : build.getPluginManagement().getPlugins() )
- {
- if ( plugin.getDependencies() != null && !plugin.getDependencies().isEmpty() )
- {
- result.addAll( plugin.getDependencies() );
- }
- }
- }
- return result;
- }
-
- private static Set extractDependenciesFromPlugins( List plugins )
- {
- Set result = new TreeSet<>( DependencyComparator.INSTANCE );
- for ( Plugin plugin : plugins )
- {
- if ( plugin.getDependencies() != null && !plugin.getDependencies().isEmpty() )
- {
- result.addAll( plugin.getDependencies() );
- }
- }
- return result;
- }
-
- /**
- * Returns a set of dependencies where the dependencies which are defined in the dependency management section have
- * been filtered out.
- *
- * @param dependencies The set of dependencies.
- * @param dependencyManagement The set of dependencies from the dependency management section.
- * @return A new set of dependencies which are from the set of dependencies but not from the set of dependency
- * management dependencies.
- * @since 1.0-beta-1
- */
- private static Set removeDependencyManagment( Set dependencies,
- Set dependencyManagement )
- {
- Set result = new TreeSet<>( DependencyComparator.INSTANCE );
- for ( Dependency dependency : dependencies )
- {
- boolean matched = false;
- for ( Dependency managedDependency : dependencyManagement )
- {
- if ( dependenciesMatch( dependency, managedDependency ) )
- {
- matched = true;
- break;
- }
- }
- if ( !matched )
- {
- result.add( dependency );
- }
- }
- return result;
- }
-
// open for tests
protected static boolean dependenciesMatch( Dependency dependency, Dependency managedDependency )
{
@@ -491,106 +428,48 @@ public void execute()
logInit();
validateInput();
- Set dependencyManagement = new TreeSet<>( DependencyComparator.INSTANCE );
- DependencyManagement projectDependencyManagement = getProjectDependencyManagement( getProject() );
- if ( projectDependencyManagement != null )
- {
-
- List dependenciesFromPom = projectDependencyManagement.getDependencies();
- for ( Dependency dependency : dependenciesFromPom )
- {
- getLog().debug( "dependency from pom: " + dependency.getGroupId() + ":" + dependency.getArtifactId()
- + ":" + dependency.getVersion() + ":" + dependency.getScope() );
- if ( dependency.getVersion() == null )
- {
- // get parent and get the information from there.
- if ( getProject().hasParent() )
- {
- getLog().debug( "Reading parent dependencyManagement information" );
- DependencyManagement parentProjectDependencyManagement =
- getProjectDependencyManagement( getProject().getParent() );
- if ( parentProjectDependencyManagement != null )
- {
- List parentDeps = parentProjectDependencyManagement.getDependencies();
- for ( Dependency parentDep : parentDeps )
- {
- // only groupId && artifactId needed cause version is null
- if ( dependency.getGroupId().equals( parentDep.getGroupId() )
- && dependency.getArtifactId().equals( parentDep.getArtifactId() )
- && dependency.getType().equals( parentDep.getType() ) )
- {
- dependencyManagement.add( parentDep );
- }
- }
- }
- }
- else
- {
- String message = "We can't get the version for the dependency " + dependency.getGroupId() + ":"
- + dependency.getArtifactId() + " cause there does not exist a parent.";
- getLog().error( message );
- // Throw error cause we will not able to get a version for a dependency.
- throw new MojoExecutionException( message );
- }
- }
- else
- {
- dependency = getHelper().interpolateVersion( dependency, getProject() );
- dependencyManagement.add( dependency );
- }
- }
- }
-
- Set dependencies = new TreeSet<>( DependencyComparator.INSTANCE );
- dependencies.addAll( getProject().getDependencies() );
-
- if ( isProcessingDependencyManagement() )
- {
- dependencies = removeDependencyManagment( dependencies, dependencyManagement );
- }
-
- Set pluginDependencies = new TreeSet<>( DependencyComparator.INSTANCE );
-
- if ( isProcessingPluginDependencies() )
- {
- pluginDependencies = extractDependenciesFromPlugins( getProject().getBuildPlugins() );
- }
-
- Set pluginDependenciesInPluginManagement = new TreeSet<>( DependencyComparator.INSTANCE );
- if ( isProcessPluginDependenciesInDependencyManagement() )
- {
- pluginDependenciesInPluginManagement =
- extractPluginDependenciesFromPluginsInPluginManagement( getProject().getBuild() );
- }
+ Set dependencyManagement = emptySet();
try
{
if ( isProcessingDependencyManagement() )
{
- dependencyManagement = filterDependencyManagementIncludes( dependencyManagement );
+ dependencyManagement = filterDependencies( extractDependenciesFromDependencyManagement( getProject(),
+ processDependencyManagementTransitive, getLog() ),
+ dependencyManagementIncludes, dependencyManagementExcludes, "Dependecy Management",
+ getLog() );
- logUpdates( getHelper().lookupDependenciesUpdates( dependencyManagement, false ),
- "Dependency Management" );
+ logUpdates( getHelper().lookupDependenciesUpdates( dependencyManagement,
+ false ), "Dependency Management" );
}
if ( isProcessingDependencies() )
{
- dependencies = filterDependencyIncludes( dependencies );
-
- logUpdates( getHelper().lookupDependenciesUpdates( dependencies, false ), "Dependencies" );
+ Set finalDependencyManagement = dependencyManagement;
+ logUpdates( getHelper().lookupDependenciesUpdates(
+ filterDependencies( getProject().getDependencies()
+ .parallelStream()
+ .filter( dep -> finalDependencyManagement.parallelStream()
+ .noneMatch( depMan -> dependenciesMatch( dep, depMan ) ) )
+ .collect( () -> new TreeSet<>( DependencyComparator.INSTANCE ), Set::add, Set::addAll ),
+ dependencyIncludes, dependencyExcludes, "Dependencies", getLog() ),
+ false ),
+ "Dependencies" );
}
if ( isProcessPluginDependenciesInDependencyManagement() )
{
- pluginDependenciesInPluginManagement =
- filterPluginManagementIncludes( pluginDependenciesInPluginManagement );
-
- logUpdates( getHelper().lookupDependenciesUpdates( pluginDependenciesInPluginManagement, false ),
- "pluginManagement of plugins" );
+ logUpdates( getHelper().lookupDependenciesUpdates( filterDependencies(
+ extractPluginDependenciesFromPluginsInPluginManagement( getProject() ),
+ pluginManagementDependencyIncludes, pluginManagementDependencyExcludes,
+ "Plugin Management Dependencies", getLog() ), false ),
+ "pluginManagement of plugins" );
}
if ( isProcessingPluginDependencies() )
{
- pluginDependencies = filterPluginDependencyIncludes( pluginDependencies );
-
- logUpdates( getHelper().lookupDependenciesUpdates( pluginDependencies, false ), "Plugin Dependencies" );
+ logUpdates( getHelper().lookupDependenciesUpdates( filterDependencies(
+ extractDependenciesFromPlugins( getProject() ),
+ pluginDependencyIncludes, pluginDependencyExcludes, "Plugin Dependencies",
+ getLog() ), false ),
+ "Plugin Dependencies" );
}
}
catch ( VersionRetrievalException e )
@@ -628,72 +507,6 @@ static void validateGAVList( List gavList, int numSections, String argum
}
}
- private Set filterDependencyIncludes( Set dependencies )
- {
- return filterDependencies( dependencies, dependencyIncludes, dependencyExcludes, "Dependencies" );
- }
-
- private Set filterDependencyManagementIncludes( Set dependencyManagement )
- {
- return filterDependencies( dependencyManagement,
- 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(
- Set dependencies,
- List includes,
- List excludes,
- String section
- )
- {
- DependencyFilter includeDeps = DependencyFilter.parseFrom( includes );
- DependencyFilter excludeDeps = DependencyFilter.parseFrom( excludes );
-
- Set filtered = includeDeps.retainingIn( dependencies );
- filtered = excludeDeps.removingFrom( filtered );
-
- 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 )
- {
- return project.getDependencyManagement();
- }
- else
- {
- return project.getOriginalModel().getDependencyManagement();
- }
- }
-
private Optional calculateUpdateScope()
{
return allowAnyUpdates
diff --git a/versions-maven-plugin/src/site/markdown/index.md b/versions-maven-plugin/src/site/markdown/index.md
index f008eb1a60..69a48c2e8e 100644
--- a/versions-maven-plugin/src/site/markdown/index.md
+++ b/versions-maven-plugin/src/site/markdown/index.md
@@ -86,6 +86,12 @@ The Versions Plugin has the following reporting goals.
* [versions:parent-updates-report](./parent-updates-report-mojo.html) produces a report on possible parent artifact
upgrades.
+## Enforcer rules overview
+
+The Versions Plugin currently provides one Maven Enforcer Plugin rule:
+* [maxDependencyUpdates](../versions-enforcer/max-dependency-updates.html) allows the user to specify a maximum number of updates which,
+ if exceeded, will trigger the enforcer plugin to fail.
+
## Usage
General instructions on how to use the Versions Plugin can be found on the [usage page](./usage.html). Some more
diff --git a/versions-test/pom.xml b/versions-test/pom.xml
new file mode 100644
index 0000000000..1ddf047d9e
--- /dev/null
+++ b/versions-test/pom.xml
@@ -0,0 +1,72 @@
+
+
+
+
+
+ versions
+ org.codehaus.mojo.versions
+ 2.14.0-SNAPSHOT
+
+ 4.0.0
+
+ versions-test
+
+ Versions Test
+ Test utilities
+
+
+
+ org.apache.maven
+ maven-compat
+ ${mavenVersion}
+ provided
+
+
+ org.apache.maven.doxia
+ doxia-integration-tools
+ ${doxiaVersion}
+
+
+ org.apache.maven.doxia
+ doxia-site-renderer
+ ${doxia-sitetoolsVersion}
+
+
+ org.codehaus.mojo.versions
+ versions-common
+ ${project.version}
+
+
+ org.apache.commons
+ commons-text
+
+
+ org.mockito
+ mockito-inline
+
+
+ org.apache.maven.plugin-testing
+ maven-plugin-testing-harness
+
+
+
+
\ No newline at end of file
diff --git a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/utils/MockUtils.java b/versions-test/src/main/java/org/codehaus/mojo/versions/utils/MockUtils.java
similarity index 100%
rename from versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/utils/MockUtils.java
rename to versions-test/src/main/java/org/codehaus/mojo/versions/utils/MockUtils.java
index bf980f3786..733344f143 100644
--- a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/utils/MockUtils.java
+++ b/versions-test/src/main/java/org/codehaus/mojo/versions/utils/MockUtils.java
@@ -1,3 +1,5 @@
+package org.codehaus.mojo.versions.utils;
+
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
@@ -17,8 +19,6 @@
* under the License.
*/
-package org.codehaus.mojo.versions.utils;
-
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
diff --git a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/utils/TestChangeRecorder.java b/versions-test/src/main/java/org/codehaus/mojo/versions/utils/TestChangeRecorder.java
similarity index 100%
rename from versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/utils/TestChangeRecorder.java
rename to versions-test/src/main/java/org/codehaus/mojo/versions/utils/TestChangeRecorder.java
diff --git a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/utils/TestUtils.java b/versions-test/src/main/java/org/codehaus/mojo/versions/utils/TestUtils.java
similarity index 100%
rename from versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/utils/TestUtils.java
rename to versions-test/src/main/java/org/codehaus/mojo/versions/utils/TestUtils.java
diff --git a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/utils/VersionStub.java b/versions-test/src/main/java/org/codehaus/mojo/versions/utils/VersionStub.java
similarity index 100%
rename from versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/utils/VersionStub.java
rename to versions-test/src/main/java/org/codehaus/mojo/versions/utils/VersionStub.java