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