View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements. See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache license, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License. You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the license for the specific language governing permissions and
15   * limitations under the license.
16   */
17  package org.apache.logging.log4j.core.filter;
18  
19  import java.util.ArrayList;
20  import java.util.Arrays;
21  import java.util.Iterator;
22  import java.util.List;
23  import java.util.concurrent.TimeUnit;
24  
25  import org.apache.logging.log4j.Level;
26  import org.apache.logging.log4j.Marker;
27  import org.apache.logging.log4j.core.AbstractLifeCycle;
28  import org.apache.logging.log4j.core.Filter;
29  import org.apache.logging.log4j.core.LifeCycle2;
30  import org.apache.logging.log4j.core.LogEvent;
31  import org.apache.logging.log4j.core.Logger;
32  import org.apache.logging.log4j.core.config.Node;
33  import org.apache.logging.log4j.core.config.plugins.Plugin;
34  import org.apache.logging.log4j.core.config.plugins.PluginElement;
35  import org.apache.logging.log4j.core.config.plugins.PluginFactory;
36  import org.apache.logging.log4j.core.util.ObjectArrayIterator;
37  import org.apache.logging.log4j.message.Message;
38  import org.apache.logging.log4j.util.PerformanceSensitive;
39  
40  /**
41   * Composes and invokes one or more filters.
42   */
43  @Plugin(name = "filters", category = Node.CATEGORY, printObject = true)
44  @PerformanceSensitive("allocation")
45  public final class CompositeFilter extends AbstractLifeCycle implements Iterable<Filter>, Filter {
46  
47      private static final Filter[] EMPTY_FILTERS = new Filter[0];
48      private final Filter[] filters;
49  
50      private CompositeFilter() {
51          this.filters = EMPTY_FILTERS;
52      }
53  
54      private CompositeFilter(final Filter[] filters) {
55          this.filters = filters == null ? EMPTY_FILTERS : filters;
56      }
57  
58      public CompositeFilter addFilter(final Filter filter) {
59          if (filter == null) {
60              // null does nothing
61              return this;
62          }
63          if (filter instanceof CompositeFilter) {
64              final int size = this.filters.length + ((CompositeFilter) filter).size();
65              final Filter[] copy = Arrays.copyOf(this.filters, size);
66              final int index = this.filters.length;
67              for (final Filter currentFilter : ((CompositeFilter) filter).filters) {
68                  copy[index] = currentFilter;
69              }
70              return new CompositeFilter(copy);
71          }
72          final Filter[] copy = Arrays.copyOf(this.filters, this.filters.length + 1);
73          copy[this.filters.length] = filter;
74          return new CompositeFilter(copy);
75      }
76  
77      public CompositeFilter removeFilter(final Filter filter) {
78          if (filter == null) {
79              // null does nothing
80              return this;
81          }
82          // This is not a great implementation but simpler than copying Apache Commons
83          // Lang ArrayUtils.removeElement() and associated bits (MutableInt),
84          // which is OK since removing a filter should not be on the critical path.
85          final List<Filter> filterList = new ArrayList<>(Arrays.asList(this.filters));
86          if (filter instanceof CompositeFilter) {
87              for (final Filter currentFilter : ((CompositeFilter) filter).filters) {
88                  filterList.remove(currentFilter);
89              }
90          } else {
91              filterList.remove(filter);
92          }
93          return new CompositeFilter(filterList.toArray(new Filter[this.filters.length - 1]));
94      }
95  
96      @Override
97      public Iterator<Filter> iterator() {
98          return new ObjectArrayIterator<>(filters);
99      }
100 
101     /**
102      * Gets a new list over the internal filter array.
103      *
104      * @return a new list over the internal filter array
105      * @deprecated Use {@link #getFiltersArray()}
106      */
107     @Deprecated
108     public List<Filter> getFilters() {
109         return Arrays.asList(filters);
110     }
111 
112     public Filter[] getFiltersArray() {
113         return filters;
114     }
115 
116     /**
117      * Returns whether this composite contains any filters.
118      *
119      * @return whether this composite contains any filters.
120      */
121     public boolean isEmpty() {
122         return this.filters.length == 0;
123     }
124 
125     public int size() {
126         return filters.length;
127     }
128 
129     @Override
130     public void start() {
131         this.setStarting();
132         for (final Filter filter : filters) {
133             filter.start();
134         }
135         this.setStarted();
136     }
137 
138     @Override
139     public boolean stop(final long timeout, final TimeUnit timeUnit) {
140         this.setStopping();
141         for (final Filter filter : filters) {
142             if (filter instanceof LifeCycle2) {
143                 ((LifeCycle2) filter).stop(timeout, timeUnit);
144             } else {
145                 filter.stop();
146             }
147         }
148         setStopped();
149         return true;
150     }
151 
152     /**
153      * Returns the result that should be returned when the filter does not match the event.
154      *
155      * @return the Result that should be returned when the filter does not match the event.
156      */
157     @Override
158     public Result getOnMismatch() {
159         return Result.NEUTRAL;
160     }
161 
162     /**
163      * Returns the result that should be returned when the filter matches the event.
164      *
165      * @return the Result that should be returned when the filter matches the event.
166      */
167     @Override
168     public Result getOnMatch() {
169         return Result.NEUTRAL;
170     }
171 
172     /**
173      * Filter an event.
174      *
175      * @param logger
176      *            The Logger.
177      * @param level
178      *            The event logging Level.
179      * @param marker
180      *            The Marker for the event or null.
181      * @param msg
182      *            String text to filter on.
183      * @param params
184      *            An array of parameters or null.
185      * @return the Result.
186      */
187     @Override
188     public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
189             final Object... params) {
190         Result result = Result.NEUTRAL;
191         for (int i = 0; i < filters.length; i++) {
192             result = filters[i].filter(logger, level, marker, msg, params);
193             if (result == Result.ACCEPT || result == Result.DENY) {
194                 return result;
195             }
196         }
197         return result;
198     }
199 
200     /**
201      * Filter an event.
202      *
203      * @param logger
204      *            The Logger.
205      * @param level
206      *            The event logging Level.
207      * @param marker
208      *            The Marker for the event or null.
209      * @param msg
210      *            String text to filter on.
211      * @param p0 the message parameters
212      * @return the Result.
213      */
214     @Override
215     public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
216             final Object p0) {
217         Result result = Result.NEUTRAL;
218         for (int i = 0; i < filters.length; i++) {
219             result = filters[i].filter(logger, level, marker, msg, p0);
220             if (result == Result.ACCEPT || result == Result.DENY) {
221                 return result;
222             }
223         }
224         return result;
225     }
226 
227     /**
228      * Filter an event.
229      *
230      * @param logger
231      *            The Logger.
232      * @param level
233      *            The event logging Level.
234      * @param marker
235      *            The Marker for the event or null.
236      * @param msg
237      *            String text to filter on.
238      * @param p0 the message parameters
239      * @param p1 the message parameters
240      * @return the Result.
241      */
242     @Override
243     public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
244             final Object p0, final Object p1) {
245         Result result = Result.NEUTRAL;
246         for (int i = 0; i < filters.length; i++) {
247             result = filters[i].filter(logger, level, marker, msg, p0, p1);
248             if (result == Result.ACCEPT || result == Result.DENY) {
249                 return result;
250             }
251         }
252         return result;
253     }
254 
255     /**
256      * Filter an event.
257      *
258      * @param logger
259      *            The Logger.
260      * @param level
261      *            The event logging Level.
262      * @param marker
263      *            The Marker for the event or null.
264      * @param msg
265      *            String text to filter on.
266      * @param p0 the message parameters
267      * @param p1 the message parameters
268      * @param p2 the message parameters
269      * @return the Result.
270      */
271     @Override
272     public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
273             final Object p0, final Object p1, final Object p2) {
274         Result result = Result.NEUTRAL;
275         for (int i = 0; i < filters.length; i++) {
276             result = filters[i].filter(logger, level, marker, msg, p0, p1, p2);
277             if (result == Result.ACCEPT || result == Result.DENY) {
278                 return result;
279             }
280         }
281         return result;
282     }
283 
284     /**
285      * Filter an event.
286      *
287      * @param logger
288      *            The Logger.
289      * @param level
290      *            The event logging Level.
291      * @param marker
292      *            The Marker for the event or null.
293      * @param msg
294      *            String text to filter on.
295      * @param p0 the message parameters
296      * @param p1 the message parameters
297      * @param p2 the message parameters
298      * @param p3 the message parameters
299      * @return the Result.
300      */
301     @Override
302     public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
303             final Object p0, final Object p1, final Object p2, final Object p3) {
304         Result result = Result.NEUTRAL;
305         for (int i = 0; i < filters.length; i++) {
306             result = filters[i].filter(logger, level, marker, msg, p0, p1, p2, p3);
307             if (result == Result.ACCEPT || result == Result.DENY) {
308                 return result;
309             }
310         }
311         return result;
312     }
313 
314     /**
315      * Filter an event.
316      *
317      * @param logger
318      *            The Logger.
319      * @param level
320      *            The event logging Level.
321      * @param marker
322      *            The Marker for the event or null.
323      * @param msg
324      *            String text to filter on.
325      * @param p0 the message parameters
326      * @param p1 the message parameters
327      * @param p2 the message parameters
328      * @param p3 the message parameters
329      * @param p4 the message parameters
330      * @return the Result.
331      */
332     @Override
333     public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
334             final Object p0, final Object p1, final Object p2, final Object p3,
335             final Object p4) {
336         Result result = Result.NEUTRAL;
337         for (int i = 0; i < filters.length; i++) {
338             result = filters[i].filter(logger, level, marker, msg, p0, p1, p2, p3, p4);
339             if (result == Result.ACCEPT || result == Result.DENY) {
340                 return result;
341             }
342         }
343         return result;
344     }
345 
346     /**
347      * Filter an event.
348      *
349      * @param logger
350      *            The Logger.
351      * @param level
352      *            The event logging Level.
353      * @param marker
354      *            The Marker for the event or null.
355      * @param msg
356      *            String text to filter on.
357      * @param p0 the message parameters
358      * @param p1 the message parameters
359      * @param p2 the message parameters
360      * @param p3 the message parameters
361      * @param p4 the message parameters
362      * @param p5 the message parameters
363      * @return the Result.
364      */
365     @Override
366     public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
367             final Object p0, final Object p1, final Object p2, final Object p3,
368             final Object p4, final Object p5) {
369         Result result = Result.NEUTRAL;
370         for (int i = 0; i < filters.length; i++) {
371             result = filters[i].filter(logger, level, marker, msg, p0, p1, p2, p3, p4, p5);
372             if (result == Result.ACCEPT || result == Result.DENY) {
373                 return result;
374             }
375         }
376         return result;
377     }
378 
379     /**
380      * Filter an event.
381      *
382      * @param logger
383      *            The Logger.
384      * @param level
385      *            The event logging Level.
386      * @param marker
387      *            The Marker for the event or null.
388      * @param msg
389      *            String text to filter on.
390      * @param p0 the message parameters
391      * @param p1 the message parameters
392      * @param p2 the message parameters
393      * @param p3 the message parameters
394      * @param p4 the message parameters
395      * @param p5 the message parameters
396      * @param p6 the message parameters
397      * @return the Result.
398      */
399     @Override
400     public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
401             final Object p0, final Object p1, final Object p2, final Object p3,
402             final Object p4, final Object p5, final Object p6) {
403         Result result = Result.NEUTRAL;
404         for (int i = 0; i < filters.length; i++) {
405             result = filters[i].filter(logger, level, marker, msg, p0, p1, p2, p3, p4, p5, p6);
406             if (result == Result.ACCEPT || result == Result.DENY) {
407                 return result;
408             }
409         }
410         return result;
411     }
412 
413     /**
414      * Filter an event.
415      *
416      * @param logger
417      *            The Logger.
418      * @param level
419      *            The event logging Level.
420      * @param marker
421      *            The Marker for the event or null.
422      * @param msg
423      *            String text to filter on.
424      * @param p0 the message parameters
425      * @param p1 the message parameters
426      * @param p2 the message parameters
427      * @param p3 the message parameters
428      * @param p4 the message parameters
429      * @param p5 the message parameters
430      * @param p6 the message parameters
431      * @param p7 the message parameters
432      * @return the Result.
433      */
434     @Override
435     public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
436             final Object p0, final Object p1, final Object p2, final Object p3,
437             final Object p4, final Object p5, final Object p6,
438             final Object p7) {
439         Result result = Result.NEUTRAL;
440         for (int i = 0; i < filters.length; i++) {
441             result = filters[i].filter(logger, level, marker, msg, p0, p1, p2, p3, p4, p5, p6, p7);
442             if (result == Result.ACCEPT || result == Result.DENY) {
443                 return result;
444             }
445         }
446         return result;
447     }
448 
449     /**
450      * Filter an event.
451      *
452      * @param logger
453      *            The Logger.
454      * @param level
455      *            The event logging Level.
456      * @param marker
457      *            The Marker for the event or null.
458      * @param msg
459      *            String text to filter on.
460      * @param p0 the message parameters
461      * @param p1 the message parameters
462      * @param p2 the message parameters
463      * @param p3 the message parameters
464      * @param p4 the message parameters
465      * @param p5 the message parameters
466      * @param p6 the message parameters
467      * @param p7 the message parameters
468      * @param p8 the message parameters
469      * @return the Result.
470      */
471     @Override
472     public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
473             final Object p0, final Object p1, final Object p2, final Object p3,
474             final Object p4, final Object p5, final Object p6,
475             final Object p7, final Object p8) {
476         Result result = Result.NEUTRAL;
477         for (int i = 0; i < filters.length; i++) {
478             result = filters[i].filter(logger, level, marker, msg, p0, p1, p2, p3, p4, p5, p6, p7, p8);
479             if (result == Result.ACCEPT || result == Result.DENY) {
480                 return result;
481             }
482         }
483         return result;
484     }
485 
486     /**
487      * Filter an event.
488      *
489      * @param logger
490      *            The Logger.
491      * @param level
492      *            The event logging Level.
493      * @param marker
494      *            The Marker for the event or null.
495      * @param msg
496      *            String text to filter on.
497      * @param p0 the message parameters
498      * @param p1 the message parameters
499      * @param p2 the message parameters
500      * @param p3 the message parameters
501      * @param p4 the message parameters
502      * @param p5 the message parameters
503      * @param p6 the message parameters
504      * @param p7 the message parameters
505      * @param p8 the message parameters
506      * @param p9 the message parameters
507      * @return the Result.
508      */
509     @Override
510     public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
511             final Object p0, final Object p1, final Object p2, final Object p3,
512             final Object p4, final Object p5, final Object p6,
513             final Object p7, final Object p8, final Object p9) {
514         Result result = Result.NEUTRAL;
515         for (int i = 0; i < filters.length; i++) {
516             result = filters[i].filter(logger, level, marker, msg, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9);
517             if (result == Result.ACCEPT || result == Result.DENY) {
518                 return result;
519             }
520         }
521         return result;
522     }
523 
524     /**
525      * Filter an event.
526      *
527      * @param logger
528      *            The Logger.
529      * @param level
530      *            The event logging Level.
531      * @param marker
532      *            The Marker for the event or null.
533      * @param msg
534      *            Any Object.
535      * @param t
536      *            A Throwable or null.
537      * @return the Result.
538      */
539     @Override
540     public Result filter(final Logger logger, final Level level, final Marker marker, final Object msg,
541             final Throwable t) {
542         Result result = Result.NEUTRAL;
543         for (int i = 0; i < filters.length; i++) {
544             result = filters[i].filter(logger, level, marker, msg, t);
545             if (result == Result.ACCEPT || result == Result.DENY) {
546                 return result;
547             }
548         }
549         return result;
550     }
551 
552     /**
553      * Filter an event.
554      *
555      * @param logger
556      *            The Logger.
557      * @param level
558      *            The event logging Level.
559      * @param marker
560      *            The Marker for the event or null.
561      * @param msg
562      *            The Message
563      * @param t
564      *            A Throwable or null.
565      * @return the Result.
566      */
567     @Override
568     public Result filter(final Logger logger, final Level level, final Marker marker, final Message msg,
569             final Throwable t) {
570         Result result = Result.NEUTRAL;
571         for (int i = 0; i < filters.length; i++) {
572             result = filters[i].filter(logger, level, marker, msg, t);
573             if (result == Result.ACCEPT || result == Result.DENY) {
574                 return result;
575             }
576         }
577         return result;
578     }
579 
580     /**
581      * Filter an event.
582      *
583      * @param event
584      *            The Event to filter on.
585      * @return the Result.
586      */
587     @Override
588     public Result filter(final LogEvent event) {
589         Result result = Result.NEUTRAL;
590         for (int i = 0; i < filters.length; i++) {
591             result = filters[i].filter(event);
592             if (result == Result.ACCEPT || result == Result.DENY) {
593                 return result;
594             }
595         }
596         return result;
597     }
598 
599     @Override
600     public String toString() {
601         final StringBuilder sb = new StringBuilder();
602         for (int i = 0; i < filters.length; i++) {
603             if (sb.length() == 0) {
604                 sb.append('{');
605             } else {
606                 sb.append(", ");
607             }
608             sb.append(filters[i].toString());
609         }
610         if (sb.length() > 0) {
611             sb.append('}');
612         }
613         return sb.toString();
614     }
615 
616     /**
617      * Create a CompositeFilter.
618      *
619      * @param filters
620      *            An array of Filters to call.
621      * @return The CompositeFilter.
622      */
623     @PluginFactory
624     public static CompositeFilter createFilters(@PluginElement("Filters") final Filter[] filters) {
625         return new CompositeFilter(filters);
626     }
627 
628 }