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   * <div>
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   * </div>
40   *
41   * <p>
42   * A <a href="https://checkstyle.org/dtds/suppressions_1_2.dtd">suppressions XML document</a>
43   * contains a set of {@code suppress} elements, where each {@code suppress}
44   * element can have the following attributes:
45   * </p>
46   * <ul>
47   * <li>
48   * {@code files} - a <a href="https://checkstyle.org/property_types.html#Pattern">
49   * Pattern</a> matched against the file name associated with an audit event.
50   * It is optional.
51   * </li>
52   * <li>
53   * {@code checks} - a <a href="https://checkstyle.org/property_types.html#Pattern">
54   * Pattern</a> matched against the name of the check associated with an audit event.
55   * Optional as long as {@code id} or {@code message} is specified.
56   * </li>
57   * <li>
58   * {@code message} - a <a href="https://checkstyle.org/property_types.html#Pattern">
59   * Pattern</a> matched against the message of the check associated with an audit event.
60   * Optional as long as {@code checks} or {@code id} is specified.
61   * </li>
62   * <li>
63   * {@code id} - a <a href="https://checkstyle.org/property_types.html#String">String</a>
64   * matched against the <a href="https://checkstyle.org/config.html#Id">check id</a>
65   * associated with an audit event.
66   * Optional as long as {@code checks} or {@code message} is specified.
67   * </li>
68   * <li>
69   * {@code lines} - a comma-separated list of values, where each value is an
70   * <a href="https://checkstyle.org/property_types.html#int">int</a>
71   * or a range of integers denoted by integer-integer.
72   * It is optional.
73   * </li>
74   * <li>
75   * {@code columns} - a comma-separated list of values, where each value is an
76   * <a href="https://checkstyle.org/property_types.html#int">int</a>
77   * or a range of integers denoted by integer-integer.
78   * It is optional.
79   * </li>
80   * </ul>
81   *
82   * <p>
83   * Each audit event is checked against each {@code suppress} element.
84   * It is suppressed if all specified attributes match against the audit event.
85   * </p>
86   *
87   * <p>
88   * ATTENTION: filtering by message is dependent on runtime locale.
89   * If project is running in different languages it is better to avoid filtering by message.
90   * </p>
91   *
92   * <p>
93   * You can download template of empty suppression filter
94   * <a href="https://checkstyle.org/files/suppressions_none.xml">here</a>.
95   * </p>
96   *
97   * <p>
98   * Location of the file defined in {@code file} property is checked in the following order:
99   * </p>
100  * <ol>
101  * <li>
102  * as a filesystem location
103  * </li>
104  * <li>
105  * if no file found, and the location starts with either {@code http://} or {@code https://},
106  * then it is interpreted as a URL
107  * </li>
108  * <li>
109  * if no file found, then passed to the {@code ClassLoader.getResource()} method.
110  * </li>
111  * </ol>
112  *
113  * <p>
114  * SuppressionFilter can suppress Checks that have Treewalker or Checker as parent module.
115  * </p>
116  * <ul>
117  * <li>
118  * Property {@code file} - Specify the location of the <em>suppressions XML document</em> file.
119  * Type is {@code java.lang.String}.
120  * Default value is {@code null}.
121  * </li>
122  * <li>
123  * Property {@code optional} - Control what to do when the file is not existing.
124  * If {@code optional} is set to {@code false} the file must exist, or else it
125  * ends with error. On the other hand if optional is {@code true} and file is
126  * not found, the filter accept all audit events.
127  * Type is {@code boolean}.
128  * Default value is {@code false}.
129  * </li>
130  * </ul>
131  *
132  * <p>
133  * Parent is {@code com.puppycrawl.tools.checkstyle.Checker}
134  * </p>
135  *
136  * @since 3.2
137  */
138 public class SuppressionFilter
139         extends AbstractAutomaticBean
140         implements Filter, ExternalResourceHolder {
141 
142     /** Specify the location of the <em>suppressions XML document</em> file. */
143     private String file;
144     /**
145      * Control what to do when the file is not existing. If {@code optional} is
146      * set to {@code false} the file must exist, or else it ends with error.
147      * On the other hand if optional is {@code true} and file is not found,
148      * the filter accept all audit events.
149      */
150     private boolean optional;
151     /** Set of individual suppresses. */
152     private FilterSet filters = new FilterSet();
153 
154     /**
155      * Setter to specify the location of the <em>suppressions XML document</em> file.
156      *
157      * @param fileName name of the suppressions file.
158      * @since 3.2
159      */
160     public void setFile(String fileName) {
161         file = fileName;
162     }
163 
164     /**
165      * Setter to control what to do when the file is not existing.
166      * If {@code optional} is set to {@code false} the file must exist, or else
167      * it ends with error. On the other hand if optional is {@code true}
168      * and file is not found, the filter accept all audit events.
169      *
170      * @param optional tells if config file existence is optional.
171      * @since 6.15
172      */
173     public void setOptional(boolean optional) {
174         this.optional = optional;
175     }
176 
177     @Override
178     public boolean accept(AuditEvent event) {
179         return filters.accept(event);
180     }
181 
182     @Override
183     protected void finishLocalSetup() throws CheckstyleException {
184         if (file != null) {
185             if (optional) {
186                 if (FilterUtil.isFileExists(file)) {
187                     filters = SuppressionsLoader.loadSuppressions(file);
188                 }
189             }
190             else {
191                 filters = SuppressionsLoader.loadSuppressions(file);
192             }
193         }
194     }
195 
196     @Override
197     public Set<String> getExternalResourceLocations() {
198         return UnmodifiableCollectionUtil.singleton(file);
199     }
200 
201 }