1 #region Copyright & License 2 // 3 // Copyright 2001-2005 The Apache Software Foundation 4 // 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 // 17 #endregion 18 19 using System; 20 using System.Text.RegularExpressions; 21 22 using log4net; 23 using log4net.Core; 24 using log4net.Util; 25 26 namespace log4net.Filter 27 { 28 /// <summary> 29 /// Simple filter to match a string in the rendered message 30 /// </summary> 31 /// <remarks> 32 /// <para> 33 /// Simple filter to match a string in the rendered message 34 /// </para> 35 /// </remarks> 36 /// <author>Nicko Cadell</author> 37 /// <author>Gert Driesen</author> 38 public class StringMatchFilter : FilterSkeleton 39 { 40 #region Member Variables 41 42 /// <summary> 43 /// Flag to indicate the behavior when we have a match 44 /// </summary> 45 protected bool m_acceptOnMatch = true; 46 47 /// <summary> 48 /// The string to substring match against the message 49 /// </summary> 50 protected string m_stringToMatch; 51 52 /// <summary> 53 /// A string regex to match 54 /// </summary> 55 protected string m_stringRegexToMatch; 56 57 /// <summary> 58 /// A regex object to match (generated from m_stringRegexToMatch) 59 /// </summary> 60 protected Regex m_regexToMatch; 61 62 #endregion 63 64 #region Constructors 65 66 /// <summary> 67 /// Default constructor 68 /// </summary> StringMatchFilter()69 public StringMatchFilter() 70 { 71 } 72 73 #endregion 74 75 #region Implementation of IOptionHandler 76 77 /// <summary> 78 /// Initialize and precompile the Regex if required 79 /// </summary> 80 /// <remarks> 81 /// <para> 82 /// This is part of the <see cref="IOptionHandler"/> delayed object 83 /// activation scheme. The <see cref="ActivateOptions"/> method must 84 /// be called on this object after the configuration properties have 85 /// been set. Until <see cref="ActivateOptions"/> is called this 86 /// object is in an undefined state and must not be used. 87 /// </para> 88 /// <para> 89 /// If any of the configuration properties are modified then 90 /// <see cref="ActivateOptions"/> must be called again. 91 /// </para> 92 /// </remarks> ActivateOptions()93 override public void ActivateOptions() 94 { 95 if (m_stringRegexToMatch != null) 96 { 97 m_regexToMatch = new Regex(m_stringRegexToMatch, RegexOptions.Compiled); 98 } 99 } 100 101 #endregion 102 103 /// <summary> 104 /// <see cref="FilterDecision.Accept"/> when matching <see cref="StringToMatch"/> or <see cref="RegexToMatch"/> 105 /// </summary> 106 /// <remarks> 107 /// <para> 108 /// The <see cref="AcceptOnMatch"/> property is a flag that determines 109 /// the behavior when a matching <see cref="Level"/> is found. If the 110 /// flag is set to true then the filter will <see cref="FilterDecision.Accept"/> the 111 /// logging event, otherwise it will <see cref="FilterDecision.Neutral"/> the event. 112 /// </para> 113 /// <para> 114 /// The default is <c>true</c> i.e. to <see cref="FilterDecision.Accept"/> the event. 115 /// </para> 116 /// </remarks> 117 public bool AcceptOnMatch 118 { 119 get { return m_acceptOnMatch; } 120 set { m_acceptOnMatch = value; } 121 } 122 123 /// <summary> 124 /// Sets the static string to match 125 /// </summary> 126 /// <remarks> 127 /// <para> 128 /// The string that will be substring matched against 129 /// the rendered message. If the message contains this 130 /// string then the filter will match. If a match is found then 131 /// the result depends on the value of <see cref="AcceptOnMatch"/>. 132 /// </para> 133 /// <para> 134 /// One of <see cref="StringToMatch"/> or <see cref="RegexToMatch"/> 135 /// must be specified. 136 /// </para> 137 /// </remarks> 138 public string StringToMatch 139 { 140 get { return m_stringToMatch; } 141 set { m_stringToMatch = value; } 142 } 143 144 /// <summary> 145 /// Sets the regular expression to match 146 /// </summary> 147 /// <remarks> 148 /// <para> 149 /// The regular expression pattern that will be matched against 150 /// the rendered message. If the message matches this 151 /// pattern then the filter will match. If a match is found then 152 /// the result depends on the value of <see cref="AcceptOnMatch"/>. 153 /// </para> 154 /// <para> 155 /// One of <see cref="StringToMatch"/> or <see cref="RegexToMatch"/> 156 /// must be specified. 157 /// </para> 158 /// </remarks> 159 public string RegexToMatch 160 { 161 get { return m_stringRegexToMatch; } 162 set { m_stringRegexToMatch = value; } 163 } 164 165 #region Override implementation of FilterSkeleton 166 167 /// <summary> 168 /// Check if this filter should allow the event to be logged 169 /// </summary> 170 /// <param name="loggingEvent">the event being logged</param> 171 /// <returns>see remarks</returns> 172 /// <remarks> 173 /// <para> 174 /// The rendered message is matched against the <see cref="StringToMatch"/>. 175 /// If the <see cref="StringToMatch"/> occurs as a substring within 176 /// the message then a match will have occurred. If no match occurs 177 /// this function will return <see cref="FilterDecision.Neutral"/> 178 /// allowing other filters to check the event. If a match occurs then 179 /// the value of <see cref="AcceptOnMatch"/> is checked. If it is 180 /// true then <see cref="FilterDecision.Accept"/> is returned otherwise 181 /// <see cref="FilterDecision.Deny"/> is returned. 182 /// </para> 183 /// </remarks> Decide(LoggingEvent loggingEvent)184 override public FilterDecision Decide(LoggingEvent loggingEvent) 185 { 186 if (loggingEvent == null) 187 { 188 throw new ArgumentNullException("loggingEvent"); 189 } 190 191 string msg = loggingEvent.RenderedMessage; 192 193 // Check if we have been setup to filter 194 if (msg == null || (m_stringToMatch == null && m_regexToMatch == null)) 195 { 196 // We cannot filter so allow the filter chain 197 // to continue processing 198 return FilterDecision.Neutral; 199 } 200 201 // Firstly check if we are matching using a regex 202 if (m_regexToMatch != null) 203 { 204 // Check the regex 205 if (m_regexToMatch.Match(msg).Success == false) 206 { 207 // No match, continue processing 208 return FilterDecision.Neutral; 209 } 210 211 // we've got a match 212 if (m_acceptOnMatch) 213 { 214 return FilterDecision.Accept; 215 } 216 return FilterDecision.Deny; 217 } 218 else if (m_stringToMatch != null) 219 { 220 // Check substring match 221 if (msg.IndexOf(m_stringToMatch) == -1) 222 { 223 // No match, continue processing 224 return FilterDecision.Neutral; 225 } 226 227 // we've got a match 228 if (m_acceptOnMatch) 229 { 230 return FilterDecision.Accept; 231 } 232 return FilterDecision.Deny; 233 } 234 return FilterDecision.Neutral; 235 236 } 237 238 #endregion 239 } 240 } 241