001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache license, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the license for the specific language governing permissions and
015 * limitations under the license.
016 */
017package org.apache.logging.log4j.core.filter;
018
019import java.util.Arrays;
020import java.util.Iterator;
021import java.util.List;
022
023import org.apache.logging.log4j.Level;
024import org.apache.logging.log4j.Marker;
025import org.apache.logging.log4j.core.AbstractLifeCycle;
026import org.apache.logging.log4j.core.Filter;
027import org.apache.logging.log4j.core.LogEvent;
028import org.apache.logging.log4j.core.Logger;
029import org.apache.logging.log4j.core.config.Node;
030import org.apache.logging.log4j.core.config.plugins.Plugin;
031import org.apache.logging.log4j.core.config.plugins.PluginElement;
032import org.apache.logging.log4j.core.config.plugins.PluginFactory;
033import org.apache.logging.log4j.core.util.ObjectArrayIterator;
034import org.apache.logging.log4j.message.Message;
035
036/**
037 * Composes and invokes one or more filters.
038 */
039@Plugin(name = "filters", category = Node.CATEGORY, printObject = true)
040public final class CompositeFilter extends AbstractLifeCycle implements Iterable<Filter>, Filter {
041
042    private static final Filter[] EMPTY_FILTERS = new Filter[0];
043    private final Filter[] filters;
044
045    private CompositeFilter() {
046        this.filters = EMPTY_FILTERS;
047    }
048
049    private CompositeFilter(final Filter[] filters) {
050        this.filters = filters == null ? EMPTY_FILTERS : filters;
051    }
052
053    public CompositeFilter addFilter(final Filter filter) {
054        if (filter == null) {
055            // null does nothing
056            return this;
057        }
058        final Filter[] copy = Arrays.copyOf(this.filters, this.filters.length + 1);
059        copy[this.filters.length] = filter;
060        return new CompositeFilter(copy);
061    }
062
063    public CompositeFilter removeFilter(final Filter filter) {
064        if (filter == null) {
065            // null does nothing
066            return this;
067        }
068        // This is not a great implementation but simpler than copying Apache Commons
069        // Lang ArrayUtils.removeElement() and associated bits (MutableInt),
070        // which is OK since removing a filter should not be on the critical path.
071        final List<Filter> filterList = Arrays.asList(this.filters);
072        filterList.remove(filter);
073        return new CompositeFilter(filterList.toArray(new Filter[this.filters.length - 1]));
074    }
075
076    @Override
077    public Iterator<Filter> iterator() {
078        return new ObjectArrayIterator<>(filters);
079    }
080
081    /**
082     * Gets a new list over the internal filter array.
083     *
084     * @return a new list over the internal filter array
085     * @deprecated Use {@link #getFiltersArray()}
086     */
087    @Deprecated
088    public List<Filter> getFilters() {
089        return Arrays.asList(filters);
090    }
091
092    public Filter[] getFiltersArray() {
093        return filters;
094    }
095
096    /**
097     * Returns whether this composite contains any filters.
098     *
099     * @return whether this composite contains any filters.
100     */
101    public boolean isEmpty() {
102        return this.filters.length == 0;
103    }
104
105    public int size() {
106        return filters.length;
107    }
108
109    @Override
110    public void start() {
111        this.setStarting();
112        for (final Filter filter : filters) {
113            filter.start();
114        }
115        this.setStarted();
116    }
117
118    @Override
119    public void stop() {
120        this.setStopping();
121        for (final Filter filter : filters) {
122            filter.stop();
123        }
124        this.setStopped();
125    }
126
127    /**
128     * Returns the result that should be returned when the filter does not match the event.
129     *
130     * @return the Result that should be returned when the filter does not match the event.
131     */
132    @Override
133    public Result getOnMismatch() {
134        return Result.NEUTRAL;
135    }
136
137    /**
138     * Returns the result that should be returned when the filter matches the event.
139     *
140     * @return the Result that should be returned when the filter matches the event.
141     */
142    @Override
143    public Result getOnMatch() {
144        return Result.NEUTRAL;
145    }
146
147    /**
148     * Filter an event.
149     *
150     * @param logger
151     *            The Logger.
152     * @param level
153     *            The event logging Level.
154     * @param marker
155     *            The Marker for the event or null.
156     * @param msg
157     *            String text to filter on.
158     * @param params
159     *            An array of parameters or null.
160     * @return the Result.
161     */
162    @Override
163    public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
164            final Object... params) {
165        Result result = Result.NEUTRAL;
166        for (int i = 0; i < filters.length; i++) {
167            result = filters[i].filter(logger, level, marker, msg, params);
168            if (result == Result.ACCEPT || result == Result.DENY) {
169                return result;
170            }
171        }
172        return result;
173    }
174
175    /**
176     * Filter an event.
177     *
178     * @param logger
179     *            The Logger.
180     * @param level
181     *            The event logging Level.
182     * @param marker
183     *            The Marker for the event or null.
184     * @param msg
185     *            String text to filter on.
186     * @param p0 the message parameters
187     * @return the Result.
188     */
189    @Override
190    public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
191            final Object p0) {
192        Result result = Result.NEUTRAL;
193        for (int i = 0; i < filters.length; i++) {
194            result = filters[i].filter(logger, level, marker, msg, p0);
195            if (result == Result.ACCEPT || result == Result.DENY) {
196                return result;
197            }
198        }
199        return result;
200    }
201
202    /**
203     * Filter an event.
204     *
205     * @param logger
206     *            The Logger.
207     * @param level
208     *            The event logging Level.
209     * @param marker
210     *            The Marker for the event or null.
211     * @param msg
212     *            String text to filter on.
213     * @param p0 the message parameters
214     * @param p1 the message parameters
215     * @return the Result.
216     */
217    @Override
218    public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
219            final Object p0, final Object p1) {
220        Result result = Result.NEUTRAL;
221        for (int i = 0; i < filters.length; i++) {
222            result = filters[i].filter(logger, level, marker, msg, p0, p1);
223            if (result == Result.ACCEPT || result == Result.DENY) {
224                return result;
225            }
226        }
227        return result;
228    }
229
230    /**
231     * Filter an event.
232     *
233     * @param logger
234     *            The Logger.
235     * @param level
236     *            The event logging Level.
237     * @param marker
238     *            The Marker for the event or null.
239     * @param msg
240     *            String text to filter on.
241     * @param p0 the message parameters
242     * @param p1 the message parameters
243     * @param p2 the message parameters
244     * @return the Result.
245     */
246    @Override
247    public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
248            final Object p0, final Object p1, final Object p2) {
249        Result result = Result.NEUTRAL;
250        for (int i = 0; i < filters.length; i++) {
251            result = filters[i].filter(logger, level, marker, msg, p0, p1, p2);
252            if (result == Result.ACCEPT || result == Result.DENY) {
253                return result;
254            }
255        }
256        return result;
257    }
258
259    /**
260     * Filter an event.
261     *
262     * @param logger
263     *            The Logger.
264     * @param level
265     *            The event logging Level.
266     * @param marker
267     *            The Marker for the event or null.
268     * @param msg
269     *            String text to filter on.
270     * @param p0 the message parameters
271     * @param p1 the message parameters
272     * @param p2 the message parameters
273     * @param p3 the message parameters
274     * @return the Result.
275     */
276    @Override
277    public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
278            final Object p0, final Object p1, final Object p2, final Object p3) {
279        Result result = Result.NEUTRAL;
280        for (int i = 0; i < filters.length; i++) {
281            result = filters[i].filter(logger, level, marker, msg, p0, p1, p2, p3);
282            if (result == Result.ACCEPT || result == Result.DENY) {
283                return result;
284            }
285        }
286        return result;
287    }
288
289    /**
290     * Filter an event.
291     *
292     * @param logger
293     *            The Logger.
294     * @param level
295     *            The event logging Level.
296     * @param marker
297     *            The Marker for the event or null.
298     * @param msg
299     *            String text to filter on.
300     * @param p0 the message parameters
301     * @param p1 the message parameters
302     * @param p2 the message parameters
303     * @param p3 the message parameters
304     * @param p4 the message parameters
305     * @return the Result.
306     */
307    @Override
308    public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
309            final Object p0, final Object p1, final Object p2, final Object p3,
310            final Object p4) {
311        Result result = Result.NEUTRAL;
312        for (int i = 0; i < filters.length; i++) {
313            result = filters[i].filter(logger, level, marker, msg, p0, p1, p2, p3, p4);
314            if (result == Result.ACCEPT || result == Result.DENY) {
315                return result;
316            }
317        }
318        return result;
319    }
320
321    /**
322     * Filter an event.
323     *
324     * @param logger
325     *            The Logger.
326     * @param level
327     *            The event logging Level.
328     * @param marker
329     *            The Marker for the event or null.
330     * @param msg
331     *            String text to filter on.
332     * @param p0 the message parameters
333     * @param p1 the message parameters
334     * @param p2 the message parameters
335     * @param p3 the message parameters
336     * @param p4 the message parameters
337     * @param p5 the message parameters
338     * @return the Result.
339     */
340    @Override
341    public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
342            final Object p0, final Object p1, final Object p2, final Object p3,
343            final Object p4, final Object p5) {
344        Result result = Result.NEUTRAL;
345        for (int i = 0; i < filters.length; i++) {
346            result = filters[i].filter(logger, level, marker, msg, p0, p1, p2, p3, p4, p5);
347            if (result == Result.ACCEPT || result == Result.DENY) {
348                return result;
349            }
350        }
351        return result;
352    }
353
354    /**
355     * Filter an event.
356     *
357     * @param logger
358     *            The Logger.
359     * @param level
360     *            The event logging Level.
361     * @param marker
362     *            The Marker for the event or null.
363     * @param msg
364     *            String text to filter on.
365     * @param p0 the message parameters
366     * @param p1 the message parameters
367     * @param p2 the message parameters
368     * @param p3 the message parameters
369     * @param p4 the message parameters
370     * @param p5 the message parameters
371     * @param p6 the message parameters
372     * @return the Result.
373     */
374    @Override
375    public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
376            final Object p0, final Object p1, final Object p2, final Object p3,
377            final Object p4, final Object p5, final Object p6) {
378        Result result = Result.NEUTRAL;
379        for (int i = 0; i < filters.length; i++) {
380            result = filters[i].filter(logger, level, marker, msg, p0, p1, p2, p3, p4, p5, p6);
381            if (result == Result.ACCEPT || result == Result.DENY) {
382                return result;
383            }
384        }
385        return result;
386    }
387
388    /**
389     * Filter an event.
390     *
391     * @param logger
392     *            The Logger.
393     * @param level
394     *            The event logging Level.
395     * @param marker
396     *            The Marker for the event or null.
397     * @param msg
398     *            String text to filter on.
399     * @param p0 the message parameters
400     * @param p1 the message parameters
401     * @param p2 the message parameters
402     * @param p3 the message parameters
403     * @param p4 the message parameters
404     * @param p5 the message parameters
405     * @param p6 the message parameters
406     * @param p7 the message parameters
407     * @return the Result.
408     */
409    @Override
410    public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
411            final Object p0, final Object p1, final Object p2, final Object p3,
412            final Object p4, final Object p5, final Object p6,
413            final Object p7) {
414        Result result = Result.NEUTRAL;
415        for (int i = 0; i < filters.length; i++) {
416            result = filters[i].filter(logger, level, marker, msg, p0, p1, p2, p3, p4, p5, p6, p7);
417            if (result == Result.ACCEPT || result == Result.DENY) {
418                return result;
419            }
420        }
421        return result;
422    }
423
424    /**
425     * Filter an event.
426     *
427     * @param logger
428     *            The Logger.
429     * @param level
430     *            The event logging Level.
431     * @param marker
432     *            The Marker for the event or null.
433     * @param msg
434     *            String text to filter on.
435     * @param p0 the message parameters
436     * @param p1 the message parameters
437     * @param p2 the message parameters
438     * @param p3 the message parameters
439     * @param p4 the message parameters
440     * @param p5 the message parameters
441     * @param p6 the message parameters
442     * @param p7 the message parameters
443     * @param p8 the message parameters
444     * @return the Result.
445     */
446    @Override
447    public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
448            final Object p0, final Object p1, final Object p2, final Object p3,
449            final Object p4, final Object p5, final Object p6,
450            final Object p7, final Object p8) {
451        Result result = Result.NEUTRAL;
452        for (int i = 0; i < filters.length; i++) {
453            result = filters[i].filter(logger, level, marker, msg, p0, p1, p2, p3, p4, p5, p6, p7, p8);
454            if (result == Result.ACCEPT || result == Result.DENY) {
455                return result;
456            }
457        }
458        return result;
459    }
460
461    /**
462     * Filter an event.
463     *
464     * @param logger
465     *            The Logger.
466     * @param level
467     *            The event logging Level.
468     * @param marker
469     *            The Marker for the event or null.
470     * @param msg
471     *            String text to filter on.
472     * @param p0 the message parameters
473     * @param p1 the message parameters
474     * @param p2 the message parameters
475     * @param p3 the message parameters
476     * @param p4 the message parameters
477     * @param p5 the message parameters
478     * @param p6 the message parameters
479     * @param p7 the message parameters
480     * @param p8 the message parameters
481     * @param p9 the message parameters
482     * @return the Result.
483     */
484    @Override
485    public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
486            final Object p0, final Object p1, final Object p2, final Object p3,
487            final Object p4, final Object p5, final Object p6,
488            final Object p7, final Object p8, final Object p9) {
489        Result result = Result.NEUTRAL;
490        for (int i = 0; i < filters.length; i++) {
491            result = filters[i].filter(logger, level, marker, msg, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9);
492            if (result == Result.ACCEPT || result == Result.DENY) {
493                return result;
494            }
495        }
496        return result;
497    }
498
499    /**
500     * Filter an event.
501     *
502     * @param logger
503     *            The Logger.
504     * @param level
505     *            The event logging Level.
506     * @param marker
507     *            The Marker for the event or null.
508     * @param msg
509     *            Any Object.
510     * @param t
511     *            A Throwable or null.
512     * @return the Result.
513     */
514    @Override
515    public Result filter(final Logger logger, final Level level, final Marker marker, final Object msg,
516            final Throwable t) {
517        Result result = Result.NEUTRAL;
518        for (int i = 0; i < filters.length; i++) {
519            result = filters[i].filter(logger, level, marker, msg, t);
520            if (result == Result.ACCEPT || result == Result.DENY) {
521                return result;
522            }
523        }
524        return result;
525    }
526
527    /**
528     * Filter an event.
529     *
530     * @param logger
531     *            The Logger.
532     * @param level
533     *            The event logging Level.
534     * @param marker
535     *            The Marker for the event or null.
536     * @param msg
537     *            The Message
538     * @param t
539     *            A Throwable or null.
540     * @return the Result.
541     */
542    @Override
543    public Result filter(final Logger logger, final Level level, final Marker marker, final Message msg,
544            final Throwable t) {
545        Result result = Result.NEUTRAL;
546        for (int i = 0; i < filters.length; i++) {
547            result = filters[i].filter(logger, level, marker, msg, t);
548            if (result == Result.ACCEPT || result == Result.DENY) {
549                return result;
550            }
551        }
552        return result;
553    }
554
555    /**
556     * Filter an event.
557     *
558     * @param event
559     *            The Event to filter on.
560     * @return the Result.
561     */
562    @Override
563    public Result filter(final LogEvent event) {
564        Result result = Result.NEUTRAL;
565        for (int i = 0; i < filters.length; i++) {
566            result = filters[i].filter(event);
567            if (result == Result.ACCEPT || result == Result.DENY) {
568                return result;
569            }
570        }
571        return result;
572    }
573
574    @Override
575    public String toString() {
576        final StringBuilder sb = new StringBuilder();
577        for (int i = 0; i < filters.length; i++) {
578            if (sb.length() == 0) {
579                sb.append('{');
580            } else {
581                sb.append(", ");
582            }
583            sb.append(filters[i].toString());
584        }
585        if (sb.length() > 0) {
586            sb.append('}');
587        }
588        return sb.toString();
589    }
590
591    /**
592     * Create a CompositeFilter.
593     *
594     * @param filters
595     *            An array of Filters to call.
596     * @return The CompositeFilter.
597     */
598    @PluginFactory
599    public static CompositeFilter createFilters(@PluginElement("Filters") final Filter[] filters) {
600        return new CompositeFilter(filters);
601    }
602
603}