1 #region Copyright & License 2 // 3 // Copyright 2006 The Apache Software Foundation 4 // 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 // 17 #endregion 18 19 using System; 20 using System.Text; 21 using System.Xml; 22 using System.Text.RegularExpressions; 23 24 namespace log4net.Util 25 { 26 /// <summary> 27 /// Utility class that represents a format string. 28 /// </summary> 29 /// <remarks> 30 /// <para> 31 /// Utility class that represents a format string. 32 /// </para> 33 /// </remarks> 34 /// <author>Nicko Cadell</author> 35 public sealed class SystemStringFormat 36 { 37 private readonly IFormatProvider m_provider; 38 private readonly string m_format; 39 private readonly object[] m_args; 40 41 #region Constructor 42 43 /// <summary> 44 /// Initialise the <see cref="SystemStringFormat"/> 45 /// </summary> 46 /// <param name="provider">An <see cref="System.IFormatProvider"/> that supplies culture-specific formatting information.</param> 47 /// <param name="format">A <see cref="System.String"/> containing zero or more format items.</param> 48 /// <param name="args">An <see cref="System.Object"/> array containing zero or more objects to format.</param> SystemStringFormat(IFormatProvider provider, string format, params object[] args)49 public SystemStringFormat(IFormatProvider provider, string format, params object[] args) 50 { 51 m_provider = provider; 52 m_format = format; 53 m_args = args; 54 } 55 56 #endregion Constructor 57 58 /// <summary> 59 /// Format the string and arguments 60 /// </summary> 61 /// <returns>the formatted string</returns> ToString()62 public override string ToString() 63 { 64 return StringFormat(m_provider, m_format, m_args); 65 } 66 67 #region StringFormat 68 69 /// <summary> 70 /// Replaces the format item in a specified <see cref="System.String"/> with the text equivalent 71 /// of the value of a corresponding <see cref="System.Object"/> instance in a specified array. 72 /// A specified parameter supplies culture-specific formatting information. 73 /// </summary> 74 /// <param name="provider">An <see cref="System.IFormatProvider"/> that supplies culture-specific formatting information.</param> 75 /// <param name="format">A <see cref="System.String"/> containing zero or more format items.</param> 76 /// <param name="args">An <see cref="System.Object"/> array containing zero or more objects to format.</param> 77 /// <returns> 78 /// A copy of format in which the format items have been replaced by the <see cref="System.String"/> 79 /// equivalent of the corresponding instances of <see cref="System.Object"/> in args. 80 /// </returns> 81 /// <remarks> 82 /// <para> 83 /// This method does not throw exceptions. If an exception thrown while formatting the result the 84 /// exception and arguments are returned in the result string. 85 /// </para> 86 /// </remarks> StringFormat(IFormatProvider provider, string format, params object[] args)87 private static string StringFormat(IFormatProvider provider, string format, params object[] args) 88 { 89 try 90 { 91 // The format is missing, log null value 92 if (format == null) 93 { 94 return null; 95 } 96 97 // The args are missing - should not happen unless we are called explicitly with a null array 98 if (args == null) 99 { 100 return format; 101 } 102 103 // Try to format the string 104 return String.Format(provider, format, args); 105 } 106 catch(Exception ex) 107 { 108 log4net.Util.LogLog.Warn("StringFormat: Exception while rendering format ["+format+"]", ex); 109 return StringFormatError(ex, format, args); 110 } 111 catch 112 { 113 log4net.Util.LogLog.Warn("StringFormat: Exception while rendering format ["+format+"]"); 114 return StringFormatError(null, format, args); 115 } 116 } 117 118 /// <summary> 119 /// Process an error during StringFormat 120 /// </summary> StringFormatError(Exception formatException, string format, object[] args)121 private static string StringFormatError(Exception formatException, string format, object[] args) 122 { 123 try 124 { 125 StringBuilder buf = new StringBuilder("<log4net.Error>"); 126 127 if (formatException != null) 128 { 129 buf.Append("Exception during StringFormat: ").Append(formatException.Message); 130 } 131 else 132 { 133 buf.Append("Exception during StringFormat"); 134 } 135 buf.Append(" <format>").Append(format).Append("</format>"); 136 buf.Append("<args>"); 137 RenderArray(args, buf); 138 buf.Append("</args>"); 139 buf.Append("</log4net.Error>"); 140 141 return buf.ToString(); 142 } 143 catch(Exception ex) 144 { 145 log4net.Util.LogLog.Error("StringFormat: INTERNAL ERROR during StringFormat error handling", ex); 146 return "<log4net.Error>Exception during StringFormat. See Internal Log.</log4net.Error>"; 147 } 148 catch 149 { 150 log4net.Util.LogLog.Error("StringFormat: INTERNAL ERROR during StringFormat error handling"); 151 return "<log4net.Error>Exception during StringFormat. See Internal Log.</log4net.Error>"; 152 } 153 } 154 155 /// <summary> 156 /// Dump the contents of an array into a string builder 157 /// </summary> RenderArray(Array array, StringBuilder buffer)158 private static void RenderArray(Array array, StringBuilder buffer) 159 { 160 if (array == null) 161 { 162 buffer.Append(SystemInfo.NullText); 163 } 164 else 165 { 166 if (array.Rank != 1) 167 { 168 buffer.Append(array.ToString()); 169 } 170 else 171 { 172 buffer.Append("{"); 173 int len = array.Length; 174 175 if (len > 0) 176 { 177 RenderObject(array.GetValue(0), buffer); 178 for (int i = 1; i < len; i++) 179 { 180 buffer.Append(", "); 181 RenderObject(array.GetValue(i), buffer); 182 } 183 } 184 buffer.Append("}"); 185 } 186 } 187 } 188 189 /// <summary> 190 /// Dump an object to a string 191 /// </summary> RenderObject(Object obj, StringBuilder buffer)192 private static void RenderObject(Object obj, StringBuilder buffer) 193 { 194 if (obj == null) 195 { 196 buffer.Append(SystemInfo.NullText); 197 } 198 else 199 { 200 try 201 { 202 buffer.Append(obj); 203 } 204 catch(Exception ex) 205 { 206 buffer.Append("<Exception: ").Append(ex.Message).Append(">"); 207 } 208 catch 209 { 210 buffer.Append("<Exception>"); 211 } 212 } 213 } 214 215 #endregion StringFormat 216 } 217 } 218