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.shared.artifact.filter.resolve.transform;
20  
21  import java.util.ArrayList;
22  import java.util.Collection;
23  import java.util.List;
24  import java.util.regex.Matcher;
25  import java.util.regex.Pattern;
26  
27  import org.apache.maven.shared.artifact.filter.resolve.AbstractFilter;
28  import org.apache.maven.shared.artifact.filter.resolve.AndFilter;
29  import org.apache.maven.shared.artifact.filter.resolve.ExclusionsFilter;
30  import org.apache.maven.shared.artifact.filter.resolve.FilterTransformer;
31  import org.apache.maven.shared.artifact.filter.resolve.OrFilter;
32  import org.apache.maven.shared.artifact.filter.resolve.PatternExclusionsFilter;
33  import org.apache.maven.shared.artifact.filter.resolve.PatternInclusionsFilter;
34  import org.apache.maven.shared.artifact.filter.resolve.ScopeFilter;
35  import org.apache.maven.shared.artifact.filter.resolve.TransformableFilter;
36  import org.eclipse.aether.graph.DependencyFilter;
37  import org.eclipse.aether.util.filter.AndDependencyFilter;
38  import org.eclipse.aether.util.filter.ExclusionsDependencyFilter;
39  import org.eclipse.aether.util.filter.OrDependencyFilter;
40  import org.eclipse.aether.util.filter.PatternExclusionsDependencyFilter;
41  import org.eclipse.aether.util.filter.PatternInclusionsDependencyFilter;
42  import org.eclipse.aether.util.filter.ScopeDependencyFilter;
43  
44  import static java.util.Objects.requireNonNull;
45  
46  /**
47   * FilterTransformer implementation for Eclipse Aether.
48   *
49   * @author Robert Scholte
50   * @since 3.0
51   */
52  public class EclipseAetherFilterTransformer implements FilterTransformer<DependencyFilter> {
53      /**
54       * When using as regular expression, group(1) + group(3) will be the coordinate,
55       * group(2) will be the classifier.
56       */
57      private static final String GAE_C_V = "(.*:.*:.*):(.+)(:.*)";
58  
59      /** {@inheritDoc} */
60      @Override
61      public AndDependencyFilter transform(AndFilter andFilter) {
62          Collection<DependencyFilter> filters = new ArrayList<>();
63          for (TransformableFilter filter : andFilter.getFilters()) {
64              filters.add(filter.transform(this));
65          }
66          return new AndDependencyFilter(filters);
67      }
68  
69      /** {@inheritDoc} */
70      @Override
71      public ExclusionsDependencyFilter transform(ExclusionsFilter filter) {
72          return new ExclusionsDependencyFilter(filter.getExcludes());
73      }
74  
75      /** {@inheritDoc} */
76      @Override
77      public OrDependencyFilter transform(OrFilter orFilter) {
78          Collection<DependencyFilter> filters = new ArrayList<>();
79          for (TransformableFilter filter : orFilter.getFilters()) {
80              filters.add(filter.transform(this));
81          }
82          return new OrDependencyFilter(filters);
83      }
84  
85      /** {@inheritDoc} */
86      @Override
87      public ScopeDependencyFilter transform(ScopeFilter filter) {
88          return new ScopeDependencyFilter(filter.getIncluded(), filter.getExcluded());
89      }
90  
91      /** {@inheritDoc} */
92      @Override
93      public DependencyFilter transform(PatternExclusionsFilter filter) {
94          return new PatternExclusionsDependencyFilter(filter.getExcludes());
95      }
96  
97      /** {@inheritDoc} */
98      @Override
99      public DependencyFilter transform(PatternInclusionsFilter filter) {
100         // if any include contains a classifier:
101         // split all includes and make it an or-filter for every include
102         // for the classifier, add an and-filter with a classifierfilter and patterninclusionfilter
103 
104         for (String include : filter.getIncludes()) {
105             if (include.matches(GAE_C_V)) {
106                 return newAdvancedPatternInclusionFilter(filter.getIncludes());
107             }
108         }
109 
110         return new PatternInclusionsDependencyFilter(filter.getIncludes());
111     }
112 
113     /** {@inheritDoc} */
114     @Override
115     public DependencyFilter transform(final AbstractFilter filter) {
116         return (node, parents) -> {
117             requireNonNull(node, "node cannot be null");
118             requireNonNull(parents, "parents cannot be null");
119 
120             return filter.accept(new EclipseAetherNode(node), null);
121         };
122     }
123 
124     private DependencyFilter newAdvancedPatternInclusionFilter(Collection<String> includes) {
125         List<DependencyFilter> filters = new ArrayList<>(includes.size());
126 
127         Pattern pattern = Pattern.compile(GAE_C_V);
128         for (String include : includes) {
129             Matcher matcher = pattern.matcher(include);
130             if (matcher.matches()) {
131                 DependencyFilter patternFilter =
132                         new PatternInclusionsDependencyFilter(matcher.group(1) + matcher.group(3));
133 
134                 final String classifier = matcher.group(2);
135 
136                 filters.add(new AndDependencyFilter(patternFilter, (node, parents) -> {
137                     requireNonNull(node, "node cannot be null");
138                     requireNonNull(parents, "parents cannot be null");
139 
140                     String nodeClassifier = node.getArtifact().getClassifier();
141 
142                     if (nodeClassifier == null) {
143                         return false;
144                     } else {
145                         return "*".equals(classifier) || nodeClassifier.matches(classifier);
146                     }
147                 }));
148             } else {
149                 filters.add(new PatternInclusionsDependencyFilter(include));
150             }
151         }
152         return new OrDependencyFilter(filters);
153     }
154 }