1   ////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code for adherence to a set of rules.
3   // Copyright (C) 2001-2019 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.Collections;
23  import java.util.HashSet;
24  import java.util.Objects;
25  import java.util.Set;
26  
27  import com.puppycrawl.tools.checkstyle.TreeWalkerAuditEvent;
28  import com.puppycrawl.tools.checkstyle.TreeWalkerFilter;
29  import com.puppycrawl.tools.checkstyle.api.AutomaticBean;
30  import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
31  import com.puppycrawl.tools.checkstyle.api.ExternalResourceHolder;
32  import com.puppycrawl.tools.checkstyle.utils.FilterUtil;
33  
34  /**
35   * This filter accepts TreeWalkerAuditEvents according to file, check and xpath query,
36   * as specified in a suppression file.
37   *
38   * @noinspection NonFinalFieldReferenceInEquals, NonFinalFieldReferencedInHashCode
39   */
40  public class SuppressionXpathFilter extends AutomaticBean implements
41          TreeWalkerFilter, ExternalResourceHolder {
42  
43      /** Filename of suppression file. */
44      private String file;
45      /** Tells whether config file existence is optional. */
46      private boolean optional;
47      /** Set of individual xpath suppresses. */
48      private Set<TreeWalkerFilter> filters = new HashSet<>();
49  
50      /**
51       * Sets name of the suppression file.
52       * @param fileName name of the suppressions file.
53       */
54      public void setFile(String fileName) {
55          file = fileName;
56      }
57  
58      /**
59       * Sets whether config file existence is optional.
60       * @param optional tells if config file existence is optional.
61       */
62      public void setOptional(boolean optional) {
63          this.optional = optional;
64      }
65  
66      @Override
67      public boolean equals(Object obj) {
68          if (this == obj) {
69              return true;
70          }
71          if (obj == null || getClass() != obj.getClass()) {
72              return false;
73          }
74          final SuppressionXpathFilter suppressionXpathFilter = (SuppressionXpathFilter) obj;
75          return Objects.equals(filters, suppressionXpathFilter.filters);
76      }
77  
78      @Override
79      public int hashCode() {
80          return Objects.hash(filters);
81      }
82  
83      @Override
84      public boolean accept(TreeWalkerAuditEvent treeWalkerAuditEvent) {
85          boolean result = true;
86          for (TreeWalkerFilter filter : filters) {
87              if (!filter.accept(treeWalkerAuditEvent)) {
88                  result = false;
89                  break;
90              }
91          }
92          return result;
93      }
94  
95      @Override
96      public Set<String> getExternalResourceLocations() {
97          return Collections.singleton(file);
98      }
99  
100     @Override
101     protected void finishLocalSetup() throws CheckstyleException {
102         if (file != null) {
103             if (optional) {
104                 if (FilterUtil.isFileExists(file)) {
105                     filters = SuppressionsLoader.loadXpathSuppressions(file);
106                 }
107                 else {
108                     filters = new HashSet<>();
109                 }
110             }
111             else {
112                 filters = SuppressionsLoader.loadXpathSuppressions(file);
113             }
114         }
115     }
116 
117 }