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 java.util.ArrayList;
020    import java.util.Arrays;
021    import java.util.Collections;
022    import java.util.Iterator;
023    import java.util.List;
024    
025    import org.apache.logging.log4j.Level;
026    import org.apache.logging.log4j.Marker;
027    import org.apache.logging.log4j.core.AbstractLifeCycle;
028    import org.apache.logging.log4j.core.Filter;
029    import org.apache.logging.log4j.core.LogEvent;
030    import org.apache.logging.log4j.core.Logger;
031    import org.apache.logging.log4j.core.config.plugins.Plugin;
032    import org.apache.logging.log4j.core.config.plugins.PluginElement;
033    import org.apache.logging.log4j.core.config.plugins.PluginFactory;
034    import org.apache.logging.log4j.message.Message;
035    
036    /**
037     * Composes and invokes one or more filters.
038     */
039    @Plugin(name = "filters", category = "Core", printObject = true)
040    public final class CompositeFilter extends AbstractLifeCycle implements Iterable<Filter>, Filter {
041    
042        private final List<Filter> filters;
043    
044        private CompositeFilter() {
045            this.filters = new ArrayList<Filter>();
046        }
047    
048        private CompositeFilter(final List<Filter> filters) {
049            if (filters == null) {
050                this.filters = Collections.unmodifiableList(new ArrayList<Filter>());
051                return;
052            }
053            this.filters = Collections.unmodifiableList(filters);
054        }
055    
056        public CompositeFilter addFilter(final Filter filter) {
057            if (filter == null) {
058                // null does nothing
059                return this;
060            }
061            final List<Filter> filterList = new ArrayList<Filter>(this.filters);
062            filterList.add(filter);
063            return new CompositeFilter(Collections.unmodifiableList(filterList));
064        }
065    
066        public CompositeFilter removeFilter(final Filter filter) {
067            if (filter == null) {
068                // null does nothing
069                return this;
070            }
071            final List<Filter> filterList = new ArrayList<Filter>(this.filters);
072            filterList.remove(filter);
073            return new CompositeFilter(Collections.unmodifiableList(filterList));
074        }
075    
076        @Override
077        public Iterator<Filter> iterator() {
078            return filters.iterator();
079        }
080    
081        public List<Filter> getFilters() {
082            return filters;
083        }
084    
085        /**
086         * Returns whether this composite contains any filters.
087         * 
088         * @return whether this composite contains any filters.
089         */
090        public boolean isEmpty() {
091            return this.filters.isEmpty();
092        }
093    
094        public int size() {
095            return filters.size();
096        }
097    
098        @Override
099        public void start() {
100            this.setStarting();
101            for (final Filter filter : filters) {
102                filter.start();
103            }
104            this.setStarted();
105        }
106    
107        @Override
108        public void stop() {
109            this.setStopping();
110            for (final Filter filter : filters) {
111                filter.stop();
112            }
113            this.setStopped();
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> filterList = filters == null || filters.length == 0 ?
266                new ArrayList<Filter>() : Arrays.asList(filters);
267            return new CompositeFilter(filterList);
268        }
269    
270    }