nicko       2004/09/09 14:53:14

  Modified:    src      MDC.cs NDC.cs
               src/Appender EventLogAppender.cs RemotingAppender.cs
                        SmtpAppender.cs SmtpPickupDirAppender.cs
                        UdpAppender.cs
               src/Core LoggingEvent.cs
               src/Filter MdcFilter.cs NdcFilter.cs
               src/Layout PatternLayout.cs RawPropertyLayout.cs
                        XMLLayout.cs XmlLayoutSchemaLog4j.cs
               src/Layout/Pattern NdcPatternConverter.cs
                        PropertyPatternConverter.cs
               src/Util PatternString.cs
  Added:       src      ThreadContext.cs
               src/Core IFixingRequired.cs
               src/Filter PropertyFilter.cs
               src/Util CompositeProperties.cs ThreadContextList.cs
                        ThreadContextLists.cs ThreadContextProperties.cs
                        ThreadContextStack.cs ThreadContextStacks.cs
               src/Util/PatternStringConverters PropertyPatternConverter.cs
  Removed:     src/Layout/Pattern GlobalPropertyPatternConverter.cs
                        MdcPatternConverter.cs
  Log:
  Added ThreadContext.
  The ThreadContext.Properties is a replacement for the MDC. The 
ThreadContext.Stacks is a replacement for the NDC.
  The ThreadContext.Stacks and ThreadContext.Lists are stored in the 
ThreadContext.Properties.
  The MDC and NDC forward to the new implementation where possible.
  The contexts are composed into layers; GlobalContext.Properties are 
overridden by ThreadContext.Properties and they are overridden by 
LoggingEvent.EventProperties.
  Changed filters and layouts to lookup properties from the LoggingEvent.
  
  Revision  Changes    Path
  1.4       +16 -71    logging-log4net/src/MDC.cs
  
  Index: MDC.cs
  ===================================================================
  RCS file: /home/cvs/logging-log4net/src/MDC.cs,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- MDC.cs    30 May 2004 11:30:34 -0000      1.3
  +++ MDC.cs    9 Sep 2004 21:53:13 -0000       1.4
  @@ -26,6 +26,10 @@
        /// </summary>
        /// <remarks>
        /// <para>
  +     /// The MDC is deprecated and has been replaced by the <see 
cref="ThreadContext.Properties"/>.
  +     /// The current MDC implementation forwards to the 
ThreadContext.Properties.
  +     /// </para>
  +     /// <para>
        /// The MDC class is similar to the <see cref="NDC"/> class except that 
it is
        /// based on a map instead of a stack. It provides <i>mapped
        /// diagnostic contexts</i>. A <i>Mapped Diagnostic Context</i>, or
  @@ -39,6 +43,7 @@
        /// </remarks>
        /// <author>Nicko Cadell</author>
        /// <author>Gert Driesen</author>
  +     /*[Obsolete("MDC has been replaced by ThreadContext.Properties")]*/
        public sealed class MDC
        {
                #region Private Instance Constructors
  @@ -68,13 +73,15 @@
                /// </remarks>
                /// <param name="key">The key to lookup in the MDC.</param>
                /// <returns>The string value held for the key, or a 
<c>null</c> reference if no corresponding value is found.</returns>
  +             /*[Obsolete("MDC has been replaced by 
ThreadContext.Properties")]*/
                public static string Get(string key)
                {
  -                     if (key == null)
  +                     object obj = ThreadContext.Properties[key];
  +                     if (obj == null)
                        {
  -                             throw new ArgumentNullException("key");
  +                             return null;
                        }
  -                     return GetMap()[key] as string;
  +                     return obj.ToString();
                }
   
                /// <summary>
  @@ -94,21 +101,10 @@
                /// </remarks>
                /// <param name="key">The key to store the value under.</param>
                /// <param name="value">The value to store.</param>
  +             /*[Obsolete("MDC has been replaced by 
ThreadContext.Properties")]*/
                public static void Set(string key, string value)
                {
  -                     if (key == null)
  -                     {
  -                             throw new ArgumentNullException("key");
  -                     }
  -
  -                     if (value == null)
  -                     {
  -                             GetMap().Remove(key);
  -                     }
  -                     else
  -                     {
  -                             GetMap()[key] = value;
  -                     }
  +                     ThreadContext.Properties[key] = value;
                }
   
                /// <summary>
  @@ -120,14 +116,10 @@
                /// </para>
                /// </remarks>
                /// <param name="key">The key to remove.</param>
  +             /*[Obsolete("MDC has been replaced by 
ThreadContext.Properties")]*/
                public static void Remove(string key)
                {
  -                     if (key == null)
  -                     {
  -                             throw new ArgumentNullException("key");
  -                     }
  -
  -                     Set(key, null);
  +                     ThreadContext.Properties.Remove(key);
                }
   
                /// <summary>
  @@ -138,59 +130,12 @@
                /// Remove all the entries from this thread's MDC
                /// </para>
                /// </remarks>
  +             /*[Obsolete("MDC has been replaced by 
ThreadContext.Properties")]*/
                public static void Clear()
                {
  -                     Hashtable map = 
(Hashtable)System.Threading.Thread.GetData(s_slot);
  -                     if (map != null)
  -                     {
  -                             map.Clear();
  -                     }
  +                     ThreadContext.Properties.Clear();
                }
   
                #endregion Public Static Methods
  -
  -             #region Internal Static Methods
  -
  -             /// <summary>
  -             /// Gets the map on this thread.
  -             /// </summary>
  -             /// <returns>The map on the current thread.</returns>
  -             internal static IDictionary GetMap()
  -             {
  -                     Hashtable map = 
(Hashtable)System.Threading.Thread.GetData(s_slot);
  -                     if (map == null)
  -                     {
  -                             map = new Hashtable();
  -                             System.Threading.Thread.SetData(s_slot, map);
  -                     }
  -                     return map;
  -             }
  -
  -             /// <summary>
  -             /// Gets a readonly copy of the map on this thread.
  -             /// </summary>
  -             /// <returns>A readonly copy of the map on the current 
thread.</returns>
  -             internal static IDictionary CopyMap()
  -             {
  -                     Hashtable map = 
(Hashtable)System.Threading.Thread.GetData(s_slot);
  -                     if (map == null)
  -                     {
  -                             return log4net.Util.EmptyDictionary.Instance;
  -                     }
  -
  -                     // Return a copy of the map
  -                     return (IDictionary)map.Clone();
  -             }
  -
  -             #endregion Internal Static Methods
  -
  -             #region Private Static Fields
  -
  -             /// <summary>
  -             /// The thread local data slot to use for context information.
  -             /// </summary>
  -             private readonly static LocalDataStoreSlot s_slot = 
System.Threading.Thread.AllocateDataSlot();
  -
  -             #endregion Private Static Fields
        }
   }
  
  
  
  1.7       +20 -233   logging-log4net/src/NDC.cs
  
  Index: NDC.cs
  ===================================================================
  RCS file: /home/cvs/logging-log4net/src/NDC.cs,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- NDC.cs    7 Jun 2004 01:09:08 -0000       1.6
  +++ NDC.cs    9 Sep 2004 21:53:13 -0000       1.7
  @@ -29,6 +29,10 @@
        /// </summary>
        /// <remarks>
        /// <para>
  +     /// The NDC is deprecated and has been replaced by the <see 
cref="ThreadContext.Stacks"/>.
  +     /// The current NDC implementation forwards to the 
