#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.Text; using System.Xml; using System.Text.RegularExpressions; namespace log4net.Util { /// /// Utility class that represents a format string. /// /// /// /// Utility class that represents a format string. /// /// /// Nicko Cadell public sealed class SystemStringFormat { private readonly IFormatProvider m_provider; private readonly string m_format; private readonly object[] m_args; #region Constructor /// /// Initialise the /// /// An that supplies culture-specific formatting information. /// A containing zero or more format items. /// An array containing zero or more objects to format. public SystemStringFormat(IFormatProvider provider, string format, params object[] args) { m_provider = provider; m_format = format; m_args = args; } #endregion Constructor /// /// Format the string and arguments /// /// the formatted string public override string ToString() { return StringFormat(m_provider, m_format, m_args); } #region StringFormat /// /// Replaces the format item in a specified with the text equivalent /// of the value of a corresponding instance in a specified array. /// A specified parameter supplies culture-specific formatting information. /// /// An that supplies culture-specific formatting information. /// A containing zero or more format items. /// An array containing zero or more objects to format. /// /// A copy of format in which the format items have been replaced by the /// equivalent of the corresponding instances of in args. /// /// /// /// This method does not throw exceptions. If an exception thrown while formatting the result the /// exception and arguments are returned in the result string. /// /// private static string StringFormat(IFormatProvider provider, string format, params object[] args) { try { // The format is missing, log null value if (format == null) { return null; } // The args are missing - should not happen unless we are called explicitly with a null array if (args == null) { return format; } // Try to format the string return String.Format(provider, format, args); } catch(Exception ex) { log4net.Util.LogLog.Warn(declaringType, "Exception while rendering format ["+format+"]", ex); return StringFormatError(ex, format, args); } #if !NET_2_0 && !MONO_2_0 && !MONO_3_5 && !MONO_4_0 && !NETSTANDARD1_3 catch { log4net.Util.LogLog.Warn(declaringType, "Exception while rendering format ["+format+"]"); return StringFormatError(null, format, args); } #endif } /// /// Process an error during StringFormat /// private static string StringFormatError(Exception formatException, string format, object[] args) { try { StringBuilder buf = new StringBuilder(""); if (formatException != null) { buf.Append("Exception during StringFormat: ").Append(formatException.Message); } else { buf.Append("Exception during StringFormat"); } buf.Append(" ").Append(format).Append(""); buf.Append(""); RenderArray(args, buf); buf.Append(""); buf.Append(""); return buf.ToString(); } catch(Exception ex) { log4net.Util.LogLog.Error(declaringType, "INTERNAL ERROR during StringFormat error handling", ex); return "Exception during StringFormat. See Internal Log."; } #if !NET_2_0 && !MONO_2_0 && !MONO_3_5 && !MONO_4_0 && !NETSTANDARD1_3 catch { log4net.Util.LogLog.Error(declaringType, "INTERNAL ERROR during StringFormat error handling"); return "Exception during StringFormat. See Internal Log."; } #endif } /// /// Dump the contents of an array into a string builder /// private static void RenderArray(Array array, StringBuilder buffer) { if (array == null) { buffer.Append(SystemInfo.NullText); } else { if (array.Rank != 1) { buffer.Append(array.ToString()); } else { buffer.Append("{"); int len = array.Length; if (len > 0) { RenderObject(array.GetValue(0), buffer); for (int i = 1; i < len; i++) { buffer.Append(", "); RenderObject(array.GetValue(i), buffer); } } buffer.Append("}"); } } } /// /// Dump an object to a string /// private static void RenderObject(Object obj, StringBuilder buffer) { if (obj == null) { buffer.Append(SystemInfo.NullText); } else { try { buffer.Append(obj); } catch(Exception ex) { buffer.Append(""); } #if !NET_2_0 && !MONO_2_0 && !MONO_3_5 && !MONO_4_0 && !NETSTANDARD1_3 catch { buffer.Append(""); } #endif } } #endregion StringFormat #region Private Static Fields /// /// The fully qualified type of the SystemStringFormat class. /// /// /// Used by the internal logger to record the Type of the /// log message. /// private readonly static Type declaringType = typeof(SystemStringFormat); #endregion Private Static Fields } }