logging-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dpsen...@apache.org
Subject svn commit: r1486883 - in /logging/log4net/trunk/src: ./ Core/ DateFormatter/ Layout/Pattern/
Date Tue, 28 May 2013 11:40:46 GMT
Author: dpsenner
Date: Tue May 28 11:40:46 2013
New Revision: 1486883

URL: http://svn.apache.org/r1486883
Log:
LOG4NET-341 fix location info to not contain a reference to StackFrame any more

Added:
    logging/log4net/trunk/src/Core/MethodItem.cs
    logging/log4net/trunk/src/Core/StackFrameItem.cs
Modified:
    logging/log4net/trunk/src/Core/LocationInfo.cs
    logging/log4net/trunk/src/DateFormatter/AbsoluteTimeDateFormatter.cs
    logging/log4net/trunk/src/Layout/Pattern/StackTraceDetailPatternConverter.cs
    logging/log4net/trunk/src/Layout/Pattern/StackTracePatternConverter.cs
    logging/log4net/trunk/src/log4net.vs2008.csproj
    logging/log4net/trunk/src/log4net.vs2010.csproj

Modified: logging/log4net/trunk/src/Core/LocationInfo.cs
URL: http://svn.apache.org/viewvc/logging/log4net/trunk/src/Core/LocationInfo.cs?rev=1486883&r1=1486882&r2=1486883&view=diff
==============================================================================
--- logging/log4net/trunk/src/Core/LocationInfo.cs (original)
+++ logging/log4net/trunk/src/Core/LocationInfo.cs Tue May 28 11:40:46 2013
@@ -118,10 +118,10 @@ namespace log4net.Core
 						// take into account the frames we skip above
 						int adjustedFrameCount = st.FrameCount - frameIndex;
                         ArrayList stackFramesList = new ArrayList(adjustedFrameCount);
-						m_stackFrames = new StackFrame[adjustedFrameCount];
+						m_stackFrames = new StackFrameItem[adjustedFrameCount];
 						for (int i=frameIndex; i < st.FrameCount; i++) 
 						{
-							stackFramesList.Add(st.GetFrame(i));
+							stackFramesList.Add(new StackFrameItem(st.GetFrame(i)));
 						}
 												
 						stackFramesList.CopyTo(m_stackFrames, 0);
@@ -275,7 +275,7 @@ namespace log4net.Core
 		/// <summary>
 		/// Gets the stack frames from the stack trace of the caller making the log request
 		/// </summary>
-		public StackFrame[] StackFrames
+		public StackFrameItem[] StackFrames
 		{
 			get { return m_stackFrames; }
 		}
@@ -291,7 +291,7 @@ namespace log4net.Core
 		private readonly string m_methodName;
 		private readonly string m_fullInfo;
 #if !NETCF
-		private readonly StackFrame[] m_stackFrames;
+		private readonly StackFrameItem[] m_stackFrames;
 #endif
 
 		#endregion Private Instance Fields