ThreadContext.Stacks["NDC"].
  +     /// </para>
  +     /// <para>
        /// A Nested Diagnostic Context, or NDC in short, is an instrument
        /// to distinguish interleaved log output from different sources. Log
        /// output is typically interleaved when a server handles multiple
  @@ -56,6 +60,7 @@
        /// </example>
        /// <author>Nicko Cadell</author>
        /// <author>Gert Driesen</author>
  +     /*[Obsolete("NDC has been replaced by ThreadContext.Stacks")]*/
        public sealed class NDC
        {
                #region Private Instance Constructors
  @@ -88,9 +93,10 @@
                /// </para>
                /// </remarks>
                /// <seealso cref="SetMaxDepth"/>
  +             [Obsolete("NDC has been replaced by ThreadContext.Stacks", 
true)]
                public static int Depth
                {
  -                     get { return GetStack().Count; }
  +                     get { throw new NotSupportedException("NDC has been 
replaced by ThreadContext.Stacks"); }
                }
   
                #endregion Public Static Properties
  @@ -104,9 +110,10 @@
                /// <remarks>
                /// After calling this method the <see cref="Depth"/> will be 
<c>0</c>.
                /// </remarks>
  +             [Obsolete("NDC has been replaced by ThreadContext.Stacks", 
true)]
                public static void Clear() 
                {
  -                     GetStack().Clear();
  +                     throw new NotSupportedException("NDC has been replaced 
by ThreadContext.Stacks");
                }
   
                /// <summary>
  @@ -118,9 +125,10 @@
                /// parent thread.
                /// </remarks>
                /// <returns>A clone of the context info for this 
thread.</returns>
  +             [Obsolete("NDC has been replaced by ThreadContext.Stacks", 
true)]
                public static Stack CloneStack() 
                {
  -                     return (Stack)GetStack().Clone();
  +                     throw new NotSupportedException("NDC has been replaced 
by ThreadContext.Stacks");
                }
   
                /// <summary>
  @@ -136,14 +144,10 @@
                /// this method.
                /// </remarks>
                /// <param name="stack">The context stack to inherit.</param>
  +             [Obsolete("NDC has been replaced by ThreadContext.Stacks", 
true)]
                public static void Inherit(Stack stack) 
                {
  -                     if (stack == null)
  -                     {
  -                             throw new ArgumentNullException("stack");
  -                     }
  -
  -                     System.Threading.Thread.SetData(s_slot, stack);
  +                     throw new NotSupportedException("NDC has been replaced 
by ThreadContext.Stacks");
                }
   
                /// <summary>
  @@ -158,14 +162,10 @@
                /// The message in the context that was removed from the top 
                /// of the stack.
                /// </returns>
  +             /*[Obsolete("NDC has been replaced by ThreadContext.Stacks")]*/
                public static string Pop() 
                {
  -                     Stack stack = GetStack();
  -                     if (stack.Count > 0)
  -                     {
  -                             return 
((DiagnosticContext)(stack.Pop())).Message;
  -                     }
  -                     return "";
  +                     return ThreadContext.Stacks["NDC"].Pop();
                }
   
                /// <summary>
  @@ -190,12 +190,10 @@
                ///     }
                /// </code>
                /// </example>
  +             /*[Obsolete("NDC has been replaced by ThreadContext.Stacks")]*/
                public static IDisposable Push(string message) 
                {
  -                     Stack stack = GetStack();
  -                     stack.Push(new DiagnosticContext(message, 
(stack.Count>0) ? (DiagnosticContext)stack.Peek() : null));
  -
  -                     return new NDCAutoDisposeFrame(stack, stack.Count - 1);
  +                     return ThreadContext.Stacks["NDC"].Push(message);
                }
   
                /// <summary>
  @@ -205,6 +203,7 @@
                /// <remarks>
                /// This method is not implemented.
                /// </remarks>
  +             [Obsolete("NDC has been replaced by ThreadContext.Stacks")]
                public static void Remove() 
                {
                }
  @@ -220,224 +219,12 @@
                /// call. This can be used to return to a known context depth.
                /// </remarks>
                /// <param name="maxDepth">The maximum depth of the 
stack</param>
  +             [Obsolete("NDC has been replaced by ThreadContext.Stacks", 
true)]
                static public void SetMaxDepth(int maxDepth) 
                {
  -                     if (maxDepth < 0)
  -                     {
  -                             throw 
log4net.Util.SystemInfo.CreateArgumentOutOfRangeException("maxDepth", 
(object)maxDepth, "Parameter: maxDepth, Value: ["+maxDepth+"] out of range. 
Nonnegative number required");
  -                     }
  -
  -                     Stack stack = GetStack();
  -                     while(stack.Count > maxDepth)
  -                     {
  -                             stack.Pop();
  -                     }
  +                     throw new NotSupportedException("NDC has been replaced 
by ThreadContext.Stacks");
                }
   
                #endregion Public Static Methods
  -
  -             #region Internal Static Methods
  -
  -             /// <summary>
  -             /// Gets the current context information.
  -             /// </summary>
  -             /// <returns>The current context information.</returns>
  -             internal static string Get() 
  -             {
  -                     Stack stack = GetStack();
  -                     if (stack.Count > 0)
  -                     {
  -                             return 
((DiagnosticContext)(stack.Peek())).FullMessage;
  -                     }
  -                     return null;
  -             }
  -  
  -             #endregion Internal Static Methods
  -
  -             #region Private Static Methods
  -
  -             /// <summary>
  -             /// Gets the stack of context objects on this thread.
  -             /// </summary>
  -             /// <returns>The stack of context objects on the current 
thread.</returns>
  -             static private Stack GetStack()
  -             {
  -                     Stack stack = 
(Stack)System.Threading.Thread.GetData(s_slot);
  -                     if (stack == null)
  -                     {
  -                             stack = new Stack();
  -                             System.Threading.Thread.SetData(s_slot, stack);
  -                     }
  -                     return stack;
  -             }
  -
  -             #endregion Private Static Methods
  -
  -             #region Private Static Fields
  -
  -             /// <summary>
  -             /// The thread local data slot to use for context information.
  -             /// </summary>
  -             private readonly static LocalDataStoreSlot s_slot = 
System.Threading.Thread.AllocateDataSlot();
  -
  -             #endregion Private Static Fields
  -
  -             /// <summary>
  -             /// Inner class used to represent a single context in the stack.
  -             /// </summary>
  -             internal class DiagnosticContext 
  -             {
  -                     #region Internal Instance Constructors
  -
  -                     /// <summary>
  -                     /// Initializes a new instance of the <see 
cref="DiagnosticContext" /> class
  -                     /// with the specified message and parent context.
  -                     /// </summary>
  -                     /// <param name="message">The message for this 
context.</param>
  -                     /// <param name="parent">The parent context in the 
chain.</param>
  -                     internal DiagnosticContext(string message, 
DiagnosticContext parent) 
  -                     {
  -                             m_message = message;
  -                             if (parent != null) 
  -                             {
  -                                     m_fullMessage = parent.FullMessage + ' 
' + message;
  -                             } 
  -                             else 
  -                             {
  -                                     m_fullMessage = message;
  -                             }
  -                     }
  -
  -                     #endregion Internal Instance Constructors
  -
  -                     #region Internal Instance Properties
  -
  -                     /// <summary>
  -                     /// Get the message.
  -                     /// </summary>
  -                     /// <value>The message.</value>
  -                     internal string Message
  -                     {
  -                             get { return m_message; }
  -                     }
  -
  -                     /// <summary>
  -                     /// Gets the full text of the context down to the root 
level.
  -                     /// </summary>
  -                     /// <value>
  -                     /// The full text of the context down to the root level.
  -                     /// </value>
  -                     internal string FullMessage
  -                     {
  -                             get { return m_fullMessage; }
  -                     }
  -
  -                     #endregion Internal Instance Properties
  -
  -                     #region Private Instance Fields
  -
  -                     private string m_fullMessage;
  -                     private string m_message;
  -    
  -                     #endregion
  -             }
  -
  -             /// <summary>
  -             /// Inner class that is returned from <see cref="NDC.Push"/>
  -             /// </summary>
  -             /// <remarks>
  -             /// This class is disposable and when it is disposed it 
automatically
  -             /// returns the NDC to the correct depth.
  -             /// </remarks>
  -             internal class NDCAutoDisposeFrame : IDisposable
  -             {
  -                     #region Internal Instance Constructors
  -
  -                     /// <summary>
  -                     /// Initializes a new instance of the <see 
cref="NDCAutoDisposeFrame" /> class with
  -                     /// the specified stack and return depth.
  -                     /// </summary>
  -                     /// <param name="frameStack">The internal stack used by 
the NDC.</param>
  -                     /// <param name="frameDepth">The depth to return the 
stack to when this object is disposed.</param>
  -                     internal NDCAutoDisposeFrame(Stack frameStack, int 
frameDepth)
  -                     {
  -                             m_frameStack = frameStack;
  -                             m_frameDepth = frameDepth;
  -                     }
  -
  -                     #endregion Internal Instance Constructors
  -
  -                     #region Implementation of IDisposable
  -
  -                     /// <summary>
  -                     /// Returns the NDC stack to the correct depth.
  -                     /// </summary>
  -                     public void Dispose()
  -                     {
  -                             if (m_frameDepth >= 0 && m_frameStack != null)
  -                             {
  -                                     while(m_frameStack.Count > m_frameDepth)
  -                                     {
  -                                             m_frameStack.Pop();
  -                                     }
  -                             }
  -                     }
  -
  -                     #endregion Implementation of IDisposable
  -
  -                     #region Private Instance Fields
  -
  -                     /// <summary>
  -                     /// The NDC internal stack
  -                     /// </summary>
  -                     private Stack m_frameStack;
  -
  -                     /// <summary>
  -                     /// The depth to rethrow the stack to when this 
instance is disposed
  -                     /// </summary>
  -                     private int m_frameDepth;
  -
  -                     #endregion Private Instance Fields
  -             }
  -
  -#if NETCF
  -             /// <summary>
  -             /// Subclass of <see cref="System.Collections.Stack"/> to
  -             /// provide missing methods.
  -             /// </summary>
  -             /// <remarks>
  -             /// The Compact Framework version of the <see 
cref="System.Collections.Stack"/>
  -             /// class is missing the <c>Clear</c> and <c>Clone</c> methods.
  -             /// This subclass adds implementations of those missing methods.
  -             /// </remarks>
  -             public class Stack : System.Collections.Stack
  -             {
  -                     /// <summary>
  -                     /// Clears the stack of all elements.
  -                     /// </summary>
  -                     public void Clear()
  -                     {
  -                             while(Count > 0)
  -                             {
  -                                     Pop();
  -                             }
  -                     }
  -
  -                     /// <summary>
  -                     /// Makes a shallow copy of the stack's elements.
  -                     /// </summary>
  -                     /// <returns>A new stack that has a shallow copy of the 
stack's elements.</returns>
  -                     public Stack Clone()
  -                     {
  -                             Stack res = new Stack();
  -                             object[] items = ToArray();
  -                             foreach(object item in items)
  -                             {
  -                                     res.Push(item);
  -                             }
  -                             return res;
  -                     }
  -             }
  -#endif
        }
   }
  
  
  
  1.1                  logging-log4net/src/ThreadContext.cs
  
  Index: ThreadContext.cs
  ===================================================================
  #region Copyright & License
  //
  // Copyright 2001-2004 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 log4net.Util;
  
  namespace log4net
  {
        /// <summary>
        /// The log4net Thread Context.
        /// </summary>
        /// <remarks>
        /// <para>
        /// The <c>ThreadContext</c> provides a location for thread specific 
debugging 
        /// information to be stored.
        /// </para>
        /// <para>
        /// The thread context has a properties map and a stack.
        /// The properties and stack can 
        /// be included in the output of log messages. The <see 
cref="log4net.Layout.PatternLayout"/>
        /// supports selecting and outputting these properties.
        /// </para>
        /// <para>
        /// The Thread Context provides a diagnostic context for the current 
thread. 
        /// This is an instrument for distinguishing interleaved log
        /// output from different sources. Log output is typically interleaved
        /// when a server handles multiple clients near-simultaneously.
        /// </para>
        /// <para>
        /// The Thread Context is managed on a per thread basis.
        /// </para>
        /// </remarks>
        /// <example>Example of using the thread context properties to store a 
username.
        /// <code>
        /// ThreadContext.Properties["user"] = userName;
        ///     log.Info("This log message has a ThreadContext Property called 
'user'");
        /// </code>
        /// </example>
        /// <example>Example of how to push a message into the context stack
        /// <code>
        ///     using(ThreadContext.Stack.Push("my context message"))
        ///     {
        ///             log.Info("This log message has a ThreadContext Stack 
message that includes 'my context message'");
        ///     
        ///     } // at the end of the using block the message is automatically 
popped 
        /// </code>
        /// </example>
        /// <author>Nicko Cadell</author>
        public sealed class ThreadContext
        {
                #region Private Instance Constructors
  
                /// <summary>
                /// Private Constructor. 
                /// </summary>
                /// <remarks>
                /// Uses a private access modifier to prevent instantiation of 
this class.
                /// </remarks>
                private ThreadContext()
                {
                }
  
                #endregion Private Instance Constructors
  
                #region Public Static Properties
  
                /// <summary>
                /// The thread properties map
                /// </summary>
                /// <value>
                /// The thread properties map
                /// </value>
                public static ThreadContextProperties Properties
                {
                        get { return s_properties; }
                }
  
                /// <summary>
                /// The thread stacks
                /// </summary>
                /// <value>
                /// stack map
                /// </value>
                public static ThreadContextStacks Stacks
                {
                        get { return s_stacks; }
                }
  
                /// <summary>
                /// The thread lists
                /// </summary>
                /// <value>
                /// list map
                /// </value>
                public static ThreadContextLists Lists
                {
                        get { return s_lists; }
                }
  
                #endregion Public Static Properties
  
                #region Private Static Fields
  
                /// <summary>
                /// The thread context properties instance
                /// </summary>
                private readonly static ThreadContextProperties s_properties = 
new ThreadContextProperties();
  
                /// <summary>
                /// The thread context stacks instance
                /// </summary>
                private readonly static ThreadContextStacks s_stacks = new 
ThreadContextStacks();
  
                /// <summary>
                /// The thread context lists instance
                /// </summary>
                private readonly static ThreadContextLists s_lists = new 
ThreadContextLists();
  
                #endregion Private Static Fields
        }
  }
  
  
  
  1.9       +3 -3      logging-log4net/src/Appender/EventLogAppender.cs
  
  Index: EventLogAppender.cs
  ===================================================================
  RCS file: /home/cvs/logging-log4net/src/Appender/EventLogAppender.cs,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- EventLogAppender.cs       24 Jul 2004 14:54:02 -0000      1.8
  +++ EventLogAppender.cs       9 Sep 2004 21:53:13 -0000       1.9
  @@ -44,7 +44,7 @@
        /// <remarks>
        /// <para>
        /// The <c>EventID</c> of the event log entry can be
  -     /// set using the <c>EventLogEventID</c> property (<see 
cref="LoggingEvent.Properties"/>)
  +     /// set using the <c>EventLogEventID</c> property (<see 
cref="LoggingEvent.EventProperties"/>)
        /// on the <see cref="LoggingEvent"/>.
        /// </para>
        /// <para>
  @@ -203,7 +203,7 @@
                /// <para>Writes the event to the system event log using the 
                /// <see cref="ApplicationName"/>.</para>
                /// 
  -             /// <para>If the event has an <c>EventID</c> property (see <see 
cref="LoggingEvent.Properties"/>)
  +             /// <para>If the event has an <c>EventID</c> property (see <see 
cref="LoggingEvent.EventProperties"/>)
                /// set then this integer will be used as the event log event 
id.</para>
                /// 
                /// <para>
  @@ -218,7 +218,7 @@
                        int eventID = 0;
   
                        // Look for the EventLogEventID property
  -                     object eventIDPropertyObj = 
loggingEvent.Properties["EventID"];
  +                     object eventIDPropertyObj = 
loggingEvent.LookupProperty("EventID");
                        if (eventIDPropertyObj != null)
                        {
                                if (eventIDPropertyObj is int)
  
  
  
  1.6       +0 -15     logging-log4net/src/Appender/RemotingAppender.cs
  
  Index: RemotingAppender.cs
  ===================================================================
  RCS file: /home/cvs/logging-log4net/src/Appender/RemotingAppender.cs,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- RemotingAppender.cs       30 May 2004 18:01:18 -0000      1.5
  +++ RemotingAppender.cs       9 Sep 2004 21:53:13 -0000       1.6
  @@ -42,10 +42,6 @@
        /// object to deliver events to is specified by setting the
        /// appenders <see cref="RemotingAppender.Sink"/> property.</para>
        /// <para>
  -     /// This appender sets the <c>log4net:HostName</c> property in the 
  -     /// <see cref="LoggingEvent.Properties"/> collection to the name of 
  -     /// the machine on which the event is logged.</para>
  -     /// <para>
        /// The RemotingAppender buffers events before sending them. This 
allows it to 
        /// make more efficient use of the remoting infrastructure.</para>
        /// <para>
  @@ -249,17 +245,6 @@
                        try
                        {
                                LoggingEvent[] events = (LoggingEvent[])state;
  -
  -                             string hostName = SystemInfo.HostName;
  -
  -                             // Set the hostname
  -                             foreach(LoggingEvent e in events)
  -                             {
  -                                     if 
(e.Properties[LoggingEvent.HostNameProperty] == null)
  -                                     {
  -                                             
e.Properties[LoggingEvent.HostNameProperty] = hostName;
  -                                     }
  -                             }
   
                                // Send the events
                                m_sinkObj.LogEvents(events);
  
  
  
  1.6       +0 -9      logging-log4net/src/Appender/SmtpAppender.cs
  
  Index: SmtpAppender.cs
  ===================================================================
  RCS file: /home/cvs/logging-log4net/src/Appender/SmtpAppender.cs,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- SmtpAppender.cs   11 Aug 2004 20:04:05 -0000      1.5
  +++ SmtpAppender.cs   9 Sep 2004 21:53:13 -0000       1.6
  @@ -233,17 +233,8 @@
                                        writer.Write(t);
                                }
   
  -
  -                             string hostName = SystemInfo.HostName;
  -
                                for(int i = 0; i < events.Length; i++) 
                                {
  -                                     // Set the hostname property
  -                                     if 
(events[i].Properties[LoggingEvent.HostNameProperty] == null)
  -                                     {
  -                                             
events[i].Properties[LoggingEvent.HostNameProperty] = hostName;
  -                                     }
  -
                                        // Render the event and append the text 
to the buffer
                                        RenderLoggingEvent(writer, events[i]);
                                }
  
  
  
  1.3       +1 -14     logging-log4net/src/Appender/SmtpPickupDirAppender.cs
  
  Index: SmtpPickupDirAppender.cs
  ===================================================================
  RCS file: /home/cvs/logging-log4net/src/Appender/SmtpPickupDirAppender.cs,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- SmtpPickupDirAppender.cs  16 Feb 2004 02:10:51 -0000      1.2
  +++ SmtpPickupDirAppender.cs  9 Sep 2004 21:53:13 -0000       1.3
  @@ -46,11 +46,6 @@
        /// cyclic buffer. This keeps memory requirements at a reasonable level 
while 
        /// still delivering useful application context.
        /// </para>
  -     /// <para>
  -     /// This appender sets the <c>log4net:HostName</c> property in the 
  -     /// <see cref="LoggingEvent.Properties"/> collection to the name of 
  -     /// the machine on which the event is logged.
  -     /// </para>
        /// </remarks>
        /// <author>Niall Daley</author>
        /// <author>Nicko Cadell</author>
  @@ -125,7 +120,7 @@
                override protected void SendBuffer(LoggingEvent[] events) 
                {
                        // Note: this code already owns the monitor for this
  -                     // appender. This frees us from needing to synchronize 
on 'cb'.
  +                     // appender. This frees us from needing to synchronize 
again.
                        try 
                        {         
                                using(StreamWriter writer = 
File.CreateText(Path.Combine(m_pickupDir, SystemInfo.NewGuid().ToString("N"))))
  @@ -141,16 +136,8 @@
                                                writer.Write(t);
                                        }
   
  -                                     string hostName = SystemInfo.HostName;
  -
                                        for(int i = 0; i < events.Length; i++) 
                                        {
  -                                             // Set the hostname property
  -                                             if 
(events[i].Properties[LoggingEvent.HostNameProperty] == null)
  -                                             {
  -                                                     
events[i].Properties[LoggingEvent.HostNameProperty] = hostName;
  -                                             }
  -
                                                // Render the event and append 
the text to the buffer
                                                RenderLoggingEvent(writer, 
events[i]);
                                        }
  
  
  
  1.6       +2 -16     logging-log4net/src/Appender/UdpAppender.cs
  
  Index: UdpAppender.cs
  ===================================================================
  RCS file: /home/cvs/logging-log4net/src/Appender/UdpAppender.cs,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- UdpAppender.cs    7 Jun 2004 01:07:50 -0000       1.5
  +++ UdpAppender.cs    9 Sep 2004 21:53:13 -0000       1.6
  @@ -37,11 +37,6 @@
        /// UDP guarantees neither that messages arrive, nor that they arrive 
in the correct order.
        /// </para>
        /// <para>
  -     /// This appender sets the <c>log4net:HostName</c> property in the 
  -     /// <see cref="LoggingEvent.Properties"/> collection to the name of 
  -     /// the machine on which the event is logged.
  -     /// </para>
  -     /// <para>
        /// To view the logging results, a custom application can be developed 
that listens for logging 
        /// events.
        /// </para>
  @@ -306,9 +301,6 @@
                        set { this.m_client = value; }
                }
   
  -             #endregion Protected Instance Properties
  -
  -             #region Private Instance Properties
   
                /// <summary>
                /// Gets or sets the cached remote endpoint to which the 
logging events should be sent.
  @@ -321,13 +313,13 @@
                /// with the values of the <see cref="RemoteAddress" /> and 
<see cref="RemotePort"/>
                /// properties.
                /// </remarks>
  -             private IPEndPoint RemoteEndPoint
  +             protected IPEndPoint RemoteEndPoint
                {
                        get { return this.m_remoteEndPoint; }
                        set { this.m_remoteEndPoint = value; }
                }
   
  -             #endregion Private Instance Properties
  +             #endregion Protected Instance Properties
   
                #region Implementation of IOptionHandler
   
  @@ -402,12 +394,6 @@
                /// </remarks>
                protected override void Append(LoggingEvent loggingEvent) 
                {
  -                     // Set the hostname property
  -                     if 
(loggingEvent.Properties[LoggingEvent.HostNameProperty] == null)
  -                     {
  -                             
loggingEvent.Properties[LoggingEvent.HostNameProperty] = SystemInfo.HostName;
  -                     }
  -
                        try 
                        {
                                Byte [] buffer = 
m_encoding.GetBytes(RenderLoggingEvent(loggingEvent).ToCharArray());
  
  
  
  1.10      +184 -129  logging-log4net/src/Core/LoggingEvent.cs
  
  Index: LoggingEvent.cs
  ===================================================================
  RCS file: /home/cvs/logging-log4net/src/Core/LoggingEvent.cs,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- LoggingEvent.cs   22 Aug 2004 19:26:50 -0000      1.9
  +++ LoggingEvent.cs   9 Sep 2004 21:53:13 -0000       1.10
  @@ -55,11 +55,6 @@
                public string Ndc;
   
                /// <summary>
  -             /// The local cache of the MDC dictionary
  -             /// </summary>
  -             public IDictionary Mdc;
  -
  -             /// <summary>
                /// The application supplied message of logging event.
                /// </summary>
                public string Message;
  @@ -115,14 +110,6 @@
                /// </remarks>
                public PropertiesDictionary Properties;
   
  -             /// <summary>
  -             /// Global properties
  -             /// </summary>
  -             /// <remarks>
  -             /// Global properties are defined on the <see 
cref="GlobalContext"/>
  -             /// </remarks>
  -             public ReadOnlyPropertiesDictionary GlobalProperties;
  -
                #endregion Public Instance Fields
        }
   
  @@ -135,6 +122,7 @@
                /// <summary>
                /// Fix the MDC
                /// </summary>
  +             [Obsolete("Replaced by composite Properties")]
                Mdc = 0x01,
   
                /// <summary>
  @@ -187,6 +175,11 @@
                Exception = 0x100,
   
                /// <summary>
  +             /// Fix the event properties
  +             /// </summary>
  +             Properties = 0x200,
  +
  +             /// <summary>
                /// No fields fixed
                /// </summary>
                None = 0x0,
  @@ -204,15 +197,15 @@
                /// This set of partial fields gives good performance. The 
following fields are fixed:
                /// </para>
                /// <list type="bullet">
  -             /// <item><description><see cref="Mdc"/></description></item>
                /// <item><description><see cref="Ndc"/></description></item>
                /// <item><description><see 
cref="Message"/></description></item>
                /// <item><description><see 
cref="ThreadName"/></description></item>
                /// <item><description><see 
cref="Exception"/></description></item>
                /// <item><description><see cref="Domain"/></description></item>
  +             /// <item><description><see 
cref="Properties"/></description></item>
                /// </list>
                /// </remarks>
  -             Partial = Mdc | Ndc | Message | ThreadName | Exception | Domain,
  +             Partial = Ndc | Message | ThreadName | Exception | Domain | 
Properties,
        }
   
        /// <summary>
  @@ -281,9 +274,6 @@
   
                        // Store the event creation time
                        m_data.TimeStamp = DateTime.Now;
  -
  -                     // Lookup the global properties as soon as possible
  -                     m_data.GlobalProperties = 
log4net.GlobalContext.Properties.GetReadOnlyProperties();
                }
   
                /// <summary>
  @@ -354,7 +344,6 @@
                        m_data.Level = (Level)info.GetValue("Level", 
typeof(Level));
   
                        m_data.Ndc = info.GetString("Ndc");
  -                     m_data.Mdc = (IDictionary) info.GetValue("Mdc", 
typeof(IDictionary));
                        m_data.Message = info.GetString("Message");
                        m_data.ThreadName = info.GetString("ThreadName");
                        m_data.TimeStamp = info.GetDateTime("TimeStamp");
  @@ -362,7 +351,6 @@
                        m_data.UserName = info.GetString("UserName");
                        m_data.ExceptionString = 
info.GetString("ExceptionString");
                        m_data.Properties = (PropertiesDictionary) 
info.GetValue("Properties", typeof(PropertiesDictionary));
  -                     m_data.GlobalProperties = 
(ReadOnlyPropertiesDictionary) info.GetValue("GlobalProperties", 
typeof(ReadOnlyPropertiesDictionary));
                        m_data.Domain = info.GetString("Domain");
                        m_data.Identity = info.GetString("Identity");
                }
  @@ -465,43 +453,27 @@
                        }
                }
   
  -             /// <summary>
  -             /// Gets the text of the <see cref="NDC"/>.
  -             /// </summary>
  -             /// <value>
  -             /// The text of the <see cref="NDC"/>.
  -             /// </value>
  -             public string NestedContext
  -             {
  -                     get
  -                     {
  -                             if (m_data.Ndc == null) 
  -                             {
  -                                     m_data.Ndc = NDC.Get();
  -                                     if (m_data.Ndc == null)
  -                                     {
  -                                             m_data.Ndc = "";
  -                                     }
  -                             }
  -                             return m_data.Ndc; 
  -                     }
  -             }
  -
  -             /// <summary>
  -             /// Get the MDC dictionary.
  -             /// </summary>
  -             public IDictionary MappedContext
  -             {
  -                     get
  -                     {
  -                             if (m_data.Mdc == null)
  -                             {
  -                                     // This creates a live copy of the MDC
  -                                     m_data.Mdc = MDC.GetMap();
  -                             }
  -                             return m_data.Mdc;
  -                     }
  -             }
  +//           /// <summary>
  +//           /// Gets the text of the <see cref="ThreadContext.Stacks"/>.
  +//           /// </summary>
  +//           /// <value>
  +//           /// The text of the <see cref="ThreadContext.Stacks"/>.
  +//           /// </value>
  +//           public string NestedContext
  +//           {
  +//                   get
  +//                   {
  +//                           if (m_data.Ndc == null) 
  +//                           {
  +//                                   m_data.Ndc = 
