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.LogEvent;
022    import org.apache.logging.log4j.core.Logger;
023    import org.apache.logging.log4j.core.config.plugins.Plugin;
024    import org.apache.logging.log4j.core.config.plugins.PluginAttr;
025    import org.apache.logging.log4j.core.config.plugins.PluginFactory;
026    import org.apache.logging.log4j.message.Message;
027    
028    import java.util.Locale;
029    import java.util.regex.Matcher;
030    import java.util.regex.Pattern;
031    
032    /**
033     * This filter returns the onMatch result if the message matches the regular expression.
034     *
035     * The "useRawMsg" attribute can be used to indicate whether the regular expression should be
036     * applied to the result of calling Message.getMessageFormat (true) or Message.getFormattedMessage()
037     * (false). The default is false.
038     *
039     */
040    @Plugin(name = "RegexFilter", type = "Core", elementType = "filter", printObject = true)
041    public final class RegexFilter extends AbstractFilter {
042    
043        private final Pattern pattern;
044        private final boolean useRawMessage;
045    
046        private RegexFilter(boolean raw, Pattern pattern, Result onMatch, Result onMismatch) {
047            super(onMatch, onMismatch);
048            this.pattern = pattern;
049            this.useRawMessage = raw;
050        }
051    
052        @Override
053        public Result filter(Logger logger, Level level, Marker marker, String msg, Object[] params) {
054            return filter(msg);
055        }
056    
057        @Override
058        public Result filter(Logger logger, Level level, Marker marker, Object msg, Throwable t) {
059            return filter(msg.toString());
060        }
061    
062        @Override
063        public Result filter(Logger logger, Level level, Marker marker, Message msg, Throwable t) {
064            String text = useRawMessage ? msg.getFormat() : msg.getFormattedMessage();
065            return filter(text);
066        }
067    
068        @Override
069        public Result filter(LogEvent event) {
070            String text = useRawMessage ? event.getMessage().getFormat() : event.getMessage().getFormattedMessage();
071            return filter(text);
072        }
073    
074        private Result filter(String msg) {
075            if (msg == null) {
076                return onMismatch;
077            }
078            Matcher m = pattern.matcher(msg);
079            return m.matches() ? onMatch : onMismatch;
080        }
081    
082        @Override
083        public String toString() {
084            StringBuilder sb = new StringBuilder();
085            sb.append("useRaw=").append(useRawMessage);
086            sb.append(", pattern=").append(pattern.toString());
087            return sb.toString();
088        }
089    
090        /**
091         * Create a Filter that matches a regular expression.
092         * @param regex The regular expression to match.
093         * @param useRawMsg If true, the raw message will be used, otherwise the formatted message will be used.
094         * @param match The action to perform when a match occurs.
095         * @param mismatch The action to perform when a mismatch occurs.
096         * @return The RegexFilter.
097         */
098        @PluginFactory
099        public static RegexFilter createFilter(@PluginAttr("regex") String regex,
100                                               @PluginAttr("useRawMsg") String useRawMsg,
101                                                @PluginAttr("onMatch") String match,
102                                                @PluginAttr("onMismatch") String mismatch) {
103    
104            if (regex == null) {
105                LOGGER.error("A regular expression must be provided for RegexFilter");
106                return null;
107            }
108            boolean raw = useRawMsg == null ? false : Boolean.parseBoolean(useRawMsg);
109            Pattern pattern;
110            try {
111                pattern = Pattern.compile(regex);
112            } catch (Exception ex) {
113                LOGGER.error("RegexFilter caught exception compiling pattern: " + regex + " cause: " + ex.getMessage());
114                return null;
115            }
116            Result onMatch = Result.toResult(match);
117            Result onMismatch = Result.toResult(mismatch);
118    
119            return new RegexFilter(raw, pattern, onMatch, onMismatch);
120        }
121    
122    }