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