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 }