View Javadoc
1   /*
2    * This file is part of dependency-check-core.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   *
16   * Copyright (c) 2017 Hans Aikema. All Rights Reserved.
17   */
18  package org.owasp.dependencycheck.xml.hints;
19  
20  import java.util.regex.Pattern;
21  import org.owasp.dependencycheck.dependency.Confidence;
22  import org.owasp.dependencycheck.dependency.Evidence;
23  
24  /**
25   * EvidenceMatcher can match one or more {@link Evidence}s. By using regular
26   * expressions for some fields and allowing omission of Evidence fields it can
27   * be used to match more than one occurrence of evidence to enable hints that
28   * work for a range of similar false positives/false negatives.
29   *
30   * The EvidenceMatcher is used for processing Evidences of a project's
31   * dependencies in conjunction with the {@code <given>} and {@code <remove>}
32   * clauses of the hints file.
33   *
34   * @author Hans Aikema
35   */
36  public class EvidenceMatcher {
37  
38      /**
39       * The name that the {@link Evidence} should have for a match.
40       */
41      private final String name;
42  
43      /**
44       * The source that the {@link Evidence} should have for a match. A
45       * {@code null}-value is allowed and functions as a wildcard.
46       */
47      private final String source;
48  
49      /**
50       * The value that the {@link Evidence} should have for a match.
51       */
52      private final String value;
53  
54      /**
55       * Whether the {@link EvidenceMatcher#value} should be interpreted as a
56       * regular expression.
57       */
58      private final boolean regex;
59  
60      /**
61       * The confidence that the {@link Evidence} should have for a match. A
62       * {@code null}-value is allowed and functions as a wildcard.
63       */
64      private final Confidence confidence;
65  
66      /**
67       * Creates a new EvidenceMatcher objects.
68       *
69       * @param source the source of the evidence, a source that is {@code null}
70       * indicates any source should match.
71       * @param name the non-{@code null} name of the evidence.
72       * @param value the non-{@code null} value of the evidence.
73       * @param regex whether value is a regex.
74       * @param confidence the confidence of the evidence, a confidence that is
75       * {@code null} indicates any confidence should match.
76       */
77      public EvidenceMatcher(String source, String name, String value, boolean regex, Confidence confidence) {
78          this.source = source;
79          this.name = name;
80          this.value = value;
81          this.confidence = confidence;
82          this.regex = regex;
83      }
84  
85      /**
86       * Tests whether the given Evidence matches this EvidenceMatcher.
87       *
88       * @param evidence the evidence to match
89       * @return whether the evidence matches this matcher
90       */
91      public boolean matches(Evidence evidence) {
92          return sourceMatches(evidence)
93                  && confidenceMatches(evidence)
94                  && name.equalsIgnoreCase(evidence.getName())
95                  && valueMatches(evidence);
96      }
97  
98      /**
99       * Standard toString() implementation.
100      *
101      * @return the string representation of the object
102      */
103     @Override
104     public String toString() {
105         return "HintEvidenceMatcher{" + "name=" + name + ", source=" + source + ", value=" + value
106                 + ", confidence=" + confidence + ", regex=" + regex + '}';
107     }
108 
109     /**
110      * package-private getter to allow testability of the parser without mocking.
111      *
112      * @return The name property
113      */
114     String getName() {
115         return name;
116     }
117 
118     /**
119      * package-private getter to allow testability of the parser without mocking.
120      *
121      * @return The source property
122      */
123     String getSource() {
124         return source;
125     }
126 
127     /**
128      * package-private getter to allow testability of the parser without mocking.
129      *
130      * @return The value property
131      */
132     String getValue() {
133         return value;
134     }
135 
136     /**
137      * package-private getter to allow testability of the parser without mocking.
138      *
139      * @return The regex property
140      */
141     boolean isRegex() {
142         return regex;
143     }
144 
145     /**
146      * package-private getter to allow testability of the parser without mocking.
147      *
148      * @return The confidence property
149      */
150     Confidence getConfidence() {
151         return confidence;
152     }
153 
154     /**
155      * Checks whether the value of the evidence matches this matcher. When
156      * {@link #isRegex()} is {@code true} value is used as a
157      * {@link java.util.regex.Pattern} that it should match. Otherwise the value
158      * must be case-insensitive equal to the evidence's value.
159      *
160      * @param evidence the evidence to match
161      * @return <code>true</code> if the evidence matches; otherwise
162      * <code>false</code>
163      */
164     private boolean valueMatches(Evidence evidence) {
165         final boolean result;
166         if (regex) {
167             result = Pattern.matches(value, evidence.getValue());
168         } else {
169             result = value.equalsIgnoreCase(evidence.getValue());
170         }
171         return result;
172     }
173 
174     /**
175      * Checks whether the source of the evidence matches this matcher. If our
176      * source is {@code null} any source in the evidence matches. Otherwise the
177      * source in the evidence must be case-insensitive equal to our source.
178      *
179      * @param evidence The evidence to inspect
180      * @return {@code true} is the source of the evidence matches, false
181      * otherwise.
182      */
183     private boolean sourceMatches(Evidence evidence) {
184         return this.source == null || source.equalsIgnoreCase(evidence.getSource());
185     }
186 
187     /**
188      * Checks whether the confidence of the evidence matches this matcher. If
189      * our confidence is {@code null} any confidence in the evidence matches.
190      * Otherwise the confidence in the evidence must be exactly equal to our
191      * confidence.
192      *
193      * @param evidence The evidence to inspect
194      * @return {@code true} is the confidence of the evidence matches, false
195      * otherwise.
196      */
197     private boolean confidenceMatches(Evidence evidence) {
198         return this.confidence == null || confidence.equals(evidence.getConfidence());
199     }
200 
201 }