ThreadContext.Stack.GetFullMessage();
  +//                                   if (m_data.Ndc == null)
  +//                                   {
  +//                                           m_data.Ndc = "";
  +//                                   }
  +//                           }
  +//                           return m_data.Ndc; 
  +//                   }
  +//           }
   
                /// <summary>
                /// Gets the message object used to initialize this event.
  @@ -683,7 +655,8 @@
                                                        // some undefined set 
of SecurityPermission flags.
                                                        
LogLog.Debug("LoggingEvent: Security exception while trying to get current 
thread ID. Error Ignored. Empty thread name.");
   
  -                                                     m_data.ThreadName = "";
  +                                                     // As a last resort use 
the hash code of the Thread object
  +                                                     m_data.ThreadName = 
System.Threading.Thread.CurrentThread.GetHashCode().ToString();
                                                }
                                        }
   #endif
  @@ -836,45 +809,27 @@
                /// Additional event specific properties.
                /// </value>
                /// <remarks>
  +             /// <para>
                /// A logger or an appender may attach additional
                /// properties to specific events. These properties
                /// have a string key and an object value.
  +             /// </para>
  +             /// <para>
  +             /// This property is for events that have been added directly to
  +             /// this event. The aggregate properties (which include these
  +             /// event properties) can be retrieved using <see 
cref="LookupProperty"/>
  +             /// and <see cref="GetProperties"/>.
  +             /// </para>
                /// </remarks>
  -             public PropertiesDictionary Properties
  -             {
  -                     get 
  -                     { 
  -                             if (m_data.Properties == null)
  -                             {
  -                                     m_data.Properties = new 
PropertiesDictionary();
  -                             }
  -                             return m_data.Properties; 
  -                     }
  -             }
  -
  -             /// <summary>
  -             /// Gets the global properties defined when this event was 
created.
  -             /// </summary>
  -             /// <value>
  -             /// Globally defined properties.
  -             /// </value>
  -             /// <remarks>
  -             /// Global properties are defined by the <see 
