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", type = "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(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(Filter filter) {
063            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(Filter filter) {
069            List<Filter> filters = new ArrayList<Filter>(this.filters);
070            filters.remove(filter);
071            return new CompositeFilter(Collections.unmodifiableList(filters));
072        }
073    
074        public Iterator<Filter> iterator() {
075            return filters.iterator();
076        }
077    
078        public List<Filter> getFilters() {
079            return filters;
080        }
081    
082        public boolean hasFilters() {
083            return hasFilters;
084        }
085    
086        public int size() {
087            return filters.size();
088        }
089    
090        public void start() {
091            for (Filter filter : filters) {
092                if (filter instanceof LifeCycle) {
093                    ((LifeCycle) filter).start();
094                }
095            }
096            isStarted = true;
097        }
098    
099        public void stop() {
100            for (Filter filter : filters) {
101                if (filter instanceof LifeCycle) {
102                    ((LifeCycle) filter).stop();
103                }
104            }
105            isStarted = false;
106        }
107    
108        public boolean isStarted() {
109            return isStarted;
110        }
111    
112        /**
113         * Returns the result that should be returned when the filter does not match the event.
114         * 
115         * @return the Result that should be returned when the filter does not match the event.
116         */
117        public Result getOnMismatch() {
118            return Result.NEUTRAL;
119        }
120    
121        /**
122         * Returns the result that should be returned when the filter matches the event.
123         * 
124         * @return the Result that should be returned when the filter matches the event.
125         */
126        public Result getOnMatch() {
127            return Result.NEUTRAL;
128        }
129    
130        /**
131         * Filter an event.
132         * 
133         * @param logger
134         *            The Logger.
135         * @param level
136         *            The event logging Level.
137         * @param marker
138         *            The Marker for the event or null.
139         * @param msg
140         *            String text to filter on.
141         * @param params
142         *            An array of parameters or null.
143         * @return the Result.
144         */
145        public Result filter(Logger logger, Level level, Marker marker, String msg, Object... params) {
146            Result result = Result.NEUTRAL;
147            for (Filter filter : filters) {
148                result = filter.filter(logger, level, marker, msg, params);
149                if (result == Result.ACCEPT || result == Result.DENY) {
150                    return result;
151                }
152            }
153            return result;
154        }
155    
156        /**
157         * Filter an event.
158         * 
159         * @param logger
160         *            The Logger.
161         * @param level
162         *            The event logging Level.
163         * @param marker
164         *            The Marker for the event or null.
165         * @param msg
166         *            Any Object.
167         * @param t
168         *            A Throwable or null.
169         * @return the Result.
170         */
171        public Result filter(Logger logger, Level level, Marker marker, Object msg, Throwable t) {
172            Result result = Result.NEUTRAL;
173            for (Filter filter : filters) {
174                result = filter.filter(logger, level, marker, msg, t);
175                if (result == Result.ACCEPT || result == Result.DENY) {
176                    return result;
177                }
178            }
179            return result;
180        }
181    
182        /**
183         * Filter an event.
184         * 
185         * @param logger
186         *            The Logger.
187         * @param level
188         *            The event logging Level.
189         * @param marker
190         *            The Marker for the event or null.
191         * @param msg
192         *            The Message
193         * @param t
194         *            A Throwable or null.
195         * @return the Result.
196         */
197        public Result filter(Logger logger, Level level, Marker marker, Message msg, Throwable t) {
198            Result result = Result.NEUTRAL;
199            for (Filter filter : filters) {
200                result = filter.filter(logger, level, marker, msg, t);
201                if (result == Result.ACCEPT || result == Result.DENY) {
202                    return result;
203                }
204            }
205            return result;
206        }
207    
208        /**
209         * Filter an event.
210         * 
211         * @param event
212         *            The Event to filter on.
213         * @return the Result.
214         */
215        public Result filter(LogEvent event) {
216            Result result = Result.NEUTRAL;
217            for (Filter filter : filters) {
218                result = filter.filter(event);
219                if (result == Result.ACCEPT || result == Result.DENY) {
220                    return result;
221                }
222            }
223            return result;
224        }
225    
226        @Override
227        public String toString() {
228            StringBuilder sb = new StringBuilder();
229            for (Filter filter : filters) {
230                if (sb.length() == 0) {
231                    sb.append("{");
232                } else {
233                    sb.append(", ");
234                }
235                sb.append(filter.toString());
236            }
237            if (sb.length() > 0) {
238                sb.append("}");
239            }
240            return sb.toString();
241        }
242    
243        /**
244         * Create a CompositeFilter.
245         * 
246         * @param filters
247         *            An array of Filters to call.
248         * @return The CompositeFilter.
249         */
250        @PluginFactory
251        public static CompositeFilter createFilters(@PluginElement("filters") Filter[] filters) {
252            List<Filter> f = filters == null || filters.length == 0 ? new ArrayList<Filter>() : Arrays.asList(filters);
253            return new CompositeFilter(f);
254        }
255    
256    }