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     */
017    package org.apache.logging.log4j.core.filter;
018    
019    import org.apache.logging.log4j.Level;
020    import org.apache.logging.log4j.Marker;
021    import org.apache.logging.log4j.core.Filter;
022    import org.apache.logging.log4j.core.LifeCycle;
023    import org.apache.logging.log4j.core.LogEvent;
024    import org.apache.logging.log4j.core.Logger;
025    import org.apache.logging.log4j.core.config.plugins.Plugin;
026    import org.apache.logging.log4j.core.config.plugins.PluginElement;
027    import org.apache.logging.log4j.core.config.plugins.PluginFactory;
028    import org.apache.logging.log4j.message.Message;
029    
030    import java.util.ArrayList;
031    import java.util.Arrays;
032    import java.util.Collections;
033    import java.util.Iterator;
034    import java.util.List;
035    
036    /**
037     * Composes and invokes one or more filters.
038     */
039    @Plugin(name = "filters", category = "Core", printObject = true)
040    public final class CompositeFilter implements Iterable<Filter>, Filter, LifeCycle {
041    
042        private final List<Filter> filters;
043        private final boolean hasFilters;
044    
045        private boolean isStarted;
046    
047        private CompositeFilter() {
048            this.filters = new ArrayList<Filter>();
049            this.hasFilters = false;
050        }
051    
052        private CompositeFilter(final List<Filter> filters) {
053            if (filters == null) {
054                this.filters = Collections.unmodifiableList(new ArrayList<Filter>());
055                this.hasFilters = false;
056                return;
057            }
058            this.filters = Collections.unmodifiableList(filters);
059            this.hasFilters = this.filters.size() > 0;
060        }
061    
062        public CompositeFilter addFilter(final Filter filter) {
063            final List<Filter> filters = new ArrayList<Filter>(this.filters);
064            filters.add(filter);
065            return new CompositeFilter(Collections.unmodifiableList(filters));
066        }
067    
068        public CompositeFilter removeFilter(final Filter filter) {
069            final List<Filter> filters = new ArrayList<Filter>(this.filters);
070            filters.remove(filter);
071            return new CompositeFilter(Collections.unmodifiableList(filters));
072        }
073    
074        @Override
075        public Iterator<Filter> iterator() {
076            return filters.iterator();
077        }
078    
079        public List<Filter> getFilters() {
080            return filters;
081        }
082    
083        public boolean hasFilters() {
084            return hasFilters;
085        }
086    
087        public int size() {
088            return filters.size();
089        }
090    
091        @Override
092        public void start() {
093            for (final Filter filter : filters) {
094                if (filter instanceof LifeCycle) {
095                    ((LifeCycle) filter).start();
096                }
097            }
098            isStarted = true;
099        }
100    
101        @Override
102        public void stop() {
103            for (final Filter filter : filters) {
104                if (filter instanceof LifeCycle) {
105                    ((LifeCycle) filter).stop();
106                }
107            }
108            isStarted = false;
109        }
110    
111        @Override
112        public boolean isStarted() {
113            return isStarted;
114        }
115    
116        /**
117         * Returns the result that should be returned when the filter does not match the event.
118         *
119         * @return the Result that should be returned when the filter does not match the event.
120         */
121        @Override
122        public Result getOnMismatch() {
123            return Result.NEUTRAL;
124        }
125    
126        /**
127         * Returns the result that should be returned when the filter matches the event.
128         *
129         * @return the Result that should be returned when the filter matches the event.
130         */
131        @Override
132        public Result getOnMatch() {
133            return Result.NEUTRAL;
134        }
135    
136        /**
137         * Filter an event.
138         *
139         * @param logger
140         *            The Logger.
141         * @param level
142         *            The event logging Level.
143         * @param marker
144         *            The Marker for the event or null.
145         * @param msg
146         *            String text to filter on.
147         * @param params
148         *            An array of parameters or null.
149         * @return the Result.
150         */
151        @Override
152        public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
153                             final Object... params) {
154            Result result = Result.NEUTRAL;
155            for (final Filter filter : filters) {
156                result = filter.filter(logger, level, marker, msg, params);
157                if (result == Result.ACCEPT || result == Result.DENY) {
158                    return result;
159                }
160            }
161            return result;
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         *            Any Object.
175         * @param t
176         *            A Throwable or null.
177         * @return the Result.
178         */
179        @Override
180        public Result filter(final Logger logger, final Level level, final Marker marker, final Object msg,
181                             final Throwable t) {
182            Result result = Result.NEUTRAL;
183            for (final Filter filter : filters) {
184                result = filter.filter(logger, level, marker, msg, t);
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         *            The Message
203         * @param t
204         *            A Throwable or null.
205         * @return the Result.
206         */
207        @Override
208        public Result filter(final Logger logger, final Level level, final Marker marker, final Message msg,
209                             final Throwable t) {
210            Result result = Result.NEUTRAL;
211            for (final Filter filter : filters) {
212                result = filter.filter(logger, level, marker, msg, t);
213                if (result == Result.ACCEPT || result == Result.DENY) {
214                    return result;
215                }
216            }
217            return result;
218        }
219    
220        /**
221         * Filter an event.
222         *
223         * @param event
224         *            The Event to filter on.
225         * @return the Result.
226         */
227        @Override
228        public Result filter(final LogEvent event) {
229            Result result = Result.NEUTRAL;
230            for (final Filter filter : filters) {
231                result = filter.filter(event);
232                if (result == Result.ACCEPT || result == Result.DENY) {
233                    return result;
234                }
235            }
236            return result;
237        }
238    
239        @Override
240        public String toString() {
241            final StringBuilder sb = new StringBuilder();
242            for (final Filter filter : filters) {
243                if (sb.length() == 0) {
244                    sb.append("{");
245                } else {
246                    sb.append(", ");
247                }
248                sb.append(filter.toString());
249            }
250            if (sb.length() > 0) {
251                sb.append("}");
252            }
253            return sb.toString();
254        }
255    
256        /**
257         * Create a CompositeFilter.
258         *
259         * @param filters
260         *            An array of Filters to call.
261         * @return The CompositeFilter.
262         */
263        @PluginFactory
264        public static CompositeFilter createFilters(@PluginElement("filters") final Filter[] filters) {
265            final List<Filter> f = filters == null || filters.length == 0 ?
266                new ArrayList<Filter>() : Arrays.asList(filters);
267            return new CompositeFilter(f);
268        }
269    
270    }