#region Apache License // // Licensed to the Apache Software Foundation (ASF) under one or more // contributor license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright ownership. // The ASF licenses this file to you under the Apache License, Version 2.0 // (the "License"); you may not use this file except in compliance with // the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #endregion using System; using System.Collections; using System.IO; using log4net.Util; using log4net.Util.PatternStringConverters; using log4net.Core; namespace log4net.Util { /// /// This class implements a patterned string. /// /// /// /// This string has embedded patterns that are resolved and expanded /// when the string is formatted. /// /// /// This class functions similarly to the /// in that it accepts a pattern and renders it to a string. Unlike the /// however the PatternString /// does not render the properties of a specific but /// of the process in general. /// /// /// The recognized conversion pattern names are: /// /// /// /// Conversion Pattern Name /// Effect /// /// /// appdomain /// /// /// Used to output the friendly name of the current AppDomain. /// /// /// /// /// date /// /// /// Used to output the current date and time in the local time zone. /// To output the date in universal time use the %utcdate pattern. /// The date conversion /// specifier may be followed by a date format specifier enclosed /// between braces. For example, %date{HH:mm:ss,fff} or /// %date{dd MMM yyyy HH:mm:ss,fff}. If no date format specifier is /// given then ISO8601 format is /// assumed (). /// /// /// The date format specifier admits the same syntax as the /// time pattern string of the . /// /// /// For better results it is recommended to use the log4net date /// formatters. These can be specified using one of the strings /// "ABSOLUTE", "DATE" and "ISO8601" for specifying /// , /// and respectively /// . For example, /// %date{ISO8601} or %date{ABSOLUTE}. /// /// /// These dedicated date formatters perform significantly /// better than . /// /// /// /// /// env /// /// /// Used to output the a specific environment variable. The key to /// lookup must be specified within braces and directly following the /// pattern specifier, e.g. %env{COMPUTERNAME} would include the value /// of the COMPUTERNAME environment variable. /// /// /// The env pattern is not supported on the .NET Compact Framework. /// /// /// /// /// identity /// /// /// Used to output the user name for the currently active user /// (Principal.Identity.Name). /// /// /// /// /// newline /// /// /// Outputs the platform dependent line separator character or /// characters. /// /// /// This conversion pattern name offers the same performance as using /// non-portable line separator strings such as "\n", or "\r\n". /// Thus, it is the preferred way of specifying a line separator. /// /// /// /// /// processid /// /// /// Used to output the system process ID for the current process. /// /// /// /// /// property /// /// /// Used to output a specific context property. The key to /// lookup must be specified within braces and directly following the /// pattern specifier, e.g. %property{user} would include the value /// from the property that is keyed by the string 'user'. Each property value /// that is to be included in the log must be specified separately. /// Properties are stored in logging contexts. By default /// the log4net:HostName property is set to the name of machine on /// which the event was originally logged. /// /// /// If no key is specified, e.g. %property then all the keys and their /// values are printed in a comma separated list. /// /// /// The properties of an event are combined from a number of different /// contexts. These are listed below in the order in which they are searched. /// /// /// /// the thread properties /// /// The that are set on the current /// thread. These properties are shared by all events logged on this thread. /// /// /// /// the global properties /// /// The that are set globally. These /// properties are shared by all the threads in the AppDomain. /// /// /// /// /// /// /// random /// /// /// Used to output a random string of characters. The string is made up of /// uppercase letters and numbers. By default the string is 4 characters long. /// The length of the string can be specified within braces directly following the /// pattern specifier, e.g. %random{8} would output an 8 character string. /// /// /// /// /// username /// /// /// Used to output the WindowsIdentity for the currently /// active user. /// /// /// /// /// utcdate /// /// /// Used to output the date of the logging event in universal time. /// The date conversion /// specifier may be followed by a date format specifier enclosed /// between braces. For example, %utcdate{HH:mm:ss,fff} or /// %utcdate{dd MMM yyyy HH:mm:ss,fff}. If no date format specifier is /// given then ISO8601 format is /// assumed (). /// /// /// The date format specifier admits the same syntax as the /// time pattern string of the . /// /// /// For better results it is recommended to use the log4net date /// formatters. These can be specified using one of the strings /// "ABSOLUTE", "DATE" and "ISO8601" for specifying /// , /// and respectively /// . For example, /// %utcdate{ISO8601} or %utcdate{ABSOLUTE}. /// /// /// These dedicated date formatters perform significantly /// better than . /// /// /// /// /// % /// /// /// The sequence %% outputs a single percent sign. /// /// /// /// /// /// Additional pattern converters may be registered with a specific /// instance using or /// . /// /// /// See the for details on the /// format modifiers supported by the patterns. /// /// /// Nicko Cadell public class PatternString : IOptionHandler { #region Static Fields /// /// Internal map of converter identifiers to converter types. /// private static Hashtable s_globalRulesRegistry; #endregion Static Fields #region Member Variables /// /// the pattern /// private string m_pattern; /// /// the head of the pattern converter chain /// private PatternConverter m_head; /// /// patterns defined on this PatternString only /// private Hashtable m_instanceRulesRegistry = new Hashtable(); #endregion #region Static Constructor /// /// Initialize the global registry /// static PatternString() { s_globalRulesRegistry = new Hashtable(15); s_globalRulesRegistry.Add("appdomain", typeof(AppDomainPatternConverter)); s_globalRulesRegistry.Add("date", typeof(DatePatternConverter)); #if !NETCF s_globalRulesRegistry.Add("env", typeof(EnvironmentPatternConverter)); s_globalRulesRegistry.Add("envFolderPath", typeof(EnvironmentFolderPathPatternConverter)); #endif s_globalRulesRegistry.Add("identity", typeof(IdentityPatternConverter)); s_globalRulesRegistry.Add("literal", typeof(LiteralPatternConverter)); s_globalRulesRegistry.Add("newline", typeof(NewLinePatternConverter)); s_globalRulesRegistry.Add("processid", typeof(ProcessIdPatternConverter)); s_globalRulesRegistry.Add("property", typeof(PropertyPatternConverter)); s_globalRulesRegistry.Add("random", typeof(RandomStringPatternConverter)); s_globalRulesRegistry.Add("username", typeof(UserNamePatternConverter)); s_globalRulesRegistry.Add("utcdate", typeof(UtcDatePatternConverter)); s_globalRulesRegistry.Add("utcDate", typeof(UtcDatePatternConverter)); s_globalRulesRegistry.Add("UtcDate", typeof(UtcDatePatternConverter)); } #endregion Static Constructor #region Constructors /// /// Default constructor /// /// /// /// Initialize a new instance of /// /// public PatternString() { } /// /// Constructs a PatternString /// /// The pattern to use with this PatternString /// /// /// Initialize a new instance of with the pattern specified. /// /// public PatternString(string pattern) { m_pattern = pattern; ActivateOptions(); } #endregion /// /// Gets or sets the pattern formatting string /// /// /// The pattern formatting string /// /// /// /// The ConversionPattern option. This is the string which /// controls formatting and consists of a mix of literal content and /// conversion specifiers. /// /// public string ConversionPattern { get { return m_pattern; } set { m_pattern = value; } } #region Implementation of IOptionHandler /// /// Initialize object options /// /// /// /// This is part of the delayed object /// activation scheme. The method must /// be called on this object after the configuration properties have /// been set. Until is called this /// object is in an undefined state and must not be used. /// /// /// If any of the configuration properties are modified then /// must be called again. /// /// virtual public void ActivateOptions() { m_head = CreatePatternParser(m_pattern).Parse(); } #endregion /// /// Create the used to parse the pattern /// /// the pattern to parse /// The /// /// /// Returns PatternParser used to parse the conversion string. Subclasses /// may override this to return a subclass of PatternParser which recognize /// custom conversion pattern name. /// /// private PatternParser CreatePatternParser(string pattern) { PatternParser patternParser = new PatternParser(pattern); // Add all the builtin patterns foreach(DictionaryEntry entry in s_globalRulesRegistry) { ConverterInfo converterInfo = new ConverterInfo(); converterInfo.Name = (string)entry.Key; converterInfo.Type = (Type)entry.Value; patternParser.PatternConverters.Add(entry.Key, converterInfo); } // Add the instance patterns foreach(DictionaryEntry entry in m_instanceRulesRegistry) { patternParser.PatternConverters[entry.Key] = entry.Value; } return patternParser; } /// /// Produces a formatted string as specified by the conversion pattern. /// /// The TextWriter to write the formatted event to /// /// /// Format the pattern to the . /// /// public void Format(TextWriter writer) { if (writer == null) { throw new ArgumentNullException("writer"); } PatternConverter c = m_head; // loop through the chain of pattern converters while(c != null) { c.Format(writer, null); c = c.Next; } } /// /// Format the pattern as a string /// /// the pattern formatted as a string /// /// /// Format the pattern to a string. /// /// public string Format() { StringWriter writer = new StringWriter(System.Globalization.CultureInfo.InvariantCulture); Format(writer); return writer.ToString(); } /// /// Add a converter to this PatternString /// /// the converter info /// /// /// This version of the method is used by the configurator. /// Programmatic users should use the alternative method. /// /// public void AddConverter(ConverterInfo converterInfo) { if (converterInfo == null) throw new ArgumentNullException("converterInfo"); if (!typeof(PatternConverter).IsAssignableFrom(converterInfo.Type)) { throw new ArgumentException("The converter type specified [" + converterInfo.Type + "] must be a subclass of log4net.Util.PatternConverter", "converterInfo"); } m_instanceRulesRegistry[converterInfo.Name] = converterInfo; } /// /// Add a converter to this PatternString /// /// the name of the conversion pattern for this converter /// the type of the converter /// /// /// Add a converter to this PatternString /// /// public void AddConverter(string name, Type type) { if (name == null) throw new ArgumentNullException("name"); if (type == null) throw new ArgumentNullException("type"); ConverterInfo converterInfo = new ConverterInfo(); converterInfo.Name = name; converterInfo.Type = type; AddConverter(converterInfo); } } }