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