cref="GlobalContext"/>
  -             /// </remarks>
  -             public ReadOnlyPropertiesDictionary GlobalProperties
  +             public PropertiesDictionary EventProperties
                {
                        get 
                        { 
  -                             // The global properties are captured in the 
constructor
  -                             // because they are global shared state they 
must be captured as soon as possible
  -
  -                             if (m_data.GlobalProperties == null)
  +                             if (m_eventProperties == null)
                                {
  -                                     // Just in case for some reason this is 
null set it to an empty collection
  -                                     // callers do not expect this property 
to return null
  -                                     m_data.GlobalProperties = new 
ReadOnlyPropertiesDictionary();
  +                                     m_eventProperties = new 
PropertiesDictionary();
                                }
  -                             return m_data.GlobalProperties; 
  +                             return m_eventProperties; 
                        }
                }
   
  @@ -926,7 +881,6 @@
                        info.AddValue("LoggerName", m_data.LoggerName);
                        info.AddValue("Level", m_data.Level);
                        info.AddValue("Ndc", m_data.Ndc);
  -                     info.AddValue("Mdc", m_data.Mdc);
                        info.AddValue("Message", m_data.Message);
                        info.AddValue("ThreadName", m_data.ThreadName);
                        info.AddValue("TimeStamp", m_data.TimeStamp);
  @@ -934,7 +888,6 @@
                        info.AddValue("UserName", m_data.UserName);
                        info.AddValue("ExceptionString", 
m_data.ExceptionString);
                        info.AddValue("Properties", m_data.Properties);
  -                     info.AddValue("GlobalProperties", 
m_data.GlobalProperties);
                        info.AddValue("Domain", m_data.Domain);
                        info.AddValue("Identity", m_data.Identity);
                }
  @@ -978,23 +931,6 @@
                }
   
                /// <summary>
  -             /// Looks up the specified key in the <see cref="MDC"/>.
  -             /// </summary>
  -             /// <param name="key">The key to lookup.</param>
  -             /// <returns>
  -             /// The value associated with the key, or <c>null</c> if the 
key was not found.
  -             /// </returns>
  -             public string LookupMappedContext(string key)
  -             {
  -                     if (m_data.Mdc == null)
  -                     {
  -                             // This creates a live copy of the MDC
  -                             m_data.Mdc = MDC.GetMap();
  -                     }
  -                     return m_data.Mdc[key] as string;
  -             }
  -
  -             /// <summary>
                /// Returns this event's exception's rendered using the 
                /// <see cref="ILoggerRepository.RendererMap" />.
                /// </summary>
  @@ -1131,20 +1067,13 @@
   
                        if (updateFlags > 0)
                        {
  -                             if ((updateFlags & FixFlags.Mdc) != 0)
  -                             {
  -                                     // Force the MDC to be cached
  -                                     CacheMappedContext();
  -
  -                                     m_fixFlags |= FixFlags.Mdc;
  -                             }
  -                             if ((updateFlags & FixFlags.Ndc) != 0)
  -                             {
  -                                     // Force the NDC to be cached
  -                                     string tmp = this.NestedContext;
  -
  -                                     m_fixFlags |= FixFlags.Ndc;
  -                             }
  +//                           if ((updateFlags & FixFlags.Ndc) != 0)
  +//                           {
  +//                                   // Force the NDC to be cached
  +//                                   string tmp = this.NestedContext;
  +//
  +//                                   m_fixFlags |= FixFlags.Ndc;
  +//                           }
                                if ((updateFlags & FixFlags.Message) != 0)
                                {
                                        // Force the message to be rendered
  @@ -1203,6 +1132,13 @@
   
                                        m_fixFlags |= FixFlags.Exception;
                                }
  +
  +                             if ((updateFlags & FixFlags.Properties) != 0)
  +                             {
  +                                     CacheProperties();
  +
  +                                     m_fixFlags |= FixFlags.Properties;
  +                             }
                        }
                }
   
  @@ -1210,16 +1146,125 @@
   
                #region Protected Instance Methods
   
  +             private void CreateCompositeProperties()
  +             {
  +                     m_compositeProperties = new CompositeProperties();
  +
  +                     if (m_eventProperties != null)
  +                     {
  +                             m_compositeProperties.Add(m_eventProperties);
  +                     }
  +                     
m_compositeProperties.Add(ThreadContext.Properties.GetProperties());
  +
  +                     // TODO: Add Repository Properties
  +
  +                     
m_compositeProperties.Add(GlobalContext.Properties.GetReadOnlyProperties());
  +             }
  +
  +             private void CacheProperties()
  +             {
  +                     if (m_data.Properties == null)
  +                     {
  +                             if (m_compositeProperties == null)
  +                             {
  +                                     CreateCompositeProperties();
  +                             }
  +
  +                             PropertiesDictionary flattenedProperties = 
m_compositeProperties.Flatten();
  +
  +                             PropertiesDictionary fixedProperties = new 
PropertiesDictionary();
  +
  +                             // Fix any IFixingRequired objects
  +                             foreach(DictionaryEntry entry in 
flattenedProperties)
  +                             {
  +                                     string key = (string)entry.Key;
  +                                     object val = entry.Value;
  +
  +                                     IFixingRequired fixingRequired = val as 
IFixingRequired;
  +                                     if (fixingRequired != null)
  +                                     {
  +                                             val = 
fixingRequired.GetFixedObject();
  +                                     }
  +
  +                                     fixedProperties[key] = val;
  +                             }
  +
  +                             m_data.Properties = fixedProperties;
  +                     }
  +             }
  +
  +             /// <summary>
  +             /// Lookup a composite property in this event
  +             /// </summary>
  +             /// <param name="key">the key for the property to lookup</param>
  +             /// <returns>the value for the property</returns>
  +             /// <remarks>
  +             /// <para>
  +             /// This event has composite properties that combine together 
properties from
  +             /// several different contexts in the following order:
  +             /// <list type="definition">
  +             ///             <item>
  +             ///             <term>this events properties</term>
  +             ///             <description>
  +             ///             This event has <see cref="EventProperties"/> 
that can be set. These 
  +             ///             properties are specific to this event only.
  +             ///             </description>
  +             ///     </item>
  +             ///     <item>
  +             ///             <term>the thread properties</term>
  +             ///             <description>
  +             ///             The <see cref="ThreadContext.Properties"/> that 
are set on the current
  +             ///             thread. These properties are shared by all 
events logged on this thread.
  +             ///             </description>
  +             ///     </item>
  +             ///     <item>
  +             ///             <term>the global properties</term>
  +             ///             <description>
  +             ///             The <see cref="GlobalContext.Properties"/> that 
are set globally. These 
  +             ///             properties are shared by all the threads in the 
AppDomain.
  +             ///             </description>
  +             ///     </item>
  +             /// </list>
  +             /// </para>
  +             /// </remarks>
  +             public object LookupProperty(string key)
  +             {
  +                     if (m_data.Properties != null)
  +                     {
  +                             return m_data.Properties[key];
  +                     }
  +                     if (m_compositeProperties == null)
  +                     {
  +                             CreateCompositeProperties();
  +                     }
  +                     return m_compositeProperties[key];
  +             }
  +
                /// <summary>
  -             /// Creates a cached copy of the <see cref="MDC" />.
  +             /// Get all the composite properties in this event
                /// </summary>
  -             protected void CacheMappedContext()
  +             /// <returns>the <see cref="PropertiesDictionary"/> containing 
all the properties</returns>
  +             /// <remarks>
  +             /// <para>
  +             /// See <see cref="LookupProperty"/> for details of the 
composite properties 
  +             /// stored by the event.
  +             /// </para>
  +             /// <para>
  +             /// This method returns a single <see 
cref="PropertiesDictionary"/> containing all the
  +             /// properties defined for this event.
  +             /// </para>
  +             /// </remarks>
  +             public PropertiesDictionary GetProperties()
                {
  -                     // Copy the MDC dictionary
  -                     if (m_data.Mdc == null || m_data.Mdc.IsReadOnly == 
false)
  +                     if (m_data.Properties != null)
  +                     {
  +                             return m_data.Properties;
  +                     }
  +                     if (m_compositeProperties == null)
                        {
  -                             m_data.Mdc = MDC.CopyMap();
  +                             CreateCompositeProperties();
                        }
  +                     return m_compositeProperties.Flatten();
                }
   
                #endregion Public Instance Methods
  @@ -1232,6 +1277,16 @@
                private LoggingEventData m_data;
   
                /// <summary>
  +             /// The internal logging event data.
  +             /// </summary>
  +             private CompositeProperties m_compositeProperties;
  +
  +             /// <summary>
  +             /// The internal logging event data.
  +             /// </summary>
  +             private PropertiesDictionary m_eventProperties;
  +
  +             /// <summary>
                /// The fully qualified classname of the calling 
                /// logger class.
                /// </summary>
  @@ -1273,17 +1328,17 @@
                #region Constants
   
                /// <summary>
  -             /// The key into the <see cref="Properties"/> map for the host 
name value.
  +             /// The key into the Properties map for the host name value.
                /// </summary>
                public const string HostNameProperty = "log4net:HostName";
   
                /// <summary>
  -             /// The key into the <see cref="Properties"/> map for the 
thread identity value.
  +             /// The key into the Properties map for the thread identity 
value.
                /// </summary>
                public const string IdentityProperty = "log4net:Identity";
   
                /// <summary>
  -             /// The key into the <see cref="Properties"/> map for the user 
name value.
  +             /// The key into the Properties map for the user name value.
                /// </summary>
                public const string UserNameProperty = "log4net:UserName";
   
  
  
  
  1.1                  logging-log4net/src/Core/IFixingRequired.cs
  
  Index: IFixingRequired.cs
  ===================================================================
  #region Copyright & License
  //
  // Copyright 2001-2004 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;
  
  namespace log4net.Core
  {
        /// <summary>
        /// Interface that indicates that the object requires fixing before it
        /// can be taken outside the context of the appender's DoAppend method.
        /// </summary>
        /// <author>Nicko Cadell</author>
        public interface IFixingRequired
        {
                /// <summary>
                /// Get a portable version of this object
                /// </summary>
                /// <returns>the portable instance of this object</returns>
                object GetFixedObject();
        }
  }
  
  
  
  1.5       +5 -2      logging-log4net/src/Filter/MdcFilter.cs
  
  Index: MdcFilter.cs
  ===================================================================
  RCS file: /home/cvs/logging-log4net/src/Filter/MdcFilter.cs,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- MdcFilter.cs      30 May 2004 11:04:08 -0000      1.4
  +++ MdcFilter.cs      9 Sep 2004 21:53:13 -0000       1.5
  @@ -180,9 +180,12 @@
                                return FilterDecision.Neutral;
                        }
   
  -                     // Lookup the string to match in from the MDC using 
  +                     // Lookup the string to match in from the properties 
using 
                        // the key specified.
  -                     string msg = loggingEvent.LookupMappedContext(m_key);
  +                     object msgObj = loggingEvent.LookupProperty(m_key);
  +
  +                     // Use an ObjectRenderer to convert the property value 
to a string
  +                     string msg = 
