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 && logger.isDebugEnabled() )
234             {
235                 logger.debug( "The following scope filters were not used: " + buffer );
236             }
237         }
238     }
239 
240     /**
241      * {@inheritDoc}
242      *
243      * @return a boolean.
244      */
245     public boolean hasMissedCriteria()
246     {
247         return !nullScopeHit || !compileScopeHit || !runtimeScopeHit || !testScopeHit || !providedScopeHit
248                 || !systemScopeHit;
249     }
250     
251     /**
252      * <p>isIncludeCompileScope.</p>
253      *
254      * @return {@link #includeCompileScope}
255      */
256     public boolean isIncludeCompileScope()
257     {
258         return includeCompileScope;
259     }
260 
261     /**
262      * <p>Setter for the field <code>includeCompileScope</code>.</p>
263      *
264      * @param pIncludeCompileScope true/false.
265      * @return {@link org.apache.maven.shared.artifact.filter.ScopeArtifactFilter}
266      */
267     public ScopeArtifactFilter setIncludeCompileScope( boolean pIncludeCompileScope )
268     {
269         this.includeCompileScope = pIncludeCompileScope;
270         
271         return this;
272     }
273 
274     /**
275      * <p>isIncludeRuntimeScope.</p>
276      *
277      * @return {@link #includeRuntimeScope}
278      */
279     public boolean isIncludeRuntimeScope()
280     {
281         return includeRuntimeScope;
282     }
283 
284     /**
285      * <p>Setter for the field <code>includeRuntimeScope</code>.</p>
286      *
287      * @param pIncludeRuntimeScope true/false
288      * @return {@link org.apache.maven.shared.artifact.filter.ScopeArtifactFilter}
289      */
290     public ScopeArtifactFilter setIncludeRuntimeScope( boolean pIncludeRuntimeScope )
291     {
292         this.includeRuntimeScope = pIncludeRuntimeScope;
293         
294         return this;
295     }
296 
297     /**
298      * <p>isIncludeTestScope.</p>
299      *
300      * @return {@link #includeTestScope}
301      */
302     public boolean isIncludeTestScope()
303     {
304         return includeTestScope;
305     }
306 
307     /**
308      * <p>Setter for the field <code>includeTestScope</code>.</p>
309      *
310      * @param pIncludeTestScope {@link #includeTestScope}
311      * @return {@link org.apache.maven.shared.artifact.filter.ScopeArtifactFilter}
312      */
313     public ScopeArtifactFilter setIncludeTestScope( boolean pIncludeTestScope )
314     {
315         this.includeTestScope = pIncludeTestScope;
316         
317         return this;
318     }
319 
320     /**
321      * <p>isIncludeProvidedScope.</p>
322      *
323      * @return {@link #includeProvidedScope}
324      */
325     public boolean isIncludeProvidedScope()
326     {
327         return includeProvidedScope;
328     }
329 
330     /**
331      * <p>Setter for the field <code>includeProvidedScope</code>.</p>
332      *
333      * @param pIncludeProvidedScope yes/no.
334      * @return {@link #ScopeArtifactFilter()}
335      */
336     public ScopeArtifactFilter setIncludeProvidedScope( boolean pIncludeProvidedScope )
337     {
338         this.includeProvidedScope = pIncludeProvidedScope;
339         
340         return this;
341     }
342 
343     /**
344      * <p>isIncludeSystemScope.</p>
345      *
346      * @return {@link #includeSystemScope}
347      */
348     public boolean isIncludeSystemScope()
349     {
350         return includeSystemScope;
351     }
352 
353     /**
354      * {@inheritDoc}
355      *
356      * @param pIncludeSystemScope a boolean.
357      * @return a {@link org.apache.maven.shared.artifact.filter.ScopeArtifactFilter} object.
358      */
359     public ScopeArtifactFilter setIncludeSystemScope( boolean pIncludeSystemScope )
360     {
361         this.includeSystemScope = pIncludeSystemScope;
362         
363         return this;
364     }
365     
366     /**
367      * Manages the following scopes:
368      *
369      * <ul>
370      *   <li>system</li>
371      *   <li>provided</li>
372      *   <li>compile</li>
373      * </ul>
374      *
375      * @param enabled whether specified scopes should be included
376      * @return this instance
377      */
378     public ScopeArtifactFilter setIncludeCompileScopeWithImplications( boolean enabled )
379     {
380         includeSystemScope = enabled;
381         includeProvidedScope = enabled;
382         includeCompileScope = enabled;
383         
384         return this;
385     }
386     
387     /**
388      * Manages the following scopes:
389      *
390      * <ul>
391      *   <li>compile</li>
392      *   <li>runtime</li>
393      * </ul>
394      *
395      * @param enabled whether specified scopes should be included
396      * @return this instance
397      */
398     public ScopeArtifactFilter setIncludeRuntimeScopeWithImplications( boolean enabled )
399     {
400         includeCompileScope = enabled;
401         includeRuntimeScope = enabled;
402         
403         return this;
404     }
405 
406     /**
407      * Manages the following scopes:
408      *
409      * <ul>
410      *   <li>system</li>
411      *   <li>provided</li>
412      *   <li>compile</li>
413      *   <li>runtime</li>
414      *   <li>test</li>
415      * </ul>
416      *
417      * @param enabled whether specified scopes should be included
418      * @return this instance
419      */
420     public ScopeArtifactFilter setIncludeTestScopeWithImplications( boolean enabled )
421     {
422         includeSystemScope = enabled;
423         includeProvidedScope = enabled;
424         includeCompileScope = enabled;
425         includeRuntimeScope = enabled;
426         includeTestScope = enabled;
427         
428         return this;
429     }
430     
431     /**
432      * Determine whether artifacts that have a null scope are included or excluded.
433      *
434      * @param enable whether null-scope should be included
435      * @return this instance
436      */
437     public ScopeArtifactFilter setIncludeNullScope( boolean enable )
438     {
439         includeNullScope = enable;
440         
441         return this;
442     }
443     
444     /**
445      * Reset hit counts and tracking of filtered artifacts, BUT NOT ENABLED SCOPES.
446      *
447      * @return this instance
448      */
449     public ScopeArtifactFilter reset()
450     {
451         compileScopeHit = false;
452         runtimeScopeHit = false;
453         testScopeHit = false;
454         providedScopeHit = false;
455         systemScopeHit = false;
456         filteredArtifactIds.clear();
457         
458         return this;
459     }
460 }