Added: logging/log4net/trunk/src/Core/MethodItem.cs
URL: http://svn.apache.org/viewvc/logging/log4net/trunk/src/Core/MethodItem.cs?rev=1486883&view=auto
==============================================================================
--- logging/log4net/trunk/src/Core/MethodItem.cs (added)
+++ logging/log4net/trunk/src/Core/MethodItem.cs Tue May 28 11:40:46 2013
@@ -0,0 +1,172 @@
+#region Apache License
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more 
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership. 
+// The ASF licenses this file to you under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with 
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#endregion
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Collections;
+
+using log4net.Util;
+
+namespace log4net.Core
+{
+	/// <summary>
+	/// provides method information without actually referencing a System.Reflection.MethodBase
+	/// as that would require that the containing assembly is loaded.
+	/// </summary>
+	/// 
+#if !NETCF
+	[Serializable]
+#endif
+	public class MethodItem
+	{
+		#region Public Instance Constructors
+
+		/// <summary>
+		/// constructs a method item for an unknown method.
+		/// </summary>
+		public MethodItem()
+		{
+			m_name = NA;
+			m_parameters = new string[0];
+		}
+
+		/// <summary>
+		/// constructs a method item from the name of the method.
+		/// </summary>
+		/// <param name="name"></param>
+		public MethodItem(string name)
+			: this()
+		{
+			m_name = name;
+		}
+
+		/// <summary>
+		/// constructs a method item from the name of the method and its parameters.
+		/// </summary>
+		/// <param name="name"></param>
+		/// <param name="parameters"></param>
+		public MethodItem(string name, string[] parameters)
+			: this(name)
+		{
+			m_parameters = parameters;
+		}
+
+        /// <summary>
+        /// constructs a method item from a method base by determining the method name and
its parameters.
+        /// </summary>
+        /// <param name="methodBase"></param>
+		public MethodItem(System.Reflection.MethodBase methodBase)
+			: this(methodBase.Name, GetMethodParameterNames(methodBase))
+        {
+		}
+
+		#endregion
+
+		private static string[] GetMethodParameterNames(System.Reflection.MethodBase methodBase)
+		{
+			ArrayList methodParameterNames = new ArrayList();
+			try
+			{
+				System.Reflection.ParameterInfo[] methodBaseGetParameters = methodBase.GetParameters();
+
+				int methodBaseGetParametersCount = methodBaseGetParameters.GetUpperBound(0);
+
+				for (int i = 0; i <= methodBaseGetParametersCount; i++)
+				{
+					methodParameterNames.Add(methodBaseGetParameters[i].ParameterType + " " + methodBaseGetParameters[i].Name);
+				}
+			}
+			catch (Exception ex)
+			{
+				LogLog.Error(declaringType, "An exception ocurred while retreiving method parameters.",
ex);
+			}
+
+			return (string[])methodParameterNames.ToArray(typeof(string));
+		}
+
+		#region Public Instance Properties
+
+		/// <summary>
+		/// Gets the method name of the caller making the logging 
+		/// request.
+		/// </summary>
+		/// <value>
+		/// The method name of the caller making the logging 
+		/// request.
+		/// </value>
+		/// <remarks>
+		/// <para>
+		/// Gets the method name of the caller making the logging 
+		/// request.
+		/// </para>
+		/// </remarks>
+		public string Name
+		{
+			get { return m_name; }
+		}
+
+		/// <summary>
+		/// Gets the method parameters of the caller making
+		/// the logging request.
+		/// </summary>
+		/// <value>
+		/// The method parameters of the caller making
+		/// the logging request
+		/// </value>
+		/// <remarks>
+		/// <para>
+		/// Gets the method parameters of the caller making
+		/// the logging request.
+		/// </para>
+		/// </remarks>
+		public string[] Parameters
+		{
+			get { return m_parameters; }
+		}
+
+		#endregion
+
+		#region Private Instance Fields
+
+		private readonly string m_name;
+		private readonly string[] m_parameters;
+
+		#endregion
+
+		#region Private Static Fields
+
+		/// <summary>
+		/// The fully qualified type of the StackFrameItem class.
+		/// </summary>
+		/// <remarks>
+		/// Used by the internal logger to record the Type of the
+		/// log message.
+		/// </remarks>
+		private readonly static Type declaringType = typeof(MethodItem);
+
+		/// <summary>
+		/// When location information is not available the constant
+		/// <c>NA</c> is returned. Current value of this string
+		/// constant is <b>?</b>.
+		/// </summary>
+		private const string NA = "?";
+
+		#endregion Private Static Fields
+	}
+}

