📄 xmlhierarchyconfigurator.cs
字号:
#region Copyright & License
//
// Copyright 2001-2005 The Apache Software Foundation
//
// Licensed 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.Globalization;
using System.Reflection;
using System.Xml;
using log4net.Appender;
using log4net.Util;
using log4net.Core;
using log4net.ObjectRenderer;
namespace log4net.Repository.Hierarchy
{
/// <summary>
/// Initializes the log4net environment using an XML DOM.
/// </summary>
/// <remarks>
/// <para>
/// Configures a <see cref="Hierarchy"/> using an XML DOM.
/// </para>
/// </remarks>
/// <author>Nicko Cadell</author>
/// <author>Gert Driesen</author>
public class XmlHierarchyConfigurator
{
private enum ConfigUpdateMode
{
Merge,
Overwrite
}
#region Public Instance Constructors
/// <summary>
/// Construct the configurator for a hierarchy
/// </summary>
/// <param name="hierarchy">The hierarchy to build.</param>
/// <remarks>
/// <para>
/// Initializes a new instance of the <see cref="XmlHierarchyConfigurator" /> class
/// with the specified <see cref="Hierarchy" />.
/// </para>
/// </remarks>
public XmlHierarchyConfigurator(Hierarchy hierarchy)
{
m_hierarchy = hierarchy;
m_appenderBag = new Hashtable();
}
#endregion Public Instance Constructors
#region Public Instance Methods
/// <summary>
/// Configure the hierarchy by parsing a DOM tree of XML elements.
/// </summary>
/// <param name="element">The root element to parse.</param>
/// <remarks>
/// <para>
/// Configure the hierarchy by parsing a DOM tree of XML elements.
/// </para>
/// </remarks>
public void Configure(XmlElement element)
{
if (element == null || m_hierarchy == null)
{
return;
}
string rootElementName = element.LocalName;
if (rootElementName != CONFIGURATION_TAG)
{
LogLog.Error("XmlHierarchyConfigurator: Xml element is - not a <" + CONFIGURATION_TAG + "> element.");
return;
}
if (!LogLog.InternalDebugging)
{
// Look for a debug attribute to enable internal debug
string debugAttribute = element.GetAttribute(INTERNAL_DEBUG_ATTR);
LogLog.Debug("XmlHierarchyConfigurator: "+INTERNAL_DEBUG_ATTR+" attribute [" + debugAttribute + "].");
if (debugAttribute.Length>0 && debugAttribute != "null")
{
LogLog.InternalDebugging = OptionConverter.ToBoolean(debugAttribute, true);
}
else
{
LogLog.Debug("XmlHierarchyConfigurator: Ignoring " + INTERNAL_DEBUG_ATTR + " attribute.");
}
string confDebug = element.GetAttribute(CONFIG_DEBUG_ATTR);
if (confDebug.Length>0 && confDebug != "null")
{
LogLog.Warn("XmlHierarchyConfigurator: The \"" + CONFIG_DEBUG_ATTR + "\" attribute is deprecated.");
LogLog.Warn("XmlHierarchyConfigurator: Use the \"" + INTERNAL_DEBUG_ATTR + "\" attribute instead.");
LogLog.InternalDebugging = OptionConverter.ToBoolean(confDebug, true);
}
}
// Default mode is merge
ConfigUpdateMode configUpdateMode = ConfigUpdateMode.Merge;
// Look for the config update attribute
string configUpdateModeAttribute = element.GetAttribute(CONFIG_UPDATE_MODE_ATTR);
if (configUpdateModeAttribute != null && configUpdateModeAttribute.Length > 0)
{
// Parse the attribute
try
{
configUpdateMode = (ConfigUpdateMode)OptionConverter.ConvertStringTo(typeof(ConfigUpdateMode), configUpdateModeAttribute);
}
catch
{
LogLog.Error("XmlHierarchyConfigurator: Invalid " + CONFIG_UPDATE_MODE_ATTR + " attribute value [" + configUpdateModeAttribute + "]");
}
}
// IMPL: The IFormatProvider argument to Enum.ToString() is deprecated in .NET 2.0
LogLog.Debug("XmlHierarchyConfigurator: Configuration update mode [" + configUpdateMode.ToString() + "].");
// Only reset configuration if overwrite flag specified
if (configUpdateMode == ConfigUpdateMode.Overwrite)
{
// Reset to original unset configuration
m_hierarchy.ResetConfiguration();
LogLog.Debug("XmlHierarchyConfigurator: Configuration reset before reading config.");
}
/* Building Appender objects, placing them in a local namespace
for future reference */
/* Process all the top level elements */
foreach (XmlNode currentNode in element.ChildNodes)
{
if (currentNode.NodeType == XmlNodeType.Element)
{
XmlElement currentElement = (XmlElement)currentNode;
if (currentElement.LocalName == LOGGER_TAG)
{
ParseLogger(currentElement);
}
else if (currentElement.LocalName == CATEGORY_TAG)
{
// TODO: deprecated use of category
ParseLogger(currentElement);
}
else if (currentElement.LocalName == ROOT_TAG)
{
ParseRoot(currentElement);
}
else if (currentElement.LocalName == RENDERER_TAG)
{
ParseRenderer(currentElement);
}
else if (currentElement.LocalName == APPENDER_TAG)
{
// We ignore appenders in this pass. They will
// be found and loaded if they are referenced.
}
else
{
// Read the param tags and set properties on the hierarchy
SetParameter(currentElement, m_hierarchy);
}
}
}
// Lastly set the hierarchy threshold
string thresholdStr = element.GetAttribute(THRESHOLD_ATTR);
LogLog.Debug("XmlHierarchyConfigurator: Hierarchy Threshold [" + thresholdStr + "]");
if (thresholdStr.Length > 0 && thresholdStr != "null")
{
Level thresholdLevel = (Level) ConvertStringTo(typeof(Level), thresholdStr);
if (thresholdLevel != null)
{
m_hierarchy.Threshold = thresholdLevel;
}
else
{
LogLog.Warn("XmlHierarchyConfigurator: Unable to set hierarchy threshold using value [" + thresholdStr + "] (with acceptable conversion types)");
}
}
// Done reading config
}
#endregion Public Instance Methods
#region Protected Instance Methods
/// <summary>
/// Parse appenders by IDREF.
/// </summary>
/// <param name="appenderRef">The appender ref element.</param>
/// <returns>The instance of the appender that the ref refers to.</returns>
/// <remarks>
/// <para>
/// Parse an XML element that represents an appender and return
/// the appender.
/// </para>
/// </remarks>
protected IAppender FindAppenderByReference(XmlElement appenderRef)
{
string appenderName = appenderRef.GetAttribute(REF_ATTR);
IAppender appender = (IAppender)m_appenderBag[appenderName];
if (appender != null)
{
return appender;
}
else
{
// Find the element with that id
XmlElement element = null;
if (appenderName != null && appenderName.Length > 0)
{
foreach (XmlElement curAppenderElement in appenderRef.OwnerDocument.GetElementsByTagName(APPENDER_TAG))
{
if (curAppenderElement.GetAttribute("name") == appenderName)
{
element = curAppenderElement;
break;
}
}
}
if (element == null)
{
LogLog.Error("XmlHierarchyConfigurator: No appender named [" + appenderName + "] could be found.");
return null;
}
else
{
appender = ParseAppender(element);
if (appender != null)
{
m_appenderBag[appenderName] = appender;
}
return appender;
}
}
}
/// <summary>
/// Parses an appender element.
/// </summary>
/// <param name="appenderElement">The appender element.</param>
/// <returns>The appender instance or <c>null</c> when parsing failed.</returns>
/// <remarks>
/// <para>
/// Parse an XML element that represents an appender and return
/// the appender instance.
/// </para>
/// </remarks>
protected IAppender ParseAppender(XmlElement appenderElement)
{
string appenderName = appenderElement.GetAttribute(NAME_ATTR);
string typeName = appenderElement.GetAttribute(TYPE_ATTR);
LogLog.Debug("XmlHierarchyConfigurator: Loading Appender [" + appenderName + "] type: [" + typeName + "]");
try
{
IAppender appender = (IAppender)Activator.CreateInstance(SystemInfo.GetTypeFromString(typeName, true, true));
appender.Name = appenderName;
foreach (XmlNode currentNode in appenderElement.ChildNodes)
{
/* We're only interested in Elements */
if (currentNode.NodeType == XmlNodeType.Element)
{
XmlElement currentElement = (XmlElement)currentNode;
// Look for the appender ref tag
if (currentElement.LocalName == APPENDER_REF_TAG)
{
string refName = currentElement.GetAttribute(REF_ATTR);
IAppenderAttachable appenderContainer = appender as IAppenderAttachable;
if (appenderContainer != null)
{
LogLog.Debug("XmlHierarchyConfigurator: Attaching appender named [" + refName + "] to appender named [" + appender.Name + "].");
IAppender referencedAppender = FindAppenderByReference(currentElement);
if (referencedAppender != null)
{
appenderContainer.AddAppender(referencedAppender);
}
}
else
{
LogLog.Error("XmlHierarchyConfigurator: Requesting attachment of appender named ["+refName+ "] to appender named [" + appender.Name + "] which does not implement log4net.Core.IAppenderAttachable.");
}
}
else
{
// For all other tags we use standard set param method
SetParameter(currentElement, appender);
}
}
}
IOptionHandler optionHandler = appender as IOptionHandler;
if (optionHandler != null)
{
optionHandler.ActivateOptions();
}
LogLog.Debug("XmlHierarchyConfigurator: Created Appender [" + appenderName + "]");
return appender;
}
catch (Exception ex)
{
// Yes, it's ugly. But all exceptions point to the same problem: we can't create an Appender
LogLog.Error("XmlHierarchyConfigurator: Could not create Appender [" + appenderName + "] of type [" + typeName + "]. Reported error follows.", ex);
return null;
}
}
/// <summary>
/// Parses a logger element.
/// </summary>
/// <param name="loggerElement">The logger element.</param>
/// <remarks>
/// <para>
/// Parse an XML element that represents a logger.
/// </para>
/// </remarks>
protected void ParseLogger(XmlElement loggerElement)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -