diff --git a/enforcer-rules/pom.xml b/enforcer-rules/pom.xml index 1116ce06..121d93c1 100644 --- a/enforcer-rules/pom.xml +++ b/enforcer-rules/pom.xml @@ -117,6 +117,7 @@ mockito-core test + org.apache.maven.shared maven-dependency-tree @@ -127,7 +128,7 @@ - + org.apache.maven maven-compat diff --git a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/AbstractBanDependencies.java b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/AbstractBanDependencies.java index c7f77b88..9701a11d 100644 --- a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/AbstractBanDependencies.java +++ b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/AbstractBanDependencies.java @@ -18,7 +18,6 @@ */ package org.apache.maven.plugins.enforcer; -import java.util.HashSet; import java.util.Set; import org.apache.maven.artifact.Artifact; import org.apache.maven.enforcer.rule.api.EnforcerRuleException; @@ -26,14 +25,7 @@ import org.apache.maven.execution.MavenSession; import org.apache.maven.plugin.logging.Log; import org.apache.maven.plugins.enforcer.utils.ArtifactUtils; -import org.apache.maven.project.DefaultProjectBuildingRequest; -import org.apache.maven.project.MavenProject; -import org.apache.maven.project.ProjectBuildingRequest; -import org.apache.maven.shared.dependency.graph.DependencyGraphBuilder; -import org.apache.maven.shared.dependency.graph.DependencyGraphBuilderException; -import org.apache.maven.shared.dependency.graph.DependencyNode; import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException; -import org.codehaus.plexus.component.repository.exception.ComponentLookupException; /** * Abstract Rule for banning dependencies. @@ -45,51 +37,36 @@ public abstract class AbstractBanDependencies extends AbstractNonCacheableEnforc /** Specify if transitive dependencies should be searched (default) or only look at direct dependencies. */ private boolean searchTransitive = true; - private transient DependencyGraphBuilder graphBuilder; - @Override public void execute(EnforcerRuleHelper helper) throws EnforcerRuleException { - MavenProject project; - try { - project = (MavenProject) helper.evaluate("${project}"); - } catch (ExpressionEvaluationException eee) { - throw new EnforcerRuleException("Unable to retrieve the MavenProject: ", eee); - } - MavenSession session; try { session = (MavenSession) helper.evaluate("${session}"); - } catch (ExpressionEvaluationException eee) { - throw new EnforcerRuleException("Unable to retrieve the reactor MavenProject: ", eee); + } catch (ExpressionEvaluationException e) { + throw new EnforcerRuleException("Cannot resolve MavenSession", e); } - try { - graphBuilder = helper.getComponent(DependencyGraphBuilder.class); - } catch (ComponentLookupException e) { - throw new EnforcerRuleException("Unable to lookup DependencyGraphBuilder: ", e); - } - - ProjectBuildingRequest buildingRequest = new DefaultProjectBuildingRequest(session.getProjectBuildingRequest()); - buildingRequest.setProject(project); - // get the correct list of dependencies - Set dependencies = getDependenciesToCheck(helper, buildingRequest); + Set dependencyArtifacts = searchTransitive + ? ArtifactUtils.getDependencyArtifacts(ArtifactUtils.resolveTransitiveDependencies(helper)) + : session.getCurrentProject().getDependencyArtifacts(); // look for banned dependencies - Set foundExcludes = checkDependencies(dependencies, helper.getLog()); + Set bannedDependencies = checkDependencies(dependencyArtifacts, helper.getLog()); // if any are found, fail the check but list all of them - if (foundExcludes != null && !foundExcludes.isEmpty()) { + if (bannedDependencies != null && !bannedDependencies.isEmpty()) { String message = getMessage(); StringBuilder buf = new StringBuilder(); if (message != null) { - buf.append(message + System.lineSeparator()); + buf.append(message).append(System.lineSeparator()); } - for (Artifact artifact : foundExcludes) { + for (Artifact artifact : bannedDependencies) { buf.append(getErrorMessage(artifact)); } - message = buf.toString() + "Use 'mvn dependency:tree' to locate the source of the banned dependencies."; + message = buf.append("Use 'mvn dependency:tree' to locate the source of the banned dependencies.") + .toString(); throw new EnforcerRuleException(message); } @@ -99,40 +76,11 @@ protected CharSequence getErrorMessage(Artifact artifact) { return "Found Banned Dependency: " + artifact.getId() + System.lineSeparator(); } - private Set getDependenciesToCheck(EnforcerRuleHelper helper, ProjectBuildingRequest buildingRequest) { - String cacheKey = buildingRequest.getProject().getId() + "_" + searchTransitive; - - // check in the cache - Set dependencies = - (Set) helper.getCache(cacheKey, () -> getDependenciesToCheck(buildingRequest)); - - return dependencies; - } - - protected Set getDependenciesToCheck(ProjectBuildingRequest buildingRequest) { - Set dependencies = null; - try { - DependencyNode node = graphBuilder.buildDependencyGraph(buildingRequest, null); - if (searchTransitive) { - dependencies = ArtifactUtils.getAllDescendants(node); - } else if (node.getChildren() != null) { - dependencies = new HashSet<>(); - for (DependencyNode depNode : node.getChildren()) { - dependencies.add(depNode.getArtifact()); - } - } - } catch (DependencyGraphBuilderException e) { - // otherwise we need to change the signature of this protected method - throw new RuntimeException(e); - } - return dependencies; - } - /** * Checks the set of dependencies against the list of excludes. * - * @param dependencies the dependencies - * @param log the log + * @param dependencies dependencies to be checked against the list of excludes + * @param log the log * @return the sets the * @throws EnforcerRuleException the enforcer rule exception */ diff --git a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BanDynamicVersions.java b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BanDynamicVersions.java index cde111c5..4c467814 100644 --- a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BanDynamicVersions.java +++ b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BanDynamicVersions.java @@ -34,6 +34,7 @@ import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper; import org.apache.maven.plugin.logging.Log; import org.apache.maven.plugins.enforcer.utils.ArtifactMatcher; +import org.apache.maven.plugins.enforcer.utils.ArtifactUtils; import org.apache.maven.project.MavenProject; import org.apache.maven.shared.utils.logging.MessageBuilder; import org.apache.maven.shared.utils.logging.MessageUtils; @@ -291,7 +292,7 @@ private static final class ExcludeArtifactPatternsPredicate implements Predicate @Override public boolean test(DependencyNode depNode) { try { - return artifactMatcher.match(RepositoryUtils.toArtifact(depNode.getArtifact())); + return artifactMatcher.match(ArtifactUtils.toArtifact(depNode)); } catch (InvalidVersionSpecificationException e) { throw new IllegalArgumentException("Invalid version found for dependency node " + depNode, e); } diff --git a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BanTransitiveDependencies.java b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BanTransitiveDependencies.java index c9038423..799fb6f9 100644 --- a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BanTransitiveDependencies.java +++ b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BanTransitiveDependencies.java @@ -18,22 +18,24 @@ */ package org.apache.maven.plugins.enforcer; -import java.util.Collections; +import static java.util.Optional.ofNullable; + +import com.google.common.base.Strings; import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; +import org.apache.maven.RepositoryUtils; import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; 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.plugins.enforcer.utils.ArtifactMatcher; -import org.apache.maven.project.DefaultProjectBuildingRequest; -import org.apache.maven.project.MavenProject; -import org.apache.maven.project.ProjectBuildingRequest; -import org.apache.maven.shared.dependency.graph.DependencyGraphBuilder; -import org.apache.maven.shared.dependency.graph.DependencyNode; -import org.apache.maven.shared.dependency.graph.internal.DefaultDependencyGraphBuilder; -import org.codehaus.plexus.component.repository.exception.ComponentLookupException; -import org.codehaus.plexus.logging.console.ConsoleLogger; +import org.apache.maven.plugins.enforcer.utils.ArtifactUtils; +import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException; +import org.eclipse.aether.artifact.ArtifactTypeRegistry; +import org.eclipse.aether.graph.Dependency; +import org.eclipse.aether.graph.DependencyNode; /** * This rule bans all transitive dependencies. There is a configuration option to exclude certain artifacts from being @@ -43,8 +45,6 @@ */ public class BanTransitiveDependencies extends AbstractNonCacheableEnforcerRule implements EnforcerRule { - private EnforcerRuleHelper helper; - /** * Specify the dependencies that will be ignored. This can be a list of artifacts in the format * groupId[:artifactId][:version][:type][:scope]. Wildcard '*' can be used to in place of specific @@ -69,7 +69,12 @@ public class BanTransitiveDependencies extends AbstractNonCacheableEnforcerRule * * @throws InvalidVersionSpecificationException */ - private static boolean searchTree(DependencyNode node, int level, ArtifactMatcher excludes, StringBuilder message) + private static boolean searchTree( + DependencyNode node, + int level, + ArtifactMatcher excludes, + Set directDependencies, + StringBuilder message) throws InvalidVersionSpecificationException { List children = node.getChildren(); @@ -87,34 +92,32 @@ private static boolean searchTree(DependencyNode node, int level, ArtifactMatche */ StringBuilder messageFromChildren = message == null ? null : new StringBuilder(); - if (excludes.match(node.getArtifact())) { + if (excludes.match(ArtifactUtils.toArtifact(node))) { // is excluded, we don't care about descendants excluded = true; hasTransitiveDependencies = false; + } else if (directDependencies.contains(node.getDependency())) { + hasTransitiveDependencies = false; } else { for (DependencyNode childNode : children) { /* * if any of the children has transitive d. so does the parent */ - hasTransitiveDependencies = - (searchTree(childNode, level + 1, excludes, messageFromChildren) || hasTransitiveDependencies); + hasTransitiveDependencies = hasTransitiveDependencies + || searchTree(childNode, level + 1, excludes, directDependencies, messageFromChildren); } } if ((excluded || hasTransitiveDependencies) && message != null) // then generate message { - for (int i = 0; i < level; i++) { - message.append(" "); - } - - message.append(node.getArtifact()); + message.append(Strings.repeat(" ", level)).append(node.getArtifact()); if (excluded) { - message.append(" [excluded]" + System.lineSeparator()); + message.append(" [excluded]").append(System.lineSeparator()); } if (hasTransitiveDependencies) { - if (level == 1) { + if (level > 0) { message.append(" has transitive dependencies:"); } @@ -127,55 +130,27 @@ private static boolean searchTree(DependencyNode node, int level, ArtifactMatche @Override public void execute(EnforcerRuleHelper helper) throws EnforcerRuleException { - this.helper = helper; - - if (excludes == null) { - excludes = Collections.emptyList(); - } - if (includes == null) { - includes = Collections.emptyList(); - } - - final ArtifactMatcher exclusions = new ArtifactMatcher(excludes, includes); - - DependencyNode rootNode = null; - + MavenSession session; try { - MavenProject project = (MavenProject) helper.evaluate("${project}"); - MavenSession session = (MavenSession) helper.evaluate("${session}"); - - ProjectBuildingRequest buildingRequest = - new DefaultProjectBuildingRequest(session.getProjectBuildingRequest()); - buildingRequest.setProject(project); - - rootNode = createDependencyGraphBuilder().buildDependencyGraph(buildingRequest, null); - } catch (Exception e) { - throw new EnforcerRuleException("Error: Could not construct dependency tree.", e); - } - - String message = getMessage(); - StringBuilder generatedMessage = null; - if (message == null) { - generatedMessage = new StringBuilder(); + session = (MavenSession) helper.evaluate("${session}"); + } catch (ExpressionEvaluationException e) { + throw new RuntimeException(e); } - + ArtifactTypeRegistry artifactTypeRegistry = + session.getRepositorySession().getArtifactTypeRegistry(); + ArtifactMatcher exclusions = new ArtifactMatcher(excludes, includes); + Set directDependencies = session.getCurrentProject().getDependencies().stream() + .map(d -> RepositoryUtils.toDependency(d, artifactTypeRegistry)) + .collect(Collectors.toSet()); + + DependencyNode rootNode = ArtifactUtils.resolveTransitiveDependencies(helper); + StringBuilder generatedMessage = new StringBuilder(); try { - if (searchTree(rootNode, 0, exclusions, generatedMessage)) { - throw new EnforcerRuleException(message == null ? generatedMessage.toString() : message); + if (searchTree(rootNode, 0, exclusions, directDependencies, generatedMessage)) { + throw new EnforcerRuleException(ofNullable(getMessage()).orElse(generatedMessage.toString())); } } catch (InvalidVersionSpecificationException e) { throw new EnforcerRuleException("Error: Invalid version range.", e); } } - - private DependencyGraphBuilder createDependencyGraphBuilder() throws ComponentLookupException { - // CHECKSTYLE_OFF: LineLength - DefaultDependencyGraphBuilder builder = (DefaultDependencyGraphBuilder) - helper.getContainer().lookup(DependencyGraphBuilder.class.getCanonicalName(), "default"); - // CHECKSTYLE_ON: LineLength - - builder.enableLogging(new ConsoleLogger(ConsoleLogger.LEVEL_DISABLED, "DefaultDependencyGraphBuilder")); - - return builder; - } } diff --git a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BannedDependencies.java b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BannedDependencies.java index d9315723..e65464ec 100644 --- a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BannedDependencies.java +++ b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BannedDependencies.java @@ -18,11 +18,7 @@ */ package org.apache.maven.plugins.enforcer; -import java.util.List; -import java.util.Set; import org.apache.maven.artifact.Artifact; -import org.apache.maven.enforcer.rule.api.EnforcerRuleException; -import org.apache.maven.plugin.logging.Log; import org.apache.maven.plugins.enforcer.utils.ArtifactUtils; /** @@ -30,97 +26,15 @@ * * @author Brian Fox */ -public class BannedDependencies extends AbstractBanDependencies { - - /** - * Specify the banned dependencies. This can be a list of artifacts in the format - * groupId[:artifactId][:version]. Any of the sections can be a wildcard - * by using '*' (ie group:*:1.0)
- * The rule will fail if any dependency matches any exclude, unless it also matches - * an include rule. - * - * @see {@link #setExcludes(List)} - * @see {@link #getExcludes()} - */ - private List excludes = null; - - /** - * Specify the allowed dependencies. This can be a list of artifacts in the format - * groupId[:artifactId][:version]. Any of the sections can be a wildcard - * by using '*' (ie group:*:1.0)
- * Includes override the exclude rules. It is meant to allow wide exclusion rules - * with wildcards and still allow a - * smaller set of includes.
- * For example, to ban all xerces except xerces-api -> exclude "xerces", include "xerces:xerces-api" - * - * @see {@link #setIncludes(List)} - * @see {@link #getIncludes()} - */ - private List includes = null; - +public class BannedDependencies extends BannedDependenciesBase { @Override - protected Set checkDependencies(Set theDependencies, Log log) throws EnforcerRuleException { - - Set excluded = ArtifactUtils.checkDependencies(theDependencies, excludes); - - // anything specifically included should be removed - // from the ban list. - if (excluded != null) { - Set included = ArtifactUtils.checkDependencies(theDependencies, includes); - - if (included != null) { - excluded.removeAll(included); - } - } - return excluded; + protected boolean validate(Artifact artifact) { + return !ArtifactUtils.matchDependencyArtifact(artifact, excludes) + || ArtifactUtils.matchDependencyArtifact(artifact, includes); } - /** - * Gets the excludes. - * - * @return the excludes - */ - public List getExcludes() { - return this.excludes; - } - - /** - * Specify the banned dependencies. This can be a list of artifacts in the format - * groupId[:artifactId][:version]. Any of the sections can be a wildcard - * by using '*' (ie group:*:1.0)
- * The rule will fail if any dependency matches any exclude, unless it also matches an - * include rule. - * - * @see #getExcludes() - * @param theExcludes the excludes to set - */ - public void setExcludes(List theExcludes) { - this.excludes = theExcludes; - } - - /** - * Gets the includes. - * - * @return the includes - */ - public List getIncludes() { - return this.includes; - } - - /** - * Specify the allowed dependencies. This can be a list of artifacts in the format - * groupId[:artifactId][:version]. Any of the sections can be a wildcard - * by using '*' (ie group:*:1.0)
- * Includes override the exclude rules. It is meant to allow wide exclusion rules with - * wildcards and still allow a - * smaller set of includes.
- * For example, to ban all xerces except xerces-api → exclude "xerces", - * include "xerces:xerces-api" - * - * @see #setIncludes(List) - * @param theIncludes the includes to set - */ - public void setIncludes(List theIncludes) { - this.includes = theIncludes; + @Override + protected String getErrorMessage() { + return "banned via the exclude/include list"; } } diff --git a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BannedDependenciesBase.java b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BannedDependenciesBase.java new file mode 100644 index 00000000..32402f7c --- /dev/null +++ b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BannedDependenciesBase.java @@ -0,0 +1,195 @@ +/* + * 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. + */ +package org.apache.maven.plugins.enforcer; + +import com.google.common.base.Strings; +import java.util.List; +import org.apache.maven.artifact.Artifact; +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.plugins.enforcer.utils.ArtifactUtils; +import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException; +import org.eclipse.aether.graph.DependencyNode; + +/** + * Abstract base class for rules which validate the transitive + * dependency tree by traversing all children and validating every + * dependency artifact. + */ +abstract class BannedDependenciesBase extends AbstractNonCacheableEnforcerRule { + + /** + * Specify the banned dependencies. This can be a list of artifacts in the format + * groupId[:artifactId][:version]. Any of the sections can be a wildcard + * by using '*' (ie group:*:1.0)
+ * The rule will fail if any dependency matches any exclude, unless it also matches + * an include rule. + * + * @see #setExcludes(List) + * @see #getExcludes() + */ + protected List excludes = null; + + /** + * Specify the allowed dependencies. This can be a list of artifacts in the format + * groupId[:artifactId][:version]. Any of the sections can be a wildcard + * by using '*' (ie group:*:1.0)
+ * Includes override the exclude rules. It is meant to allow wide exclusion rules + * with wildcards and still allow a + * smaller set of includes.
+ * For example, to ban all xerces except xerces-api -> exclude "xerces", include "xerces:xerces-api" + * + * @see #setIncludes(List) + * @see #getIncludes() + */ + protected List includes = null; + + /** Specify if transitive dependencies should be searched (default) or only look at direct dependencies. */ + private boolean searchTransitive = true; + + @Override + public void execute(EnforcerRuleHelper helper) throws EnforcerRuleException { + MavenSession session; + try { + session = (MavenSession) helper.evaluate("${session}"); + } catch (ExpressionEvaluationException e) { + throw new EnforcerRuleException("Cannot resolve MavenSession", e); + } + + DependencyNode rootNode = ArtifactUtils.resolveTransitiveDependencies(helper); + if (!searchTransitive) { + String result = session.getCurrentProject().getDependencyArtifacts().stream() + .filter(a -> !validate(a)) + .collect( + StringBuilder::new, + (messageBuilder, node) -> messageBuilder + .append(node.getId()) + .append(" <--- ") + .append(getErrorMessage()), + (m1, m2) -> m1.append(m2.toString())) + .toString(); + if (!result.isEmpty()) { + throw new EnforcerRuleException(result); + } + } else { + StringBuilder messageBuilder = new StringBuilder(); + if (!validate(rootNode, 0, messageBuilder)) { + throw new EnforcerRuleException(messageBuilder.toString()); + } + } + } + + protected boolean validate(DependencyNode node, int level, StringBuilder messageBuilder) { + boolean rootFailed = level > 0 && !validate(ArtifactUtils.toArtifact(node)); + StringBuilder childMessageBuilder = new StringBuilder(); + if (rootFailed + || !node.getChildren().stream() + .map(childNode -> validate(childNode, level + 1, childMessageBuilder)) + .reduce(true, Boolean::logicalAnd)) { + messageBuilder + .append(Strings.repeat(" ", level)) + .append(ArtifactUtils.toArtifact(node).getId()); + if (rootFailed) { + messageBuilder.append(" <--- ").append(getErrorMessage()); + } + messageBuilder.append(System.lineSeparator()).append(childMessageBuilder); + return false; + } + return true; + } + + protected abstract String getErrorMessage(); + + /** + * Validates a dependency artifact if it fulfills the enforcer rule + * + * @param dependency dependency to be checked against the list of excludes + * @return {@code true} if the dependency passes the rule, {@code false} if the dependency + * triggers a validation error + */ + protected abstract boolean validate(Artifact dependency); + + /** + * Checks if is search transitive. + * + * @return the searchTransitive + */ + public boolean isSearchTransitive() { + return this.searchTransitive; + } + + /** + * Sets the search transitive. + * + * @param theSearchTransitive the searchTransitive to set + */ + public void setSearchTransitive(boolean theSearchTransitive) { + this.searchTransitive = theSearchTransitive; + } + + /** + * Gets the excludes. + * + * @return the excludes + */ + public List getExcludes() { + return this.excludes; + } + + /** + * Specify the banned dependencies. This can be a list of artifacts in the format + * groupId[:artifactId][:version]. Any of the sections can be a wildcard + * by using '*' (ie group:*:1.0)
+ * The rule will fail if any dependency matches any exclude, unless it also matches an + * include rule. + * + * @see #getExcludes() + * @param theExcludes the excludes to set + */ + public void setExcludes(List theExcludes) { + this.excludes = theExcludes; + } + + /** + * Gets the includes. + * + * @return the includes + */ + public List getIncludes() { + return this.includes; + } + + /** + * Specify the allowed dependencies. This can be a list of artifacts in the format + * groupId[:artifactId][:version]. Any of the sections can be a wildcard + * by using '*' (ie group:*:1.0)
+ * Includes override the exclude rules. It is meant to allow wide exclusion rules with + * wildcards and still allow a + * smaller set of includes.
+ * For example, to ban all xerces except xerces-api → exclude "xerces", + * include "xerces:xerces-api" + * + * @see #setIncludes(List) + * @param theIncludes the includes to set + */ + public void setIncludes(List theIncludes) { + this.includes = theIncludes; + } +} diff --git a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BannedPlugins.java b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BannedPlugins.java index 31620e9b..03deb7c3 100644 --- a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BannedPlugins.java +++ b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BannedPlugins.java @@ -18,23 +18,52 @@ */ package org.apache.maven.plugins.enforcer; -import java.util.Set; import org.apache.maven.artifact.Artifact; -import org.apache.maven.project.ProjectBuildingRequest; +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.plugins.enforcer.utils.ArtifactUtils; +import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException; /** * This rule checks that lists of plugins are not included. * * @author Marvin Froeder */ -public class BannedPlugins extends BannedDependencies { +public class BannedPlugins extends BannedDependenciesBase { + + @Override + public void execute(EnforcerRuleHelper helper) throws EnforcerRuleException { + MavenSession session; + try { + session = (MavenSession) helper.evaluate("${session}"); + } catch (ExpressionEvaluationException e) { + throw new EnforcerRuleException("Cannot resolve MavenSession", e); + } + + String result = session.getCurrentProject().getPluginArtifacts().stream() + .filter(a -> !validate(a)) + .collect( + StringBuilder::new, + (messageBuilder, node) -> messageBuilder + .append(node.getId()) + .append(" <--- ") + .append(getErrorMessage()), + (m1, m2) -> m1.append(m2.toString())) + .toString(); + if (!result.isEmpty()) { + throw new EnforcerRuleException(result); + } + } + @Override - protected Set getDependenciesToCheck(ProjectBuildingRequest buildingRequest) { - return buildingRequest.getProject().getPluginArtifacts(); + protected String getErrorMessage() { + return "banned plugin"; } @Override - protected CharSequence getErrorMessage(Artifact artifact) { - return "Found Banned Plugin: " + artifact.getId() + System.lineSeparator(); + protected boolean validate(Artifact artifact) { + return !ArtifactUtils.matchDependencyArtifact(artifact, excludes) + || ArtifactUtils.matchDependencyArtifact(artifact, includes); } } diff --git a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/DependencyConvergence.java b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/DependencyConvergence.java index 287f64bc..cc7e76ef 100644 --- a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/DependencyConvergence.java +++ b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/DependencyConvergence.java @@ -22,22 +22,17 @@ import java.util.Collections; import java.util.List; import org.apache.maven.artifact.Artifact; -import org.apache.maven.artifact.repository.ArtifactRepository; -import org.apache.maven.artifact.resolver.filter.ArtifactFilter; 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.plugin.logging.Log; +import org.apache.maven.plugins.enforcer.utils.ArtifactUtils; import org.apache.maven.plugins.enforcer.utils.DependencyVersionMap; -import org.apache.maven.project.DefaultProjectBuildingRequest; -import org.apache.maven.project.MavenProject; -import org.apache.maven.project.ProjectBuildingRequest; -import org.apache.maven.shared.dependency.graph.DependencyCollectorBuilder; -import org.apache.maven.shared.dependency.graph.DependencyCollectorBuilderException; -import org.apache.maven.shared.dependency.graph.DependencyNode; -import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException; -import org.codehaus.plexus.component.repository.exception.ComponentLookupException; +import org.eclipse.aether.collection.DependencyCollectionContext; +import org.eclipse.aether.collection.DependencySelector; +import org.eclipse.aether.graph.Dependency; +import org.eclipse.aether.graph.DependencyNode; +import org.eclipse.aether.util.graph.selector.ExclusionDependencySelector; /** * @author Rex Hoffman @@ -51,58 +46,41 @@ public class DependencyConvergence implements EnforcerRule { private List excludes; + private DependencyVersionMap dependencyVersionMap; + public void setUniqueVersions(boolean uniqueVersions) { this.uniqueVersions = uniqueVersions; } - // CHECKSTYLE_OFF: LineLength - /** - * Uses the {@link EnforcerRuleHelper} to populate the values of the - * {@link DependencyTreeBuilder#buildDependencyTree(MavenProject, ArtifactRepository, ArtifactFactory, ArtifactMetadataSource, ArtifactFilter, ArtifactCollector)} - * factory method.
- * This method simply exists to hide all the ugly lookup that the {@link EnforcerRuleHelper} has to do. - * - * @param helper - * @return a Dependency Node which is the root of the project's dependency tree - * @throws EnforcerRuleException - */ - // CHECKSTYLE_ON: LineLength - private DependencyNode getNode(EnforcerRuleHelper helper) throws EnforcerRuleException { - try { - MavenProject project = (MavenProject) helper.evaluate("${project}"); - MavenSession session = (MavenSession) helper.evaluate("${session}"); - DependencyCollectorBuilder dependencyCollectorBuilder = - helper.getComponent(DependencyCollectorBuilder.class); - ArtifactRepository repository = (ArtifactRepository) helper.evaluate("${localRepository}"); - - ProjectBuildingRequest buildingRequest = - new DefaultProjectBuildingRequest(session.getProjectBuildingRequest()); - buildingRequest.setProject(project); - buildingRequest.setLocalRepository(repository); - ArtifactFilter filter = (Artifact a) -> - ("compile".equalsIgnoreCase(a.getScope()) || "runtime".equalsIgnoreCase(a.getScope())) - && !a.isOptional(); - - return dependencyCollectorBuilder.collectDependencyGraph(buildingRequest, filter); - } catch (ExpressionEvaluationException | ComponentLookupException e) { - throw new EnforcerRuleException("Unable to lookup a component " + e.getLocalizedMessage(), e); - } catch (DependencyCollectorBuilderException e) { - throw new EnforcerRuleException("Could not build dependency tree " + e.getLocalizedMessage(), e); - } - } - @Override public void execute(EnforcerRuleHelper helper) throws EnforcerRuleException { if (log == null) { log = helper.getLog(); } try { - DependencyNode node = getNode(helper); - DependencyVersionMap visitor = new DependencyVersionMap(log); - visitor.setUniqueVersions(uniqueVersions); - node.accept(visitor); - List errorMsgs = new ArrayList<>(); - errorMsgs.addAll(getConvergenceErrorMsgs(visitor.getConflictedVersionNumbers(includes, excludes))); + DependencyNode node = ArtifactUtils.resolveTransitiveDependencies( + helper, + // TODO: use a modified version of ExclusionDependencySelector to process excludes and includes + new DependencySelector() { + @Override + public boolean selectDependency(Dependency dependency) { + // regular OptionalDependencySelector only discriminates optional dependencies at level 2+ + return !dependency.isOptional() + // regular ScopeDependencySelector is case-sensitive + && !dependency.getScope().equalsIgnoreCase(Artifact.SCOPE_TEST); + } + + @Override + public DependencySelector deriveChildSelector(DependencyCollectionContext context) { + return this; + } + }, + new ExclusionDependencySelector()); + dependencyVersionMap = new DependencyVersionMap(log).setUniqueVersions(uniqueVersions); + node.accept(dependencyVersionMap); + + List errorMsgs = new ArrayList<>( + getConvergenceErrorMsgs(dependencyVersionMap.getConflictedVersionNumbers(includes, excludes))); for (CharSequence errorMsg : errorMsgs) { log.warn(errorMsg); } @@ -120,7 +98,7 @@ private StringBuilder buildTreeString(DependencyNode node) { DependencyNode currentNode = node; while (currentNode != null) { loc.add(currentNode.getArtifact().toString()); - currentNode = currentNode.getParent(); + currentNode = dependencyVersionMap.getParent(currentNode); } Collections.reverse(loc); StringBuilder builder = new StringBuilder(); @@ -128,8 +106,7 @@ private StringBuilder buildTreeString(DependencyNode node) { for (int j = 0; j < i; j++) { builder.append(" "); } - builder.append("+-" + loc.get(i)); - builder.append(System.lineSeparator()); + builder.append("+-").append(loc.get(i)).append(System.lineSeparator()); } return builder; } @@ -144,15 +121,16 @@ private List getConvergenceErrorMsgs(List> errors) private String buildConvergenceErrorMsg(List nodeList) { StringBuilder builder = new StringBuilder(); - builder.append(System.lineSeparator() + "Dependency convergence error for " - + nodeList.get(0).getArtifact().toString() - + " paths to dependency are:" + System.lineSeparator()); + builder.append(System.lineSeparator()) + .append("Dependency convergence error for ") + .append(nodeList.get(0).getArtifact().toString()) + .append(" paths to dependency are:") + .append(System.lineSeparator()); if (nodeList.size() > 0) { builder.append(buildTreeString(nodeList.get(0))); } for (DependencyNode node : nodeList.subList(1, nodeList.size())) { - builder.append("and" + System.lineSeparator()); - builder.append(buildTreeString(node)); + builder.append("and").append(System.lineSeparator()).append(buildTreeString(node)); } return builder.toString(); } @@ -168,7 +146,7 @@ public boolean isCacheable() { } @Override - public boolean isResultValid(EnforcerRule rule) { + public boolean isResultValid(EnforcerRule ignored) { return false; } } diff --git a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/RequirePluginVersions.java b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/RequirePluginVersions.java index 2e18784c..c3b82200 100644 --- a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/RequirePluginVersions.java +++ b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/RequirePluginVersions.java @@ -28,12 +28,11 @@ import java.util.Map; import java.util.Set; import org.apache.maven.BuildFailureException; +import org.apache.maven.RepositoryUtils; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.factory.ArtifactFactory; import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.artifact.resolver.ArtifactNotFoundException; -import org.apache.maven.artifact.resolver.ArtifactResolutionException; -import org.apache.maven.artifact.resolver.ArtifactResolver; import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; import org.apache.maven.artifact.versioning.VersionRange; import org.apache.maven.enforcer.rule.api.EnforcerRuleException; @@ -66,6 +65,9 @@ import org.codehaus.plexus.component.repository.exception.ComponentLookupException; import org.codehaus.plexus.util.StringUtils; import org.codehaus.plexus.util.xml.pull.XmlPullParserException; +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.resolution.ArtifactRequest; +import org.eclipse.aether.resolution.ArtifactResolutionException; /** * This rule will enforce that all plugins specified in the poms have a version declared. @@ -163,8 +165,7 @@ public class RequirePluginVersions extends AbstractNonCacheableEnforcerRule { /** The factory. */ private ArtifactFactory factory; - /** The resolver. */ - private ArtifactResolver resolver; + private RepositorySystem repositorySystem; /** The local. */ private ArtifactRepository local; @@ -199,7 +200,7 @@ public void execute(EnforcerRuleHelper helper) throws EnforcerRuleException { session = (MavenSession) helper.evaluate("${session}"); pluginManager = helper.getComponent(PluginManager.class); factory = helper.getComponent(ArtifactFactory.class); - resolver = helper.getComponent(ArtifactResolver.class); + repositorySystem = helper.getComponent(RepositorySystem.class); local = (ArtifactRepository) helper.evaluate("${localRepository}"); utils = new EnforcerRuleUtils(helper); @@ -441,7 +442,7 @@ public Set getProfilePlugins(MavenProject project) { * @param project project to search * @return matching plugin, null if not found. */ - protected Plugin findCurrentPlugin(Plugin plugin, MavenProject project) { + protected Plugin findCurrentPlugin(Plugin plugin, MavenProject project) throws EnforcerRuleException { Plugin found = null; try { Model model = project.getModel(); @@ -452,33 +453,25 @@ protected Plugin findCurrentPlugin(Plugin plugin, MavenProject project) { } if (found == null) { - found = resolvePlugin(plugin, project); - } + Artifact artifact = factory.createPluginArtifact( + plugin.getGroupId(), plugin.getArtifactId(), VersionRange.createFromVersion("LATEST")); - return found; - } - - /** - * Resolve plugin. - * - * @param plugin the plugin - * @param project the project - * @return the plugin - */ - protected Plugin resolvePlugin(Plugin plugin, MavenProject project) { - - List pluginRepositories = project.getPluginArtifactRepositories(); - Artifact artifact = factory.createPluginArtifact( - plugin.getGroupId(), plugin.getArtifactId(), VersionRange.createFromVersion("LATEST")); - - try { - this.resolver.resolve(artifact, pluginRepositories, this.local); + try { + repositorySystem.resolveArtifact( + session.getRepositorySession(), + new ArtifactRequest( + RepositoryUtils.toArtifact(artifact), + session.getCurrentProject().getRemotePluginRepositories(), + "resolvePlugin")); + } catch (ArtifactResolutionException e) { + throw new EnforcerRuleException("Unable to resolve the plugin " + artifact.getArtifactId(), e); + } plugin.setVersion(artifact.getVersion()); - } catch (ArtifactResolutionException | ArtifactNotFoundException e) { - // What does this mean? + + found = plugin; } - return plugin; + return found; } /** @@ -805,9 +798,9 @@ private PluginDescriptor verifyPlugin( } catch (PluginVersionResolutionException | InvalidVersionSpecificationException | InvalidPluginException - | ArtifactNotFoundException - | ArtifactResolutionException - | PluginVersionNotFoundException e) { + | PluginVersionNotFoundException + | org.apache.maven.artifact.resolver.ArtifactResolutionException + | ArtifactNotFoundException e) { throw new LifecycleExecutionException(e.getMessage(), e); } return pluginDescriptor; diff --git a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/RequireReleaseDeps.java b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/RequireReleaseDeps.java index f3f9224d..abbb0d0c 100644 --- a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/RequireReleaseDeps.java +++ b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/RequireReleaseDeps.java @@ -18,15 +18,13 @@ */ package org.apache.maven.plugins.enforcer; -import java.util.Collections; +import static java.util.Optional.ofNullable; + import java.util.HashSet; -import java.util.List; -import java.util.Optional; import java.util.Set; import org.apache.maven.artifact.Artifact; import org.apache.maven.enforcer.rule.api.EnforcerRuleException; import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper; -import org.apache.maven.plugin.logging.Log; import org.apache.maven.plugins.enforcer.utils.ArtifactUtils; import org.apache.maven.project.MavenProject; import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException; @@ -36,7 +34,7 @@ * * @author Brian Fox */ -public class RequireReleaseDeps extends AbstractBanDependencies { +public class RequireReleaseDeps extends BannedDependenciesBase { /** * Allows this rule to execute only when this project is a release. @@ -55,24 +53,6 @@ public class RequireReleaseDeps extends AbstractBanDependencies { */ private boolean failWhenParentIsSnapshot = true; - /** - * Dependencies to ignore when checking for release versions. For example, inter-module dependencies - * can be excluded from the check and therefore allowed to contain snapshot versions. - * - * @see {@link #setExcludes(List)} - * @see {@link #getExcludes()} - */ - private List excludes = null; - - /** - * Dependencies to include when checking for release versions. If any of the included dependencies - * have snapshot versions, the rule will fail. - * - * @see {@link #setIncludes(List)} - * @see {@link #getIncludes()} - */ - private List includes = null; - // Override parent to allow optional ignore of this rule. @Override public void execute(EnforcerRuleHelper helper) throws EnforcerRuleException { @@ -98,8 +78,10 @@ public void execute(EnforcerRuleHelper helper) throws EnforcerRuleException { Artifact parentArtifact = project.getParentArtifact(); if (parentArtifact != null) { - Set artifacts = filterArtifacts(Collections.singleton(parentArtifact)); - parentArtifact = Optional.ofNullable(artifacts) + Set singletonArtifact = new HashSet<>(); + singletonArtifact.add(parentArtifact); + Set artifacts = filterArtifacts(singletonArtifact); + parentArtifact = ofNullable(artifacts) .flatMap(s -> s.stream().findFirst()) .orElse(null); } @@ -111,6 +93,11 @@ public void execute(EnforcerRuleHelper helper) throws EnforcerRuleException { } } + @Override + protected String getErrorMessage() { + return "is not a release dependency"; + } + /** * @param helper * @return The evaluated {@link MavenProject}. @@ -125,19 +112,10 @@ private MavenProject getProject(EnforcerRuleHelper helper) throws EnforcerRuleEx } @Override - protected Set checkDependencies(Set dependencies, Log log) throws EnforcerRuleException { - Set foundSnapshots = new HashSet<>(); - - Set filteredDependencies = filterArtifacts(dependencies); - - if (filteredDependencies != null) { - for (Artifact artifact : filteredDependencies) { - if (artifact.isSnapshot()) { - foundSnapshots.add(artifact); - } - } - } - return foundSnapshots; + protected boolean validate(Artifact artifact) { + return ArtifactUtils.matchDependencyArtifact(artifact, excludes) + && !ArtifactUtils.matchDependencyArtifact(artifact, includes) + || !artifact.isSnapshot(); } /* @@ -148,27 +126,16 @@ protected Set checkDependencies(Set dependencies, Log log) t * @return the resulting set of dependencies */ protected Set filterArtifacts(Set dependencies) throws EnforcerRuleException { - if (includes == null && excludes == null) { - return dependencies; - } - - Set included; if (includes != null) { - included = ArtifactUtils.checkDependencies(dependencies, includes); - } else { - included = new HashSet<>(dependencies); + dependencies = ArtifactUtils.filterDependencyArtifacts(dependencies, includes); } - // anything specifically included should be removed - // from the ban list. - if (included != null) { - Set excluded = ArtifactUtils.checkDependencies(dependencies, excludes); - - if (excluded != null) { - included.removeAll(excluded); - } + if (dependencies != null && excludes != null) { + ofNullable(ArtifactUtils.filterDependencyArtifacts(dependencies, excludes)) + .ifPresent(dependencies::removeAll); } - return included; + + return dependencies; } public final boolean isOnlyWhenRelease() { @@ -186,20 +153,4 @@ public final boolean isFailWhenParentIsSnapshot() { public final void setFailWhenParentIsSnapshot(boolean failWhenParentIsSnapshot) { this.failWhenParentIsSnapshot = failWhenParentIsSnapshot; } - - public final void setExcludes(List excludes) { - this.excludes = excludes; - } - - public final List getExcludes() { - return excludes; - } - - public void setIncludes(List includes) { - this.includes = includes; - } - - public List getIncludes() { - return includes; - } } diff --git a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/RequireUpperBoundDeps.java b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/RequireUpperBoundDeps.java index e3935cc3..dfc5e2c5 100644 --- a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/RequireUpperBoundDeps.java +++ b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/RequireUpperBoundDeps.java @@ -20,29 +20,23 @@ import java.util.ArrayList; import java.util.Collections; -import java.util.LinkedHashMap; +import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.maven.artifact.Artifact; -import org.apache.maven.artifact.repository.ArtifactRepository; -import org.apache.maven.artifact.resolver.filter.ArtifactFilter; import org.apache.maven.artifact.versioning.ArtifactVersion; import org.apache.maven.artifact.versioning.DefaultArtifactVersion; import org.apache.maven.artifact.versioning.OverConstrainedVersionException; 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.plugin.logging.Log; -import org.apache.maven.project.DefaultProjectBuildingRequest; -import org.apache.maven.project.MavenProject; -import org.apache.maven.project.ProjectBuildingRequest; -import org.apache.maven.shared.dependency.graph.DependencyCollectorBuilder; -import org.apache.maven.shared.dependency.graph.DependencyCollectorBuilderException; -import org.apache.maven.shared.dependency.graph.DependencyNode; -import org.apache.maven.shared.dependency.graph.traversal.DependencyNodeVisitor; +import org.apache.maven.plugins.enforcer.utils.ArtifactUtils; +import org.apache.maven.plugins.enforcer.utils.ParentNodeProvider; +import org.apache.maven.plugins.enforcer.utils.ParentsVisitor; import org.apache.maven.shared.utils.logging.MessageUtils; -import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException; -import org.codehaus.plexus.component.repository.exception.ComponentLookupException; +import org.eclipse.aether.graph.DependencyNode; +import org.eclipse.aether.graph.DependencyVisitor; +import org.eclipse.aether.util.graph.manager.DependencyManagerUtils; /** * Rule to enforce that the resolved dependency is also the most recent one of all transitive dependencies. @@ -72,6 +66,8 @@ public class RequireUpperBoundDeps extends AbstractNonCacheableEnforcerRule { */ private List includes = null; + private RequireUpperBoundDepsVisitor upperBoundDepsVisitor; + /** * Set to {@code true} if timestamped snapshots should be used. * @@ -99,55 +95,17 @@ public void setIncludes(List includes) { this.includes = includes; } - // CHECKSTYLE_OFF: LineLength - /** - * Uses the {@link EnforcerRuleHelper} to populate the values of the - * {@link DependencyCollectorBuilder#collectDependencyGraph(ProjectBuildingRequest, ArtifactFilter)} - * factory method.
- * This method simply exists to hide all the ugly lookup that the {@link EnforcerRuleHelper} has to do. - * - * @param helper - * @return a Dependency Node which is the root of the project's dependency tree - * @throws EnforcerRuleException when the build should fail - */ - // CHECKSTYLE_ON: LineLength - private DependencyNode getNode(EnforcerRuleHelper helper) throws EnforcerRuleException { - try { - MavenProject project = (MavenProject) helper.evaluate("${project}"); - MavenSession session = (MavenSession) helper.evaluate("${session}"); - DependencyCollectorBuilder dependencyCollectorBuilder = - helper.getComponent(DependencyCollectorBuilder.class); - ArtifactRepository repository = (ArtifactRepository) helper.evaluate("${localRepository}"); - - ProjectBuildingRequest buildingRequest = - new DefaultProjectBuildingRequest(session.getProjectBuildingRequest()); - buildingRequest.setProject(project); - buildingRequest.setLocalRepository(repository); - ArtifactFilter filter = (Artifact a) -> - ("compile".equalsIgnoreCase(a.getScope()) || "runtime".equalsIgnoreCase(a.getScope())) - && !a.isOptional(); - - return dependencyCollectorBuilder.collectDependencyGraph(buildingRequest, filter); - } catch (ExpressionEvaluationException e) { - throw new EnforcerRuleException("Unable to lookup an expression " + e.getLocalizedMessage(), e); - } catch (ComponentLookupException e) { - throw new EnforcerRuleException("Unable to lookup a component " + e.getLocalizedMessage(), e); - } catch (DependencyCollectorBuilderException e) { - throw new EnforcerRuleException("Could not build dependency tree " + e.getLocalizedMessage(), e); - } - } - @Override public void execute(EnforcerRuleHelper helper) throws EnforcerRuleException { if (log == null) { log = helper.getLog(); } - DependencyNode node = getNode(helper); - RequireUpperBoundDepsVisitor visitor = new RequireUpperBoundDepsVisitor(); - visitor.setUniqueVersions(uniqueVersions); - visitor.setIncludes(includes); - node.accept(visitor); - List errorMessages = buildErrorMessages(visitor.getConflicts()); + DependencyNode node = ArtifactUtils.resolveTransitiveDependencies(helper); + upperBoundDepsVisitor = new RequireUpperBoundDepsVisitor() + .setUniqueVersions(uniqueVersions) + .setIncludes(includes); + node.accept(upperBoundDepsVisitor); + List errorMessages = buildErrorMessages(upperBoundDepsVisitor.getConflicts()); if (errorMessages.size() > 0) { throw new EnforcerRuleException( "Failed while enforcing RequireUpperBoundDeps. The error(s) are " + errorMessages); @@ -157,7 +115,7 @@ public void execute(EnforcerRuleHelper helper) throws EnforcerRuleException { private List buildErrorMessages(List> conflicts) { List errorMessages = new ArrayList<>(conflicts.size()); for (List conflict : conflicts) { - Artifact artifact = conflict.get(0).getArtifact(); + org.eclipse.aether.artifact.Artifact artifact = conflict.get(0).getArtifact(); String groupArt = artifact.getGroupId() + ":" + artifact.getArtifactId(); if (excludes != null && excludes.contains(groupArt)) { log.info("Ignoring requireUpperBoundDeps in " + groupArt); @@ -170,13 +128,17 @@ private List buildErrorMessages(List> conflicts) { private String buildErrorMessage(List conflict) { StringBuilder errorMessage = new StringBuilder(); - errorMessage.append(System.lineSeparator() + "Require upper bound dependencies error for " - + getFullArtifactName(conflict.get(0), false) + " paths to dependency are:" + System.lineSeparator()); + errorMessage + .append(System.lineSeparator()) + .append("Require upper bound dependencies error for ") + .append(getFullArtifactName(conflict.get(0), false)) + .append(" paths to dependency are:") + .append(System.lineSeparator()); if (conflict.size() > 0) { errorMessage.append(buildTreeString(conflict.get(0))); } for (DependencyNode node : conflict.subList(1, conflict.size())) { - errorMessage.append("and" + System.lineSeparator()); + errorMessage.append("and").append(System.lineSeparator()); errorMessage.append(buildTreeString(node)); } return errorMessage.toString(); @@ -188,13 +150,13 @@ private StringBuilder buildTreeString(DependencyNode node) { while (currentNode != null) { StringBuilder line = new StringBuilder(getFullArtifactName(currentNode, false)); - if (currentNode.getPremanagedVersion() != null) { + if (DependencyManagerUtils.getPremanagedVersion(currentNode) != null) { line.append(" (managed) <-- "); line.append(getFullArtifactName(currentNode, true)); } loc.add(line.toString()); - currentNode = currentNode.getParent(); + currentNode = upperBoundDepsVisitor.getParent(currentNode); } Collections.reverse(loc); StringBuilder builder = new StringBuilder(); @@ -209,9 +171,9 @@ private StringBuilder buildTreeString(DependencyNode node) { } private String getFullArtifactName(DependencyNode node, boolean usePremanaged) { - Artifact artifact = node.getArtifact(); + Artifact artifact = ArtifactUtils.toArtifact(node); - String version = node.getPremanagedVersion(); + String version = DependencyManagerUtils.getPremanagedVersion(node); if (!usePremanaged || version == null) { version = uniqueVersions ? artifact.getVersion() : artifact.getBaseVersion(); } @@ -232,42 +194,42 @@ private String getFullArtifactName(DependencyNode node, boolean usePremanaged) { return result; } - private static class RequireUpperBoundDepsVisitor implements DependencyNodeVisitor { + private static class RequireUpperBoundDepsVisitor implements DependencyVisitor, ParentNodeProvider { + private final ParentsVisitor parentsVisitor = new ParentsVisitor(); private boolean uniqueVersions; - private List includes = null; - public void setUniqueVersions(boolean uniqueVersions) { + public RequireUpperBoundDepsVisitor setUniqueVersions(boolean uniqueVersions) { this.uniqueVersions = uniqueVersions; + return this; } - public void setIncludes(List includes) { + public RequireUpperBoundDepsVisitor setIncludes(List includes) { this.includes = includes; + return this; } - private Map> keyToPairsMap = new LinkedHashMap<>(); + private final Map> keyToPairsMap = new HashMap<>(); - public boolean visit(DependencyNode node) { - DependencyNodeHopCountPair pair = new DependencyNodeHopCountPair(node); + @Override + public boolean visitEnter(DependencyNode node) { + parentsVisitor.visitEnter(node); + DependencyNodeHopCountPair pair = new DependencyNodeHopCountPair(node, this); String key = pair.constructKey(); if (includes != null && !includes.isEmpty() && !includes.contains(key)) { return true; } - List pairs = keyToPairsMap.get(key); - if (pairs == null) { - pairs = new ArrayList<>(); - keyToPairsMap.put(key, pairs); - } - pairs.add(pair); - Collections.sort(pairs); + keyToPairsMap.computeIfAbsent(key, k1 -> new ArrayList<>()).add(pair); + keyToPairsMap.get(key).sort(DependencyNodeHopCountPair::compareTo); return true; } - public boolean endVisit(DependencyNode node) { - return true; + @Override + public boolean visitLeave(DependencyNode node) { + return parentsVisitor.visitLeave(node); } public List> getConflicts() { @@ -286,14 +248,6 @@ public List> getConflicts() { private boolean containsConflicts(List pairs) { DependencyNodeHopCountPair resolvedPair = pairs.get(0); - - // search for artifact with lowest hopCount - for (DependencyNodeHopCountPair hopPair : pairs.subList(1, pairs.size())) { - if (hopPair.getHopCount() < resolvedPair.getHopCount()) { - resolvedPair = hopPair; - } - } - ArtifactVersion resolvedVersion = resolvedPair.extractArtifactVersion(uniqueVersions, false); for (DependencyNodeHopCountPair pair : pairs) { @@ -304,30 +258,35 @@ private boolean containsConflicts(List pairs) { } return false; } + + @Override + public DependencyNode getParent(DependencyNode node) { + return parentsVisitor.getParent(node); + } } private static class DependencyNodeHopCountPair implements Comparable { - - private DependencyNode node; - + private final DependencyNode node; private int hopCount; + private final ParentNodeProvider parentNodeProvider; - private DependencyNodeHopCountPair(DependencyNode node) { + private DependencyNodeHopCountPair(DependencyNode node, ParentNodeProvider parentNodeProvider) { + this.parentNodeProvider = parentNodeProvider; this.node = node; countHops(); } private void countHops() { hopCount = 0; - DependencyNode parent = node.getParent(); + DependencyNode parent = parentNodeProvider.getParent(node); while (parent != null) { hopCount++; - parent = parent.getParent(); + parent = parentNodeProvider.getParent(parent); } } private String constructKey() { - Artifact artifact = node.getArtifact(); + Artifact artifact = ArtifactUtils.toArtifact(node); return artifact.getGroupId() + ":" + artifact.getArtifactId(); } @@ -336,11 +295,11 @@ public DependencyNode getNode() { } private ArtifactVersion extractArtifactVersion(boolean uniqueVersions, boolean usePremanagedVersion) { - if (usePremanagedVersion && node.getPremanagedVersion() != null) { - return new DefaultArtifactVersion(node.getPremanagedVersion()); + if (usePremanagedVersion && DependencyManagerUtils.getPremanagedVersion(node) != null) { + return new DefaultArtifactVersion(DependencyManagerUtils.getPremanagedVersion(node)); } - Artifact artifact = node.getArtifact(); + Artifact artifact = ArtifactUtils.toArtifact(node); String version = uniqueVersions ? artifact.getVersion() : artifact.getBaseVersion(); if (version != null) { return new DefaultArtifactVersion(version); @@ -357,7 +316,7 @@ public int getHopCount() { } public int compareTo(DependencyNodeHopCountPair other) { - return Integer.valueOf(hopCount).compareTo(Integer.valueOf(other.getHopCount())); + return Integer.compare(hopCount, other.getHopCount()); } } } diff --git a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/ArtifactMatcher.java b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/ArtifactMatcher.java index bf0a8760..ba96fc97 100644 --- a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/ArtifactMatcher.java +++ b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/ArtifactMatcher.java @@ -18,15 +18,19 @@ */ package org.apache.maven.plugins.enforcer.utils; +import static java.util.Optional.ofNullable; + import java.util.Collection; -import java.util.LinkedList; +import java.util.HashSet; import java.util.Objects; +import java.util.function.Function; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.versioning.DefaultArtifactVersion; import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; import org.apache.maven.artifact.versioning.VersionRange; import org.apache.maven.model.Dependency; import org.apache.maven.plugins.enforcer.AbstractVersionEnforcer; +import org.codehaus.plexus.util.StringUtils; /** * This class is used for matching Artifacts against a list of patterns. @@ -64,26 +68,34 @@ public Pattern(String pattern) { } } - public boolean match(Artifact artifact) throws InvalidVersionSpecificationException { + public boolean match(Artifact artifact) { Objects.requireNonNull(artifact, "artifact must not be null"); - return match( - artifact.getGroupId(), - artifact.getArtifactId(), - artifact.getVersion(), - artifact.getType(), - artifact.getScope(), - artifact.getClassifier()); + try { + return match( + artifact.getGroupId(), + artifact.getArtifactId(), + artifact.getVersion(), + artifact.getType(), + artifact.getScope(), + artifact.getClassifier()); + } catch (InvalidVersionSpecificationException e) { + throw new IllegalArgumentException(e); + } } - public boolean match(Dependency dependency) throws InvalidVersionSpecificationException { + public boolean match(Dependency dependency) { Objects.requireNonNull(dependency, "dependency must not be null"); - return match( - dependency.getGroupId(), - dependency.getArtifactId(), - dependency.getVersion(), - dependency.getType(), - dependency.getScope(), - dependency.getClassifier()); + try { + return match( + dependency.getGroupId(), + dependency.getArtifactId(), + dependency.getVersion(), + dependency.getType(), + dependency.getScope(), + dependency.getClassifier()); + } catch (InvalidVersionSpecificationException e) { + throw new IllegalArgumentException(e); + } } private boolean match( @@ -113,11 +125,8 @@ private boolean match( case 3: if (!matches(parts[2], version)) { - // CHECKSTYLE_OFF: LineLength if (!AbstractVersionEnforcer.containsVersion( - VersionRange.createFromVersionSpec(parts[2]), new DefaultArtifactVersion(version))) - // CHECKSTYLE_ON: LineLength - { + VersionRange.createFromVersionSpec(parts[2]), new DefaultArtifactVersion(version))) { return false; } } @@ -158,74 +167,54 @@ public String toString() { } } - private Collection patterns = new LinkedList<>(); + private final Collection excludePatterns = new HashSet<>(); - private Collection ignorePatterns = new LinkedList<>(); + private final Collection includePatterns = new HashSet<>(); /** * Construct class by providing patterns as strings. Empty strings are ignored. * - * @param patterns includes - * @param ignorePatterns excludes + * @param excludeStrings includes + * @param includeStrings excludes * @throws NullPointerException if any of the arguments is null */ - public ArtifactMatcher(final Collection patterns, final Collection ignorePatterns) { - Objects.requireNonNull(patterns, "patterns must not be null"); - Objects.requireNonNull(ignorePatterns, "ignorePatterns must not be null"); - for (String pattern : patterns) { - if (pattern != null && !"".equals(pattern)) { - this.patterns.add(new Pattern(pattern)); - } - } + public ArtifactMatcher(final Collection excludeStrings, final Collection includeStrings) { + ofNullable(excludeStrings).ifPresent(excludes -> excludes.stream() + .filter(StringUtils::isNotEmpty) + .map(Pattern::new) + .forEach(excludePatterns::add)); + ofNullable(includeStrings).ifPresent(includes -> includes.stream() + .filter(StringUtils::isNotEmpty) + .map(Pattern::new) + .forEach(includePatterns::add)); + } - for (String ignorePattern : ignorePatterns) { - if (ignorePattern != null && !"".equals(ignorePattern)) { - this.ignorePatterns.add(new Pattern(ignorePattern)); - } - } + private boolean match(Function matcher) throws InvalidVersionSpecificationException { + return excludePatterns.stream().anyMatch(matcher::apply) + && includePatterns.stream().noneMatch(matcher::apply); } /** * Check if artifact matches patterns. * * @param artifact the artifact to match - * @return {@code true} if artifact matches any {@link #patterns} and none of the {@link #ignorePatterns}, otherwise + * @return {@code true} if artifact matches any {@link #excludePatterns} and none of the {@link #includePatterns}, otherwise * {@code false} * @throws InvalidVersionSpecificationException if any pattern contains an invalid version range */ public boolean match(Artifact artifact) throws InvalidVersionSpecificationException { - for (Pattern pattern : patterns) { - if (pattern.match(artifact)) { - for (Pattern ignorePattern : ignorePatterns) { - if (ignorePattern.match(artifact)) { - return false; - } - } - return true; - } - } - return false; + return match(p -> p.match(artifact)); } /** * Check if dependency matches patterns. * * @param dependency the dependency to match - * @return {@code true} if dependency matches any {@link #patterns} and none of the {@link #ignorePatterns}, + * @return {@code true} if dependency matches any {@link #excludePatterns} and none of the {@link #includePatterns}, * otherwise {@code false} * @throws InvalidVersionSpecificationException if any pattern contains an invalid version range */ public boolean match(Dependency dependency) throws InvalidVersionSpecificationException { - for (Pattern pattern : patterns) { - if (pattern.match(dependency)) { - for (Pattern ignorePattern : ignorePatterns) { - if (ignorePattern.match(dependency)) { - return false; - } - } - return true; - } - } - return false; + return match(p -> p.match(dependency)); } } diff --git a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/ArtifactUtils.java b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/ArtifactUtils.java index 4061b242..c1c017dc 100644 --- a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/ArtifactUtils.java +++ b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/ArtifactUtils.java @@ -18,15 +18,38 @@ */ package org.apache.maven.plugins.enforcer.utils; +import static java.util.Optional.ofNullable; + +import java.util.Collection; import java.util.HashSet; -import java.util.List; import java.util.Set; +import java.util.stream.Collectors; import org.apache.commons.lang3.StringUtils; +import org.apache.maven.RepositoryUtils; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; 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.DependencyManagement; import org.apache.maven.plugins.enforcer.utils.ArtifactMatcher.Pattern; -import org.apache.maven.shared.dependency.graph.DependencyNode; +import org.apache.maven.project.MavenProject; +import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException; +import org.codehaus.plexus.component.repository.exception.ComponentLookupException; +import org.eclipse.aether.DefaultRepositorySystemSession; +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.artifact.ArtifactTypeRegistry; +import org.eclipse.aether.collection.CollectRequest; +import org.eclipse.aether.collection.DependencyCollectionException; +import org.eclipse.aether.collection.DependencySelector; +import org.eclipse.aether.graph.DependencyNode; +import org.eclipse.aether.util.graph.manager.DependencyManagerUtils; +import org.eclipse.aether.util.graph.selector.AndDependencySelector; +import org.eclipse.aether.util.graph.transformer.ConflictResolver; +import org.eclipse.aether.util.graph.transformer.JavaScopeDeriver; +import org.eclipse.aether.util.graph.transformer.JavaScopeSelector; +import org.eclipse.aether.util.graph.transformer.NearestVersionSelector; +import org.eclipse.aether.util.graph.transformer.SimpleOptionalitySelector; /** * @@ -34,54 +57,149 @@ * @since 3.0.0 */ public final class ArtifactUtils { - private ArtifactUtils() {} - public static Set getAllDescendants(DependencyNode node) { - Set children = null; - if (node.getChildren() != null) { - children = new HashSet<>(); - for (DependencyNode depNode : node.getChildren()) { - children.add(depNode.getArtifact()); - Set subNodes = getAllDescendants(depNode); - if (subNodes != null) { - children.addAll(subNodes); - } + /** + * Converts {@link DependencyNode} to {@link Artifact}; in comparison + * to {@link RepositoryUtils#toArtifact(org.eclipse.aether.artifact.Artifact)}, this method + * assigns {@link Artifact#getScope()} and {@link Artifact#isOptional()} based on + * the dependency information from the node. + * + * @param node {@link DependencyNode} to convert to {@link Artifact} + * @return target artifact + */ + public static Artifact toArtifact(DependencyNode node) { + Artifact artifact = RepositoryUtils.toArtifact(node.getArtifact()); + ofNullable(node.getDependency()).ifPresent(dependency -> { + ofNullable(dependency.getScope()).ifPresent(artifact::setScope); + artifact.setOptional(dependency.isOptional()); + }); + return artifact; + } + + /** + * Retrieves the {@link DependencyNode} instance containing the result of the transitive dependency + * for the current {@link MavenProject}. + * + * @param helper (may not be null) an instance of the {@link EnforcerRuleHelper} class + * @param selectors zero or more {@link DependencySelector} instances + * @return a Dependency Node which is the root of the project's dependency tree + * @throws EnforcerRuleException thrown if the lookup fails + */ + public static DependencyNode resolveTransitiveDependencies( + EnforcerRuleHelper helper, DependencySelector... selectors) throws EnforcerRuleException { + try { + RepositorySystem repositorySystem = helper.getComponent(RepositorySystem.class); + MavenSession session = (MavenSession) helper.evaluate("${session}"); + MavenProject project = session.getCurrentProject(); + ArtifactTypeRegistry artifactTypeRegistry = + session.getRepositorySession().getArtifactTypeRegistry(); + + DefaultRepositorySystemSession repositorySystemSession = + new DefaultRepositorySystemSession(session.getRepositorySession()); + repositorySystemSession.setDependencyGraphTransformer(new ConflictResolver( + new NearestVersionSelector(), + new JavaScopeSelector(), + new SimpleOptionalitySelector(), + new JavaScopeDeriver())); + repositorySystemSession.setConfigProperty(ConflictResolver.CONFIG_PROP_VERBOSE, true); + repositorySystemSession.setConfigProperty(DependencyManagerUtils.CONFIG_PROP_VERBOSE, true); + if (selectors.length > 0) { + repositorySystemSession.setDependencySelector(new AndDependencySelector(selectors)); } + + CollectRequest collectRequest = new CollectRequest( + project.getDependencies().stream() + .map(d -> RepositoryUtils.toDependency(d, artifactTypeRegistry)) + .collect(Collectors.toList()), + ofNullable(project.getDependencyManagement()) + .map(DependencyManagement::getDependencies) + .map(list -> list.stream() + .map(d -> RepositoryUtils.toDependency(d, artifactTypeRegistry)) + .collect(Collectors.toList())) + .orElse(null), + project.getRemoteProjectRepositories()); + Artifact artifact = project.getArtifact(); + collectRequest.setRootArtifact(RepositoryUtils.toArtifact(artifact)); + + return repositorySystem + .collectDependencies(repositorySystemSession, collectRequest) + .getRoot(); + } catch (ExpressionEvaluationException | ComponentLookupException e) { + throw new EnforcerRuleException("Unable to lookup a component " + e.getLocalizedMessage(), e); + } catch (DependencyCollectionException e) { + throw new EnforcerRuleException("Could not build dependency tree " + e.getLocalizedMessage(), e); } - return children; } /** - * Checks the set of dependencies against the list of patterns. + *

Retrieves all child dependency artifacts from the given {@link DependencyNode} and returns them + * as a set of {@link Artifact}.

+ *

Note: Thus, the result will not contain the root artifact.

+ * @param node root node + * @return set of all child dependency artifacts + */ + public static Set getDependencyArtifacts(DependencyNode node) { + return getDependencyArtifacts(node, new HashSet<>()); + } + + private static Set getDependencyArtifacts(DependencyNode node, Set set) { + node.getChildren().forEach(child -> { + set.add(toArtifact(child)); + getDependencyArtifacts(child, set); + }); + return set; + } + + /** + * Returns a subset of dependency artifacts that match the given collection of patterns * - * @param thePatterns the patterns - * @param dependencies the dependencies + * @param dependencies dependency artifacts to match against patterns + * @param patterns patterns to match against the artifacts * @return a set containing artifacts matching one of the patterns or null * @throws EnforcerRuleException the enforcer rule exception */ - public static Set checkDependencies(Set dependencies, List thePatterns) + public static Set filterDependencyArtifacts(Set dependencies, Collection patterns) throws EnforcerRuleException { - Set foundMatches = null; - - if (thePatterns != null && thePatterns.size() > 0) { - - for (String pattern : thePatterns) { - String[] subStrings = pattern.split(":"); - subStrings = StringUtils.stripAll(subStrings); - String resultPattern = StringUtils.join(subStrings, ":"); + try { + return ofNullable(patterns) + .map(collection -> collection.stream() + .map(p -> p.split(":")) + .map(StringUtils::stripAll) + .map(arr -> String.join(":", arr)) + .flatMap(pattern -> + dependencies.stream().filter(artifact -> compareDependency(pattern, artifact))) + .collect(Collectors.toSet())) + .orElse(null); + } catch (IllegalArgumentException e) { + if (e.getCause() instanceof InvalidVersionSpecificationException) { + throw new EnforcerRuleException(e.getMessage()); + } + throw e; + } + } - for (Artifact artifact : dependencies) { - if (compareDependency(resultPattern, artifact)) { - // only create if needed - if (foundMatches == null) { - foundMatches = new HashSet(); - } - foundMatches.add(artifact); - } - } + /** + * Checks if the given dependency artifact matches the given collection of patterns + * + * @param artifact dependency artifact to match against patterns + * @param patterns patterns to match against the artifacts + * @return {@code true} if the given artifact matches the set of patterns + */ + public static boolean matchDependencyArtifact(Artifact artifact, Collection patterns) { + try { + return ofNullable(patterns) + .map(collection -> collection.stream() + .map(p -> p.split(":")) + .map(StringUtils::stripAll) + .map(arr -> String.join(":", arr)) + .anyMatch(pattern -> compareDependency(pattern, artifact))) + .orElse(false); + } catch (IllegalArgumentException e) { + if (e.getCause() instanceof InvalidVersionSpecificationException) { + throw new IllegalArgumentException(e.getMessage()); } + throw e; } - return foundMatches; } /** @@ -91,18 +209,8 @@ public static Set checkDependencies(Set dependencies, Listtrue if the artifact matches one of the patterns - * @throws EnforcerRuleException the enforcer rule exception */ - static boolean compareDependency(String pattern, Artifact artifact) throws EnforcerRuleException { - - ArtifactMatcher.Pattern am = new Pattern(pattern); - boolean result; - try { - result = am.match(artifact); - } catch (InvalidVersionSpecificationException e) { - throw new EnforcerRuleException("Invalid Version Range: ", e); - } - - return result; + static boolean compareDependency(String pattern, Artifact artifact) { + return new Pattern(pattern).match(artifact); } } diff --git a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/DependencyVersionMap.java b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/DependencyVersionMap.java index f0aabbad..959b4878 100644 --- a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/DependencyVersionMap.java +++ b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/DependencyVersionMap.java @@ -23,38 +23,43 @@ import java.util.List; import java.util.Map; import org.apache.commons.lang3.StringUtils; -import org.apache.maven.artifact.Artifact; import org.apache.maven.enforcer.rule.api.EnforcerRuleException; import org.apache.maven.plugin.logging.Log; -import org.apache.maven.shared.dependency.graph.DependencyNode; -import org.apache.maven.shared.dependency.graph.traversal.DependencyNodeVisitor; +import org.eclipse.aether.artifact.Artifact; +import org.eclipse.aether.graph.DependencyNode; +import org.eclipse.aether.graph.DependencyVisitor; /** * @author Brian Fox - * */ -public class DependencyVersionMap implements DependencyNodeVisitor { +public class DependencyVersionMap implements DependencyVisitor, ParentNodeProvider { + private ParentsVisitor parentsVisitor; private boolean uniqueVersions; - - private Map> idsToNode; + private final Map> idsToNode = new HashMap<>(); public DependencyVersionMap(Log log) { - idsToNode = new HashMap<>(); + this.parentsVisitor = new ParentsVisitor(); } - public void setUniqueVersions(boolean uniqueVersions) { + public DependencyVersionMap setUniqueVersions(boolean uniqueVersions) { this.uniqueVersions = uniqueVersions; + return this; } @Override - public boolean visit(DependencyNode node) { + public boolean visitEnter(DependencyNode node) { addDependency(node); - return !containsConflicts(node); + return parentsVisitor.visitEnter(node) && !containsConflicts(node); + } + + @Override + public boolean visitLeave(DependencyNode node) { + return parentsVisitor.visitLeave(node); } @Override - public boolean endVisit(DependencyNode node) { - return true; + public DependencyNode getParent(DependencyNode node) { + return parentsVisitor.getParent(node); } private String constructKey(DependencyNode node) { @@ -67,12 +72,7 @@ private String constructKey(Artifact artifact) { public void addDependency(DependencyNode node) { String key = constructKey(node); - List nodes = idsToNode.get(key); - if (nodes == null) { - nodes = new ArrayList<>(); - idsToNode.put(key, nodes); - } - nodes.add(node); + idsToNode.computeIfAbsent(key, k -> new ArrayList<>()).add(node); } private String getVersion(Artifact artifact) { @@ -111,7 +111,7 @@ public List> getConflictedVersionNumbers(List inclu if (formattedIncludes != null || formattedExcludes != null) { filteredNodes = new ArrayList<>(); for (DependencyNode node : nodes) { - if (includeArtifact(node.getArtifact(), formattedIncludes, formattedExcludes)) { + if (includeArtifact(node, formattedIncludes, formattedExcludes)) { filteredNodes.add(node); } } @@ -123,12 +123,12 @@ public List> getConflictedVersionNumbers(List inclu return output; } - private static boolean includeArtifact(Artifact artifact, List includes, List excludes) + private static boolean includeArtifact(DependencyNode node, List includes, List excludes) throws EnforcerRuleException { boolean included = includes == null || includes.isEmpty(); if (!included) { for (String pattern : includes) { - if (ArtifactUtils.compareDependency(pattern, artifact)) { + if (ArtifactUtils.compareDependency(pattern, ArtifactUtils.toArtifact(node))) { included = true; break; } @@ -140,7 +140,7 @@ private static boolean includeArtifact(Artifact artifact, List includes, boolean excluded = false; if (excludes != null) { for (String pattern : excludes) { - if (ArtifactUtils.compareDependency(pattern, artifact)) { + if (ArtifactUtils.compareDependency(pattern, ArtifactUtils.toArtifact(node))) { excluded = true; break; } diff --git a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/EnforcerRuleUtils.java b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/EnforcerRuleUtils.java index 6d6b4a4a..f8b854c0 100644 --- a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/EnforcerRuleUtils.java +++ b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/EnforcerRuleUtils.java @@ -19,16 +19,10 @@ package org.apache.maven.plugins.enforcer.utils; import java.util.List; -import org.apache.maven.artifact.factory.ArtifactFactory; -import org.apache.maven.artifact.repository.ArtifactRepository; -import org.apache.maven.artifact.resolver.ArtifactResolver; import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper; import org.apache.maven.model.Plugin; import org.apache.maven.model.ReportPlugin; -import org.apache.maven.plugin.logging.Log; -import org.apache.maven.project.MavenProject; import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException; -import org.codehaus.plexus.component.repository.exception.ComponentLookupException; /** * The Class EnforcerRuleUtils. @@ -36,68 +30,15 @@ * @author Brian Fox */ public class EnforcerRuleUtils { - - /** The resolver. */ - ArtifactResolver resolver; - - /** The local. */ - ArtifactRepository local; - - /** The remote repositories. */ - List remoteRepositories; - - /** The log. */ - Log log; - - /** The project. */ - MavenProject project; - private EnforcerRuleHelper helper; - /** - * Instantiates a new enforcer rule utils. - * - * @param theFactory unused - * @param theResolver the the resolver - * @param theLocal the the local - * @param theRemoteRepositories the the remote repositories - * @param project the project - * @param theLog the the log - */ - public EnforcerRuleUtils( - ArtifactFactory theFactory, - ArtifactResolver theResolver, - ArtifactRepository theLocal, - List theRemoteRepositories, - MavenProject project, - Log theLog) { - super(); - this.resolver = theResolver; - this.local = theLocal; - this.remoteRepositories = theRemoteRepositories; - this.log = theLog; - this.project = project; - } - /** * Instantiates a new enforcer rule utils. * * @param helper the helper */ public EnforcerRuleUtils(EnforcerRuleHelper helper) { - this.helper = helper; - // get the various expressions out of the - // helper. - try { - resolver = helper.getComponent(ArtifactResolver.class); - local = (ArtifactRepository) helper.evaluate("${localRepository}"); - project = (MavenProject) helper.evaluate("${project}"); - remoteRepositories = project.getRemoteArtifactRepositories(); - } catch (ComponentLookupException | ExpressionEvaluationException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } } private void resolve(Plugin plugin) { diff --git a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/ParentNodeProvider.java b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/ParentNodeProvider.java new file mode 100644 index 00000000..0edecfaf --- /dev/null +++ b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/ParentNodeProvider.java @@ -0,0 +1,34 @@ +/* + * 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. + */ +package org.apache.maven.plugins.enforcer.utils; + +import org.eclipse.aether.graph.DependencyNode; + +/** + * Provides the information about {@link org.eclipse.aether.graph.DependencyNode} parent nodes + */ +public interface ParentNodeProvider { + + /** + * Returns the parent node of the given node + * @param node node to get the information for + * @return parent node or {@code null} is no information is known + */ + DependencyNode getParent(DependencyNode node); +} diff --git a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/ParentsVisitor.java b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/ParentsVisitor.java new file mode 100644 index 00000000..98e10f06 --- /dev/null +++ b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/ParentsVisitor.java @@ -0,0 +1,52 @@ +/* + * 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. + */ +package org.apache.maven.plugins.enforcer.utils; + +import java.util.HashMap; +import java.util.Map; +import java.util.Stack; +import org.eclipse.aether.graph.DependencyNode; +import org.eclipse.aether.graph.DependencyVisitor; + +/** + * A {@link DependencyVisitor} building a map of parent nodes + */ +public class ParentsVisitor implements DependencyVisitor, ParentNodeProvider { + + private final Map parents = new HashMap<>(); + private final Stack parentStack = new Stack<>(); + + @Override + public DependencyNode getParent(DependencyNode node) { + return parents.get(node); + } + + @Override + public boolean visitEnter(DependencyNode node) { + parents.put(node, parentStack.isEmpty() ? null : parentStack.peek()); + parentStack.push(node); + return true; + } + + @Override + public boolean visitLeave(DependencyNode node) { + parentStack.pop(); + return true; + } +} diff --git a/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/BannedDependenciesTestSetup.java b/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/BannedDependenciesTestSetup.java index 69e8c85e..7d218620 100644 --- a/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/BannedDependenciesTestSetup.java +++ b/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/BannedDependenciesTestSetup.java @@ -21,22 +21,22 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; -import java.util.Set; import org.apache.maven.artifact.Artifact; import org.apache.maven.enforcer.rule.api.EnforcerRuleException; import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper; import org.apache.maven.plugin.testing.ArtifactStubFactory; import org.apache.maven.project.MavenProject; -import org.apache.maven.project.ProjectBuildingRequest; public class BannedDependenciesTestSetup { + private final MavenProject project; + public BannedDependenciesTestSetup() throws IOException { this.excludes = new ArrayList<>(); this.includes = new ArrayList<>(); ArtifactStubFactory factory = new ArtifactStubFactory(); - MockProject project = new MockProject(); + project = new MockProject(); project.setArtifacts(factory.getMixedArtifacts()); project.setDependencyArtifacts(factory.getScopedArtifacts()); @@ -83,12 +83,9 @@ public void setExcludes(List excludes) { private BannedDependencies newBannedDependenciesRule() { return new BannedDependencies() { @Override - protected Set getDependenciesToCheck(ProjectBuildingRequest buildingRequest) { - MavenProject project = buildingRequest.getProject(); - - // the integration with dependencyGraphTree is verified with the integration tests - // for unit-testing - return isSearchTransitive() ? project.getArtifacts() : project.getDependencyArtifacts(); + protected boolean validate(Artifact artifact) { + return (isSearchTransitive() ? project.getArtifacts() : project.getDependencyArtifacts()) + .stream().map(super::validate).reduce(true, Boolean::logicalAnd); } }; } diff --git a/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/EnforcerTestUtils.java b/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/EnforcerTestUtils.java index b920c397..c8876472 100644 --- a/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/EnforcerTestUtils.java +++ b/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/EnforcerTestUtils.java @@ -18,15 +18,14 @@ */ package org.apache.maven.plugins.enforcer; +import static java.util.Arrays.asList; import static org.mockito.Mockito.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import java.util.Arrays; -import java.util.Collections; import java.util.Properties; -import org.apache.maven.artifact.Artifact; -import org.apache.maven.artifact.DefaultArtifact; +import org.apache.maven.RepositoryUtils; +import org.apache.maven.artifact.handler.DefaultArtifactHandler; import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper; import org.apache.maven.execution.MavenExecutionRequest; import org.apache.maven.execution.MavenExecutionResult; @@ -41,13 +40,18 @@ import org.apache.maven.plugins.enforcer.utils.MockEnforcerExpressionEvaluator; import org.apache.maven.project.MavenProject; import org.apache.maven.project.ProjectBuildingRequest; -import org.apache.maven.shared.dependency.graph.DependencyCollectorBuilder; -import org.apache.maven.shared.dependency.graph.internal.DefaultDependencyNode; import org.codehaus.plexus.PlexusContainer; import org.codehaus.plexus.classworlds.ClassWorld; import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator; -import org.codehaus.plexus.component.repository.exception.ComponentLookupException; -import org.mockito.Mockito; +import org.eclipse.aether.DefaultRepositorySystemSession; +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.artifact.ArtifactType; +import org.eclipse.aether.artifact.DefaultArtifact; +import org.eclipse.aether.collection.CollectRequest; +import org.eclipse.aether.collection.CollectResult; +import org.eclipse.aether.collection.DependencyCollectionException; +import org.eclipse.aether.graph.DefaultDependencyNode; +import org.eclipse.aether.graph.DependencyNode; /** * The Class EnforcerTestUtils. @@ -73,8 +77,9 @@ public static MavenSession getMavenSession() { when(mer.getUserProperties()).thenReturn(new Properties()); when(mer.getSystemProperties()).thenReturn(systemProperties); - MavenExecutionResult meresult = mock(MavenExecutionResult.class); - return new MavenSession(mock, null, mer, meresult); + MavenExecutionResult meResult = mock(MavenExecutionResult.class); + + return new MavenSession(mock, new DefaultRepositorySystemSession(), mer, meResult); } /** @@ -106,6 +111,22 @@ public static EnforcerRuleHelper getHelper(MavenProject project) { return getHelper(project, false); } + private static RepositorySystem mockRepositorySystem() throws DependencyCollectionException { + ArtifactType jarType = RepositoryUtils.newArtifactType("jar", new DefaultArtifactHandler("jar")); + final DependencyNode node = new DefaultDependencyNode( + new DefaultArtifact("groupId", "artifactId", "classifier", "jar", "version", jarType)); + node.setChildren(asList( + new DefaultDependencyNode( + new DefaultArtifact("groupId", "artifact", "classifier", "jar", "1.0.0", jarType)), + new DefaultDependencyNode( + new DefaultArtifact("groupId", "artifact", "classifier", "jar", "2.0.0", jarType)))); + + RepositorySystem mockRepositorySystem = mock(RepositorySystem.class); + when(mockRepositorySystem.collectDependencies(any(), any(CollectRequest.class))) + .then(i -> new CollectResult(i.getArgument(1)).setRoot(node)); + return mockRepositorySystem; + } + /** * Gets the helper. * @@ -114,43 +135,29 @@ public static EnforcerRuleHelper getHelper(MavenProject project) { * @return the helper */ public static EnforcerRuleHelper getHelper(MavenProject project, boolean mockExpression) { - MavenSession session = getMavenSession(); - MojoExecution mockExecution = mock(MojoExecution.class); - ExpressionEvaluator eval; - if (mockExpression) { - eval = new MockEnforcerExpressionEvaluator(session); - } else { - session.setCurrentProject(project); - eval = new PluginParameterExpressionEvaluator(session, mockExecution); - } - PlexusContainer container = Mockito.mock(PlexusContainer.class); - - Artifact artifact = - new DefaultArtifact("groupId", "artifactId", "version", "compile", "jar", "classifier", null); - Artifact v1 = new DefaultArtifact("groupId", "artifact", "1.0.0", "compile", "jar", "", null); - Artifact v2 = new DefaultArtifact("groupId", "artifact", "2.0.0", "compile", "jar", "", null); - final DefaultDependencyNode node = new DefaultDependencyNode(artifact); - DefaultDependencyNode child1 = new DefaultDependencyNode(node, v1, null, null, null); - child1.setChildren(Collections.emptyList()); - DefaultDependencyNode child2 = new DefaultDependencyNode(node, v2, null, null, null); - child2.setChildren(Collections.emptyList()); - node.setChildren(Arrays.asList(child1, child2)); - - try { - when(container.lookup(DependencyCollectorBuilder.class)).thenReturn((buildingRequest, filter) -> node); - } catch (ComponentLookupException e) { - // test will fail - } - ClassWorld classWorld = new ClassWorld("test", EnforcerTestUtils.class.getClassLoader()); - MojoDescriptor mojoDescriptor = new MojoDescriptor(); - mojoDescriptor.setRealm(classWorld.getClassRealm("test")); - when(mockExecution.getMojoDescriptor()).thenReturn(mojoDescriptor); try { + MavenSession session = getMavenSession(); + MojoExecution mockExecution = mock(MojoExecution.class); + ExpressionEvaluator eval; + if (mockExpression) { + eval = new MockEnforcerExpressionEvaluator(session); + } else { + session.setCurrentProject(project); + eval = new PluginParameterExpressionEvaluator(session, mockExecution); + } + + PlexusContainer container = mock(PlexusContainer.class); + when(container.lookup(RepositorySystem.class)).then(i -> mockRepositorySystem()); + + ClassWorld classWorld = new ClassWorld("test", EnforcerTestUtils.class.getClassLoader()); + MojoDescriptor mojoDescriptor = new MojoDescriptor(); + mojoDescriptor.setRealm(classWorld.getClassRealm("test")); + when(mockExecution.getMojoDescriptor()).thenReturn(mojoDescriptor); when(container.lookup(MojoExecution.class)).thenReturn(mockExecution); - } catch (ComponentLookupException e) { - // test will fail + return new DefaultEnforcementRuleHelper(session, eval, new SystemStreamLog(), container); + } catch (Exception e) { + throw new RuntimeException(e); } - return new DefaultEnforcementRuleHelper(session, eval, new SystemStreamLog(), container); } /** diff --git a/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/TestRequireReleaseDeps.java b/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/TestRequireReleaseDeps.java index 29736ea6..f83819ba 100644 --- a/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/TestRequireReleaseDeps.java +++ b/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/TestRequireReleaseDeps.java @@ -22,13 +22,12 @@ import java.io.IOException; import java.util.Collections; -import java.util.Set; import org.apache.maven.artifact.Artifact; import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper; import org.apache.maven.plugin.testing.ArtifactStubFactory; import org.apache.maven.plugins.enforcer.utils.EnforcerRuleUtilsHelper; import org.apache.maven.project.MavenProject; -import org.apache.maven.project.ProjectBuildingRequest; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** @@ -37,6 +36,12 @@ * @author Brian Fox */ class TestRequireReleaseDeps { + private MavenProject project; + + @BeforeEach + public void setUp() { + project = new MockProject(); + } /** * Test rule. @@ -46,7 +51,6 @@ class TestRequireReleaseDeps { @Test void testRule() throws Exception { ArtifactStubFactory factory = new ArtifactStubFactory(); - MockProject project = new MockProject(); EnforcerRuleHelper helper = EnforcerTestUtils.getHelper(project); project.setArtifacts(factory.getMixedArtifacts()); project.setDependencyArtifacts(factory.getScopedArtifacts()); @@ -95,7 +99,6 @@ void testWildcardIgnore() throws Exception { rule.setSearchTransitive(false); ArtifactStubFactory factory = new ArtifactStubFactory(); - MockProject project = new MockProject(); project.setArtifact(factory.getReleaseArtifact()); project.setDependencyArtifacts(Collections.singleton(factory.createArtifact("g", "a", "1.0-SNAPSHOT", "test"))); EnforcerRuleHelper helper = EnforcerTestUtils.getHelper(project); @@ -114,9 +117,7 @@ void testId() { @Test void parentShouldBeExcluded() throws IOException { - ArtifactStubFactory factory = new ArtifactStubFactory(); - MockProject project = new MockProject(); project.setArtifact(factory.getSnapshotArtifact()); MavenProject parent = new MockProject(); @@ -134,12 +135,9 @@ void parentShouldBeExcluded() throws IOException { private RequireReleaseDeps newRequireReleaseDeps() { return new RequireReleaseDeps() { @Override - protected Set getDependenciesToCheck(ProjectBuildingRequest buildingRequest) { - MavenProject project = buildingRequest.getProject(); - - // the integration with dependencyGraphTree is verified with the integration tests - // for unit-testing - return isSearchTransitive() ? project.getArtifacts() : project.getDependencyArtifacts(); + protected boolean validate(Artifact artifactl) { + return (isSearchTransitive() ? project.getArtifacts() : project.getDependencyArtifacts()) + .stream().map(super::validate).reduce(true, Boolean::logicalAnd); } }; } diff --git a/maven-enforcer-plugin/src/it/projects/banned-dependencies-fail/invoker.properties b/maven-enforcer-plugin/src/it/projects/banned-dependencies-fail/invoker.properties new file mode 100644 index 00000000..58b6526e --- /dev/null +++ b/maven-enforcer-plugin/src/it/projects/banned-dependencies-fail/invoker.properties @@ -0,0 +1,18 @@ +# 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. + +invoker.buildResult = failure diff --git a/maven-enforcer-plugin/src/it/projects/banned-dependencies-fail/pom.xml b/maven-enforcer-plugin/src/it/projects/banned-dependencies-fail/pom.xml new file mode 100644 index 00000000..33d215fe --- /dev/null +++ b/maven-enforcer-plugin/src/it/projects/banned-dependencies-fail/pom.xml @@ -0,0 +1,66 @@ + + + + + + 4.0.0 + + org.apache.maven.its.enforcer + test + 1.0 + + + + + + + org.apache.maven.plugins.enforcer.its + menforcer128_api + 1.4.0 + + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + @project.version@ + + + test + + enforce + + + + + + org.apache.maven.plugins.enforcer.its:menforcer128_api + + + + + + + + + + diff --git a/maven-enforcer-plugin/src/it/projects/banned-dependencies-fail/verify.groovy b/maven-enforcer-plugin/src/it/projects/banned-dependencies-fail/verify.groovy new file mode 100644 index 00000000..415c0e3f --- /dev/null +++ b/maven-enforcer-plugin/src/it/projects/banned-dependencies-fail/verify.groovy @@ -0,0 +1,20 @@ +/* + * 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. + */ +def buildLog = new File( basedir, 'build.log' ).text +assert buildLog.contains( 'org.apache.maven.plugins.enforcer.its:menforcer128_api:jar:1.4.0 <--- banned via the exclude/include list' ) diff --git a/maven-enforcer-plugin/src/it/projects/banned-plugins-fails/verify.groovy b/maven-enforcer-plugin/src/it/projects/banned-plugins-fails/verify.groovy index 1d825f36..7fd32569 100644 --- a/maven-enforcer-plugin/src/it/projects/banned-plugins-fails/verify.groovy +++ b/maven-enforcer-plugin/src/it/projects/banned-plugins-fails/verify.groovy @@ -16,6 +16,6 @@ * specific language governing permissions and limitations * under the License. */ -File buildLog = new File( basedir, 'build.log' ) -assert buildLog.text.contains( '[ERROR] Rule 0: org.apache.maven.plugins.enforcer.BannedPlugins failed with message:' ) -assert buildLog.text.contains( 'Found Banned Plugin: org.codehaus.mojo:build-helper-maven-plugin:maven-plugin' ) +def buildLog = new File( basedir, 'build.log' ).text +assert buildLog.contains( '[ERROR] Rule 0: org.apache.maven.plugins.enforcer.BannedPlugins failed with message:' ) +assert buildLog =~ /org.codehaus.mojo:build-helper-maven-plugin:maven-plugin:.* <--- banned plugin/ diff --git a/maven-enforcer-plugin/src/it/projects/multimodule-ban-transitive-dependencies_failure/verify.groovy b/maven-enforcer-plugin/src/it/projects/multimodule-ban-transitive-dependencies_failure/verify.groovy index 793e850e..c6657d7a 100644 --- a/maven-enforcer-plugin/src/it/projects/multimodule-ban-transitive-dependencies_failure/verify.groovy +++ b/maven-enforcer-plugin/src/it/projects/multimodule-ban-transitive-dependencies_failure/verify.groovy @@ -19,4 +19,4 @@ File buildLog = new File( basedir, 'build.log' ) assert buildLog.text.contains( 'Rule 0: org.apache.maven.plugins.enforcer.BanTransitiveDependencies failed with message:' ) -assert buildLog.text.contains( 'org.apache.maven.its.enforcer:module1:jar:1.0-SNAPSHOT:compile has transitive dependencies:' ) +assert buildLog.text.contains( 'org.apache.maven.its.enforcer:module1:jar:1.0-SNAPSHOT has transitive dependencies:' ) diff --git a/maven-enforcer-plugin/src/it/projects/multimodule-require-release-dependencies-exclude_failure/verify.groovy b/maven-enforcer-plugin/src/it/projects/multimodule-require-release-dependencies-exclude_failure/verify.groovy index 437bb461..f091ed1d 100644 --- a/maven-enforcer-plugin/src/it/projects/multimodule-require-release-dependencies-exclude_failure/verify.groovy +++ b/maven-enforcer-plugin/src/it/projects/multimodule-require-release-dependencies-exclude_failure/verify.groovy @@ -19,4 +19,4 @@ File buildLog = new File( basedir, 'build.log' ) assert buildLog.text.contains( 'Rule 0: org.apache.maven.plugins.enforcer.RequireReleaseDeps failed with message:' ) -assert buildLog.text.contains( 'Found Banned Dependency: org.apache.maven.its.enforcer:module1:jar:1.0-SNAPSHOT' ) +assert buildLog.text =~ /org.apache.maven.its.enforcer:module1:jar:1.0-SNAPSHOT.*is not a release dependency/ \ No newline at end of file