View Javadoc
1   package org.apache.maven.shared.artifact.filter;
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.List;
24  
25  import org.apache.maven.artifact.Artifact;
26  import org.apache.maven.artifact.DefaultArtifact;
27  import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
28  import org.slf4j.Logger;
29  
30  /**
31   * <p>
32   * {@link ArtifactFilter} implementation that selects artifacts based on their scopes.
33   * </p>
34   * <strong>NOTE:</strong> None of the fine-grained scopes imply other scopes when enabled;
35   * when fine-grained scope control is used, each scope must be enabled separately,
36   * UNLESS the corresponding XXXWithImplications() method is used to enable that
37   * scope.
38   */
39  public class ScopeArtifactFilter
40      implements ArtifactFilter, StatisticsReportingArtifactFilter
41  {
42      private boolean includeCompileScope;
43  
44      private boolean includeRuntimeScope;
45  
46      private boolean includeTestScope;
47  
48      private boolean includeProvidedScope;
49  
50      private boolean includeSystemScope;
51      
52      private boolean includeNullScope = true;
53      
54      private boolean nullScopeHit = false;
55  
56      private boolean compileScopeHit = false;
57  
58      private boolean runtimeScopeHit = false;
59  
60      private boolean testScopeHit = false;
61  
62      private boolean providedScopeHit = false;
63  
64      private boolean systemScopeHit = false;
65  
66      private final List<String> filteredArtifactIds = new ArrayList<>();
67      
68      /**
69       * Constructor that is meant to be used with fine-grained manipulation to
70       * enable/disable specific scopes using the associated mutator methods.
71       */
72      public ScopeArtifactFilter()
73      {
74          // don't enable anything by default.
75          this( null );
76      }
77  
78      /**
79       * Constructor that uses the implied nature of Maven scopes to determine which
80       * artifacts to include. For instance, 'test' scope implies compile, provided, and runtime,
81       * while 'runtime' scope implies only compile.
82       *
83       * @param scope the scope
84       */
85      public ScopeArtifactFilter( String scope )
86      {
87          if ( DefaultArtifact.SCOPE_COMPILE.equals( scope ) )
88          {
89              setIncludeCompileScopeWithImplications( true );
90          }
91          else if ( DefaultArtifact.SCOPE_RUNTIME.equals( scope ) )
92          {
93              setIncludeRuntimeScopeWithImplications( true );
94          }
95          else if ( DefaultArtifact.SCOPE_TEST.equals( scope ) )
96          {
97              setIncludeTestScopeWithImplications( true );
98          }
99          else if ( DefaultArtifact.SCOPE_PROVIDED.equals( scope ) )
100         {
101             setIncludeProvidedScope( true );
102         }
103         else if ( DefaultArtifact.SCOPE_SYSTEM.equals( scope ) )
104         {
105             setIncludeSystemScope( true );
106         }
107     }
108 
109     /** {@inheritDoc} */
110     public boolean include( Artifact artifact )
111     {
112         boolean result = true;
113         
114         if ( artifact.getScope() == null )
115         {
116             nullScopeHit = true;
117             result = includeNullScope;
118         }
119         else if ( Artifact.SCOPE_COMPILE.equals( artifact.getScope() ) )
120         {
121             compileScopeHit = true;
122             result = includeCompileScope;
123         }
124         else if ( Artifact.SCOPE_RUNTIME.equals( artifact.getScope() ) )
125         {
126             runtimeScopeHit = true;
127             result = includeRuntimeScope;
128         }
129         else if ( Artifact.SCOPE_TEST.equals( artifact.getScope() ) )
130         {
131             testScopeHit = true;
132             result = includeTestScope;
133         }
134         else if ( Artifact.SCOPE_PROVIDED.equals( artifact.getScope() ) )
135         {
136             providedScopeHit = true;
137             result = includeProvidedScope;
138         }
139         else if ( Artifact.SCOPE_SYSTEM.equals( artifact.getScope() ) )
140         {
141             systemScopeHit = true;
142             result = includeSystemScope;
143         }
144 
145         if ( !result )
146         {
147             // We have to be very careful with artifacts that have ranges, 
148             // because DefaultArtifact.getId() as of <= 2.1.0-M1 will throw a NPE 
149             // if a range is specified.
150             String id;
151             if ( artifact.getVersionRange() != null )
152             {
153                 id = artifact.getDependencyConflictId() + ":" + artifact.getVersionRange();
154             }
155             else
156             {
157                 id = artifact.getId();
158             }
159             
160             filteredArtifactIds.add( id );
161         }
162 
163         return result;
164     }
165 
166     /**
167      * <p>toString.</p>
168      *
169      * @return Information converted to a string.
170      */
171     public String toString()
172     {
173         return "Scope filter [null-scope=" + includeNullScope + ", compile=" + includeCompileScope + ", runtime="
174             + includeRuntimeScope + ", test=" + includeTestScope + ", provided=" + includeProvidedScope + ", system="
175             + includeSystemScope + "]";
176     }
177 
178     /** {@inheritDoc} */
179     public void reportFilteredArtifacts( Logger logger )
180     {
181         if ( !filteredArtifactIds.isEmpty() && logger.isDebugEnabled() )
182         {
183             StringBuilder buffer = new StringBuilder( "The following artifacts were removed by this filter: " );
184 
185             for ( String artifactId : filteredArtifactIds )
186             {
187                 buffer.append( '\n' ).append( artifactId );
188             }
189 
190             logger.debug( buffer.toString() );
191         }
192     }
193 
194     /** {@inheritDoc} */
195     public void reportMissedCriteria( Logger logger )
196     {
197         if ( logger.isDebugEnabled() )
198         {
199             StringBuilder buffer = new StringBuilder();
200 
201             boolean report = false;
202             if ( !nullScopeHit )
203             {
204                 buffer.append( "\no [Null Scope]" );
205                 report = true;
206             }
207             if ( !compileScopeHit )
208             {
209                 buffer.append( "\no Compile" );
210                 report = true;
211             }
212             if ( !runtimeScopeHit )
213             {
214                 buffer.append( "\no Runtime" );
215                 report = true;
216             }
217             if ( !testScopeHit )
218             {
219                 buffer.append( "\no Test" );
220                 report = true;
221             }
222             if ( !providedScopeHit )
223             {
224                 buffer.append( "\no Provided" );
225                 report = true;
226             }
227             if ( !systemScopeHit )
228             {
229                 buffer.append( "\no System" );
230                 report = true;
231             }
232 
233             if ( report )
234             {
235                 logger.debug( "The following scope filters were not used: " + buffer.toString() );
236             }
237         }
238     }
239 
240     /**
241      * {@inheritDoc}
242      *
243      * @return a boolean.
244      */
245     public boolean hasMissedCriteria()
246     {
247         boolean report = false;
248 
249         if ( !nullScopeHit )
250         {
251             report = true;
252         }
253         if ( !compileScopeHit )
254         {
255             report = true;
256         }
257         if ( !runtimeScopeHit )
258         {
259             report = true;
260         }
261         if ( !testScopeHit )
262         {
263             report = true;
264         }
265         if ( !providedScopeHit )
266         {
267             report = true;
268         }
269         if ( !systemScopeHit )
270         {
271             report = true;
272         }
273 
274         return report;
275     }
276     
277     /**
278      * <p>isIncludeCompileScope.</p>
279      *
280      * @return {@link #includeCompileScope}
281      */
282     public boolean isIncludeCompileScope()
283     {
284         return includeCompileScope;
285     }
286 
287     /**
288      * <p>Setter for the field <code>includeCompileScope</code>.</p>
289      *
290      * @param pIncludeCompileScope true/false.
291      * @return {@link org.apache.maven.shared.artifact.filter.ScopeArtifactFilter}
292      */
293     public ScopeArtifactFilter setIncludeCompileScope( boolean pIncludeCompileScope )
294     {
295         this.includeCompileScope = pIncludeCompileScope;
296         
297         return this;
298     }
299 
300     /**
301      * <p>isIncludeRuntimeScope.</p>
302      *
303      * @return {@link #includeRuntimeScope}
304      */
305     public boolean isIncludeRuntimeScope()
306     {
307         return includeRuntimeScope;
308     }
309 
310     /**
311      * <p>Setter for the field <code>includeRuntimeScope</code>.</p>
312      *
313      * @param pIncludeRuntimeScope true/false
314      * @return {@link org.apache.maven.shared.artifact.filter.ScopeArtifactFilter}
315      */
316     public ScopeArtifactFilter setIncludeRuntimeScope( boolean pIncludeRuntimeScope )
317     {
318         this.includeRuntimeScope = pIncludeRuntimeScope;
319         
320         return this;
321     }
322 
323     /**
324      * <p>isIncludeTestScope.</p>
325      *
326      * @return {@link #includeTestScope}
327      */
328     public boolean isIncludeTestScope()
329     {
330         return includeTestScope;
331     }
332 
333     /**
334      * <p>Setter for the field <code>includeTestScope</code>.</p>
335      *
336      * @param pIncludeTestScope {@link #includeTestScope}
337      * @return {@link org.apache.maven.shared.artifact.filter.ScopeArtifactFilter}
338      */
339     public ScopeArtifactFilter setIncludeTestScope( boolean pIncludeTestScope )
340     {
341         this.includeTestScope = pIncludeTestScope;
342         
343         return this;
344     }
345 
346     /**
347      * <p>isIncludeProvidedScope.</p>
348      *
349      * @return {@link #includeProvidedScope}
350      */
351     public boolean isIncludeProvidedScope()
352     {
353         return includeProvidedScope;
354     }
355 
356     /**
357      * <p>Setter for the field <code>includeProvidedScope</code>.</p>
358      *
359      * @param pIncludeProvidedScope yes/no.
360      * @return {@link #ScopeArtifactFilter()}
361      */
362     public ScopeArtifactFilter setIncludeProvidedScope( boolean pIncludeProvidedScope )
363     {
364         this.includeProvidedScope = pIncludeProvidedScope;
365         
366         return this;
367     }
368 
369     /**
370      * <p>isIncludeSystemScope.</p>
371      *
372      * @return {@link #includeSystemScope}
373      */
374     public boolean isIncludeSystemScope()
375     {
376         return includeSystemScope;
377     }
378 
379     /**
380      * {@inheritDoc}
381      *
382      * @param pIncludeSystemScope a boolean.
383      * @return a {@link org.apache.maven.shared.artifact.filter.ScopeArtifactFilter} object.
384      */
385     public ScopeArtifactFilter setIncludeSystemScope( boolean pIncludeSystemScope )
386     {
387         this.includeSystemScope = pIncludeSystemScope;
388         
389         return this;
390     }
391     
392     /**
393      * Manages the following scopes:
394      *
395      * <ul>
396      *   <li>system</li>
397      *   <li>provided</li>
398      *   <li>compile</li>
399      * </ul>
400      *
401      * @param enabled whether specified scopes should be included
402      * @return this instance
403      */
404     public ScopeArtifactFilter setIncludeCompileScopeWithImplications( boolean enabled )
405     {
406         includeSystemScope = enabled;
407         includeProvidedScope = enabled;
408         includeCompileScope = enabled;
409         
410         return this;
411     }
412     
413     /**
414      * Manages the following scopes:
415      *
416      * <ul>
417      *   <li>compile</li>
418      *   <li>runtime</li>
419      * </ul>
420      *
421      * @param enabled whether specified scopes should be included
422      * @return this instance
423      */
424     public ScopeArtifactFilter setIncludeRuntimeScopeWithImplications( boolean enabled )
425     {
426         includeCompileScope = enabled;
427         includeRuntimeScope = enabled;
428         
429         return this;
430     }
431 
432     /**
433      * Manages the following scopes:
434      *
435      * <ul>
436      *   <li>system</li>
437      *   <li>provided</li>
438      *   <li>compile</li>
439      *   <li>runtime</li>
440      *   <li>test</li>
441      * </ul>
442      *
443      * @param enabled whether specified scopes should be included
444      * @return this instance
445      */
446     public ScopeArtifactFilter setIncludeTestScopeWithImplications( boolean enabled )
447     {
448         includeSystemScope = enabled;
449         includeProvidedScope = enabled;
450         includeCompileScope = enabled;
451         includeRuntimeScope = enabled;
452         includeTestScope = enabled;
453         
454         return this;
455     }
456     
457     /**
458      * Determine whether artifacts that have a null scope are included or excluded.
459      *
460      * @param enable whether null-scope should be included
461      * @return this instance
462      */
463     public ScopeArtifactFilter setIncludeNullScope( boolean enable )
464     {
465         includeNullScope = enable;
466         
467         return this;
468     }
469     
470     /**
471      * Reset hit counts and tracking of filtered artifacts, BUT NOT ENABLED SCOPES.
472      *
473      * @return this instance
474      */
475     public ScopeArtifactFilter reset()
476     {
477         compileScopeHit = false;
478         runtimeScopeHit = false;
479         testScopeHit = false;
480         providedScopeHit = false;
481         systemScopeHit = false;
482         filteredArtifactIds.clear();
483         
484         return this;
485     }
486 }