View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.shared.artifact.filter;
20  
21  import java.util.ArrayList;
22  import java.util.List;
23  
24  import org.apache.maven.artifact.Artifact;
25  import org.apache.maven.artifact.DefaultArtifact;
26  import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
27  import org.slf4j.Logger;
28  
29  /**
30   * <p>
31   * {@link ArtifactFilter} implementation that selects artifacts based on their scopes.
32   * </p>
33   * <strong>NOTE:</strong> None of the fine-grained scopes imply other scopes when enabled;
34   * when fine-grained scope control is used, each scope must be enabled separately,
35   * UNLESS the corresponding XXXWithImplications() method is used to enable that
36   * scope.
37   */
38  public class ScopeArtifactFilter implements ArtifactFilter, StatisticsReportingArtifactFilter {
39      private boolean includeCompileScope;
40  
41      private boolean includeRuntimeScope;
42  
43      private boolean includeTestScope;
44  
45      private boolean includeProvidedScope;
46  
47      private boolean includeSystemScope;
48  
49      private boolean includeNullScope = true;
50  
51      private boolean nullScopeHit = false;
52  
53      private boolean compileScopeHit = false;
54  
55      private boolean runtimeScopeHit = false;
56  
57      private boolean testScopeHit = false;
58  
59      private boolean providedScopeHit = false;
60  
61      private boolean systemScopeHit = false;
62  
63      private final List<String> filteredArtifactIds = new ArrayList<>();
64  
65      /**
66       * Constructor that is meant to be used with fine-grained manipulation to
67       * enable/disable specific scopes using the associated mutator methods.
68       */
69      public ScopeArtifactFilter() {
70          // don't enable anything by default.
71          this(null);
72      }
73  
74      /**
75       * Constructor that uses the implied nature of Maven scopes to determine which
76       * artifacts to include. For instance, 'test' scope implies compile, provided, and runtime,
77       * while 'runtime' scope implies only compile.
78       *
79       * @param scope the scope
80       */
81      public ScopeArtifactFilter(String scope) {
82          if (DefaultArtifact.SCOPE_COMPILE.equals(scope)) {
83              setIncludeCompileScopeWithImplications(true);
84          } else if (DefaultArtifact.SCOPE_RUNTIME.equals(scope)) {
85              setIncludeRuntimeScopeWithImplications(true);
86          } else if (DefaultArtifact.SCOPE_TEST.equals(scope)) {
87              setIncludeTestScopeWithImplications(true);
88          } else if (DefaultArtifact.SCOPE_PROVIDED.equals(scope)) {
89              setIncludeProvidedScope(true);
90          } else if (DefaultArtifact.SCOPE_SYSTEM.equals(scope)) {
91              setIncludeSystemScope(true);
92          }
93      }
94  
95      /** {@inheritDoc} */
96      public boolean include(Artifact artifact) {
97          boolean result = true;
98  
99          if (artifact.getScope() == null) {
100             nullScopeHit = true;
101             result = includeNullScope;
102         } else if (Artifact.SCOPE_COMPILE.equals(artifact.getScope())) {
103             compileScopeHit = true;
104             result = includeCompileScope;
105         } else if (Artifact.SCOPE_RUNTIME.equals(artifact.getScope())) {
106             runtimeScopeHit = true;
107             result = includeRuntimeScope;
108         } else if (Artifact.SCOPE_TEST.equals(artifact.getScope())) {
109             testScopeHit = true;
110             result = includeTestScope;
111         } else if (Artifact.SCOPE_PROVIDED.equals(artifact.getScope())) {
112             providedScopeHit = true;
113             result = includeProvidedScope;
114         } else if (Artifact.SCOPE_SYSTEM.equals(artifact.getScope())) {
115             systemScopeHit = true;
116             result = includeSystemScope;
117         }
118 
119         if (!result) {
120             // We have to be very careful with artifacts that have ranges,
121             // because DefaultArtifact.getId() as of <= 2.1.0-M1 will throw a NPE
122             // if a range is specified.
123             String id;
124             if (artifact.getVersionRange() != null) {
125                 id = artifact.getDependencyConflictId() + ":" + artifact.getVersionRange();
126             } else {
127                 id = artifact.getId();
128             }
129 
130             filteredArtifactIds.add(id);
131         }
132 
133         return result;
134     }
135 
136     /**
137      * <p>toString.</p>
138      *
139      * @return Information converted to a string.
140      */
141     public String toString() {
142         return "Scope filter [null-scope=" + includeNullScope + ", compile=" + includeCompileScope + ", runtime="
143                 + includeRuntimeScope + ", test=" + includeTestScope + ", provided=" + includeProvidedScope
144                 + ", system="
145                 + includeSystemScope + "]";
146     }
147 
148     /** {@inheritDoc} */
149     public void reportFilteredArtifacts(Logger logger) {
150         if (!filteredArtifactIds.isEmpty() && logger.isDebugEnabled()) {
151             StringBuilder buffer = new StringBuilder("The following artifacts were removed by this filter: ");
152 
153             for (String artifactId : filteredArtifactIds) {
154                 buffer.append('\n').append(artifactId);
155             }
156 
157             logger.debug(buffer.toString());
158         }
159     }
160 
161     /** {@inheritDoc} */
162     public void reportMissedCriteria(Logger logger) {
163         if (logger.isDebugEnabled()) {
164             StringBuilder buffer = new StringBuilder();
165 
166             boolean report = false;
167             if (!nullScopeHit) {
168                 buffer.append("\no [Null Scope]");
169                 report = true;
170             }
171             if (!compileScopeHit) {
172                 buffer.append("\no Compile");
173                 report = true;
174             }
175             if (!runtimeScopeHit) {
176                 buffer.append("\no Runtime");
177                 report = true;
178             }
179             if (!testScopeHit) {
180                 buffer.append("\no Test");
181                 report = true;
182             }
183             if (!providedScopeHit) {
184                 buffer.append("\no Provided");
185                 report = true;
186             }
187             if (!systemScopeHit) {
188                 buffer.append("\no System");
189                 report = true;
190             }
191 
192             if (report && logger.isDebugEnabled()) {
193                 logger.debug("The following scope filters were not used: " + buffer);
194             }
195         }
196     }
197 
198     /**
199      * {@inheritDoc}
200      *
201      * @return a boolean.
202      */
203     public boolean hasMissedCriteria() {
204         return !nullScopeHit
205                 || !compileScopeHit
206                 || !runtimeScopeHit
207                 || !testScopeHit
208                 || !providedScopeHit
209                 || !systemScopeHit;
210     }
211 
212     /**
213      * <p>isIncludeCompileScope.</p>
214      *
215      * @return {@link #includeCompileScope}
216      */
217     public boolean isIncludeCompileScope() {
218         return includeCompileScope;
219     }
220 
221     /**
222      * <p>Setter for the field <code>includeCompileScope</code>.</p>
223      *
224      * @param pIncludeCompileScope true/false.
225      * @return {@link org.apache.maven.shared.artifact.filter.ScopeArtifactFilter}
226      */
227     public ScopeArtifactFilter setIncludeCompileScope(boolean pIncludeCompileScope) {
228         this.includeCompileScope = pIncludeCompileScope;
229 
230         return this;
231     }
232 
233     /**
234      * <p>isIncludeRuntimeScope.</p>
235      *
236      * @return {@link #includeRuntimeScope}
237      */
238     public boolean isIncludeRuntimeScope() {
239         return includeRuntimeScope;
240     }
241 
242     /**
243      * <p>Setter for the field <code>includeRuntimeScope</code>.</p>
244      *
245      * @param pIncludeRuntimeScope true/false
246      * @return {@link org.apache.maven.shared.artifact.filter.ScopeArtifactFilter}
247      */
248     public ScopeArtifactFilter setIncludeRuntimeScope(boolean pIncludeRuntimeScope) {
249         this.includeRuntimeScope = pIncludeRuntimeScope;
250 
251         return this;
252     }
253 
254     /**
255      * <p>isIncludeTestScope.</p>
256      *
257      * @return {@link #includeTestScope}
258      */
259     public boolean isIncludeTestScope() {
260         return includeTestScope;
261     }
262 
263     /**
264      * <p>Setter for the field <code>includeTestScope</code>.</p>
265      *
266      * @param pIncludeTestScope {@link #includeTestScope}
267      * @return {@link org.apache.maven.shared.artifact.filter.ScopeArtifactFilter}
268      */
269     public ScopeArtifactFilter setIncludeTestScope(boolean pIncludeTestScope) {
270         this.includeTestScope = pIncludeTestScope;
271 
272         return this;
273     }
274 
275     /**
276      * <p>isIncludeProvidedScope.</p>
277      *
278      * @return {@link #includeProvidedScope}
279      */
280     public boolean isIncludeProvidedScope() {
281         return includeProvidedScope;
282     }
283 
284     /**
285      * <p>Setter for the field <code>includeProvidedScope</code>.</p>
286      *
287      * @param pIncludeProvidedScope yes/no.
288      * @return {@link #ScopeArtifactFilter()}
289      */
290     public ScopeArtifactFilter setIncludeProvidedScope(boolean pIncludeProvidedScope) {
291         this.includeProvidedScope = pIncludeProvidedScope;
292 
293         return this;
294     }
295 
296     /**
297      * <p>isIncludeSystemScope.</p>
298      *
299      * @return {@link #includeSystemScope}
300      */
301     public boolean isIncludeSystemScope() {
302         return includeSystemScope;
303     }
304 
305     /**
306      * {@inheritDoc}
307      *
308      * @param pIncludeSystemScope a boolean.
309      * @return a {@link org.apache.maven.shared.artifact.filter.ScopeArtifactFilter} object.
310      */
311     public ScopeArtifactFilter setIncludeSystemScope(boolean pIncludeSystemScope) {
312         this.includeSystemScope = pIncludeSystemScope;
313 
314         return this;
315     }
316 
317     /**
318      * Manages the following scopes:
319      *
320      * <ul>
321      *   <li>system</li>
322      *   <li>provided</li>
323      *   <li>compile</li>
324      * </ul>
325      *
326      * @param enabled whether specified scopes should be included
327      * @return this instance
328      */
329     public ScopeArtifactFilter setIncludeCompileScopeWithImplications(boolean enabled) {
330         includeSystemScope = enabled;
331         includeProvidedScope = enabled;
332         includeCompileScope = enabled;
333 
334         return this;
335     }
336 
337     /**
338      * Manages the following scopes:
339      *
340      * <ul>
341      *   <li>compile</li>
342      *   <li>runtime</li>
343      * </ul>
344      *
345      * @param enabled whether specified scopes should be included
346      * @return this instance
347      */
348     public ScopeArtifactFilter setIncludeRuntimeScopeWithImplications(boolean enabled) {
349         includeCompileScope = enabled;
350         includeRuntimeScope = enabled;
351 
352         return this;
353     }
354 
355     /**
356      * Manages the following scopes:
357      *
358      * <ul>
359      *   <li>system</li>
360      *   <li>provided</li>
361      *   <li>compile</li>
362      *   <li>runtime</li>
363      *   <li>test</li>
364      * </ul>
365      *
366      * @param enabled whether specified scopes should be included
367      * @return this instance
368      */
369     public ScopeArtifactFilter setIncludeTestScopeWithImplications(boolean enabled) {
370         includeSystemScope = enabled;
371         includeProvidedScope = enabled;
372         includeCompileScope = enabled;
373         includeRuntimeScope = enabled;
374         includeTestScope = enabled;
375 
376         return this;
377     }
378 
379     /**
380      * Determine whether artifacts that have a null scope are included or excluded.
381      *
382      * @param enable whether null-scope should be included
383      * @return this instance
384      */
385     public ScopeArtifactFilter setIncludeNullScope(boolean enable) {
386         includeNullScope = enable;
387 
388         return this;
389     }
390 
391     /**
392      * Reset hit counts and tracking of filtered artifacts, BUT NOT ENABLED SCOPES.
393      *
394      * @return this instance
395      */
396     public ScopeArtifactFilter reset() {
397         compileScopeHit = false;
398         runtimeScopeHit = false;
399         testScopeHit = false;
400         providedScopeHit = false;
401         systemScopeHit = false;
402         filteredArtifactIds.clear();
403 
404         return this;
405     }
406 }