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