Added: logging/log4net/trunk/src/Core/StackFrameItem.cs
URL: http://svn.apache.org/viewvc/logging/log4net/trunk/src/Core/StackFrameItem.cs?rev=1486883&view=auto
==============================================================================
--- logging/log4net/trunk/src/Core/StackFrameItem.cs (added)
+++ logging/log4net/trunk/src/Core/StackFrameItem.cs Tue May 28 11:40:46 2013
@@ -0,0 +1,188 @@
+#region Apache License
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more 
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership. 
+// The ASF licenses this file to you under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with 
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#endregion
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Diagnostics;
+using System.Reflection;
+
+namespace log4net.Core
+{
+    /// <summary>
+    /// provides stack frame information without actually referencing a System.Diagnostics.StackFrame
+    /// as that would require that the containing assembly is loaded.
+    /// </summary>
+    /// 
+#if !NETCF
+    [Serializable]
+#endif
+    public class StackFrameItem
+    {
+        #region Public Instance Constructors
+
+        /// <summary>
+        /// returns a stack frame item from a stack frame. This 
+        /// </summary>
+        /// <param name="frame"></param>
+        /// <returns></returns>
+        public StackFrameItem(StackFrame frame)
+        {
+            // set default values
+            m_lineNumber = NA;
+            m_fileName = NA;
+            m_method = new MethodItem();
+            m_className = NA;
+
+            // get frame values
+            m_lineNumber = frame.GetFileLineNumber().ToString(System.Globalization.NumberFormatInfo.InvariantInfo);
+            m_fileName = frame.GetFileName();
+            // get method values
+            MethodBase method = frame.GetMethod();
+            if (method != null)
+            {
+				m_className = method.DeclaringType.FullName;
+				m_method = new MethodItem(method);
+            }
+
+            // set full info
+            m_fullInfo = m_className + '.' + m_method.Name + '(' + m_fileName + ':' + m_lineNumber
+ ')';
+        }
+
+        #endregion
+
+        #region Public Instance Properties
+
+        /// <summary>
+        /// Gets the fully qualified class name of the caller making the logging 
+        /// request.
+        /// </summary>
+        /// <value>
+        /// The fully qualified class name of the caller making the logging 
+        /// request.
+        /// </value>
+        /// <remarks>
+        /// <para>
+        /// Gets the fully qualified class name of the caller making the logging 
+        /// request.
+        /// </para>
+        /// </remarks>
+        public string ClassName
+        {
+            get { return m_className; }
+        }
+
+        /// <summary>
+        /// Gets the file name of the caller.
+        /// </summary>
+        /// <value>
+        /// The file name of the caller.
+        /// </value>
+        /// <remarks>
+        /// <para>
+        /// Gets the file name of the caller.
+        /// </para>
+        /// </remarks>
+        public string FileName
+        {
+            get { return m_fileName; }
+        }
+
+        /// <summary>
+        /// Gets the line number of the caller.
+        /// </summary>
+        /// <value>
+        /// The line number of the caller.
+        /// </value>
+        /// <remarks>
+        /// <para>
+        /// Gets the line number of the caller.
+        /// </para>
+        /// </remarks>
+        public string LineNumber
+        {
+            get { return m_lineNumber; }
+        }
+
+        /// <summary>
+        /// Gets the method name of the caller.
+        /// </summary>
+        /// <value>
+        /// The method name of the caller.
+        /// </value>
+        /// <remarks>
+        /// <para>
+        /// Gets the method name of the caller.
+        /// </para>
+        /// </remarks>
+        public MethodItem Method
+        {
+            get { return m_method; }
+        }
+
+        /// <summary>
+        /// Gets all available caller information
+        /// </summary>
+        /// <value>
+        /// All available caller information, in the format
+        /// <c>fully.qualified.classname.of.caller.methodName(Filename:line)</c>
+        /// </value>
+        /// <remarks>
+        /// <para>
+        /// Gets all available caller information, in the format
+        /// <c>fully.qualified.classname.of.caller.methodName(Filename:line)</c>
+        /// </para>
+        /// </remarks>
+        public string FullInfo
+        {
+            get { return m_fullInfo; }
+        }
+
+        #endregion Public Instance Properties
+
+        #region Private Instance Fields
+
+        private readonly string m_lineNumber;
+        private readonly string m_fileName;
+        private readonly string m_className;
+        private readonly string m_fullInfo;
+		private readonly MethodItem m_method;
+
+        #endregion
+
+        #region Private Static Fields
+
+        /// <summary>
+        /// The fully qualified type of the StackFrameItem class.
+        /// </summary>
+        /// <remarks>
+        /// Used by the internal logger to record the Type of the
+        /// log message.
+        /// </remarks>
+        private readonly static Type declaringType = typeof(StackFrameItem);
+
+        /// <summary>
+        /// When location information is not available the constant
+        /// <c>NA</c> is returned. Current value of this string
+        /// constant is <b>?</b>.
+        /// </summary>
+        private const string NA = "?";
+
+        #endregion Private Static Fields
+    }
+}

