View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.enforcer.rules.utils;
20  
21  import java.util.Collection;
22  import java.util.Set;
23  import java.util.stream.Collectors;
24  
25  import org.apache.commons.lang3.StringUtils;
26  import org.apache.maven.RepositoryUtils;
27  import org.apache.maven.artifact.Artifact;
28  import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
29  import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
30  import org.eclipse.aether.graph.DependencyNode;
31  
32  import static java.util.Optional.ofNullable;
33  
34  /**
35   *
36   * @author Robert Scholte
37   * @since 3.0.0
38   */
39  public final class ArtifactUtils {
40  
41      /**
42       * Converts {@link DependencyNode} to {@link Artifact}; in comparison
43       * to {@link RepositoryUtils#toArtifact(org.eclipse.aether.artifact.Artifact)}, this method
44       * assigns {@link Artifact#getScope()} and {@link Artifact#isOptional()} based on
45       * the dependency information from the node.
46       *
47       * @param node {@link DependencyNode} to convert to {@link Artifact}
48       * @return target artifact
49       */
50      public static Artifact toArtifact(DependencyNode node) {
51          Artifact artifact = RepositoryUtils.toArtifact(node.getArtifact());
52          ofNullable(node.getDependency()).ifPresent(dependency -> {
53              ofNullable(dependency.getScope()).ifPresent(artifact::setScope);
54              artifact.setOptional(dependency.isOptional());
55          });
56          return artifact;
57      }
58  
59      /**
60       * Returns a subset of dependency artifacts that match the given collection of patterns
61       *
62       * @param dependencies dependency artifacts to match against patterns
63       * @param patterns patterns to match against the artifacts
64       * @return a set containing artifacts matching one of the patterns or <code>null</code>
65       * @throws EnforcerRuleException the enforcer rule exception
66       */
67      public static Set<Artifact> filterDependencyArtifacts(Set<Artifact> dependencies, Collection<String> patterns)
68              throws EnforcerRuleException {
69          try {
70              return ofNullable(patterns)
71                      .map(collection -> collection.stream()
72                              .map(p -> p.split(":"))
73                              .map(StringUtils::stripAll)
74                              .map(arr -> String.join(":", arr))
75                              .flatMap(pattern ->
76                                      dependencies.stream().filter(artifact -> compareDependency(pattern, artifact)))
77                              .collect(Collectors.toSet()))
78                      .orElse(null);
79          } catch (IllegalArgumentException e) {
80              if (e.getCause() instanceof InvalidVersionSpecificationException) {
81                  throw new EnforcerRuleException(e.getMessage());
82              }
83              throw e;
84          }
85      }
86  
87      /**
88       * Checks if the given dependency artifact matches the given collection of patterns
89       *
90       * @param artifact dependency artifact to match against patterns
91       * @param patterns patterns to match against the artifacts
92       * @return {@code true} if the given artifact matches the set of patterns
93       */
94      public static boolean matchDependencyArtifact(Artifact artifact, Collection<String> patterns) {
95          try {
96              return ofNullable(patterns)
97                      .map(collection -> collection.stream()
98                              .map(p -> p.split(":"))
99                              .map(StringUtils::stripAll)
100                             .map(arr -> String.join(":", arr))
101                             .anyMatch(pattern -> compareDependency(pattern, artifact)))
102                     .orElse(false);
103         } catch (IllegalArgumentException e) {
104             if (e.getCause() instanceof InvalidVersionSpecificationException) {
105                 throw new IllegalArgumentException(e.getMessage());
106             }
107             throw e;
108         }
109     }
110 
111     /**
112      * Compares the given pattern against the given artifact. The pattern should follow the format
113      * <code>groupId:artifactId:version:type:scope:classifier</code>.
114      *
115      * @param pattern The pattern to compare the artifact with.
116      * @param artifact the artifact
117      * @return <code>true</code> if the artifact matches one of the patterns
118      */
119     public static boolean compareDependency(String pattern, Artifact artifact) {
120         return new ArtifactMatcher.Pattern(pattern).match(artifact);
121     }
122 }