loggingEvent.Repository.RendererMap.FindAndRender(msgObj);
   
                        // Check if we have been setup to filter
                        if (msg == null || (m_stringToMatch == null && 
m_regexToMatch == null))
  
  
  
  1.5       +11 -1     logging-log4net/src/Filter/NdcFilter.cs
  
  Index: NdcFilter.cs
  ===================================================================
  RCS file: /home/cvs/logging-log4net/src/Filter/NdcFilter.cs,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- NdcFilter.cs      30 May 2004 11:04:08 -0000      1.4
  +++ NdcFilter.cs      9 Sep 2004 21:53:13 -0000       1.5
  @@ -156,7 +156,17 @@
                                throw new ArgumentNullException("loggingEvent");
                        }
   
  -                     string msg = loggingEvent.NestedContext;
  +                     string msg = null;
  +
  +                     object msgObj = loggingEvent.LookupProperty("NDC");
  +                     if (msgObj is string)
  +                     {
  +                             msg = (string)msgObj;
  +                     }
  +                     else if (msgObj is ThreadContextStack)
  +                     {
  +                             msg = 
((ThreadContextStack)msgObj).GetFullMessage();
  +                     }
   
                        // Check if we have been setup to filter
                        if (msg == null || (m_stringToMatch == null && 
m_regexToMatch == null))
  
  
  
  1.1                  logging-log4net/src/Filter/PropertyFilter.cs
  
  Index: PropertyFilter.cs
  ===================================================================
  #region Copyright & License
  //
  // Copyright 2001-2004 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.Text.RegularExpressions;
  
  using log4net;
  using log4net.Core;
  using log4net.Util;
  
  namespace log4net.Filter
  {
        /// <summary>
        /// Simple filter to match a string in the event properties
        /// </summary>
        /// <remarks>
        /// Simple filter to match a string in the event properties
        /// </remarks>
        /// <author>Nicko Cadell</author>
        public class PropertyFilter : FilterSkeleton
        {
                #region Member Variables
  
                /// <summary>
                /// Flag to indicate the behavior when we have a match
                /// </summary>
                private bool m_acceptOnMatch = true;
  
                /// <summary>
                /// The string to substring match against the message
                /// </summary>
                private string m_stringToMatch;
  
                /// <summary>
                /// A string regex to match
                /// </summary>
                private string m_stringRegexToMatch;
  
                /// <summary>
                /// A regex object to match (generated from 
m_stringRegexToMatch)
                /// </summary>
                private Regex m_regexToMatch;
  
                /// <summary>
                /// The key to use to lookup the string from the event 
properties
                /// </summary>
                private string m_key;
  
                #endregion
  
                #region Constructors
  
                /// <summary>
                /// Default constructor
                /// </summary>
                public PropertyFilter()
                {
                }
  
                #endregion
  
                #region Implementation of IOptionHandler
  
                /// <summary>
                /// Initialize and precompile the Regex if required
                /// </summary>
                /// <remarks>
                /// <para>
                /// This is part of the <see cref="IOptionHandler"/> delayed 
object
                /// activation scheme. The <see cref="ActivateOptions"/> method 
must 
                /// be called on this object after the configuration properties 
have
                /// been set. Until <see cref="ActivateOptions"/> is called this
                /// object is in an undefined state and must not be used. 
                /// </para>
                /// <para>
                /// If any of the configuration properties are modified then 
                /// <see cref="ActivateOptions"/> must be called again.
                /// </para>
                /// </remarks>
                override public void ActivateOptions() 
                {
                        if (m_stringRegexToMatch != null)
                        {
                                m_regexToMatch = new 
Regex(m_stringRegexToMatch, RegexOptions.Compiled);
                        }
                }
  
                #endregion
  
                /// <summary>
                /// The <see cref="AcceptOnMatch"/> property is a flag that 
determines
                /// the behavior when a matching <see cref="Level"/> is found. 
If the
                /// flag is set to true then the filter will <see 
cref="FilterDecision.Accept"/> the 
                /// logging event, otherwise it will <see 
cref="FilterDecision.Deny"/> the event.
                /// </summary>
                public bool AcceptOnMatch
                {
                        get { return m_acceptOnMatch; }
                        set { m_acceptOnMatch = value; }
                }
  
                /// <summary>
                /// The string that will be substring matched against
                /// the rendered message. If the message contains this
                /// string then the filter will match.
                /// </summary>
                public string StringToMatch
                {
                        get { return m_stringToMatch; }
                        set { m_stringToMatch = value; }
                }
  
                /// <summary>
                /// The regular expression pattern that will be matched against
                /// the rendered message. If the message matches this
                /// pattern then the filter will match.
                /// </summary>
                public string RegexToMatch
                {
                        get { return m_stringRegexToMatch; }
                        set { m_stringRegexToMatch = value; }
                }
  
                /// <summary>
                /// The key to lookup in the event properties and then match 
against.
                /// </summary>
                public string Key
                {
                        get { return m_key; }
                        set { m_key = value; }
                }
  
                #region Override implementation of FilterSkeleton
  
                /// <summary>
                /// Check if this filter should allow the event to be logged
                /// </summary>
                /// <remarks>
                /// The event property for the <see cref="Key"/> is matched 
against 
                /// the <see cref="StringToMatch"/>.
                /// If the <see cref="StringToMatch"/> occurs as a substring 
within
                /// the property value then a match will have occurred. If no 
match occurs
                /// this function will return <see 
cref="FilterDecision.Neutral"/>
                /// allowing other filters to check the event. If a match 
occurs then
                /// the value of <see cref="AcceptOnMatch"/> is checked. If it 
is
                /// true then <see cref="FilterDecision.Accept"/> is returned 
otherwise
                /// <see cref="FilterDecision.Deny"/> is returned.
                /// </remarks>
                /// <param name="loggingEvent">the event being logged</param>
                /// <returns>see remarks</returns>
                override public FilterDecision Decide(LoggingEvent 
loggingEvent) 
                {
                        if (loggingEvent == null)
                        {
                                throw new ArgumentNullException("loggingEvent");
                        }
  
                        // Check if we have a key to lookup the event property 
value with
                        if (m_key == null)
                        {
                                // We cannot filter so allow the filter chain
                                // to continue processing
                                return FilterDecision.Neutral;
                        }
  
                        // Lookup the string to match in from the properties 
using 
                        // the key specified.
                        object msgObj = loggingEvent.LookupProperty(m_key);
  
                        // Use an ObjectRenderer to convert the property value 
to a string
                        string msg = 
loggingEvent.Repository.RendererMap.FindAndRender(msgObj);
  
                        // Check if we have been setup to filter
                        if (msg == null || (m_stringToMatch == null && 
m_regexToMatch == null))
                        {
                                // We cannot filter so allow the filter chain
                                // to continue processing
                                return FilterDecision.Neutral;
                        }
      
                        // Firstly check if we are matching using a regex
                        if (m_regexToMatch != null)
                        {
                                // Check the regex
                                if (m_regexToMatch.Match(msg).Success == false)
                                {
                                        // No match, continue processing
                                        return FilterDecision.Neutral;
                                } 
  
                                // we've got a match
                                if (m_acceptOnMatch) 
                                {
                                        return FilterDecision.Accept;
                                } 
                                return FilterDecision.Deny;
                        }
                        else if (m_stringToMatch != null)
                        {
                                // Check substring match
                                if (msg.IndexOf(m_stringToMatch) == -1) 
                                {
                                        // No match, continue processing
                                        return FilterDecision.Neutral;
                                } 
  
                                // we've got a match
                                if (m_acceptOnMatch) 
                                {
                                        return FilterDecision.Accept;
                                } 
                                return FilterDecision.Deny;
                        }
                        return FilterDecision.Neutral;
                }
  
                #endregion
        }
  }
  
  
  
  1.10      +43 -34    logging-log4net/src/Layout/PatternLayout.cs
  
  Index: PatternLayout.cs
  ===================================================================
  RCS file: /home/cvs/logging-log4net/src/Layout/PatternLayout.cs,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- PatternLayout.cs  19 Aug 2004 21:18:47 -0000      1.9
  +++ PatternLayout.cs  9 Sep 2004 21:53:13 -0000       1.10
  @@ -164,24 +164,6 @@
        ///                     </description>
        ///             </item>
        ///             <item>
  -     ///                     <term>global</term>
  -     ///                     <description>
  -     ///                     <para>
  -     ///                     Used to output the a global property. The key 
to 
  -     ///                     lookup must be specified within braces and 
directly following the
  -     ///                     pattern specifier, e.g. <b>%global{user}</b> 
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 added to events by loggers or 
appenders. By default
  -     ///                     no properties are defined.
  -     ///                     </para>
  -     ///                     <para>
  -     ///                     If no key is specified, e.g. <b>%global</b> 
then all the keys and their
  -     ///                     values are printed in a comma separated list.
  -     ///                     </para>
  -     ///                     </description>
  -     ///             </item>
  -     ///             <item>
        ///                     <term>identity</term>
        ///                     <description>
        ///                             <para>
  @@ -292,16 +274,9 @@
        ///                     <term>mdc</term>
        ///                     <description>
        ///                     <para>
  -     ///                     Used to output the MDC (mapped diagnostic 
context) associated
  -     ///                     with the thread that generated the logging 
event. The key to lookup
  -     ///                     must be specified within braces and directly 
following the
  -     ///                     pattern specifier, e.g. <c>%mdc{user}</c> would 
include the value
  -     ///                     from the MDC that is keyed by the string 
'user'. Each MDC value
  -     ///                     that is to be included in the log must be 
specified separately.
  -     ///                     </para>
  -     ///                     <para>
  -     ///                     If no key is specified, e.g. <b>%mdc</b> then 
all the keys and their
  -     ///                     values are printed in a comma separated list.
  +     ///                     The MDC (old name for the 
ThreadContext.Properties) is now part of the
  +     ///                     combined event properties. This pattern is 
supported for compatibility
  +     ///                     but is equivalent to <b>property</b>.
        ///                     </para>
        ///                     </description>
        ///             </item>
  @@ -357,6 +332,10 @@
        ///         <term>P</term>
        ///         <description>Equivalent to <b>property</b></description>
        ///     </item>
  +     ///     <item>
  +     ///         <term>properties</term>
  +     ///         <description>Equivalent to <b>property</b></description>
  +     ///     </item>
        ///             <item>
        ///                     <term>property</term>
        ///                     <description>
  @@ -366,13 +345,42 @@
        ///                     pattern specifier, e.g. <b>%property{user}</b> 
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 added to events by loggers or 
appenders. By default
  -     ///                     no properties are defined.
  +     ///                     Properties are added to events by loggers or 
appenders. By default 
  +     ///                     the <c>log4net:HostName</c> property is set to 
the name of machine on 
  +     ///                     which the event was originally logged.
        ///                     </para>
        ///                     <para>
        ///                     If no key is specified, e.g. <b>%property</b> 
then all the keys and their
        ///                     values are printed in a comma separated list.
        ///                     </para>
  +     ///                     <para>
  +     ///                     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.
  +     ///                     </para>
  +     ///                     <list type="definition">
  +     ///                             <item>
  +     ///                                     <term>the event 
properties</term>
  +     ///                                     <description>
  +     ///                                     The event has <see 
cref="LoggingEvent.EventProperties"/> that can be set. These 
  +     ///                                     properties are specific to this 
event only.
  +     ///                                     </description>
  +     ///                             </item>
  +     ///                             <item>
  +     ///                                     <term>the thread 
properties</term>
  +     ///                                     <description>
  +     ///                                     The <see 
cref="ThreadContext.Properties"/> that are set on the current
  +     ///                                     thread. These properties are 
shared by all events logged on this thread.
  +     ///                                     </description>
  +     ///                             </item>
  +     ///                             <item>
  +     ///                                     <term>the global 
properties</term>
  +     ///                                     <description>
  +     ///                                     The <see 
cref="GlobalContext.Properties"/> that are set globally. These 
  +     ///                                     properties are shared by all 
the threads in the AppDomain.
  +     ///                                     </description>
  +     ///                             </item>
  +     ///                     </list>                         
  +     ///                     
        ///                     </description>
        ///             </item>
        ///     <item>
  @@ -702,8 +710,6 @@
                        s_globalRulesRegistry.Add("F", 
typeof(FileLocationPatternConverter));
                        s_globalRulesRegistry.Add("file", 
typeof(FileLocationPatternConverter));
   
  -                     s_globalRulesRegistry.Add("global", 
typeof(GlobalPropertyPatternConverter));
  -
                        s_globalRulesRegistry.Add("l", 
typeof(FullLocationPatternConverter));
                        s_globalRulesRegistry.Add("location", 
typeof(FullLocationPatternConverter));
   
  @@ -721,6 +727,7 @@
   
                        s_globalRulesRegistry.Add("P", 
typeof(PropertyPatternConverter));
                        s_globalRulesRegistry.Add("property", 
typeof(PropertyPatternConverter));
  +                     s_globalRulesRegistry.Add("properties", 
typeof(PropertyPatternConverter));
   
                        s_globalRulesRegistry.Add("r", 
typeof(RelativeTimePatternConverter));
                        s_globalRulesRegistry.Add("timestamp", 
typeof(RelativeTimePatternConverter));
  @@ -728,11 +735,13 @@
                        s_globalRulesRegistry.Add("t", 
typeof(ThreadPatternConverter));
                        s_globalRulesRegistry.Add("thread", 
typeof(ThreadPatternConverter));
   
  +                     // For backwards compatibility the NDC patters
                        s_globalRulesRegistry.Add("x", 
typeof(NdcPatternConverter));
                        s_globalRulesRegistry.Add("ndc", 
typeof(NdcPatternConverter));
   
  -                     s_globalRulesRegistry.Add("X", 
typeof(MdcPatternConverter));
  -                     s_globalRulesRegistry.Add("mdc", 
typeof(MdcPatternConverter));
  +                     // For backwards compatibility the MDC patters just do 
a property lookup
  +                     s_globalRulesRegistry.Add("X", 
typeof(PropertyPatternConverter));
  +                     s_globalRulesRegistry.Add("mdc", 
typeof(PropertyPatternConverter));
   
                        s_globalRulesRegistry.Add("a", 
typeof(AppDomainPatternConverter));
                        s_globalRulesRegistry.Add("appdomain", 
typeof(AppDomainPatternConverter));
  
  
  
  1.3       +2 -2      logging-log4net/src/Layout/RawPropertyLayout.cs
  
  Index: RawPropertyLayout.cs
  ===================================================================
  RCS file: /home/cvs/logging-log4net/src/Layout/RawPropertyLayout.cs,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- RawPropertyLayout.cs      16 Feb 2004 02:10:53 -0000      1.2
  +++ RawPropertyLayout.cs      9 Sep 2004 21:53:13 -0000       1.3
  @@ -49,7 +49,7 @@
                private string m_key;
   
                /// <summary>
  -             /// The name of the value to lookup in the <see 
cref="LoggingEvent.Properties"/> collection.
  +             /// The name of the value to lookup in the LoggingEvent 