Modified: logging/log4net/trunk/src/DateFormatter/AbsoluteTimeDateFormatter.cs
URL: http://svn.apache.org/viewvc/logging/log4net/trunk/src/DateFormatter/AbsoluteTimeDateFormatter.cs?rev=1486883&r1=1486882&r2=1486883&view=diff
==============================================================================
--- logging/log4net/trunk/src/DateFormatter/AbsoluteTimeDateFormatter.cs (original)
+++ logging/log4net/trunk/src/DateFormatter/AbsoluteTimeDateFormatter.cs Tue May 28 11:40:46
2013
@@ -101,71 +101,68 @@ namespace log4net.DateFormatter
 		/// </remarks>
 		virtual public void FormatDate(DateTime dateToFormat, TextWriter writer)
 		{
-			lock (s_lastTimeStrings)
-			{
-				// Calculate the current time precise only to the second
-				long currentTimeToTheSecond = (dateToFormat.Ticks - (dateToFormat.Ticks % TimeSpan.TicksPerSecond));
+			// Calculate the current time precise only to the second
+			long currentTimeToTheSecond = (dateToFormat.Ticks - (dateToFormat.Ticks % TimeSpan.TicksPerSecond));
 
-				string timeString = null;
-				// Compare this time with the stored last time
-				// If we are in the same second then append
-				// the previously calculated time string
-				if (s_lastTimeToTheSecond != currentTimeToTheSecond)
-				{
-					s_lastTimeStrings.Clear();
-				}
-				else
-				{
-					timeString = (string)s_lastTimeStrings[GetType()];
-				}
+                        string timeString = null;
+			// Compare this time with the stored last time
+			// If we are in the same second then append
+			// the previously calculated time string
+                        if (s_lastTimeToTheSecond != currentTimeToTheSecond)
+                        {
+                            s_lastTimeStrings.Clear();
+                        }
+                        else
+                        {
+                            timeString = (string) s_lastTimeStrings[GetType()];
+                        }
+
+                        if (timeString == null)
+                        {
+				// lock so that only one thread can use the buffer and
+				// update the s_lastTimeToTheSecond and s_lastTimeStrings
 
-				if (timeString == null)
+				// PERF: Try removing this lock and using a new StringBuilder each time
+				lock(s_lastTimeBuf)
 				{
-					// lock so that only one thread can use the buffer and
-					// update the s_lastTimeToTheSecond and s_lastTimeStrings
+                                        timeString = (string) s_lastTimeStrings[GetType()];
 
-					// PERF: Try removing this lock and using a new StringBuilder each time
-					lock (s_lastTimeBuf)
-					{
-						timeString = (string)s_lastTimeStrings[GetType()];
-
-						if (timeString == null)
-						{
-							// We are in a new second.
-							s_lastTimeBuf.Length = 0;
+                                        if (timeString == null)
+                                        {
+						// We are in a new second.
+						s_lastTimeBuf.Length = 0;
 
-							// Calculate the new string for this second
-							FormatDateWithoutMillis(dateToFormat, s_lastTimeBuf);
+						// Calculate the new string for this second
+						FormatDateWithoutMillis(dateToFormat, s_lastTimeBuf);
 
-							// Render the string buffer to a string
-							timeString = s_lastTimeBuf.ToString();
+						// Render the string buffer to a string
+                                                timeString = s_lastTimeBuf.ToString();
 
 #if NET_1_1
 						// Ensure that the above string is written into the variable NOW on all threads.
 						// This is only required on multiprocessor machines with weak memeory models
 						System.Threading.Thread.MemoryBarrier();
 #endif
-							// Store the time as a string (we only have to do this once per second)
-							s_lastTimeStrings[GetType()] = timeString;
-							s_lastTimeToTheSecond = currentTimeToTheSecond;
-						}
+						// Store the time as a string (we only have to do this once per second)
+                                                s_lastTimeStrings[GetType()] = timeString;
+						s_lastTimeToTheSecond = currentTimeToTheSecond;
 					}
 				}
-				writer.Write(timeString);
-				
-				// Append the current millisecond info
-				writer.Write(',');
-				int millis = dateToFormat.Millisecond;
-				if (millis < 100)
-				{
-					writer.Write('0');
-				}
-				if (millis < 10)
-				{
-					writer.Write('0');
-				}
-				writer.Write(millis);
 			}
+			writer.Write(timeString);
+	
+			// Append the current millisecond info
+			writer.Write(',');
+			int millis = dateToFormat.Millisecond;
+			if (millis < 100) 
+			{
+				writer.Write('0');
+			}
+			if (millis < 10) 
+			{
+				writer.Write('0');
+			}
+			writer.Write(millis);
 		}
 
 		#endregion Implementation of IDateFormatter

Modified: logging/log4net/trunk/src/Layout/Pattern/StackTraceDetailPatternConverter.cs
URL: http://svn.apache.org/viewvc/logging/log4net/trunk/src/Layout/Pattern/StackTraceDetailPatternConverter.cs?rev=1486883&r1=1486882&r2=1486883&view=diff
==============================================================================
--- logging/log4net/trunk/src/Layout/Pattern/StackTraceDetailPatternConverter.cs (original)
+++ logging/log4net/trunk/src/Layout/Pattern/StackTraceDetailPatternConverter.cs Tue May 28
11:40:46 2013
@@ -41,14 +41,14 @@ namespace log4net.Layout.Pattern
     /// <author>Adam Davies</author>
     internal class StackTraceDetailPatternConverter : StackTracePatternConverter
     {
-        internal override string GetMethodInformation(System.Reflection.MethodBase method)
+        internal override string GetMethodInformation(MethodItem method)
         {
             string returnValue="";
 
             try
             {
                 string param = "";
-                string[] names = GetMethodParameterNames(method);
+                string[] names = method.Parameters;
                 StringBuilder sb = new StringBuilder();
                 if (names != null && names.GetUpperBound(0) > 0)
                 {
@@ -74,28 +74,6 @@ namespace log4net.Layout.Pattern
             return returnValue;
         }
 
-        private string[] GetMethodParameterNames(System.Reflection.MethodBase methodBase)
-        {
-            ArrayList methodParameterNames = new ArrayList();
-            try
-            {
-                System.Reflection.ParameterInfo[] methodBaseGetParameters = methodBase.GetParameters();
-                
-                int methodBaseGetParametersCount = methodBaseGetParameters.GetUpperBound(0);
-
-                for (int i = 0; i <= methodBaseGetParametersCount; i++)
-                {
-                    methodParameterNames.Add(methodBaseGetParameters[i].ParameterType + "
" + methodBaseGetParameters[i].Name);
-                }
-            }
-            catch (Exception ex)
-            {
-                LogLog.Error(declaringType, "An exception ocurred while retreiving method
parameters.", ex);
-            }
-
-            return (string[])methodParameterNames.ToArray(typeof (string));
-        }
-
         #region Private Static Fields
 
         /// <summary>

Modified: logging/log4net/trunk/src/Layout/Pattern/StackTracePatternConverter.cs
URL: http://svn.apache.org/viewvc/logging/log4net/trunk/src/Layout/Pattern/StackTracePatternConverter.cs?rev=1486883&r1=1486882&r2=1486883&view=diff
==============================================================================
--- logging/log4net/trunk/src/Layout/Pattern/StackTracePatternConverter.cs (original)
+++ logging/log4net/trunk/src/Layout/Pattern/StackTracePatternConverter.cs Tue May 28 11:40:46
2013
@@ -95,7 +95,7 @@ namespace log4net.Layout.Pattern
 		/// </remarks>
 		override protected void Convert(TextWriter writer, LoggingEvent loggingEvent)
 		{
-			StackFrame[] stackframes = loggingEvent.LocationInformation.StackFrames;
+			StackFrameItem[] stackframes = loggingEvent.LocationInformation.StackFrames;
 			if ((stackframes == null) || (stackframes.Length <= 0))
 			{
 				LogLog.Error(declaringType, "loggingEvent.LocationInformation.StackFrames was null or
empty.");
@@ -111,8 +111,8 @@ namespace log4net.Layout.Pattern
 					continue;
 				}
 				
-				StackFrame stackFrame = stackframes[stackFrameIndex];
-                writer.Write("{0}.{1}", stackFrame.GetMethod().DeclaringType.Name, GetMethodInformation(stackFrame.GetMethod()));
+				StackFrameItem stackFrame = stackframes[stackFrameIndex];
+                writer.Write("{0}.{1}", stackFrame.ClassName, GetMethodInformation(stackFrame.Method));
 				if (stackFrameIndex > 0)
 				{
                     // TODO: make this user settable?
@@ -128,7 +128,7 @@ namespace log4net.Layout.Pattern
         /// <param name="method"></param>
         /// <remarks>This method was created, so this class could be used as a base
class for StackTraceDetailPatternConverter</remarks>
         /// <returns>string</returns>
-        internal virtual string GetMethodInformation(System.Reflection.MethodBase method)
+        internal virtual string GetMethodInformation(MethodItem method)
         {
             return method.Name;
         }

Modified: logging/log4net/trunk/src/log4net.vs2008.csproj
URL: http://svn.apache.org/viewvc/logging/log4net/trunk/src/log4net.vs2008.csproj?rev=1486883&r1=1486882&r2=1486883&view=diff
==============================================================================
--- logging/log4net/trunk/src/log4net.vs2008.csproj (original)
+++ logging/log4net/trunk/src/log4net.vs2008.csproj Tue May 28 11:40:46 2013
@@ -301,12 +301,18 @@
     <Compile Include="Core\LogImpl.cs">
       <SubType>Code</SubType>
     </Compile>
+    <Compile Include="Core\MethodItem.cs">
+      <SubType>Code</SubType>
+    </Compile>
     <Compile Include="Core\SecurityContext.cs">
       <SubType>Code</SubType>
     </Compile>
     <Compile Include="Core\SecurityContextProvider.cs">
       <SubType>Code</SubType>
     </Compile>
+    <Compile Include="Core\StackFrameItem.cs">
+      <SubType>Code</SubType>
+    </Compile>
     <Compile Include="Core\TimeEvaluator.cs" />
     <Compile Include="Core\WrapperMap.cs">
       <SubType>Code</SubType>

Modified: logging/log4net/trunk/src/log4net.vs2010.csproj
URL: http://svn.apache.org/viewvc/logging/log4net/trunk/src/log4net.vs2010.csproj?rev=1486883&r1=1486882&r2=1486883&view=diff
==============================================================================
--- logging/log4net/trunk/src/log4net.vs2010.csproj (original)
+++ logging/log4net/trunk/src/log4net.vs2010.csproj Tue May 28 11:40:46 2013
@@ -317,12 +317,18 @@
     <Compile Include="Core\LogImpl.cs">
       <SubType>Code</SubType>
     </Compile>
+    <Compile Include="Core\MethodItem.cs">
+      <SubType>Code</SubType>
+    </Compile>
     <Compile Include="Core\SecurityContext.cs">
       <SubType>Code</SubType>
     </Compile>
     <Compile Include="Core\SecurityContextProvider.cs">
       <SubType>Code</SubType>
     </Compile>
+    <Compile Include="Core\StackFrameItem.cs">
+      <SubType>Code</SubType>
+    </Compile>
     <Compile Include="Core\TimeEvaluator.cs" />
     <Compile Include="Core\WrapperMap.cs">
       <SubType>Code</SubType>



Mime
View raw message