View Javadoc
1   package org.apache.maven.shared.artifact.filter.resolve.transform;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.util.ArrayList;
23  import java.util.Collection;
24  import java.util.List;
25  import java.util.regex.Matcher;
26  import java.util.regex.Pattern;
27  
28  import static java.util.Objects.requireNonNull;
29  
30  import org.apache.maven.shared.artifact.filter.resolve.AbstractFilter;
31  import org.apache.maven.shared.artifact.filter.resolve.AndFilter;
32  import org.apache.maven.shared.artifact.filter.resolve.ExclusionsFilter;
33  import org.apache.maven.shared.artifact.filter.resolve.FilterTransformer;
34  import org.apache.maven.shared.artifact.filter.resolve.OrFilter;
35  import org.apache.maven.shared.artifact.filter.resolve.PatternExclusionsFilter;
36  import org.apache.maven.shared.artifact.filter.resolve.PatternInclusionsFilter;
37  import org.apache.maven.shared.artifact.filter.resolve.ScopeFilter;
38  import org.apache.maven.shared.artifact.filter.resolve.TransformableFilter;
39  import org.eclipse.aether.graph.DependencyFilter;
40  import org.eclipse.aether.graph.DependencyNode;
41  import org.eclipse.aether.util.filter.AndDependencyFilter;
42  import org.eclipse.aether.util.filter.ExclusionsDependencyFilter;
43  import org.eclipse.aether.util.filter.OrDependencyFilter;
44  import org.eclipse.aether.util.filter.PatternExclusionsDependencyFilter;
45  import org.eclipse.aether.util.filter.PatternInclusionsDependencyFilter;
46  import org.eclipse.aether.util.filter.ScopeDependencyFilter;
47  
48  /**
49   * FilterTransformer implementation for Eclipse Aether.
50   *
51   * @author Robert Scholte
52   * @since 3.0
53   */
54  public class EclipseAetherFilterTransformer
55      implements FilterTransformer<DependencyFilter>
56  {
57      /**
58       * When using as regular expression, group(1) + group(3) will be the coordinate,
59       * group(2) will be the classifier.
60       */
61      private static final String GAE_C_V = "(.*:.*:.*):(.+)(:.*)";
62  
63      /** {@inheritDoc} */
64      @Override
65      public AndDependencyFilter transform( AndFilter andFilter )
66      {
67          Collection<DependencyFilter> filters = new ArrayList<>();
68          for ( TransformableFilter filter : andFilter.getFilters() )
69          {
70              filters.add( filter.transform( this ) );
71          }
72          return new AndDependencyFilter( filters );
73      }
74  
75      /** {@inheritDoc} */
76      @Override
77      public ExclusionsDependencyFilter transform( ExclusionsFilter filter )
78      {
79          return new ExclusionsDependencyFilter( filter.getExcludes() );
80      }
81  
82      /** {@inheritDoc} */
83      @Override
84      public OrDependencyFilter transform( OrFilter orFilter )
85      {
86          Collection<DependencyFilter> filters = new ArrayList<>();
87          for ( TransformableFilter filter : orFilter.getFilters() )
88          {
89              filters.add( filter.transform( this ) );
90          }
91          return new OrDependencyFilter( filters );
92      }
93  
94      /** {@inheritDoc} */
95      @Override
96      public ScopeDependencyFilter transform( ScopeFilter filter )
97      {
98          return new ScopeDependencyFilter( filter.getIncluded(), filter.getExcluded() );
99      }
100 
101     /** {@inheritDoc} */
102     @Override
103     public DependencyFilter transform( PatternExclusionsFilter filter )
104     {
105         return new PatternExclusionsDependencyFilter( filter.getExcludes() );
106     }
107 
108     /** {@inheritDoc} */
109     @Override
110     public DependencyFilter transform( PatternInclusionsFilter filter )
111     {
112         // if any include contains a classifier:
113         // split all includes and make it an or-filter for every include
114         // for the classifier, add an and-filter with a classifierfilter and patterninclusionfilter
115 
116         for ( String include : filter.getIncludes() )
117         {
118             if ( include.matches( GAE_C_V ) )
119             {
120                 return newAdvancedPatternInclusionFilter( filter.getIncludes() );
121             }
122         }
123 
124         return new PatternInclusionsDependencyFilter( filter.getIncludes() );
125     }
126 
127     /** {@inheritDoc} */
128     @Override
129     public DependencyFilter transform( final AbstractFilter filter )
130     {
131         return new DependencyFilter()
132         {
133             @Override
134             public boolean accept( DependencyNode node, List<DependencyNode> parents )
135             {
136                 requireNonNull( node, "node cannot be null" );
137                 requireNonNull( parents, "parents cannot be null" );
138 
139                 return filter.accept( new EclipseAetherNode( node ), null );
140             }
141         };
142     }
143 
144     private DependencyFilter newAdvancedPatternInclusionFilter( Collection<String> includes )
145     {
146         List<DependencyFilter> filters = new ArrayList<>( includes.size() );
147 
148         Pattern pattern = Pattern.compile( GAE_C_V );
149         for ( String include : includes )
150         {
151             Matcher matcher = pattern.matcher( include );
152             if ( matcher.matches() )
153             {
154                 DependencyFilter patternFilter =
155                     new PatternInclusionsDependencyFilter( matcher.group( 1 ) + matcher.group( 3 ) );
156 
157                 final String classifier = matcher.group( 2 );
158 
159                 DependencyFilter classifierFilter = new DependencyFilter()
160                 {
161                     @Override
162                     public boolean accept( DependencyNode node, List<DependencyNode> parents )
163                     {
164                         requireNonNull( node, "node cannot be null" );
165                         requireNonNull( parents, "parents cannot be null" );
166 
167                         String nodeClassifier = node.getArtifact().getClassifier();
168 
169                         if ( nodeClassifier == null )
170                         {
171                             return false;
172                         }
173                         else
174                         {
175                             return "*".equals( classifier ) || nodeClassifier.matches( classifier );
176                         }
177                     }
178                 };
179 
180                 filters.add( new AndDependencyFilter( patternFilter, classifierFilter ) );
181             }
182             else
183             {
184                 filters.add( new PatternInclusionsDependencyFilter( include ) );
185             }
186         }
187         return new OrDependencyFilter( filters );
188     }
189 }