Properties collection.
                /// </summary>
                public string Key
                {
  @@ -69,7 +69,7 @@
                /// </remarks>
                public virtual object Format(LoggingEvent loggingEvent)
                {
  -                     return loggingEvent.Properties[m_key];
  +                     return loggingEvent.LookupProperty(m_key);
                }
   
                #endregion
  
  
  
  1.7       +9 -66     logging-log4net/src/Layout/XMLLayout.cs
  
  Index: XMLLayout.cs
  ===================================================================
  RCS file: /home/cvs/logging-log4net/src/Layout/XMLLayout.cs,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- XMLLayout.cs      2 Aug 2004 09:44:11 -0000       1.6
  +++ XMLLayout.cs      9 Sep 2004 21:53:13 -0000       1.7
  @@ -153,8 +153,6 @@
                        {
                                m_elmEvent = m_prefix + ":" + ELM_EVENT;
                                m_elmMessage = m_prefix + ":" + ELM_MESSAGE;
  -                             m_elmNdc = m_prefix + ":" + ELM_NDC;
  -                             m_elmMdc = m_prefix + ":" + ELM_MDC;
                                m_elmProperties = m_prefix + ":" + 
ELM_PROPERTIES;
                                m_elmGlobalProperties = m_prefix + ":" + 
ELM_GLOBAL_PROPERTIES;
                                m_elmData = m_prefix + ":" + ELM_DATA;
  @@ -198,75 +196,24 @@
                        Transform.WriteEscapedXmlString(writer, 
loggingEvent.RenderedMessage);
                        writer.WriteEndElement();
   
  -                     if (loggingEvent.NestedContext != null && 
loggingEvent.NestedContext.Length > 0)
  -                     {
  -                             // Append the NDC text
  -                             writer.WriteStartElement(m_elmNdc);
  -                             Transform.WriteEscapedXmlString(writer, 
loggingEvent.NestedContext);
  -                             writer.WriteEndElement();
  -                     }
  +                     PropertiesDictionary properties = 
loggingEvent.GetProperties();
   
  -                     if (loggingEvent.MappedContext != null && 
loggingEvent.MappedContext.Count > 0)
  +                     // Append the properties text
  +                     if (properties.Count > 0)
                        {
  -                             // Append the MDC text
  -                             writer.WriteStartElement(m_elmMdc);
  -                             foreach(System.Collections.DictionaryEntry 
entry in loggingEvent.MappedContext)
  +                             writer.WriteStartElement(m_elmGlobalProperties);
  +                             foreach(System.Collections.DictionaryEntry 
entry in properties)
                                {
                                        writer.WriteStartElement(m_elmData);
                                        writer.WriteAttributeString(ATTR_NAME, 
(string)entry.Key);
   
  -                                     // TODO Should use an ObjectRenderer to 
convert to a string
  -                                     writer.WriteAttributeString(ATTR_VALUE, 
entry.Value.ToString());
  -                                     writer.WriteEndElement();
  -                             }
  -                             writer.WriteEndElement();
  -                     }
  -
  -                     if (loggingEvent.Properties != null)
  -                     {
  -                             // Append the properties text
  -                             string[] propKeys = 
loggingEvent.Properties.GetKeys();
  -                             if (propKeys.Length > 0)
  -                             {
  -                                     
writer.WriteStartElement(m_elmProperties);
  -                                     foreach(string key in propKeys)
  -                                     {
  -                                             
writer.WriteStartElement(m_elmData);
  -                                             
writer.WriteAttributeString(ATTR_NAME, key);
  -
  -                                             // TODO Should use an 
ObjectRenderer to convert to a string
  -                                             
writer.WriteAttributeString(ATTR_VALUE, 
loggingEvent.Properties[key].ToString());
  -                                             writer.WriteEndElement();
  -                                     }
  -                                     writer.WriteEndElement();
  -                             }
  -                     }
  +                                     // Use an ObjectRenderer to convert the 
object to a string
  +                                     string valueStr = 
loggingEvent.Repository.RendererMap.FindAndRender(entry.Value);
  +                                     writer.WriteAttributeString(ATTR_VALUE, 
valueStr);
   
  -                     if (loggingEvent.GlobalProperties != null)
  -                     {
  -                             // Append the properties text
  -                             string[] propKeys = 
loggingEvent.Properties.GetKeys();
  -                             if (loggingEvent.GlobalProperties.Count > 0)
  -                             {
  -                                     
writer.WriteStartElement(m_elmGlobalProperties);
  -                                     
foreach(System.Collections.DictionaryEntry entry in 
loggingEvent.GlobalProperties)
  -                                     {
  -                                             
writer.WriteStartElement(m_elmData);
  -                                             
writer.WriteAttributeString(ATTR_NAME, (string)entry.Key);
  -
  -                                             if (entry.Value == null)
  -                                             {
  -                                                     
writer.WriteAttributeString(ATTR_VALUE, "null");
  -                                             }
  -                                             else
  -                                             {
  -                                                     // TODO Should use an 
ObjectRenderer to convert to a string
  -                                                     
writer.WriteAttributeString(ATTR_VALUE, entry.Value.ToString());
  -                                             }
  -                                             writer.WriteEndElement();
  -                                     }
                                        writer.WriteEndElement();
                                }
  +                             writer.WriteEndElement();
                        }
   
                        string exceptionStr = loggingEvent.GetExceptionString();
  @@ -304,8 +251,6 @@
   
                private string m_elmEvent = ELM_EVENT;
                private string m_elmMessage = ELM_MESSAGE;
  -             private string m_elmNdc = ELM_NDC;
  -             private string m_elmMdc = ELM_MDC;
                private string m_elmData = ELM_DATA;
                private string m_elmProperties = ELM_PROPERTIES;
                private string m_elmGlobalProperties = ELM_GLOBAL_PROPERTIES;
  @@ -320,8 +265,6 @@
   
                private const string ELM_EVENT = "event";
                private const string ELM_MESSAGE = "message";
  -             private const string ELM_NDC = "ndc";
  -             private const string ELM_MDC = "mdc";
                private const string ELM_PROPERTIES = "properties";
                private const string ELM_GLOBAL_PROPERTIES = 
"global-properties";
                private const string ELM_DATA = "data";
  
  
  
  1.7       +31 -49    logging-log4net/src/Layout/XmlLayoutSchemaLog4j.cs
  
  Index: XmlLayoutSchemaLog4j.cs
  ===================================================================
  RCS file: /home/cvs/logging-log4net/src/Layout/XmlLayoutSchemaLog4j.cs,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- XmlLayoutSchemaLog4j.cs   19 Aug 2004 22:30:57 -0000      1.6
  +++ XmlLayoutSchemaLog4j.cs   9 Sep 2004 21:53:13 -0000       1.7
  @@ -123,6 +123,8 @@
   
                */
   
  +             /* Since log4j 1.3 the log4j:MDC has been combined into the 
log4j:properties element */
  +
                /// <summary>
                /// Actually do the writing of the xml
                /// </summary>
  @@ -132,44 +134,35 @@
                {
                        // Translate logging events for log4j
   
  -                     // Copy global properties
  -                     if (loggingEvent.GlobalProperties != null)
  -                     {
  -                             foreach(System.Collections.DictionaryEntry 
entry in loggingEvent.GlobalProperties)
  -                             {
  -                                     
loggingEvent.Properties[(string)entry.Key] = entry.Value;
  -                             }
  -                     }
  -
                        // Translate hostname property
  -                     if 
(loggingEvent.Properties[LoggingEvent.HostNameProperty] != null && 
  -                             loggingEvent.Properties["log4jmachinename"] == 
null)
  +                     if 
(loggingEvent.LookupProperty(LoggingEvent.HostNameProperty) != null && 
  +                             loggingEvent.LookupProperty("log4jmachinename") 
== null)
                        {
  -                             loggingEvent.Properties["log4jmachinename"] = 
loggingEvent.Properties[LoggingEvent.HostNameProperty];
  +                             
loggingEvent.GetProperties()["log4jmachinename"] = 
loggingEvent.LookupProperty(LoggingEvent.HostNameProperty);
                        }
   
                        // translate appdomain name
  -                     if (loggingEvent.Properties["log4japp"] == null && 
  +                     if (loggingEvent.LookupProperty("log4japp") == null && 
                                loggingEvent.Domain != null && 
                                loggingEvent.Domain.Length > 0)
                        {
  -                             loggingEvent.Properties["log4japp"] = 
loggingEvent.Domain;
  +                             loggingEvent.GetProperties()["log4japp"] = 
loggingEvent.Domain;
                        }
   
                        // translate identity name
                        if (loggingEvent.Identity != null && 
                                loggingEvent.Identity.Length > 0 && 
  -                             
loggingEvent.Properties[LoggingEvent.IdentityProperty] == null)
  +                             
loggingEvent.LookupProperty(LoggingEvent.IdentityProperty) == null)
                        {
  -                             
loggingEvent.Properties[LoggingEvent.IdentityProperty] = loggingEvent.Identity;
  +                             
loggingEvent.GetProperties()[LoggingEvent.IdentityProperty] = 
loggingEvent.Identity;
                        }
   
                        // translate user name
                        if (loggingEvent.UserName != null && 
                                loggingEvent.UserName.Length > 0 && 
  -                             
loggingEvent.Properties[LoggingEvent.UserNameProperty] == null)
  +                             
loggingEvent.LookupProperty(LoggingEvent.UserNameProperty) == null)
                        {
  -                             
loggingEvent.Properties[LoggingEvent.UserNameProperty] = loggingEvent.UserName;
  +                             
loggingEvent.GetProperties()[LoggingEvent.UserNameProperty] = 
loggingEvent.UserName;
                        }
   
                        // Write the start element
  @@ -192,48 +185,37 @@
                        Transform.WriteEscapedXmlString(writer, 
loggingEvent.RenderedMessage);
                        writer.WriteEndElement();
   
  -                     if (loggingEvent.NestedContext != null && 
loggingEvent.NestedContext.Length > 0)
  +                     object ndcObj = loggingEvent.LookupProperty("NDC");
  +                     if (ndcObj != null)
                        {
  -                             // Append the NDC text
  -                             writer.WriteStartElement("log4j:NDC");
  -                             Transform.WriteEscapedXmlString(writer, 
loggingEvent.NestedContext);
  -                             writer.WriteEndElement();
  -                     }
  +                             string valueStr = 
loggingEvent.Repository.RendererMap.FindAndRender(ndcObj);
   
  -                     if (loggingEvent.MappedContext != null && 
loggingEvent.MappedContext.Count > 0)
  -                     {
  -                             // Append the MDC text
  -                             writer.WriteStartElement("log4j:MDC");
  -                             foreach(System.Collections.DictionaryEntry 
entry in loggingEvent.MappedContext)
  +                             if (valueStr != null && valueStr.Length > 0)
                                {
  -                                     writer.WriteStartElement("log4j:data");
  -                                     writer.WriteAttributeString("name", 
(string)entry.Key);
  -
  -                                     // TODO: Use an ObjectRenderer to 
convert the object to a string
  -                                     writer.WriteAttributeString("value", 
entry.Value.ToString());
  +                                     // Append the NDC text
  +                                     writer.WriteStartElement("log4j:NDC");
  +                                     Transform.WriteEscapedXmlString(writer, 
valueStr);
                                        writer.WriteEndElement();
                                }
  -                             writer.WriteEndElement();
                        }
   
  -                     if (loggingEvent.Properties != null)
  +                     // Append the properties text
  +                     PropertiesDictionary properties = 
loggingEvent.GetProperties();
  +                     if (properties.Count > 0)
                        {
  -                             // Append the properties text
  -                             string[] propKeys = 
loggingEvent.Properties.GetKeys();
  -                             if (propKeys.Length > 0)
  +                             writer.WriteStartElement("log4j:properties");
  +                             foreach(System.Collections.DictionaryEntry 
entry in properties)
                                {
  -                                     
writer.WriteStartElement("log4j:properties");
  -                                     foreach(string key in propKeys)
  -                                     {
  -                                             
writer.WriteStartElement("log4j:data");
  -                                             
writer.WriteAttributeString("name", key);
  -
  -                                             // TODO: Use an ObjectRenderer 
to convert the object to a string
  -                                             
writer.WriteAttributeString("value", loggingEvent.Properties[key].ToString());
  -                                             writer.WriteEndElement();
  -                                     }
  +                                     writer.WriteStartElement("log4j:data");
  +                                     writer.WriteAttributeString("name", 
(string)entry.Key);
  +
  +                                     // Use an ObjectRenderer to convert the 
object to a string
  +                                     string valueStr = 
loggingEvent.Repository.RendererMap.FindAndRender(entry.Value);
  +                                     writer.WriteAttributeString("value", 
valueStr);
  +
                                        writer.WriteEndElement();
                                }
  +                             writer.WriteEndElement();
                        }
   
                        string exceptionStr = loggingEvent.GetExceptionString();
  
  
  
  1.3       +2 -1      logging-log4net/src/Layout/Pattern/NdcPatternConverter.cs
  
  Index: NdcPatternConverter.cs
  ===================================================================
  RCS file: 
/home/cvs/logging-log4net/src/Layout/Pattern/NdcPatternConverter.cs,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- NdcPatternConverter.cs    16 Feb 2004 02:10:53 -0000      1.2
  +++ NdcPatternConverter.cs    9 Sep 2004 21:53:14 -0000       1.3
  @@ -38,7 +38,8 @@
                /// <returns>the relevant location information</returns>
                override protected void Convert(TextWriter writer, LoggingEvent 
loggingEvent)
                {
  -                     writer.Write( loggingEvent.NestedContext );
  +                     // Write the value for the specified key
  +                     WriteObject(writer, loggingEvent.Repository, 
loggingEvent.LookupProperty("NDC"));
                }
        }
   }
  
  
  
  1.3       +2 -2      
