1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.logging.log4j.core.filter;
18
19 import java.util.ArrayList;
20 import java.util.HashMap;
21 import java.util.List;
22 import java.util.Map;
23 import java.util.Objects;
24
25 import org.apache.logging.log4j.Level;
26 import org.apache.logging.log4j.Marker;
27 import org.apache.logging.log4j.core.Filter;
28 import org.apache.logging.log4j.core.LogEvent;
29 import org.apache.logging.log4j.core.Logger;
30 import org.apache.logging.log4j.core.config.Node;
31 import org.apache.logging.log4j.core.config.plugins.Plugin;
32 import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
33 import org.apache.logging.log4j.core.config.plugins.PluginElement;
34 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
35 import org.apache.logging.log4j.core.util.KeyValuePair;
36 import org.apache.logging.log4j.message.MapMessage;
37 import org.apache.logging.log4j.message.Message;
38 import org.apache.logging.log4j.util.BiConsumer;
39 import org.apache.logging.log4j.util.IndexedReadOnlyStringMap;
40 import org.apache.logging.log4j.util.IndexedStringMap;
41 import org.apache.logging.log4j.util.PerformanceSensitive;
42 import org.apache.logging.log4j.util.ReadOnlyStringMap;
43 import org.apache.logging.log4j.util.SortedArrayStringMap;
44
45
46
47
48 @Plugin(name = "MapFilter", category = Node.CATEGORY, elementType = Filter.ELEMENT_TYPE, printObject = true)
49 @PerformanceSensitive("allocation")
50 public class MapFilter extends AbstractFilter {
51
52 private final IndexedStringMap map;
53 private final boolean isAnd;
54
55 protected MapFilter(final Map<String, List<String>> map, final boolean oper, final Result onMatch, final Result onMismatch) {
56 super(onMatch, onMismatch);
57 this.isAnd = oper;
58 Objects.requireNonNull(map, "map cannot be null");
59
60 this.map = new SortedArrayStringMap(map.size());
61 for (final Map.Entry<String, List<String>> entry : map.entrySet()) {
62 this.map.putValue(entry.getKey(), entry.getValue());
63 }
64 }
65
66 @Override
67 public Result filter(final Logger logger, final Level level, final Marker marker, final Message msg,
68 final Throwable t) {
69 if (msg instanceof MapMessage) {
70 return filter((MapMessage<?, ?>) msg) ? onMatch : onMismatch;
71 }
72 return Result.NEUTRAL;
73 }
74
75 @Override
76 public Result filter(final LogEvent event) {
77 final Message msg = event.getMessage();
78 if (msg instanceof MapMessage) {
79 return filter((MapMessage<?, ?>) msg) ? onMatch : onMismatch;
80 }
81 return Result.NEUTRAL;
82 }
83
84 protected boolean filter(final MapMessage<?, ?> mapMessage) {
85 boolean match = false;
86 for (int i = 0; i < map.size(); i++) {
87 final String toMatch = mapMessage.get(map.getKeyAt(i));
88 match = toMatch != null && ((List<String>) map.getValueAt(i)).contains(toMatch);
89
90 if ((!isAnd && match) || (isAnd && !match)) {
91 break;
92 }
93 }
94 return match;
95 }
96
97 protected boolean filter(final Map<String, String> data) {
98 boolean match = false;
99 for (int i = 0; i < map.size(); i++) {
100 final String toMatch = data.get(map.getKeyAt(i));
101 match = toMatch != null && ((List<String>) map.getValueAt(i)).contains(toMatch);
102
103 if ((!isAnd && match) || (isAnd && !match)) {
104 break;
105 }
106 }
107 return match;
108 }
109
110 protected boolean filter(final ReadOnlyStringMap data) {
111 boolean match = false;
112 for (int i = 0; i < map.size(); i++) {
113 final String toMatch = data.getValue(map.getKeyAt(i));
114 match = toMatch != null && ((List<String>) map.getValueAt(i)).contains(toMatch);
115
116 if ((!isAnd && match) || (isAnd && !match)) {
117 break;
118 }
119 }
120 return match;
121 }
122
123 @Override
124 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
125 final Object p0) {
126 return Result.NEUTRAL;
127 }
128
129 @Override
130 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
131 final Object p0, final Object p1) {
132 return Result.NEUTRAL;
133 }
134
135 @Override
136 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
137 final Object p0, final Object p1, final Object p2) {
138 return Result.NEUTRAL;
139 }
140
141 @Override
142 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
143 final Object p0, final Object p1, final Object p2, final Object p3) {
144 return Result.NEUTRAL;
145 }
146
147 @Override
148 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
149 final Object p0, final Object p1, final Object p2, final Object p3,
150 final Object p4) {
151 return Result.NEUTRAL;
152 }
153
154 @Override
155 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
156 final Object p0, final Object p1, final Object p2, final Object p3,
157 final Object p4, final Object p5) {
158 return Result.NEUTRAL;
159 }
160
161 @Override
162 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
163 final Object p0, final Object p1, final Object p2, final Object p3,
164 final Object p4, final Object p5, final Object p6) {
165 return Result.NEUTRAL;
166 }
167
168 @Override
169 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
170 final Object p0, final Object p1, final Object p2, final Object p3,
171 final Object p4, final Object p5, final Object p6,
172 final Object p7) {
173 return Result.NEUTRAL;
174 }
175
176 @Override
177 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
178 final Object p0, final Object p1, final Object p2, final Object p3,
179 final Object p4, final Object p5, final Object p6,
180 final Object p7, final Object p8) {
181 return Result.NEUTRAL;
182 }
183
184 @Override
185 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
186 final Object p0, final Object p1, final Object p2, final Object p3,
187 final Object p4, final Object p5, final Object p6,
188 final Object p7, final Object p8, final Object p9) {
189 return Result.NEUTRAL;
190 }
191
192 @Override
193 public String toString() {
194 final StringBuilder sb = new StringBuilder();
195 sb.append("isAnd=").append(isAnd);
196 if (map.size() > 0) {
197 sb.append(", {");
198 for (int i = 0; i < map.size(); i++) {
199 if (i > 0) {
200 sb.append(", ");
201 }
202 final List<String> list = map.getValueAt(i);
203 final String value = list.size() > 1 ? list.get(0) : list.toString();
204 sb.append(map.getKeyAt(i)).append('=').append(value);
205 }
206 sb.append('}');
207 }
208 return sb.toString();
209 }
210
211 protected boolean isAnd() {
212 return isAnd;
213 }
214
215
216 @Deprecated
217 protected Map<String, List<String>> getMap() {
218 final Map<String, List<String>> result = new HashMap<>(map.size());
219 map.forEach(new BiConsumer<String, List<String>>() {
220 @Override
221 public void accept(final String key, final List<String> value) {
222 result.put(key, value);
223 }
224 });
225 return result;
226 }
227
228
229
230
231
232
233 protected IndexedReadOnlyStringMap getStringMap() {
234 return map;
235 }
236
237
238 @PluginFactory
239 public static MapFilter createFilter(
240 @PluginElement("Pairs") final KeyValuePair[] pairs,
241 @PluginAttribute("operator") final String oper,
242 @PluginAttribute("onMatch") final Result match,
243 @PluginAttribute("onMismatch") final Result mismatch) {
244 if (pairs == null || pairs.length == 0) {
245 LOGGER.error("keys and values must be specified for the MapFilter");
246 return null;
247 }
248 final Map<String, List<String>> map = new HashMap<>();
249 for (final KeyValuePair pair : pairs) {
250 final String key = pair.getKey();
251 if (key == null) {
252 LOGGER.error("A null key is not valid in MapFilter");
253 continue;
254 }
255 final String value = pair.getValue();
256 if (value == null) {
257 LOGGER.error("A null value for key " + key + " is not allowed in MapFilter");
258 continue;
259 }
260 List<String> list = map.get(pair.getKey());
261 if (list != null) {
262 list.add(value);
263 } else {
264 list = new ArrayList<>();
265 list.add(value);
266 map.put(pair.getKey(), list);
267 }
268 }
269 if (map.isEmpty()) {
270 LOGGER.error("MapFilter is not configured with any valid key value pairs");
271 return null;
272 }
273 final boolean isAnd = oper == null || !oper.equalsIgnoreCase("or");
274 return new MapFilter(map, isAnd, match, mismatch);
275 }
276 }