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