logging-log4net/src/Layout/Pattern/PropertyPatternConverter.cs
  
  Index: PropertyPatternConverter.cs
  ===================================================================
  RCS file: 
/home/cvs/logging-log4net/src/Layout/Pattern/PropertyPatternConverter.cs,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- PropertyPatternConverter.cs       16 Feb 2004 02:10:53 -0000      1.2
  +++ PropertyPatternConverter.cs       9 Sep 2004 21:53:14 -0000       1.3
  @@ -43,12 +43,12 @@
                        if (Option != null)
                        {
                                // Write the value for the specified key
  -                             WriteObject(writer, loggingEvent.Repository, 
loggingEvent.Properties[Option]);
  +                             WriteObject(writer, loggingEvent.Repository, 
loggingEvent.LookupProperty(Option));
                        }
                        else
                        {
                                // Write all the key value pairs
  -                             WriteDictionary(writer, 
loggingEvent.Repository, loggingEvent.Properties);
  +                             WriteDictionary(writer, 
loggingEvent.Repository, loggingEvent.GetProperties());
                        }
                }
        }
  
  
  
  1.7       +1 -0      logging-log4net/src/Util/PatternString.cs
  
  Index: PatternString.cs
  ===================================================================
  RCS file: /home/cvs/logging-log4net/src/Util/PatternString.cs,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- PatternString.cs  19 Aug 2004 21:21:32 -0000      1.6
  +++ PatternString.cs  9 Sep 2004 21:53:14 -0000       1.7
  @@ -85,6 +85,7 @@
                        s_globalRulesRegistry.Add("processid", 
typeof(ProcessIdPatternConverter));
                        s_globalRulesRegistry.Add("random", 
typeof(RandomStringPatternConverter));
                        s_globalRulesRegistry.Add("username", 
typeof(UserNamePatternConverter));
  +                     s_globalRulesRegistry.Add("property", 
typeof(PropertyPatternConverter));
                }
   
                #endregion Static Constructor
  
  
  
  1.1                  logging-log4net/src/Util/CompositeProperties.cs
  
  Index: CompositeProperties.cs
  ===================================================================
  #region Copyright & License
  //
  // Copyright 2001-2004 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;
  
  namespace log4net.Util
  {
        /// <summary>
        /// This class aggregates several PropertiesDictionary collections 
together.
        /// </summary>
        /// <author>Nicko Cadell</author>
        public sealed class CompositeProperties
        {
                #region Private Instance Fields
  
                private PropertiesDictionary m_flattened = null;
                private ArrayList m_nestedProperties = new ArrayList();
  
                #endregion Private Instance Fields
  
                #region Public Instance Constructors
  
                /// <summary>
                /// Initializes a new instance of the <see 
cref="CompositeProperties" /> class.
                /// </summary>
                internal CompositeProperties()
                {
                }
  
                #endregion Public Instance Constructors
  
                #region Public Instance Properties
  
                /// <summary>
                /// Gets the value of a property
                /// </summary>
                /// <value>
                /// The value for the property with the specified key
                /// </value>
                public object this[string key]
                {
                        get 
                        {
                                // Look in the flattened properties first
                                if (m_flattened != null)
                                {
                                        return m_flattened[key];
                                }
  
                                // Look for the key in all the nested properties
                                foreach(ReadOnlyPropertiesDictionary cur in 
m_nestedProperties)
                                {
                                        if (cur.Contains(key))
                                        {
                                                return cur[key];
                                        }
                                }
                                return null;
                        }
                }
  
                #endregion Public Instance Properties
  
                #region Public Instance Methods
  
                /// <summary>
                /// Add a Properties Dictionary to this composite collection
                /// </summary>
                /// <param name="properties">the properties to add</param>
                /// <remarks>
                /// <para>
                /// Properties dictionaries added first take precedence over 
dictionaries added
                /// later.
                /// </para>
                /// </remarks>
                public void Add(ReadOnlyPropertiesDictionary properties)
                {
                        m_flattened = null;
                        m_nestedProperties.Add(properties);
                }
  
                /// <summary>
                /// Flatten this composite collection into a single properties 
dictionary
                /// </summary>
                /// <returns>the flattened dictionary</returns>
                public PropertiesDictionary Flatten()
                {
                        if (m_flattened == null)
                        {
                                m_flattened = new PropertiesDictionary();
  
                                for(int i=m_nestedProperties.Count; --i>=0; )
                                {
                                        ReadOnlyPropertiesDictionary cur = 
(ReadOnlyPropertiesDictionary)m_nestedProperties[i];
  
                                        foreach(DictionaryEntry entry in cur)
                                        {
                                                m_flattened[(string)entry.Key] 
= entry.Value;
                                        }
                                }
                        }
                        return m_flattened;
                }
  
                #endregion Public Instance Methods
        }
  }
  
  
  
  
  1.1                  logging-log4net/src/Util/ThreadContextList.cs
  
  Index: ThreadContextList.cs
  ===================================================================
  #region Copyright & License
  //
  // Copyright 2001-2004 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.Text;
  using System.Collections;
  
  using log4net.Core;
  
  namespace log4net.Util
  {
        /// <summary>
        /// Implementation of List for the <see cref="log4net.ThreadContext"/>
        /// </summary>
        /// <remarks>
        /// <para>
        /// </para>
        /// </remarks>
        /// <author>Nicko Cadell</author>
        public sealed class ThreadContextList : IFixingRequired
        {
                #region Private Static Fields
  
                /// <summary>
                /// The thread local data slot used to store the stack.
                /// </summary>
                private readonly ArrayList m_list = new ArrayList();
  
                #endregion Private Static Fields
  
                #region Public Instance Constructors
  
                /// <summary>
                /// Initializes a new instance of the <see 
cref="ThreadContextStack" /> class. 
                /// </summary>
                internal ThreadContextList()
                {
                }
  
                #endregion Public Instance Constructors
  
                #region Public Methods
  
                /// <summary>
                /// Clears all the contextual information held in this list.
                /// </summary>
                public void Clear() 
                {
                        m_list.Clear();
                }
  
                /// <summary>
                /// Append a message to this list
                /// </summary>
                /// <param name="message">the message to append to this 
list</param>
                public void Append(string message) 
                {
                        m_list.Add(message);
                }
  
                #endregion Public Methods
  
                #region Internal Methods
  
                /// <summary>
                /// Gets the current context information for this list.
                /// </summary>
                /// <returns>The current context information.</returns>
                internal string GetFullMessage() 
                {
                        if (m_list.Count > 1)
                        {
                                // Build message using a string builder
  
                                StringBuilder buf = new StringBuilder();
  
                                buf.Append((string)m_list[0]);
  
                                for(int i=1; i<m_list.Count; i++)
                                {
                                        buf.Append(' ');
                                        buf.Append((string)m_list[i]);
                                }
  
                                return buf.ToString();
                        }
                        else if (m_list.Count == 1)
                        {
                                // Only one element, just return it
                                return (string)m_list[0];
                        }
                        return null;
                }
    
                #endregion Internal Methods
  
                /// <summary>
                /// Gets the current context information for this list.
                /// </summary>
                /// <returns>Gets the current context information</returns>
                public override string ToString()
                {
                        return GetFullMessage();
                }
  
                /// <summary>
                /// Get a portable version of this object
                /// </summary>
                /// <returns>the portable instance of this object</returns>
                object IFixingRequired.GetFixedObject()
                {
                        return GetFullMessage();
                }
        }
  }
  
  
  
  1.1                  logging-log4net/src/Util/ThreadContextLists.cs
  
  Index: ThreadContextLists.cs
  ===================================================================
  #region Copyright & License
  //
  // Copyright 2001-2004 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;
  
  namespace log4net.Util
  {
        /// <summary>
        /// Implementation of Lists collection for the <see 
cref="log4net.ThreadContext"/>
        /// </summary>
        /// <remarks>
        /// <para>
        /// </para>
        /// </remarks>
        /// <author>Nicko Cadell</author>
        public sealed class ThreadContextLists
        {
                #region Public Instance Constructors
  
                /// <summary>
                /// Initializes a new instance of the <see 
cref="ThreadContextLists" /> class.
                /// </summary>
                internal ThreadContextLists()
                {
                }
  
                #endregion Public Instance Constructors
  
                #region Public Instance Properties
  
                /// <summary>
                /// Gets or sets the value of a property
                /// </summary>
                /// <value>
                /// The value for the property with the specified key
                /// </value>
                public ThreadContextList this[string key]
                {
                        get 
                        {
                                ThreadContextList list = null;
  
                                object propertyValue = 
ThreadContext.Properties[key];
                                if (propertyValue == null)
                                {
                                        // List does not exist, create
                                        list = new ThreadContextList();
                                        ThreadContext.Properties[key] = list;
                                }
                                else
                                {
                                        // Look for existing list
                                        list = propertyValue as 
ThreadContextList;
                                        if (list == null)
                                        {
                                                // Property is not set to a 
list!
                                                string propertyValueString = 
"(null)";
  
                                                try
                                                {
                                                        propertyValueString = 
propertyValue.ToString();
                                                }
                                                catch
                                                {
                                                }
  
                                                
LogLog.Error("ThreadContextLists: Request for list named ["+key+"] failed 
because a property with the same name exists which is a 
["+propertyValue.GetType().Name+"] with value ["+propertyValueString+"]");
  
                                                list = new ThreadContextList();
                                        }
                                }
  
                                return list;
                        }
                }
  
                #endregion Public Instance Properties
        }
  }
  
  
  
  
  1.1                  logging-log4net/src/Util/ThreadContextProperties.cs
  
  Index: ThreadContextProperties.cs
  ===================================================================
  #region Copyright & License
  //
  // Copyright 2001-2004 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;
  
  namespace log4net.Util
  {
        /// <summary>
        /// Implementation of Properties collection for the <see 
cref="log4net.ThreadContext"/>
        /// </summary>
        /// <remarks>
        /// <para>
        /// Class implements a collection of properties that is specific to 
each thread.
        /// The class is not synchronized as each thread has its own <see 
cref="PropertiesDictionary"/>.
        /// </para>
        /// </remarks>
        /// <author>Nicko Cadell</author>
        public sealed class ThreadContextProperties
        {
                #region Private Instance Fields
  
                /// <summary>
                /// The thread local data slot to use to store a 
PropertiesDictionary.
                /// </summary>
                private readonly static LocalDataStoreSlot s_threadLocalSlot = 
System.Threading.Thread.AllocateDataSlot();
  
                #endregion Private Instance Fields
  
                #region Public Instance Constructors
  
                /// <summary>
                /// Initializes a new instance of the <see 
cref="ThreadContextProperties" /> class.
                /// </summary>
                internal ThreadContextProperties()
                {
                }
  
                #endregion Public Instance Constructors
  
                #region Public Instance Properties
  
                /// <summary>
                /// Gets or sets the value of a property
                /// </summary>
                /// <value>
                /// The value for the property with the specified key
                /// </value>
                public object this[string key]
                {
                        get { return GetProperties()[key]; }
                        set { GetProperties()[key] = value; }
                }
  
                #endregion Public Instance Properties
  
                #region Public Instance Methods
  
                /// <summary>
                /// Remove a property
                /// </summary>
                /// <param name="key">the key for the entry to remove</param>
                public void Remove(string key)
                {
                        GetProperties().Remove(key);
                }
  
                /// <summary>
                /// Clear the global context properties
                /// </summary>
                public void Clear()
                {
                        GetProperties().Clear();
                }
  
                #endregion Public Instance Methods
  
                #region Internal Instance Methods
  
                /// <summary>
                /// Get the PropertiesDictionary stored in the 
LocalDataStoreSlot for this thread.
                /// </summary>
                /// <returns>the properties for this thread</returns>
                /// <remarks>
                /// <para>
                /// The collection returned is only to be used on the calling 
thread. If the
                /// caller needs to share the collection between different 
threads then the 
                /// caller must clone the collection before doings so.
                /// </para>
                /// </remarks>
                internal PropertiesDictionary GetProperties()
                {
                        PropertiesDictionary properties = 
(PropertiesDictionary)System.Threading.Thread.GetData(s_threadLocalSlot);
                        if (properties == null)
                        {
                                properties  = new PropertiesDictionary();
                                
System.Threading.Thread.SetData(s_threadLocalSlot, properties);
                        }
                        return properties;
                }
  
                #endregion Internal Instance Methods
        }
  }
  
  
  
  
  1.1                  logging-log4net/src/Util/ThreadContextStack.cs
  
  Index: ThreadContextStack.cs
  ===================================================================
  #region Copyright & License
  //
  // Copyright 2001-2004 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;
  
  #if !NETCF
  using System.Collections;
  #endif
  
  using log4net.Core;
  
  namespace log4net.Util
  {
        /// <summary>
        /// Implementation of Stack for the <see cref="log4net.ThreadContext"/>
        /// </summary>
        /// <remarks>
        /// <para>
        /// </para>
        /// </remarks>
        /// <author>Nicko Cadell</author>
        public sealed class ThreadContextStack : IFixingRequired
        {
                #region Private Static Fields
  
                /// <summary>
                /// The stack store.
                /// </summary>
                private readonly Stack m_stack = new Stack();
  
                #endregion Private Static Fields
  
                #region Public Instance Constructors
  
                /// <summary>
                /// Initializes a new instance of the <see 
cref="ThreadContextStack" /> class. 
                /// </summary>
                internal ThreadContextStack()
                {
                }
  
                #endregion Public Instance Constructors
  
                #region Public Methods
  
  //            /// <summary>
  //            /// Clears all the contextual information held in this stack.
  //            /// </summary>
  //            public void Clear() 
  //            {
  //                    m_stack.Clear();
  //            }
  
                /// <summary>
                /// Removes the top context from this stack.
                /// </summary>
                /// <remarks>
                /// Remove the top context from this stack, and return
                /// it to the caller. If this stack is empty then an
                /// empty string (not <see langword="null"/>) is returned.
                /// </remarks>
                /// <returns>
                /// The message in the context that was removed from the top 
                /// of this stack.
                /// </returns>
                public string Pop() 
                {
                        Stack stack = m_stack;
                        if (stack.Count > 0)
                        {
                                return ((StackFrame)(stack.Pop())).Message;
                        }
                        return "";
                }
  
                /// <summary>
                /// Pushes a new context message into this stack.
                /// </summary>
                /// <param name="message">The new context message.</param>
                /// <returns>
                /// An <see cref="IDisposable"/> that can be used to clean up 
the context stack.
                /// </returns>
                /// <remarks>
                /// Pushes a new context onto this stack. An <see 
cref="IDisposable"/>
                /// is returned that can be used to clean up this stack. This
                /// can be easily combined with the <c>using</c> keyword to 
scope the
                /// context.
                /// </remarks>
                /// <example>Simple example of using the <c>Push</c> method 
with the <c>using</c> keyword.
                /// <code>
                /// 
using(log4net.ThreadContext.Stacks["NDC"].Push("Stack_Message"))
                /// {
                ///             log.Warn("This should have an ThreadContext 
Stack message");
                ///     }
                /// </code>
                /// </example>
                public IDisposable Push(string message) 
                {
                        Stack stack = m_stack;
                        stack.Push(new StackFrame(message, (stack.Count>0) ? 
(StackFrame)stack.Peek() : null));
  
                        return new AutoPopStackFrame(stack, stack.Count - 1);
                }
  
                #endregion Public Methods
  
                #region Internal Methods
  
                /// <summary>
                /// Gets the current context information for this stack.
                /// </summary>
                /// <returns>The current context information.</returns>
                internal string GetFullMessage() 
                {
                        Stack stack = m_stack;
                        if (stack.Count > 0)
                        {
                                return ((StackFrame)(stack.Peek())).FullMessage;
                        }
                        return null;
                }
    
                #endregion Internal Methods
  
                /// <summary>
                /// Gets the current context information  for this stack.
                /// </summary>
                /// <returns>Gets the current context information</returns>
                public override string ToString()
                {
                        return GetFullMessage();
                }
  
                /// <summary>
                /// Get a portable version of this object
                /// </summary>
                /// <returns>the portable instance of this object</returns>
                object IFixingRequired.GetFixedObject()
                {
                        return GetFullMessage();
                }
  
                /// <summary>
                /// Inner class used to represent a single context frame in the 
stack.
                /// </summary>
                private sealed class StackFrame 
                {
                        #region Private Instance Fields
  
                        private readonly string m_message;
                        private readonly StackFrame m_parent;
                        private string m_fullMessage = null;
      
                        #endregion
  
                        #region Internal Instance Constructors
  
                        /// <summary>
                        /// Initializes a new instance of the <see 
cref="StackFrame" /> class
                        /// with the specified message and parent context.
                        /// </summary>
                        /// <param name="message">The message for this 
context.</param>
                        /// <param name="parent">The parent context in the 
chain.</param>
                        internal StackFrame(string message, StackFrame parent) 
                        {
                                m_message = message;
                                m_parent = parent;
  
                                if (parent == null) 
                                {
                                        m_fullMessage = message;
                                } 
                        }
  
                        #endregion Internal Instance Constructors
  
                        #region Internal Instance Properties
  
                        /// <summary>
                        /// Get the message.
                        /// </summary>
                        /// <value>The message.</value>
                        internal string Message
                        {
                                get { return m_message; }
                        }
  
                        /// <summary>
                        /// Gets the full text of the context down to the root 
level.
                        /// </summary>
                        /// <value>
                        /// The full text of the context down to the root level.
                        /// </value>
                        internal string FullMessage
                        {
                                get 
                                {
                                        if (m_fullMessage == null)
                                        {
                                                m_fullMessage = 
string.Concat(m_parent.FullMessage, " ", m_message);
                                        }
                                        return m_fullMessage; 
                                }
                        }
  
                        #endregion Internal Instance Properties
                }
  
                /// <summary>
                /// Struct returned from the <see 
cref="ThreadContextStack.Push"/> method.
                /// </summary>
                /// <remarks>
                /// This struct implements the <see cref="IDisposable"/> and is 
designed to be used
                /// with the <see langword="using"/> pattern to remove the 
stack frame at the end of the scope.
                /// </remarks>
                private struct AutoPopStackFrame : IDisposable
                {
                        #region Private Instance Fields
  
                        /// <summary>
                        /// The ThreadContextStack internal stack
                        /// </summary>
                        private Stack m_frameStack;
  
                        /// <summary>
                        /// The depth to trim the stack to when this instance 
is disposed
                        /// </summary>
                        private int m_frameDepth;
  
                        #endregion Private Instance Fields
  
                        #region Internal Instance Constructors
  
                        /// <summary>
                        /// Initializes a new instance of the <see 
cref="AutoPopStackFrame" /> class with
                        /// the specified stack and return depth.
                        /// </summary>
                        /// <param name="frameStack">The internal stack used by 
the ThreadContextStack.</param>
                        /// <param name="frameDepth">The depth to return the 
stack to when this object is disposed.</param>
                        internal AutoPopStackFrame(Stack frameStack, int 
frameDepth)
                        {
                                m_frameStack = frameStack;
                                m_frameDepth = frameDepth;
                        }
  
                        #endregion Internal Instance Constructors
  
                        #region Implementation of IDisposable
  
                        /// <summary>
                        /// Returns the stack to the correct depth.
                        /// </summary>
                        public void Dispose()
                        {
                                if (m_frameDepth >= 0 && m_frameStack != null)
                                {
                                        while(m_frameStack.Count > m_frameDepth)
                                        {
                                                m_frameStack.Pop();
                                        }
                                }
                        }
  
                        #endregion Implementation of IDisposable
                }
  
  #if NETCF
                /// <summary>
                /// Subclass of <see cref="System.Collections.Stack"/> to
                /// provide missing methods.
                /// </summary>
                /// <remarks>
                /// The Compact Framework version of the <see 
cref="System.Collections.Stack"/>
                /// class is missing the <c>Clear</c> and <c>Clone</c> methods.
                /// This subclass adds implementations of those missing methods.
                /// </remarks>
                public class Stack : System.Collections.Stack
                {
                        /// <summary>
                        /// Clears the stack of all elements.
                        /// </summary>
                        public void Clear()
                        {
                                while(Count > 0)
                                {
                                        Pop();
                                }
                        }
  
                        /// <summary>
                        /// Makes a shallow copy of the stack's elements.
                        /// </summary>
                        /// <returns>A new stack that has a shallow copy of the 
stack's elements.</returns>
                        public Stack Clone()
                        {
                                Stack res = new Stack();
                                object[] items = ToArray();
                                foreach(object item in items)
                                {
                                        res.Push(item);
                                }
                                return res;
                        }
                }
  #endif
        }
  }
  
  
  
  1.1                  logging-log4net/src/Util/ThreadContextStacks.cs
  
  Index: ThreadContextStacks.cs
  ===================================================================
  #region Copyright & License
  //
  // Copyright 2001-2004 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;
  
  namespace log4net.Util
  {
        /// <summary>
        /// Implementation of Stacks collection for the <see 
cref="log4net.ThreadContext"/>
        /// </summary>
        /// <remarks>
        /// <para>
        /// </para>
        /// </remarks>
        /// <author>Nicko Cadell</author>
        public sealed class ThreadContextStacks
        {
                #region Public Instance Constructors
  
                /// <summary>
                /// Initializes a new instance of the <see 
cref="ThreadContextStacks" /> class.
                /// </summary>
                internal ThreadContextStacks()
                {
                }
  
                #endregion Public Instance Constructors
  
                #region Public Instance Properties
  
                /// <summary>
                /// Gets or sets the value of a property
                /// </summary>
                /// <value>
                /// The value for the property with the specified key
                /// </value>
                public ThreadContextStack this[string key]
                {
                        get 
                        {
                                ThreadContextStack stack = null;
  
                                object propertyValue = 
ThreadContext.Properties[key];
                                if (propertyValue == null)
                                {
                                        // Stack does not exist, create
                                        stack = new ThreadContextStack();
                                        ThreadContext.Properties[key] = stack;
                                }
                                else
                                {
                                        // Look for existing stack
                                        stack = propertyValue as 
ThreadContextStack;
                                        if (stack == null)
                                        {
                                                // Property is not set to a 
stack!
                                                string propertyValueString = 
"(null)";
  
                                                try
                                                {
                                                        propertyValueString = 
propertyValue.ToString();
                                                }
                                                catch
                                                {
                                                }
  
                                                
LogLog.Error("ThreadContextStacks: Request for stack named ["+key+"] failed 
because a property with the same name exists which is a 
["+propertyValue.GetType().Name+"] with value ["+propertyValueString+"]");
  
                                                stack = new 
ThreadContextStack();
                                        }
                                }
  
                                return stack;
                        }
                }
  
                #endregion Public Instance Properties
        }
  }
  
  
  
  
  1.1                  
logging-log4net/src/Util/PatternStringConverters/PropertyPatternConverter.cs
  
  Index: PropertyPatternConverter.cs
  ===================================================================
  #region Copyright & License
  //
  // Copyright 2001-2004 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.Text;
  using System.IO;
  using System.Collections;
  
  using log4net.Core;
  using log4net.Util;
  using log4net.Repository;
  
  namespace log4net.Util.PatternStringConverters
  {
        /// <summary>
        /// Property pattern converter
        /// </summary>
        /// <remarks>
        /// <para>
        /// This pattern converter reads the thread and global properties.
        /// The thread properties take priority over global properties.
        /// See <see cref="ThreadContext.Properties"/> for details of the 
        /// thread properties. See <see cref="GlobalContext.Properties"/> for
        /// details of the global properties.
        /// </para>
        /// <para>
        /// If the <see cref="PatternConverter.Option"/> is specified then that 
will be used to
        /// lookup a single property. If no <see 
cref="PatternConverter.Option"/> is specified
        /// then all properties will be dumped as a list of key value pairs.
        /// </para>
        /// </remarks>
        /// <author>Nicko Cadell</author>
        internal sealed class PropertyPatternConverter : PatternConverter 
        {
                /// <summary>
                /// Write the property or specified properties as required
                /// </summary>
                /// <param name="writer"><see cref="TextWriter" /> that will 
receive the formatted result.</param>
                /// <param name="state">reserved</param>
                /// <returns>the result of converting the pattern</returns>
                override protected void Convert(TextWriter writer, object 
state) 
                {
                        CompositeProperties compositeProperties = new 
CompositeProperties();
  
                        
compositeProperties.Add(ThreadContext.Properties.GetProperties());
                        // TODO: Add Repository Properties
                        
compositeProperties.Add(GlobalContext.Properties.GetReadOnlyProperties());
  
                        if (Option != null)
                        {
                                // Write the value for the specified key
                                WriteObject(writer, null, 
compositeProperties[Option]);
                        }
                        else
                        {
                                // Write all the key value pairs
                                WriteDictionary(writer, null, 
compositeProperties.Flatten());
                        }
                }
        }
  }
  
  
  

Reply via email to