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.Node;
032    import org.apache.logging.log4j.core.config.plugins.Plugin;
033    import org.apache.logging.log4j.core.config.plugins.PluginElement;
034    import org.apache.logging.log4j.core.config.plugins.PluginFactory;
035    import 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)
041    public final class CompositeFilter extends AbstractLifeCycle implements Iterable<Filter>, Filter {
042    
043        private static final long serialVersionUID = 1L;
044    
045        private final List<Filter> filters;
046    
047        private CompositeFilter() {
048            this.filters = new ArrayList<Filter>();
049        }
050    
051        private CompositeFilter(final List<Filter> filters) {
052            if (filters == null) {
053                this.filters = Collections.unmodifiableList(new ArrayList<Filter>());
054                return;
055            }
056            this.filters = Collections.unmodifiableList(filters);
057        }
058    
059        public CompositeFilter addFilter(final Filter filter) {
060            if (filter == null) {
061                // null does nothing
062                return this;
063            }
064            final List<Filter> filterList = new ArrayList<Filter>(this.filters);
065            filterList.add(filter);
066            return new CompositeFilter(Collections.unmodifiableList(filterList));
067        }
068    
069        public CompositeFilter removeFilter(final Filter filter) {
070            if (filter == null) {
071                // null does nothing
072                return this;
073            }
074            final List<Filter> filterList = new ArrayList<Filter>(this.filters);
075            filterList.remove(filter);
076            return new CompositeFilter(Collections.unmodifiableList(filterList));
077        }
078    
079        @Override
080        public Iterator<Filter> iterator() {
081            return filters.iterator();
082        }
083    
084        public List<Filter> getFilters() {
085            return filters;
086        }
087    
088        /**
089         * Returns whether this composite contains any filters.
090         *
091         * @return whether this composite contains any filters.
092         */
093        public boolean isEmpty() {
094            return this.filters.isEmpty();
095        }
096    
097        public int size() {
098            return filters.size();
099        }
100    
101        @Override
102        public void start() {
103            this.setStarting();
104            for (final Filter filter : filters) {
105                filter.start();
106            }
107            this.setStarted();
108        }
109    
110        @Override
111        public void stop() {
112            this.setStopping();
113            for (final Filter filter : filters) {
114                filter.stop();
115            }
116            this.setStopped();
117        }
118    
119        /**
120         * Returns the result that should be returned when the filter does not match the event.
121         *
122         * @return the Result that should be returned when the filter does not match the event.
123         */
124        @Override
125        public Result getOnMismatch() {
126            return Result.NEUTRAL;
127        }
128    
129        /**
130         * Returns the result that should be returned when the filter matches the event.
131         *
132         * @return the Result that should be returned when the filter matches the event.
133         */
134        @Override
135        public Result getOnMatch() {
136            return Result.NEUTRAL;
137        }
138    
139        /**
140         * Filter an event.
141         *
142         * @param logger
143         *            The Logger.
144         * @param level
145         *            The event logging Level.
146         * @param marker
147         *            The Marker for the event or null.
148         * @param msg
149         *            String text to filter on.
150         * @param params
151         *            An array of parameters or null.
152         * @return the Result.
153         */
154        @Override
155        public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
156                             final Object... params) {
157            Result result = Result.NEUTRAL;
158            for (final Filter filter : filters) {
159                result = filter.filter(logger, level, marker, msg, params);
160                if (result == Result.ACCEPT || result == Result.DENY) {
161                    return result;
162                }
163            }
164            return result;
165        }
166    
167        /**
168         * Filter an event.
169         *
170         * @param logger
171         *            The Logger.
172         * @param level
173         *            The event logging Level.
174         * @param marker
175         *            The Marker for the event or null.
176         * @param msg
177         *            Any Object.
178         * @param t
179         *            A Throwable or null.
180         * @return the Result.
181         */
182        @Override
183        public Result filter(final Logger logger, final Level level, final Marker marker, final Object msg,
184                             final Throwable t) {
185            Result result = Result.NEUTRAL;
186            for (final Filter filter : filters) {
187                result = filter.filter(logger, level, marker, msg, t);
188                if (result == Result.ACCEPT || result == Result.DENY) {
189                    return result;
190                }
191            }
192            return result;
193        }
194    
195        /**
196         * Filter an event.
197         *
198         * @param logger
199         *            The Logger.
200         * @param level
201         *            The event logging Level.
202         * @param marker
203         *            The Marker for the event or null.
204         * @param msg
205         *            The Message
206         * @param t
207         *            A Throwable or null.
208         * @return the Result.
209         */
210        @Override
211        public Result filter(final Logger logger, final Level level, final Marker marker, final Message msg,
212                             final Throwable t) {
213            Result result = Result.NEUTRAL;
214            for (final Filter filter : filters) {
215                result = filter.filter(logger, level, marker, msg, t);
216                if (result == Result.ACCEPT || result == Result.DENY) {
217                    return result;
218                }
219            }
220            return result;
221        }
222    
223        /**
224         * Filter an event.
225         *
226         * @param event
227         *            The Event to filter on.
228         * @return the Result.
229         */
230        @Override
231        public Result filter(final LogEvent event) {
232            Result result = Result.NEUTRAL;
233            for (final Filter filter : filters) {
234                result = filter.filter(event);
235                if (result == Result.ACCEPT || result == Result.DENY) {
236                    return result;
237                }
238            }
239            return result;
240        }
241    
242        @Override
243        public String toString() {
244            final StringBuilder sb = new StringBuilder();
245            for (final Filter filter : filters) {
246                if (sb.length() == 0) {
247                    sb.append('{');
248                } else {
249                    sb.append(", ");
250                }
251                sb.append(filter.toString());
252            }
253            if (sb.length() > 0) {
254                sb.append('}');
255            }
256            return sb.toString();
257        }
258    
259        /**
260         * Create a CompositeFilter.
261         *
262         * @param filters
263         *            An array of Filters to call.
264         * @return The CompositeFilter.
265         */
266        @PluginFactory
267        public static CompositeFilter createFilters(@PluginElement("Filters") final Filter[] filters) {
268            final List<Filter> filterList = filters == null || filters.length == 0 ?
269                new ArrayList<Filter>() : Arrays.asList(filters);
270            return new CompositeFilter(filterList);
271        }
272    
273    }