View Javadoc
1   ///////////////////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code and other text files for adherence to a set of rules.
3   // Copyright (C) 2001-2024 the original author or authors.
4   //
5   // This library is free software; you can redistribute it and/or
6   // modify it under the terms of the GNU Lesser General Public
7   // License as published by the Free Software Foundation; either
8   // version 2.1 of the License, or (at your option) any later version.
9   //
10  // This library is distributed in the hope that it will be useful,
11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  // Lesser General Public License for more details.
14  //
15  // You should have received a copy of the GNU Lesser General Public
16  // License along with this library; if not, write to the Free Software
17  // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  ///////////////////////////////////////////////////////////////////////////////////////////////
19  
20  package com.puppycrawl.tools.checkstyle.filters;
21  
22  import java.util.Set;
23  
24  import com.puppycrawl.tools.checkstyle.AbstractAutomaticBean;
25  import com.puppycrawl.tools.checkstyle.api.AuditEvent;
26  import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
27  import com.puppycrawl.tools.checkstyle.api.ExternalResourceHolder;
28  import com.puppycrawl.tools.checkstyle.api.Filter;
29  import com.puppycrawl.tools.checkstyle.api.FilterSet;
30  import com.puppycrawl.tools.checkstyle.utils.FilterUtil;
31  import com.puppycrawl.tools.checkstyle.utils.UnmodifiableCollectionUtil;
32  
33  /**
34   * <p>
35   * Filter {@code SuppressionFilter} rejects audit events for Check violations according to a
36   * <a href="https://checkstyle.org/dtds/suppressions_1_2.dtd">suppressions XML document</a>
37   * in a file. If there is no configured suppressions file or the optional is set to true and
38   * suppressions file was not found the Filter accepts all audit events.
39   * </p>
40   * <p>
41   * A <a href="https://checkstyle.org/dtds/suppressions_1_2.dtd">suppressions XML document</a>
42   * contains a set of {@code suppress} elements, where each {@code suppress}
43   * element can have the following attributes:
44   * </p>
45   * <ul>
46   * <li>
47   * {@code files} - a <a href="https://checkstyle.org/property_types.html#Pattern">
48   * Pattern</a> matched against the file name associated with an audit event.
49   * It is optional.
50   * </li>
51   * <li>
52   * {@code checks} - a <a href="https://checkstyle.org/property_types.html#Pattern">
53   * Pattern</a> matched against the name of the check associated with an audit event.
54   * Optional as long as {@code id} or {@code message} is specified.
55   * </li>
56   * <li>
57   * {@code message} - a <a href="https://checkstyle.org/property_types.html#Pattern">
58   * Pattern</a> matched against the message of the check associated with an audit event.
59   * Optional as long as {@code checks} or {@code id} is specified.
60   * </li>
61   * <li>
62   * {@code id} - a <a href="https://checkstyle.org/property_types.html#String">String</a>
63   * matched against the <a href="https://checkstyle.org/config.html#Id">check id</a>
64   * associated with an audit event.
65   * Optional as long as {@code checks} or {@code message} is specified.
66   * </li>
67   * <li>
68   * {@code lines} - a comma-separated list of values, where each value is an
69   * <a href="https://checkstyle.org/property_types.html#int">int</a>
70   * or a range of integers denoted by integer-integer.
71   * It is optional.
72   * </li>
73   * <li>
74   * {@code columns} - a comma-separated list of values, where each value is an
75   * <a href="https://checkstyle.org/property_types.html#int">int</a>
76   * or a range of integers denoted by integer-integer.
77   * It is optional.
78   * </li>
79   * </ul>
80   * <p>
81   * Each audit event is checked against each {@code suppress} element.
82   * It is suppressed if all specified attributes match against the audit event.
83   * </p>
84   * <p>
85   * ATTENTION: filtering by message is dependent on runtime locale.
86   * If project is running in different languages it is better to avoid filtering by message.
87   * </p>
88   * <p>
89   * You can download template of empty suppression filter
90   * <a href="https://checkstyle.org/files/suppressions_none.xml">here</a>.
91   * </p>
92   * <p>
93   * Location of the file defined in {@code file} property is checked in the following order:
94   * </p>
95   * <ol>
96   * <li>
97   * as a filesystem location
98   * </li>
99   * <li>
100  * if no file found, and the location starts with either {@code http://} or {@code https://},
101  * then it is interpreted as a URL
102  * </li>
103  * <li>
104  * if no file found, then passed to the {@code ClassLoader.getResource()} method.
105  * </li>
106  * </ol>
107  * <p>
108  * SuppressionFilter can suppress Checks that have Treewalker or Checker as parent module.
109  * </p>
110  * <ul>
111  * <li>
112  * Property {@code file} - Specify the location of the <em>suppressions XML document</em> file.
113  * Type is {@code java.lang.String}.
114  * Default value is {@code null}.
115  * </li>
116  * <li>
117  * Property {@code optional} - Control what to do when the file is not existing.
118  * If {@code optional} is set to {@code false} the file must exist, or else it
119  * ends with error. On the other hand if optional is {@code true} and file is
120  * not found, the filter accept all audit events.
121  * Type is {@code boolean}.
122  * Default value is {@code false}.
123  * </li>
124  * </ul>
125  * <p>
126  * Parent is {@code com.puppycrawl.tools.checkstyle.Checker}
127  * </p>
128  *
129  * @since 3.2
130  */
131 public class SuppressionFilter
132         extends AbstractAutomaticBean
133         implements Filter, ExternalResourceHolder {
134 
135     /** Specify the location of the <em>suppressions XML document</em> file. */
136     private String file;
137     /**
138      * Control what to do when the file is not existing. If {@code optional} is
139      * set to {@code false} the file must exist, or else it ends with error.
140      * On the other hand if optional is {@code true} and file is not found,
141      * the filter accept all audit events.
142      */
143     private boolean optional;
144     /** Set of individual suppresses. */
145     private FilterSet filters = new FilterSet();
146 
147     /**
148      * Setter to specify the location of the <em>suppressions XML document</em> file.
149      *
150      * @param fileName name of the suppressions file.
151      * @since 3.2
152      */
153     public void setFile(String fileName) {
154         file = fileName;
155     }
156 
157     /**
158      * Setter to control what to do when the file is not existing.
159      * If {@code optional} is set to {@code false} the file must exist, or else
160      * it ends with error. On the other hand if optional is {@code true}
161      * and file is not found, the filter accept all audit events.
162      *
163      * @param optional tells if config file existence is optional.
164      * @since 6.15
165      */
166     public void setOptional(boolean optional) {
167         this.optional = optional;
168     }
169 
170     @Override
171     public boolean accept(AuditEvent event) {
172         return filters.accept(event);
173     }
174 
175     @Override
176     protected void finishLocalSetup() throws CheckstyleException {
177         if (file != null) {
178             if (optional) {
179                 if (FilterUtil.isFileExists(file)) {
180                     filters = SuppressionsLoader.loadSuppressions(file);
181                 }
182             }
183             else {
184                 filters = SuppressionsLoader.loadSuppressions(file);
185             }
186         }
187     }
188 
189     @Override
190     public Set<String> getExternalResourceLocations() {
191         return UnmodifiableCollectionUtil.singleton(file);
192     }
193 
194 }