#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.IO;
using System.Text;
using System.Xml;
using log4net.Util;
using log4net.Core;
namespace log4net.Layout
{
///
/// Layout that formats the log events as XML elements.
///
///
///
/// This is an abstract class that must be subclassed by an implementation
/// to conform to a specific schema.
///
///
/// Deriving classes must implement the method.
///
///
/// Nicko Cadell
/// Gert Driesen
abstract public class XmlLayoutBase : LayoutSkeleton
{
#region Protected Instance Constructors
///
/// Protected constructor to support subclasses
///
///
///
/// Initializes a new instance of the class
/// with no location info.
///
///
protected XmlLayoutBase() : this(false)
{
IgnoresException = false;
}
///
/// Protected constructor to support subclasses
///
///
///
/// The parameter determines whether
/// location information will be output by the layout. If
/// is set to true, then the
/// file name and line number of the statement at the origin of the log
/// statement will be output.
///
///
/// If you are embedding this layout within an SMTPAppender
/// then make sure to set the LocationInfo option of that
/// appender as well.
///
///
protected XmlLayoutBase(bool locationInfo)
{
IgnoresException = false;
m_locationInfo = locationInfo;
}
#endregion Protected Instance Constructors
#region Public Instance Properties
///
/// Gets a value indicating whether to include location information in
/// the XML events.
///
///
/// true if location information should be included in the XML
/// events; otherwise, false.
///
///
///
/// If is set to true, then the file
/// name and line number of the statement at the origin of the log
/// statement will be output.
///
///
/// If you are embedding this layout within an SMTPAppender
/// then make sure to set the LocationInfo option of that
/// appender as well.
///
///
public bool LocationInfo
{
get { return m_locationInfo; }
set { m_locationInfo = value; }
}
///
/// The string to replace characters that can not be expressed in XML with.
///
///
/// Not all characters may be expressed in XML. This property contains the
/// string to replace those that can not with. This defaults to a ?. Set it
/// to the empty string to simply remove offending characters. For more
/// details on the allowed character ranges see http://www.w3.org/TR/REC-xml/#charsets
/// Character replacement will occur in the log message, the property names
/// and the property values.
///
///
///
public string InvalidCharReplacement
{
get {return m_invalidCharReplacement;}
set {m_invalidCharReplacement=value;}
}
#endregion
#region Implementation of IOptionHandler
///
/// Initialize layout 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.
///
///
override public void ActivateOptions()
{
// nothing to do
}
#endregion Implementation of IOptionHandler
#region Override implementation of LayoutSkeleton
///
/// Gets the content type output by this layout.
///
///
/// As this is the XML layout, the value is always "text/xml".
///
///
///
/// As this is the XML layout, the value is always "text/xml".
///
///
override public string ContentType
{
get { return "text/xml"; }
}
///
/// Produces a formatted string.
///
/// The event being logged.
/// The TextWriter to write the formatted event to
///
///
/// Format the and write it to the .
///
///
/// This method creates an that writes to the
/// . The is passed
/// to the method. Subclasses should override the
/// method rather than this method.
///
///
override public void Format(TextWriter writer, LoggingEvent loggingEvent)
{
if (loggingEvent == null)
{
throw new ArgumentNullException("loggingEvent");
}
// Attach the protected writer to the TextWriter passed in
m_protectCloseTextWriter.Attach(writer);
XmlTextWriter xmlWriter = new XmlTextWriter(m_protectCloseTextWriter);
xmlWriter.Formatting = Formatting.None;
xmlWriter.Namespaces = false;
// Write the event to the writer
FormatXml(xmlWriter, loggingEvent);
xmlWriter.WriteWhitespace(SystemInfo.NewLine);
// Close on xmlWriter will ensure xml is flushed
// the protected writer will ignore the actual close
xmlWriter.Close();
// detach from the writer
m_protectCloseTextWriter.Attach(null);
}
#endregion Override implementation of LayoutSkeleton
#region Protected Instance Methods
///
/// Does the actual writing of the XML.
///
/// The writer to use to output the event to.
/// The event to write.
///
///
/// Subclasses should override this method to format
/// the as XML.
///
///
abstract protected void FormatXml(XmlWriter writer, LoggingEvent loggingEvent);
#endregion Protected Instance Methods
#region Private Instance Fields
///
/// Flag to indicate if location information should be included in
/// the XML events.
///
private bool m_locationInfo = false;
///
/// Writer adapter that ignores Close
///
private readonly ProtectCloseTextWriter m_protectCloseTextWriter = new ProtectCloseTextWriter(null);
///
/// The string to replace invalid chars with
///
private string m_invalidCharReplacement="?";
#endregion Private Instance Fields
}
}