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.codehaus.plexus.logging.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 List<String> filteredArtifactIds = new ArrayList<String>();
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      * @return Information converted to a string.
168      */
169     public String toString()
170     {
171         return "Scope filter [null-scope=" + includeNullScope + ", compile=" + includeCompileScope + ", runtime="
172             + includeRuntimeScope + ", test=" + includeTestScope + ", provided=" + includeProvidedScope + ", system="
173             + includeSystemScope + "]";
174     }
175 
176     /** {@inheritDoc} */
177     public void reportFilteredArtifacts( Logger logger )
178     {
179         if ( !filteredArtifactIds.isEmpty() && logger.isDebugEnabled() )
180         {
181             StringBuilder buffer = new StringBuilder( "The following artifacts were removed by this filter: " );
182 
183             for ( String artifactId : filteredArtifactIds )
184             {
185                 buffer.append( '\n' ).append( artifactId );
186             }
187 
188             logger.debug( buffer.toString() );
189         }
190     }
191 
192     /** {@inheritDoc} */
193     public void reportMissedCriteria( Logger logger )
194     {
195         if ( logger.isDebugEnabled() )
196         {
197             StringBuilder buffer = new StringBuilder();
198 
199             boolean report = false;
200             if ( !nullScopeHit )
201             {
202                 buffer.append( "\no [Null Scope]" );
203                 report = true;
204             }
205             if ( !compileScopeHit )
206             {
207                 buffer.append( "\no Compile" );
208                 report = true;
209             }
210             if ( !runtimeScopeHit )
211             {
212                 buffer.append( "\no Runtime" );
213                 report = true;
214             }
215             if ( !testScopeHit )
216             {
217                 buffer.append( "\no Test" );
218                 report = true;
219             }
220             if ( !providedScopeHit )
221             {
222                 buffer.append( "\no Provided" );
223                 report = true;
224             }
225             if ( !systemScopeHit )
226             {
227                 buffer.append( "\no System" );
228                 report = true;
229             }
230 
231             if ( report )
232             {
233                 logger.debug( "The following scope filters were not used: " + buffer.toString() );
234             }
235         }
236     }
237 
238     /** {@inheritDoc} */
239     public boolean hasMissedCriteria()
240     {
241         boolean report = false;
242 
243         if ( !nullScopeHit )
244         {
245             report = true;
246         }
247         if ( !compileScopeHit )
248         {
249             report = true;
250         }
251         if ( !runtimeScopeHit )
252         {
253             report = true;
254         }
255         if ( !testScopeHit )
256         {
257             report = true;
258         }
259         if ( !providedScopeHit )
260         {
261             report = true;
262         }
263         if ( !systemScopeHit )
264         {
265             report = true;
266         }
267 
268         return report;
269     }
270     
271     /**
272      * @return {@link #includeCompileScope}
273      */
274     public boolean isIncludeCompileScope()
275     {
276         return includeCompileScope;
277     }
278 
279     /**
280      * @param pIncludeCompileScope true/false.
281      * @return {@link ScopeArtifactFilter}
282      */
283     public ScopeArtifactFilter setIncludeCompileScope( boolean pIncludeCompileScope )
284     {
285         this.includeCompileScope = pIncludeCompileScope;
286         
287         return this;
288     }
289 
290     /**
291      * @return {@link #includeRuntimeScope}
292      */
293     public boolean isIncludeRuntimeScope()
294     {
295         return includeRuntimeScope;
296     }
297 
298     /**
299      * @param pIncludeRuntimeScope true/false
300      * @return {@link ScopeArtifactFilter}
301      */
302     public ScopeArtifactFilter setIncludeRuntimeScope( boolean pIncludeRuntimeScope )
303     {
304         this.includeRuntimeScope = pIncludeRuntimeScope;
305         
306         return this;
307     }
308 
309     /**
310      * @return {@link #includeTestScope}
311      */
312     public boolean isIncludeTestScope()
313     {
314         return includeTestScope;
315     }
316 
317     /**
318      * @param pIncludeTestScope {@link #includeTestScope}
319      * @return {@link ScopeArtifactFilter}
320      */
321     public ScopeArtifactFilter setIncludeTestScope( boolean pIncludeTestScope )
322     {
323         this.includeTestScope = pIncludeTestScope;
324         
325         return this;
326     }
327 
328     /**
329      * @return {@link #includeProvidedScope}
330      */
331     public boolean isIncludeProvidedScope()
332     {
333         return includeProvidedScope;
334     }
335 
336     /**
337      * @param pIncludeProvidedScope yes/no.
338      * @return {@link #ScopeArtifactFilter()}
339      */
340     public ScopeArtifactFilter setIncludeProvidedScope( boolean pIncludeProvidedScope )
341     {
342         this.includeProvidedScope = pIncludeProvidedScope;
343         
344         return this;
345     }
346 
347     /**
348      * @return {@link #includeSystemScope}
349      */
350     public boolean isIncludeSystemScope()
351     {
352         return includeSystemScope;
353     }
354 
355     /** {@inheritDoc} */
356     public ScopeArtifactFilter setIncludeSystemScope( boolean pIncludeSystemScope )
357     {
358         this.includeSystemScope = pIncludeSystemScope;
359         
360         return this;
361     }
362     
363     /**
364      * Manages the following scopes:
365      * 
366      * <ul>
367      *   <li>system</li>
368      *   <li>provided</li>
369      *   <li>compile</li>
370      * </ul>
371      *
372      * @param enabled whether specified scopes should be included
373      * @return this instance 
374      */
375     public ScopeArtifactFilter setIncludeCompileScopeWithImplications( boolean enabled )
376     {
377         includeSystemScope = enabled;
378         includeProvidedScope = enabled;
379         includeCompileScope = enabled;
380         
381         return this;
382     }
383     
384     /**
385      * Manages the following scopes:
386      * 
387      * <ul>
388      *   <li>compile</li>
389      *   <li>runtime</li>
390      * </ul>
391      *
392      * @param enabled whether specified scopes should be included
393      * @return this instance 
394      */
395     public ScopeArtifactFilter setIncludeRuntimeScopeWithImplications( boolean enabled )
396     {
397         includeCompileScope = enabled;
398         includeRuntimeScope = enabled;
399         
400         return this;
401     }
402 
403     /**
404      * Manages the following scopes:
405      * 
406      * <ul>
407      *   <li>system</li>
408      *   <li>provided</li>
409      *   <li>compile</li>
410      *   <li>runtime</li>
411      *   <li>test</li>
412      * </ul>
413      *
414      * @param enabled whether specified scopes should be included
415      * @return this instance 
416      */
417     public ScopeArtifactFilter setIncludeTestScopeWithImplications( boolean enabled )
418     {
419         includeSystemScope = enabled;
420         includeProvidedScope = enabled;
421         includeCompileScope = enabled;
422         includeRuntimeScope = enabled;
423         includeTestScope = enabled;
424         
425         return this;
426     }
427     
428     /**
429      * Determine whether artifacts that have a null scope are included or excluded.
430      *
431      * @param enable whether null-scope should be included
432      * @return this instance 
433      */
434     public ScopeArtifactFilter setIncludeNullScope( boolean enable )
435     {
436         includeNullScope = enable;
437         
438         return this;
439     }
440     
441     /**
442      * Reset hit counts and tracking of filtered artifacts, BUT NOT ENABLED SCOPES.
443      *
444      * @return this instance 
445      */
446     public ScopeArtifactFilter reset()
447     {
448         compileScopeHit = false;
449         runtimeScopeHit = false;
450         testScopeHit = false;
451         providedScopeHit = false;
452         systemScopeHit = false;
453         filteredArtifactIds.clear();
454         
455         return this;
456     }
457 }