From 8dbb52b2479a9bb90bef73c53f6ea683e72190e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Volkan=20Yaz=C4=B1c=C4=B1?= Date: Mon, 4 Mar 2024 09:02:33 +0100 Subject: [PATCH 1/6] Update copyright year in `NOTICE` --- NOTICE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NOTICE b/NOTICE index 468a2f54..eaab50a6 100644 --- a/NOTICE +++ b/NOTICE @@ -1,5 +1,5 @@ Apache log4net - Copyright 2004-2022 The Apache Software Foundation + Copyright 2004-2024 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (https://www.apache.org/). From fc4c0f39120c16dc2b55717b922dad7a59f7cce4 Mon Sep 17 00:00:00 2001 From: Davyd McColl Date: Mon, 4 Mar 2024 11:27:38 +0200 Subject: [PATCH 2/6] :memo: update build docs --- doc/BUILDING.md | 31 ++++++++++++++++++++++++++++++- src/log4net/log4net.csproj | 9 +-------- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/doc/BUILDING.md b/doc/BUILDING.md index aeff9f6b..87d04916 100644 --- a/doc/BUILDING.md +++ b/doc/BUILDING.md @@ -1,11 +1,36 @@ ## Building log4net Log4net provides support for a wide array of targets, including -- older .net 2 and 3.5 (including client profiles) +- older .net 2 and 3.5 (including client profile for net-40) - more modern net40/net45 - netstandard1.3/2.0 As such, it does require a relatively full .net environment on Windows to build. +I have recently found a fairly freshly-installed win11 machine to work adequately, +after adding the "windows feature" for ".NET Framework 3.5 (includes .NET 2.0 and 3.0)" + +TL;DR (Windows): +- install Visual Studio Build Tools (at least VS2019) +- install nodejs (at least v16) +- install dotnet (v7+) and the .NET SDK (current latest) +- install dotnet 2, 3, 3.5 via "add windows features" +- in the project folder: + - `npm i` + - `npm run build` + +TL;DR (!Windows): +- install the dotnet SDK - v7 or better (at time of writing, v8 is current but + I've had some issues elsewhere, so I'm waiting a bit before recommending it + everywhere +- install Mono (you're going to need it to target certain versions of .NET) +- install nodejs 16+ + - in the project folder: + - `npm i` + - `export DOTNET_CORE=1 npm run build` + - we force using `dotnet` on non-windows targets for now. At some point, + this should become automatic + +## The full story Options: - build locally. Suggested environment: @@ -35,6 +60,10 @@ Options: - `npm run build` - optionally `npm test` to run all tests - optionally `npm run release` to generate release artifacts +- build locally (CLI edition) + - install nodejs (at least v16) + - `npm i` + - `npm run build` - build via docker for windows, using the `build-with-docker-for-windows.bat` script - build via the vs2019 Windows AppVeyer image. There is an appveyer.yml file included which (should) build if you set up AppVeyer to track diff --git a/src/log4net/log4net.csproj b/src/log4net/log4net.csproj index 015b5056..61dfe5a9 100644 --- a/src/log4net/log4net.csproj +++ b/src/log4net/log4net.csproj @@ -73,13 +73,6 @@ false true - - .NETFramework - v3.5 - Client - ..\..\build\$(Configuration)\net35-client - $(DefineConstants);NET_2_0;NET_3_5;CLIENT_PROFILE - .NETFramework v4.0 @@ -213,4 +206,4 @@ - \ No newline at end of file + From 2121c47483b55dc5186d51a3f39b5bbd1cff282e Mon Sep 17 00:00:00 2001 From: Jan Friedrich Date: Tue, 5 Mar 2024 09:01:50 +0100 Subject: [PATCH 3/6] tabs to spaces #111 --- src/log4net/Appender/AdoNetAppender.cs | 2270 +++++------ .../Appender/AnsiColorTerminalAppender.cs | 1080 +++--- src/log4net/Appender/AppenderCollection.cs | 1748 ++++----- src/log4net/Appender/AppenderSkeleton.cs | 1730 ++++----- src/log4net/Appender/AspNetTraceAppender.cs | 192 +- .../Appender/BufferingAppenderSkeleton.cs | 1236 +++--- .../Appender/BufferingForwardingAppender.cs | 450 +-- .../Appender/ColoredConsoleAppender.cs | 1234 +++--- src/log4net/Appender/ConsoleAppender.cs | 378 +- src/log4net/Appender/DebugAppender.cs | 298 +- src/log4net/Appender/EventLogAppender.cs | 986 ++--- src/log4net/Appender/FileAppender.cs | 172 +- src/log4net/Appender/ForwardingAppender.cs | 464 +-- src/log4net/Appender/IAppender.cs | 100 +- src/log4net/Appender/IBulkAppender.cs | 48 +- src/log4net/Appender/LocalSyslogAppender.cs | 1126 +++--- .../Appender/ManagedColoredConsoleAppender.cs | 532 +-- src/log4net/Appender/MemoryAppender.cs | 316 +- src/log4net/Appender/NetSendAppender.cs | 752 ++-- .../Appender/OutputDebugStringAppender.cs | 158 +- src/log4net/Appender/RemoteSyslogAppender.cs | 1144 +++--- src/log4net/Appender/RemotingAppender.cs | 596 +-- src/log4net/Appender/RollingFileAppender.cs | 3094 +++++++-------- src/log4net/Appender/SmtpAppender.cs | 1182 +++--- src/log4net/Appender/SmtpPickupDirAppender.cs | 638 +-- src/log4net/Appender/TelnetAppender.cs | 978 ++--- src/log4net/Appender/TextWriterAppender.cs | 896 ++--- src/log4net/Appender/TraceAppender.cs | 312 +- src/log4net/Appender/UdpAppender.cs | 1010 ++--- src/log4net/AssemblyInfo.cs | 4 +- src/log4net/Config/AliasDomainAttribute.cs | 86 +- .../Config/AliasRepositoryAttribute.cs | 130 +- src/log4net/Config/BasicConfigurator.cs | 178 +- src/log4net/Config/ConfiguratorAttribute.cs | 152 +- src/log4net/Config/DOMConfigurator.cs | 608 +-- .../Config/DOMConfiguratorAttribute.cs | 50 +- src/log4net/Config/DomainAttribute.cs | 110 +- .../Log4NetConfigurationSectionHandler.cs | 114 +- src/log4net/Config/PluginAttribute.cs | 314 +- src/log4net/Config/RepositoryAttribute.cs | 208 +- .../SecurityContextProviderAttribute.cs | 234 +- src/log4net/Config/XmlConfigurator.cs | 2064 +++++----- .../Config/XmlConfiguratorAttribute.cs | 806 ++-- src/log4net/Core/CompactRepositorySelector.cs | 652 ++-- src/log4net/Core/DefaultRepositorySelector.cs | 1622 ++++---- src/log4net/Core/ErrorCode.cs | 80 +- src/log4net/Core/ExceptionEvaluator.cs | 192 +- src/log4net/Core/IAppenderAttachable.cs | 180 +- src/log4net/Core/IErrorHandler.cs | 98 +- src/log4net/Core/IFixingRequired.cs | 68 +- src/log4net/Core/ILogger.cs | 168 +- src/log4net/Core/ILoggerWrapper.cs | 62 +- src/log4net/Core/IOptionHandler.cs | 68 +- src/log4net/Core/IRepositorySelector.cs | 348 +- src/log4net/Core/ITriggeringEventEvaluator.cs | 54 +- src/log4net/Core/Level.cs | 1156 +++--- src/log4net/Core/LevelCollection.cs | 1658 ++++---- src/log4net/Core/LevelEvaluator.cs | 202 +- src/log4net/Core/LevelMap.cs | 402 +- src/log4net/Core/LocationInfo.cs | 518 +-- src/log4net/Core/LogException.cs | 148 +- src/log4net/Core/LogImpl.cs | 2424 ++++++------ src/log4net/Core/LoggerManager.cs | 1648 ++++---- src/log4net/Core/LoggerWrapperImpl.cs | 112 +- src/log4net/Core/LoggingEvent.cs | 62 +- src/log4net/Core/MethodItem.cs | 272 +- src/log4net/Core/SecurityContext.cs | 62 +- src/log4net/Core/SecurityContextProvider.cs | 190 +- src/log4net/Core/StackFrameItem.cs | 38 +- src/log4net/Core/WrapperMap.cs | 462 +-- .../AbsoluteTimeDateFormatter.cs | 296 +- .../DateFormatter/DateTimeDateFormatter.cs | 138 +- src/log4net/DateFormatter/IDateFormatter.cs | 60 +- .../DateFormatter/Iso8601DateFormatter.cs | 126 +- .../DateFormatter/SimpleDateFormatter.cs | 124 +- src/log4net/Filter/DenyAllFilter.cs | 88 +- src/log4net/Filter/FilterDecision.cs | 52 +- src/log4net/Filter/FilterSkeleton.cs | 242 +- src/log4net/Filter/IFilter.cs | 150 +- src/log4net/Filter/LevelMatchFilter.cs | 204 +- src/log4net/Filter/LevelRangeFilter.cs | 314 +- src/log4net/Filter/LoggerMatchFilter.cs | 264 +- src/log4net/Filter/MdcFilter.cs | 36 +- src/log4net/Filter/NdcFilter.cs | 62 +- src/log4net/Filter/PropertyFilter.cs | 270 +- src/log4net/Filter/StringMatchFilter.cs | 424 +- src/log4net/GlobalContext.cs | 132 +- src/log4net/ILog.cs | 1856 ++++----- src/log4net/Layout/DynamicPatternLayout.cs | 216 +- src/log4net/Layout/ExceptionLayout.cs | 140 +- src/log4net/Layout/ILayout.cs | 178 +- src/log4net/Layout/IRawLayout.cs | 66 +- src/log4net/Layout/Layout2RawLayoutAdapter.cs | 114 +- src/log4net/Layout/LayoutSkeleton.cs | 408 +- .../Pattern/AppDomainPatternConverter.cs | 54 +- .../Pattern/AspNetCachePatternConverter.cs | 88 +- .../Pattern/AspNetContextPatternConverter.cs | 72 +- .../Layout/Pattern/AspNetPatternConverter.cs | 62 +- .../Pattern/AspNetRequestPatternConverter.cs | 104 +- .../Pattern/AspNetSessionPatternConverter.cs | 88 +- .../Layout/Pattern/DatePatternConverter.cs | 306 +- .../Pattern/ExceptionPatternConverter.cs | 216 +- .../Pattern/FileLocationPatternConverter.cs | 56 +- .../Pattern/FullLocationPatternConverter.cs | 52 +- .../Pattern/IdentityPatternConverter.cs | 60 +- .../Layout/Pattern/LevelPatternConverter.cs | 56 +- .../Pattern/LineLocationPatternConverter.cs | 56 +- .../Layout/Pattern/LoggerPatternConverter.cs | 52 +- .../Layout/Pattern/MessagePatternConverter.cs | 56 +- .../Pattern/MethodLocationPatternConverter.cs | 56 +- .../Layout/Pattern/NamedPatternConverter.cs | 226 +- .../Layout/Pattern/NdcPatternConverter.cs | 68 +- .../Layout/Pattern/PatternLayoutConverter.cs | 160 +- .../Pattern/PropertyPatternConverter.cs | 94 +- .../Pattern/RelativeTimePatternConverter.cs | 82 +- .../Pattern/StackTracePatternConverter.cs | 210 +- .../Layout/Pattern/ThreadPatternConverter.cs | 52 +- .../Pattern/TypeNamePatternConverter.cs | 72 +- .../Pattern/UserNamePatternConverter.cs | 34 +- .../Layout/Pattern/UtcDatePatternConverter.cs | 116 +- src/log4net/Layout/PatternLayout.cs | 2030 +++++----- src/log4net/Layout/RawLayoutConverter.cs | 114 +- src/log4net/Layout/RawPropertyLayout.cs | 110 +- src/log4net/Layout/RawTimeStampLayout.cs | 82 +- src/log4net/Layout/RawUtcTimeStampLayout.cs | 82 +- src/log4net/Layout/SimpleLayout.cs | 146 +- src/log4net/Layout/XmlLayout.cs | 700 ++-- src/log4net/Layout/XmlLayoutBase.cs | 428 +-- src/log4net/Layout/XmlLayoutSchemaLog4j.cs | 462 +-- src/log4net/LogManager.cs | 1460 +++---- src/log4net/LogicalThreadContext.cs | 228 +- src/log4net/MDC.cs | 272 +- src/log4net/NDC.cs | 608 +-- src/log4net/ObjectRenderer/DefaultRenderer.cs | 528 +-- src/log4net/ObjectRenderer/IObjectRenderer.cs | 72 +- src/log4net/ObjectRenderer/RendererMap.cs | 548 +-- src/log4net/Plugin/IPlugin.cs | 118 +- src/log4net/Plugin/IPluginFactory.cs | 46 +- src/log4net/Plugin/PluginCollection.cs | 1696 ++++---- src/log4net/Plugin/PluginMap.cs | 322 +- src/log4net/Plugin/PluginSkeleton.cs | 248 +- .../Plugin/RemoteLoggingServerPlugin.cs | 460 +-- .../Hierarchy/DefaultLoggerFactory.cs | 168 +- src/log4net/Repository/Hierarchy/Hierarchy.cs | 2012 +++++----- .../Repository/Hierarchy/ILoggerFactory.cs | 84 +- src/log4net/Repository/Hierarchy/Logger.cs | 1478 +++---- src/log4net/Repository/Hierarchy/LoggerKey.cs | 196 +- .../Repository/Hierarchy/ProvisionNode.cs | 66 +- .../Repository/Hierarchy/RootLogger.cs | 194 +- .../Hierarchy/XmlHierarchyConfigurator.cs | 2138 +++++----- .../IBasicRepositoryConfigurator.cs | 56 +- src/log4net/Repository/ILoggerRepository.cs | 574 +-- .../Repository/IXmlRepositoryConfigurator.cs | 56 +- .../Repository/LoggerRepositorySkeleton.cs | 1074 +++--- src/log4net/ThreadContext.cs | 204 +- src/log4net/Util/AppenderAttachedImpl.cs | 676 ++-- src/log4net/Util/CompositeProperties.cs | 258 +- src/log4net/Util/ContextPropertiesBase.cs | 48 +- src/log4net/Util/CountingQuietTextWriter.cs | 276 +- src/log4net/Util/CyclicBuffer.cs | 646 ++-- src/log4net/Util/EmptyCollection.cs | 298 +- src/log4net/Util/EmptyDictionary.cs | 566 +-- src/log4net/Util/FormattingInfo.cs | 200 +- src/log4net/Util/GlobalContextProperties.cs | 294 +- src/log4net/Util/ILogExtensions.cs | 3424 ++++++++--------- src/log4net/Util/LevelMapping.cs | 246 +- src/log4net/Util/LevelMappingEntry.cs | 124 +- src/log4net/Util/LogLog.cs | 818 ++-- .../Util/LogicalThreadContextProperties.cs | 402 +- src/log4net/Util/LogicalThreadContextStack.cs | 838 ++-- .../Util/LogicalThreadContextStacks.cs | 200 +- src/log4net/Util/NativeError.cs | 428 +-- src/log4net/Util/NullDictionaryEnumerator.cs | 318 +- src/log4net/Util/NullEnumerator.cs | 192 +- src/log4net/Util/NullSecurityContext.cs | 96 +- src/log4net/Util/OnlyOnceErrorHandler.cs | 420 +- src/log4net/Util/OptionConverter.cs | 1024 ++--- src/log4net/Util/PatternConverter.cs | 678 ++-- src/log4net/Util/PatternParser.cs | 798 ++-- src/log4net/Util/PatternString.cs | 874 ++--- .../AppDomainPatternConverter.cs | 52 +- .../DatePatternConverter.cs | 308 +- .../EnvironmentPatternConverter.cs | 144 +- .../IdentityPatternConverter.cs | 106 +- .../LiteralPatternConverter.cs | 150 +- .../NewLinePatternConverter.cs | 120 +- .../ProcessIdPatternConverter.cs | 94 +- .../PropertyPatternConverter.cs | 126 +- .../RandomStringPatternConverter.cs | 234 +- .../UserNamePatternConverter.cs | 106 +- .../UtcDatePatternConverter.cs | 106 +- src/log4net/Util/PropertiesDictionary.cs | 598 +-- src/log4net/Util/ProtectCloseTextWriter.cs | 114 +- src/log4net/Util/QuietTextWriter.cs | 352 +- .../Util/ReadOnlyPropertiesDictionary.cs | 686 ++-- src/log4net/Util/ReaderWriterLock.cs | 214 +- src/log4net/Util/ReusableStringWriter.cs | 126 +- src/log4net/Util/SystemInfo.cs | 2418 ++++++------ src/log4net/Util/SystemStringFormat.cs | 416 +- src/log4net/Util/TextWriterAdapter.cs | 412 +- src/log4net/Util/ThreadContextProperties.cs | 308 +- src/log4net/Util/ThreadContextStack.cs | 840 ++-- src/log4net/Util/ThreadContextStacks.cs | 196 +- src/log4net/Util/Transform.cs | 338 +- .../Util/TypeConverters/BooleanConverter.cs | 116 +- .../ConversionNotSupportedException.cs | 228 +- .../Util/TypeConverters/ConverterRegistry.cs | 492 +-- .../Util/TypeConverters/EncodingConverter.cs | 116 +- .../Util/TypeConverters/IConvertFrom.cs | 76 +- src/log4net/Util/TypeConverters/IConvertTo.cs | 76 +- .../Util/TypeConverters/IPAddressConverter.cs | 214 +- .../TypeConverters/PatternLayoutConverter.cs | 124 +- .../TypeConverters/PatternStringConverter.cs | 212 +- .../Util/TypeConverters/TypeConverter.cs | 120 +- .../TypeConverters/TypeConverterAttribute.cs | 168 +- src/log4net/Util/WindowsSecurityContext.cs | 676 ++-- 216 files changed, 48008 insertions(+), 48008 deletions(-) diff --git a/src/log4net/Appender/AdoNetAppender.cs b/src/log4net/Appender/AdoNetAppender.cs index c4e3e358..cad90c5f 100644 --- a/src/log4net/Appender/AdoNetAppender.cs +++ b/src/log4net/Appender/AdoNetAppender.cs @@ -37,1148 +37,1148 @@ namespace log4net.Appender { - /// - /// Appender that logs to a database. - /// - /// - /// - /// appends logging events to a table within a - /// database. The appender can be configured to specify the connection - /// string by setting the property. - /// The connection type (provider) can be specified by setting the - /// property. For more information on database connection strings for - /// your specific database see http://www.connectionstrings.com/. - /// - /// - /// Records are written into the database either using a prepared - /// statement or a stored procedure. The property - /// is set to (System.Data.CommandType.Text) to specify a prepared statement - /// or to (System.Data.CommandType.StoredProcedure) to specify a stored - /// procedure. - /// - /// - /// The prepared statement text or the name of the stored procedure - /// must be set in the property. - /// - /// - /// The prepared statement or stored procedure can take a number - /// of parameters. Parameters are added using the - /// method. This adds a single to the - /// ordered list of parameters. The - /// type may be subclassed if required to provide database specific - /// functionality. The specifies - /// the parameter name, database type, size, and how the value should - /// be generated using a . - /// - /// - /// - /// An example of a SQL Server table that could be logged to: - /// - /// CREATE TABLE [dbo].[Log] ( - /// [ID] [int] IDENTITY (1, 1) NOT NULL , - /// [Date] [datetime] NOT NULL , - /// [Thread] [varchar] (255) NOT NULL , - /// [Level] [varchar] (20) NOT NULL , - /// [Logger] [varchar] (255) NOT NULL , - /// [Message] [varchar] (4000) NOT NULL - /// ) ON [PRIMARY] - /// - /// - /// - /// An example configuration to log to the above table: - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// Julian Biddle - /// Nicko Cadell - /// Gert Driesen - /// Lance Nehring - public class AdoNetAppender : BufferingAppenderSkeleton - { - #region Public Instance Constructors - - /// - /// Initializes a new instance of the class. - /// - /// - /// Public default constructor to initialize a new instance of this class. - /// - public AdoNetAppender() - { - ConnectionType = "System.Data.OleDb.OleDbConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"; - UseTransactions = true; - CommandType = System.Data.CommandType.Text; - m_parameters = new ArrayList(); - ReconnectOnError = false; - } - - #endregion // Public Instance Constructors - - #region Public Instance Properties - - /// - /// Gets or sets the database connection string that is used to connect to - /// the database. - /// - /// - /// The database connection string used to connect to the database. - /// - /// - /// - /// The connections string is specific to the connection type. - /// See for more information. - /// - /// - /// Connection string for MS Access via ODBC: - /// "DSN=MS Access Database;UID=admin;PWD=;SystemDB=C:\data\System.mdw;SafeTransactions = 0;FIL=MS Access;DriverID = 25;DBQ=C:\data\train33.mdb" - /// - /// Another connection string for MS Access via ODBC: - /// "Driver={Microsoft Access Driver (*.mdb)};DBQ=C:\Work\cvs_root\log4net-1.2\access.mdb;UID=;PWD=;" - /// - /// Connection string for MS Access via OLE DB: - /// "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Work\cvs_root\log4net-1.2\access.mdb;User Id=;Password=;" - /// - public string ConnectionString - { - get { return m_connectionString; } - set { m_connectionString = value; } - } - - /// - /// The appSettings key from App.Config that contains the connection string. - /// - public string AppSettingsKey - { - get { return m_appSettingsKey; } - set { m_appSettingsKey = value; } - } - - /// - /// The connectionStrings key from App.Config that contains the connection string. - /// - /// - /// This property requires at least .NET 2.0. - /// - public string ConnectionStringName - { - get { return m_connectionStringName; } - set { m_connectionStringName = value; } - } - - /// - /// Gets or sets the type name of the connection - /// that should be created. - /// - /// - /// The type name of the connection. - /// - /// - /// - /// The type name of the ADO.NET provider to use. - /// - /// - /// The default is to use the OLE DB provider. - /// - /// - /// Use the OLE DB Provider. This is the default value. - /// System.Data.OleDb.OleDbConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - /// - /// Use the MS SQL Server Provider. - /// System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - /// - /// Use the ODBC Provider. - /// Microsoft.Data.Odbc.OdbcConnection,Microsoft.Data.Odbc,version=1.0.3300.0,publicKeyToken=b77a5c561934e089,culture=neutral - /// This is an optional package that you can download from - /// http://msdn.microsoft.com/downloads - /// search for ODBC .NET Data Provider. - /// - /// Use the Oracle Provider. - /// System.Data.OracleClient.OracleConnection, System.Data.OracleClient, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - /// This is an optional package that you can download from - /// http://msdn.microsoft.com/downloads - /// search for .NET Managed Provider for Oracle. - /// - public string ConnectionType - { - get { return m_connectionType; } - set { m_connectionType = value; } - } - - /// - /// Gets or sets the command text that is used to insert logging events - /// into the database. - /// - /// - /// The command text used to insert logging events into the database. - /// - /// - /// - /// Either the text of the prepared statement or the - /// name of the stored procedure to execute to write into - /// the database. - /// - /// - /// The property determines if - /// this text is a prepared statement or a stored procedure. - /// - /// - /// If this property is not set, the command text is retrieved by invoking - /// . - /// - /// - public string CommandText - { - get { return m_commandText; } - set { m_commandText = value; } - } - - /// - /// Gets or sets the command type to execute. - /// - /// - /// The command type to execute. - /// - /// - /// - /// This value may be either (System.Data.CommandType.Text) to specify - /// that the is a prepared statement to execute, - /// or (System.Data.CommandType.StoredProcedure) to specify that the - /// property is the name of a stored procedure - /// to execute. - /// - /// - /// The default value is (System.Data.CommandType.Text). - /// - /// - public CommandType CommandType - { - get { return m_commandType; } - set { m_commandType = value; } - } - - /// - /// Should transactions be used to insert logging events in the database. - /// - /// - /// true if transactions should be used to insert logging events in - /// the database, otherwise false. The default value is true. - /// - /// - /// - /// Gets or sets a value that indicates whether transactions should be used - /// to insert logging events in the database. - /// - /// - /// When set a single transaction will be used to insert the buffered events - /// into the database. Otherwise each event will be inserted without using - /// an explicit transaction. - /// - /// - public bool UseTransactions - { - get { return m_useTransactions; } - set { m_useTransactions = value; } - } - - /// - /// Gets or sets the used to call the NetSend method. - /// - /// - /// The used to call the NetSend method. - /// - /// - /// - /// Unless a specified here for this appender - /// the is queried for the - /// security context to use. The default behavior is to use the security context - /// of the current thread. - /// - /// - public SecurityContext SecurityContext - { - get { return m_securityContext; } - set { m_securityContext = value; } - } - - /// - /// Should this appender try to reconnect to the database on error. - /// - /// - /// true if the appender should try to reconnect to the database after an - /// error has occurred, otherwise false. The default value is false, - /// i.e. not to try to reconnect. - /// - /// - /// - /// The default behaviour is for the appender not to try to reconnect to the - /// database if an error occurs. Subsequent logging events are discarded. - /// - /// - /// To force the appender to attempt to reconnect to the database set this - /// property to true. - /// - /// - /// When the appender attempts to connect to the database there may be a - /// delay of up to the connection timeout specified in the connection string. - /// This delay will block the calling application's thread. - /// Until the connection can be reestablished this potential delay may occur multiple times. - /// - /// - public bool ReconnectOnError - { - get { return m_reconnectOnError; } - set { m_reconnectOnError = value; } - } - - #endregion // Public Instance Properties - - #region Protected Instance Properties - - /// - /// Gets or sets the underlying . - /// - /// - /// The underlying . - /// - /// - /// creates a to insert - /// logging events into a database. Classes deriving from - /// can use this property to get or set this . Use the - /// underlying returned from if - /// you require access beyond that which provides. - /// - protected IDbConnection Connection - { - get { return m_dbConnection; } - set { m_dbConnection = value; } - } - - #endregion // Protected Instance Properties - - #region Implementation of IOptionHandler - - /// - /// Initialize the appender based on the options set - /// - /// - /// - /// This is part of the delayed object - /// activation scheme. The method must - /// be called on this object after the configuration properties have - /// been set. Until is called this - /// object is in an undefined state and must not be used. - /// - /// - /// If any of the configuration properties are modified then - /// must be called again. - /// - /// - public override void ActivateOptions() - { - base.ActivateOptions(); - - if (SecurityContext == null) - { - SecurityContext = SecurityContextProvider.DefaultProvider.CreateSecurityContext(this); - } - - InitializeDatabaseConnection(); - } - - #endregion - - #region Override implementation of AppenderSkeleton - - /// - /// Override the parent method to close the database - /// - /// - /// - /// Closes the database command and database connection. - /// - /// - protected override void OnClose() - { - base.OnClose(); - DiposeConnection(); - } - - #endregion - - #region Override implementation of BufferingAppenderSkeleton - - /// - /// Inserts the events into the database. - /// - /// The events to insert into the database. - /// - /// - /// Insert all the events specified in the - /// array into the database. - /// - /// - protected override void SendBuffer(LoggingEvent[] events) - { - if (ReconnectOnError && (Connection == null || Connection.State != ConnectionState.Open)) - { - LogLog.Debug(declaringType, "Attempting to reconnect to database. Current Connection State: " + ((Connection == null) ? SystemInfo.NullText : Connection.State.ToString())); - - InitializeDatabaseConnection(); - } - - // Check that the connection exists and is open - if (Connection != null && Connection.State == ConnectionState.Open) - { - if (UseTransactions) - { - // Create transaction - // NJC - Do this on 2 lines because it can confuse the debugger - using (IDbTransaction dbTran = Connection.BeginTransaction()) - { - try - { - SendBuffer(dbTran, events); - - // commit transaction - dbTran.Commit(); - } - catch (Exception ex) - { - // rollback the transaction - try - { - dbTran.Rollback(); - } - catch (Exception) - { - // Ignore exception - } - - // Can't insert into the database. That's a bad thing - ErrorHandler.Error("Exception while writing to database", ex); - } - } - } - else - { - // Send without transaction - SendBuffer(null, events); - } - } - } - - #endregion // Override implementation of BufferingAppenderSkeleton - - #region Public Instance Methods - - /// - /// Adds a parameter to the command. - /// - /// The parameter to add to the command. - /// - /// - /// Adds a parameter to the ordered list of command parameters. - /// - /// - public void AddParameter(AdoNetAppenderParameter parameter) - { - m_parameters.Add(parameter); - } - - - #endregion // Public Instance Methods - - #region Protected Instance Methods - - /// - /// Writes the events to the database using the transaction specified. - /// - /// The transaction that the events will be executed under. - /// The array of events to insert into the database. - /// - /// - /// The transaction argument can be null if the appender has been - /// configured not to use transactions. See - /// property for more information. - /// - /// - protected virtual void SendBuffer(IDbTransaction dbTran, LoggingEvent[] events) - { - // string.IsNotNullOrWhiteSpace() does not exist in ancient .NET frameworks - if (CommandText != null && CommandText.Trim() != "") - { - using (IDbCommand dbCmd = Connection.CreateCommand()) - { - // Set the command string - dbCmd.CommandText = CommandText; - - // Set the command type - dbCmd.CommandType = CommandType; - // Send buffer using the prepared command object - if (dbTran != null) - { - dbCmd.Transaction = dbTran; - } - - try - { - // prepare the command, which is significantly faster - Prepare(dbCmd); - } - catch (Exception) - { - if (dbTran != null) - { - // rethrow exception in transaction mode, cuz now transaction is in failed state - throw; - } - - // ignore prepare exceptions as they can happen without affecting actual logging, eg on npgsql - } - - // run for all events - foreach (LoggingEvent e in events) - { - // No need to clear dbCmd.Parameters, just use existing. - // Set the parameter values - foreach (AdoNetAppenderParameter param in m_parameters) - { - param.FormatValue(dbCmd, e); - } - - // Execute the query - dbCmd.ExecuteNonQuery(); - } - } - } - else - { - // create a new command - using (IDbCommand dbCmd = Connection.CreateCommand()) - { - if (dbTran != null) - { - dbCmd.Transaction = dbTran; - } - // run for all events - foreach (LoggingEvent e in events) - { - // Get the command text from the Layout - string logStatement = GetLogStatement(e); - - LogLog.Debug(declaringType, "LogStatement [" + logStatement + "]"); - - dbCmd.CommandText = logStatement; - dbCmd.ExecuteNonQuery(); - } - } - } - } - - /// - /// Prepare entire database command object to be executed. - /// - /// The command to prepare. - protected virtual void Prepare(IDbCommand dbCmd) - { - // npgsql require parameters to prepare command - foreach (AdoNetAppenderParameter parameter in m_parameters) - { - parameter.Prepare(dbCmd); - } - - dbCmd.Prepare(); - } - - /// - /// Formats the log message into database statement text. - /// - /// The event being logged. - /// - /// This method can be overridden by subclasses to provide - /// more control over the format of the database statement. - /// - /// - /// Text that can be passed to a . - /// - protected virtual string GetLogStatement(LoggingEvent logEvent) - { - if (Layout == null) - { - ErrorHandler.Error("AdoNetAppender: No Layout specified."); - return ""; - } - else - { - using StringWriter writer = new StringWriter(System.Globalization.CultureInfo.InvariantCulture); - Layout.Format(writer, logEvent); - return writer.ToString(); - } - } - - /// - /// Creates an instance used to connect to the database. - /// - /// - /// This method is called whenever a new IDbConnection is needed (i.e. when a reconnect is necessary). - /// - /// The of the object. - /// The connectionString output from the ResolveConnectionString method. - /// An instance with a valid connection string. - protected virtual IDbConnection CreateConnection(Type connectionType, string connectionString) - { - IDbConnection connection = (IDbConnection)Activator.CreateInstance(connectionType); - connection.ConnectionString = connectionString; - return connection; - } - - /// - /// Resolves the connection string from the ConnectionString, ConnectionStringName, or AppSettingsKey - /// property. - /// - /// - /// ConnectiongStringName is only supported on .NET 2.0 and higher. - /// - /// Additional information describing the connection string. - /// A connection string used to connect to the database. - protected virtual string ResolveConnectionString(out string connectionStringContext) - { - if (ConnectionString != null && ConnectionString.Length > 0) - { - connectionStringContext = "ConnectionString"; - return ConnectionString; - } + /// + /// Appender that logs to a database. + /// + /// + /// + /// appends logging events to a table within a + /// database. The appender can be configured to specify the connection + /// string by setting the property. + /// The connection type (provider) can be specified by setting the + /// property. For more information on database connection strings for + /// your specific database see http://www.connectionstrings.com/. + /// + /// + /// Records are written into the database either using a prepared + /// statement or a stored procedure. The property + /// is set to (System.Data.CommandType.Text) to specify a prepared statement + /// or to (System.Data.CommandType.StoredProcedure) to specify a stored + /// procedure. + /// + /// + /// The prepared statement text or the name of the stored procedure + /// must be set in the property. + /// + /// + /// The prepared statement or stored procedure can take a number + /// of parameters. Parameters are added using the + /// method. This adds a single to the + /// ordered list of parameters. The + /// type may be subclassed if required to provide database specific + /// functionality. The specifies + /// the parameter name, database type, size, and how the value should + /// be generated using a . + /// + /// + /// + /// An example of a SQL Server table that could be logged to: + /// + /// CREATE TABLE [dbo].[Log] ( + /// [ID] [int] IDENTITY (1, 1) NOT NULL , + /// [Date] [datetime] NOT NULL , + /// [Thread] [varchar] (255) NOT NULL , + /// [Level] [varchar] (20) NOT NULL , + /// [Logger] [varchar] (255) NOT NULL , + /// [Message] [varchar] (4000) NOT NULL + /// ) ON [PRIMARY] + /// + /// + /// + /// An example configuration to log to the above table: + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// Julian Biddle + /// Nicko Cadell + /// Gert Driesen + /// Lance Nehring + public class AdoNetAppender : BufferingAppenderSkeleton + { + #region Public Instance Constructors + + /// + /// Initializes a new instance of the class. + /// + /// + /// Public default constructor to initialize a new instance of this class. + /// + public AdoNetAppender() + { + ConnectionType = "System.Data.OleDb.OleDbConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"; + UseTransactions = true; + CommandType = System.Data.CommandType.Text; + m_parameters = new ArrayList(); + ReconnectOnError = false; + } + + #endregion // Public Instance Constructors + + #region Public Instance Properties + + /// + /// Gets or sets the database connection string that is used to connect to + /// the database. + /// + /// + /// The database connection string used to connect to the database. + /// + /// + /// + /// The connections string is specific to the connection type. + /// See for more information. + /// + /// + /// Connection string for MS Access via ODBC: + /// "DSN=MS Access Database;UID=admin;PWD=;SystemDB=C:\data\System.mdw;SafeTransactions = 0;FIL=MS Access;DriverID = 25;DBQ=C:\data\train33.mdb" + /// + /// Another connection string for MS Access via ODBC: + /// "Driver={Microsoft Access Driver (*.mdb)};DBQ=C:\Work\cvs_root\log4net-1.2\access.mdb;UID=;PWD=;" + /// + /// Connection string for MS Access via OLE DB: + /// "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Work\cvs_root\log4net-1.2\access.mdb;User Id=;Password=;" + /// + public string ConnectionString + { + get { return m_connectionString; } + set { m_connectionString = value; } + } + + /// + /// The appSettings key from App.Config that contains the connection string. + /// + public string AppSettingsKey + { + get { return m_appSettingsKey; } + set { m_appSettingsKey = value; } + } + + /// + /// The connectionStrings key from App.Config that contains the connection string. + /// + /// + /// This property requires at least .NET 2.0. + /// + public string ConnectionStringName + { + get { return m_connectionStringName; } + set { m_connectionStringName = value; } + } + + /// + /// Gets or sets the type name of the connection + /// that should be created. + /// + /// + /// The type name of the connection. + /// + /// + /// + /// The type name of the ADO.NET provider to use. + /// + /// + /// The default is to use the OLE DB provider. + /// + /// + /// Use the OLE DB Provider. This is the default value. + /// System.Data.OleDb.OleDbConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + /// + /// Use the MS SQL Server Provider. + /// System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + /// + /// Use the ODBC Provider. + /// Microsoft.Data.Odbc.OdbcConnection,Microsoft.Data.Odbc,version=1.0.3300.0,publicKeyToken=b77a5c561934e089,culture=neutral + /// This is an optional package that you can download from + /// http://msdn.microsoft.com/downloads + /// search for ODBC .NET Data Provider. + /// + /// Use the Oracle Provider. + /// System.Data.OracleClient.OracleConnection, System.Data.OracleClient, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + /// This is an optional package that you can download from + /// http://msdn.microsoft.com/downloads + /// search for .NET Managed Provider for Oracle. + /// + public string ConnectionType + { + get { return m_connectionType; } + set { m_connectionType = value; } + } + + /// + /// Gets or sets the command text that is used to insert logging events + /// into the database. + /// + /// + /// The command text used to insert logging events into the database. + /// + /// + /// + /// Either the text of the prepared statement or the + /// name of the stored procedure to execute to write into + /// the database. + /// + /// + /// The property determines if + /// this text is a prepared statement or a stored procedure. + /// + /// + /// If this property is not set, the command text is retrieved by invoking + /// . + /// + /// + public string CommandText + { + get { return m_commandText; } + set { m_commandText = value; } + } + + /// + /// Gets or sets the command type to execute. + /// + /// + /// The command type to execute. + /// + /// + /// + /// This value may be either (System.Data.CommandType.Text) to specify + /// that the is a prepared statement to execute, + /// or (System.Data.CommandType.StoredProcedure) to specify that the + /// property is the name of a stored procedure + /// to execute. + /// + /// + /// The default value is (System.Data.CommandType.Text). + /// + /// + public CommandType CommandType + { + get { return m_commandType; } + set { m_commandType = value; } + } + + /// + /// Should transactions be used to insert logging events in the database. + /// + /// + /// true if transactions should be used to insert logging events in + /// the database, otherwise false. The default value is true. + /// + /// + /// + /// Gets or sets a value that indicates whether transactions should be used + /// to insert logging events in the database. + /// + /// + /// When set a single transaction will be used to insert the buffered events + /// into the database. Otherwise each event will be inserted without using + /// an explicit transaction. + /// + /// + public bool UseTransactions + { + get { return m_useTransactions; } + set { m_useTransactions = value; } + } + + /// + /// Gets or sets the used to call the NetSend method. + /// + /// + /// The used to call the NetSend method. + /// + /// + /// + /// Unless a specified here for this appender + /// the is queried for the + /// security context to use. The default behavior is to use the security context + /// of the current thread. + /// + /// + public SecurityContext SecurityContext + { + get { return m_securityContext; } + set { m_securityContext = value; } + } + + /// + /// Should this appender try to reconnect to the database on error. + /// + /// + /// true if the appender should try to reconnect to the database after an + /// error has occurred, otherwise false. The default value is false, + /// i.e. not to try to reconnect. + /// + /// + /// + /// The default behaviour is for the appender not to try to reconnect to the + /// database if an error occurs. Subsequent logging events are discarded. + /// + /// + /// To force the appender to attempt to reconnect to the database set this + /// property to true. + /// + /// + /// When the appender attempts to connect to the database there may be a + /// delay of up to the connection timeout specified in the connection string. + /// This delay will block the calling application's thread. + /// Until the connection can be reestablished this potential delay may occur multiple times. + /// + /// + public bool ReconnectOnError + { + get { return m_reconnectOnError; } + set { m_reconnectOnError = value; } + } + + #endregion // Public Instance Properties + + #region Protected Instance Properties + + /// + /// Gets or sets the underlying . + /// + /// + /// The underlying . + /// + /// + /// creates a to insert + /// logging events into a database. Classes deriving from + /// can use this property to get or set this . Use the + /// underlying returned from if + /// you require access beyond that which provides. + /// + protected IDbConnection Connection + { + get { return m_dbConnection; } + set { m_dbConnection = value; } + } + + #endregion // Protected Instance Properties + + #region Implementation of IOptionHandler + + /// + /// Initialize the appender based on the options set + /// + /// + /// + /// This is part of the delayed object + /// activation scheme. The method must + /// be called on this object after the configuration properties have + /// been set. Until is called this + /// object is in an undefined state and must not be used. + /// + /// + /// If any of the configuration properties are modified then + /// must be called again. + /// + /// + public override void ActivateOptions() + { + base.ActivateOptions(); + + if (SecurityContext == null) + { + SecurityContext = SecurityContextProvider.DefaultProvider.CreateSecurityContext(this); + } + + InitializeDatabaseConnection(); + } + + #endregion + + #region Override implementation of AppenderSkeleton + + /// + /// Override the parent method to close the database + /// + /// + /// + /// Closes the database command and database connection. + /// + /// + protected override void OnClose() + { + base.OnClose(); + DiposeConnection(); + } + + #endregion + + #region Override implementation of BufferingAppenderSkeleton + + /// + /// Inserts the events into the database. + /// + /// The events to insert into the database. + /// + /// + /// Insert all the events specified in the + /// array into the database. + /// + /// + protected override void SendBuffer(LoggingEvent[] events) + { + if (ReconnectOnError && (Connection == null || Connection.State != ConnectionState.Open)) + { + LogLog.Debug(declaringType, "Attempting to reconnect to database. Current Connection State: " + ((Connection == null) ? SystemInfo.NullText : Connection.State.ToString())); + + InitializeDatabaseConnection(); + } + + // Check that the connection exists and is open + if (Connection != null && Connection.State == ConnectionState.Open) + { + if (UseTransactions) + { + // Create transaction + // NJC - Do this on 2 lines because it can confuse the debugger + using (IDbTransaction dbTran = Connection.BeginTransaction()) + { + try + { + SendBuffer(dbTran, events); + + // commit transaction + dbTran.Commit(); + } + catch (Exception ex) + { + // rollback the transaction + try + { + dbTran.Rollback(); + } + catch (Exception) + { + // Ignore exception + } + + // Can't insert into the database. That's a bad thing + ErrorHandler.Error("Exception while writing to database", ex); + } + } + } + else + { + // Send without transaction + SendBuffer(null, events); + } + } + } + + #endregion // Override implementation of BufferingAppenderSkeleton + + #region Public Instance Methods + + /// + /// Adds a parameter to the command. + /// + /// The parameter to add to the command. + /// + /// + /// Adds a parameter to the ordered list of command parameters. + /// + /// + public void AddParameter(AdoNetAppenderParameter parameter) + { + m_parameters.Add(parameter); + } + + + #endregion // Public Instance Methods + + #region Protected Instance Methods + + /// + /// Writes the events to the database using the transaction specified. + /// + /// The transaction that the events will be executed under. + /// The array of events to insert into the database. + /// + /// + /// The transaction argument can be null if the appender has been + /// configured not to use transactions. See + /// property for more information. + /// + /// + protected virtual void SendBuffer(IDbTransaction dbTran, LoggingEvent[] events) + { + // string.IsNotNullOrWhiteSpace() does not exist in ancient .NET frameworks + if (CommandText != null && CommandText.Trim() != "") + { + using (IDbCommand dbCmd = Connection.CreateCommand()) + { + // Set the command string + dbCmd.CommandText = CommandText; + + // Set the command type + dbCmd.CommandType = CommandType; + // Send buffer using the prepared command object + if (dbTran != null) + { + dbCmd.Transaction = dbTran; + } + + try + { + // prepare the command, which is significantly faster + Prepare(dbCmd); + } + catch (Exception) + { + if (dbTran != null) + { + // rethrow exception in transaction mode, cuz now transaction is in failed state + throw; + } + + // ignore prepare exceptions as they can happen without affecting actual logging, eg on npgsql + } + + // run for all events + foreach (LoggingEvent e in events) + { + // No need to clear dbCmd.Parameters, just use existing. + // Set the parameter values + foreach (AdoNetAppenderParameter param in m_parameters) + { + param.FormatValue(dbCmd, e); + } + + // Execute the query + dbCmd.ExecuteNonQuery(); + } + } + } + else + { + // create a new command + using (IDbCommand dbCmd = Connection.CreateCommand()) + { + if (dbTran != null) + { + dbCmd.Transaction = dbTran; + } + // run for all events + foreach (LoggingEvent e in events) + { + // Get the command text from the Layout + string logStatement = GetLogStatement(e); + + LogLog.Debug(declaringType, "LogStatement [" + logStatement + "]"); + + dbCmd.CommandText = logStatement; + dbCmd.ExecuteNonQuery(); + } + } + } + } + + /// + /// Prepare entire database command object to be executed. + /// + /// The command to prepare. + protected virtual void Prepare(IDbCommand dbCmd) + { + // npgsql require parameters to prepare command + foreach (AdoNetAppenderParameter parameter in m_parameters) + { + parameter.Prepare(dbCmd); + } + + dbCmd.Prepare(); + } + + /// + /// Formats the log message into database statement text. + /// + /// The event being logged. + /// + /// This method can be overridden by subclasses to provide + /// more control over the format of the database statement. + /// + /// + /// Text that can be passed to a . + /// + protected virtual string GetLogStatement(LoggingEvent logEvent) + { + if (Layout == null) + { + ErrorHandler.Error("AdoNetAppender: No Layout specified."); + return ""; + } + else + { + using StringWriter writer = new StringWriter(System.Globalization.CultureInfo.InvariantCulture); + Layout.Format(writer, logEvent); + return writer.ToString(); + } + } + + /// + /// Creates an instance used to connect to the database. + /// + /// + /// This method is called whenever a new IDbConnection is needed (i.e. when a reconnect is necessary). + /// + /// The of the object. + /// The connectionString output from the ResolveConnectionString method. + /// An instance with a valid connection string. + protected virtual IDbConnection CreateConnection(Type connectionType, string connectionString) + { + IDbConnection connection = (IDbConnection)Activator.CreateInstance(connectionType); + connection.ConnectionString = connectionString; + return connection; + } + + /// + /// Resolves the connection string from the ConnectionString, ConnectionStringName, or AppSettingsKey + /// property. + /// + /// + /// ConnectiongStringName is only supported on .NET 2.0 and higher. + /// + /// Additional information describing the connection string. + /// A connection string used to connect to the database. + protected virtual string ResolveConnectionString(out string connectionStringContext) + { + if (ConnectionString != null && ConnectionString.Length > 0) + { + connectionStringContext = "ConnectionString"; + return ConnectionString; + } #if !NETSTANDARD1_3 - if (!String.IsNullOrEmpty(ConnectionStringName)) - { - ConnectionStringSettings settings = ConfigurationManager.ConnectionStrings[ConnectionStringName]; - if (settings != null) - { - connectionStringContext = "ConnectionStringName"; - return settings.ConnectionString; - } - else - { - throw new LogException("Unable to find [" + ConnectionStringName + "] ConfigurationManager.ConnectionStrings item"); - } - } + if (!String.IsNullOrEmpty(ConnectionStringName)) + { + ConnectionStringSettings settings = ConfigurationManager.ConnectionStrings[ConnectionStringName]; + if (settings != null) + { + connectionStringContext = "ConnectionStringName"; + return settings.ConnectionString; + } + else + { + throw new LogException("Unable to find [" + ConnectionStringName + "] ConfigurationManager.ConnectionStrings item"); + } + } #endif - if (AppSettingsKey != null && AppSettingsKey.Length > 0) - { - connectionStringContext = "AppSettingsKey"; - string appSettingsConnectionString = SystemInfo.GetAppSetting(AppSettingsKey); - if (appSettingsConnectionString == null || appSettingsConnectionString.Length == 0) - { - throw new LogException("Unable to find [" + AppSettingsKey + "] AppSettings key."); - } - return appSettingsConnectionString; - } - - connectionStringContext = "Unable to resolve connection string from ConnectionString, ConnectionStrings, or AppSettings."; - return string.Empty; - } - - /// - /// Retrieves the class type of the ADO.NET provider. - /// - /// - /// - /// Gets the Type of the ADO.NET provider to use to connect to the - /// database. This method resolves the type specified in the - /// property. - /// - /// - /// Subclasses can override this method to return a different type - /// if necessary. - /// - /// - /// The of the ADO.NET provider - protected virtual Type ResolveConnectionType() - { - try - { + if (AppSettingsKey != null && AppSettingsKey.Length > 0) + { + connectionStringContext = "AppSettingsKey"; + string appSettingsConnectionString = SystemInfo.GetAppSetting(AppSettingsKey); + if (appSettingsConnectionString == null || appSettingsConnectionString.Length == 0) + { + throw new LogException("Unable to find [" + AppSettingsKey + "] AppSettings key."); + } + return appSettingsConnectionString; + } + + connectionStringContext = "Unable to resolve connection string from ConnectionString, ConnectionStrings, or AppSettings."; + return string.Empty; + } + + /// + /// Retrieves the class type of the ADO.NET provider. + /// + /// + /// + /// Gets the Type of the ADO.NET provider to use to connect to the + /// database. This method resolves the type specified in the + /// property. + /// + /// + /// Subclasses can override this method to return a different type + /// if necessary. + /// + /// + /// The of the ADO.NET provider + protected virtual Type ResolveConnectionType() + { + try + { #if NETSTANDARD1_3 - // NETSTANDARD1_3 requires comma separated ConnectionType like `System.Data.SqlClient.SqlConnection, System.Data` to work properly. - return SystemInfo.GetTypeFromString((Assembly)null, ConnectionType, true, false); + // NETSTANDARD1_3 requires comma separated ConnectionType like `System.Data.SqlClient.SqlConnection, System.Data` to work properly. + return SystemInfo.GetTypeFromString((Assembly)null, ConnectionType, true, false); #else - return SystemInfo.GetTypeFromString(ConnectionType, true, false); + return SystemInfo.GetTypeFromString(ConnectionType, true, false); #endif - } - catch (Exception ex) - { - ErrorHandler.Error("Failed to load connection type [" + ConnectionType + "]", ex); - throw; - } - } - - #endregion // Protected Instance Methods - - #region Private Instance Methods - - /// - /// Connects to the database. - /// - private void InitializeDatabaseConnection() - { - string connectionStringContext = "Unable to determine connection string context."; - string resolvedConnectionString = string.Empty; - - try - { - DiposeConnection(); - - // Set the connection string - resolvedConnectionString = ResolveConnectionString(out connectionStringContext); - - Connection = CreateConnection(ResolveConnectionType(), resolvedConnectionString); - - using (SecurityContext.Impersonate(this)) - { - // Open the database connection - Connection.Open(); - } - } - catch (Exception e) - { - // Sadly, your connection string is bad. - ErrorHandler.Error("Could not open database connection [" + resolvedConnectionString + "]. Connection string context [" + connectionStringContext + "].", e); - - Connection = null; - } - } - - /// - /// Cleanup the existing connection. - /// - /// - /// Calls the IDbConnection's method. - /// - private void DiposeConnection() - { - if (Connection != null) - { - try - { - Connection.Close(); - } - catch (Exception ex) - { - LogLog.Warn(declaringType, "Exception while disposing cached connection object", ex); - } - Connection = null; - } - } - - #endregion // Private Instance Methods - - #region Protected Instance Fields - - /// - /// The list of objects. - /// - /// - /// - /// The list of objects. - /// - /// - protected ArrayList m_parameters; - - #endregion // Protected Instance Fields - - #region Private Instance Fields - - /// - /// The security context to use for privileged calls - /// - private SecurityContext m_securityContext; - - /// - /// The that will be used - /// to insert logging events into a database. - /// - private IDbConnection m_dbConnection; - - /// - /// Database connection string. - /// - private string m_connectionString; - - /// - /// The appSettings key from App.Config that contains the connection string. - /// - private string m_appSettingsKey; - - /// - /// The connectionStrings key from App.Config that contains the connection string. - /// - private string m_connectionStringName; - - /// - /// String type name of the type name. - /// - private string m_connectionType; - - /// - /// The text of the command. - /// - private string m_commandText; - - /// - /// The command type. - /// - private CommandType m_commandType; - - /// - /// Indicates whether to use transactions when writing to the database. - /// - private bool m_useTransactions; - - /// - /// Indicates whether to reconnect when a connection is lost. - /// - private bool m_reconnectOnError; - - #endregion // Private Instance Fields - - #region Private Static Fields - - /// - /// The fully qualified type of the AdoNetAppender class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(AdoNetAppender); - - #endregion Private Static Fields - } - - /// - /// Parameter type used by the . - /// - /// - /// - /// This class provides the basic database parameter properties - /// as defined by the interface. - /// - /// This type can be subclassed to provide database specific - /// functionality. The two methods that are called externally are - /// and . - /// - /// - public class AdoNetAppenderParameter - { - #region Public Instance Constructors - - /// - /// Initializes a new instance of the class. - /// - /// - /// Default constructor for the AdoNetAppenderParameter class. - /// - public AdoNetAppenderParameter() - { - Precision = 0; - Scale = 0; - Size = 0; - } - - #endregion // Public Instance Constructors - - #region Public Instance Properties - - /// - /// Gets or sets the name of this parameter. - /// - /// - /// The name of this parameter. - /// - /// - /// - /// The name of this parameter. The parameter name - /// must match up to a named parameter to the SQL stored procedure - /// or prepared statement. - /// - /// - public string ParameterName - { - get { return m_parameterName; } - set { m_parameterName = value; } - } - - /// - /// Gets or sets the database type for this parameter. - /// - /// - /// The database type for this parameter. - /// - /// - /// - /// The database type for this parameter. This property should - /// be set to the database type from the - /// enumeration. See . - /// - /// - /// This property is optional. If not specified the ADO.NET provider - /// will attempt to infer the type from the value. - /// - /// - /// - public DbType DbType - { - get { return m_dbType; } - set - { - m_dbType = value; - m_inferType = false; - } - } - - /// - /// Gets or sets the precision for this parameter. - /// - /// - /// The precision for this parameter. - /// - /// - /// - /// The maximum number of digits used to represent the Value. - /// - /// - /// This property is optional. If not specified the ADO.NET provider - /// will attempt to infer the precision from the value. - /// - /// - /// - public byte Precision - { - get { return m_precision; } - set { m_precision = value; } - } - - /// - /// Gets or sets the scale for this parameter. - /// - /// - /// The scale for this parameter. - /// - /// - /// - /// The number of decimal places to which Value is resolved. - /// - /// - /// This property is optional. If not specified the ADO.NET provider - /// will attempt to infer the scale from the value. - /// - /// - /// - public byte Scale - { - get { return m_scale; } - set { m_scale = value; } - } - - /// - /// Gets or sets the size for this parameter. - /// - /// - /// The size for this parameter. - /// - /// - /// - /// The maximum size, in bytes, of the data within the column. - /// - /// - /// This property is optional. If not specified the ADO.NET provider - /// will attempt to infer the size from the value. - /// - /// - /// For BLOB data types like VARCHAR(max) it may be impossible to infer the value automatically, use -1 as the size in this case. - /// - /// - /// - public int Size - { - get { return m_size; } - set { m_size = value; } - } - - /// - /// Gets or sets the to use to - /// render the logging event into an object for this - /// parameter. - /// - /// - /// The used to render the - /// logging event into an object for this parameter. - /// - /// - /// - /// The that renders the value for this - /// parameter. - /// - /// - /// The can be used to adapt - /// any into a - /// for use in the property. - /// - /// - public IRawLayout Layout - { - get { return m_layout; } - set { m_layout = value; } - } - - #endregion // Public Instance Properties - - #region Public Instance Methods - - /// - /// Prepare the specified database command object. - /// - /// The command to prepare. - /// - /// - /// Prepares the database command object by adding - /// this parameter to its collection of parameters. - /// - /// - public virtual void Prepare(IDbCommand command) - { - // Create a new parameter - IDbDataParameter param = command.CreateParameter(); - - // Set the parameter properties - param.ParameterName = ParameterName; - - if (!m_inferType) - { - param.DbType = DbType; - } - if (Precision != 0) - { - param.Precision = Precision; - } - if (Scale != 0) - { - param.Scale = Scale; - } - if (Size != 0) - { - param.Size = Size; - } - - // Add the parameter to the collection of params - command.Parameters.Add(param); - } - - /// - /// Renders the logging event and set the parameter value in the command. - /// - /// The command containing the parameter. - /// The event to be rendered. - /// - /// - /// Renders the logging event using this parameters layout - /// object. Sets the value of the parameter on the command object. - /// - /// - public virtual void FormatValue(IDbCommand command, LoggingEvent loggingEvent) - { - // Lookup the parameter - IDbDataParameter param = (IDbDataParameter)command.Parameters[ParameterName]; - - // Format the value - object formattedValue = Layout.Format(loggingEvent); - - // If the value is null then convert to a DBNull - if (formattedValue == null) - { - formattedValue = DBNull.Value; - } - - param.Value = formattedValue; - } - - #endregion // Public Instance Methods - - #region Private Instance Fields - - /// - /// The name of this parameter. - /// - private string m_parameterName; - - /// - /// The database type for this parameter. - /// - private DbType m_dbType; - - /// - /// Flag to infer type rather than use the DbType - /// - private bool m_inferType = true; - - /// - /// The precision for this parameter. - /// - private byte m_precision; - - /// - /// The scale for this parameter. - /// - private byte m_scale; - - /// - /// The size for this parameter. - /// - private int m_size; - - /// - /// The to use to render the - /// logging event into an object for this parameter. - /// - private IRawLayout m_layout; - - #endregion // Private Instance Fields - } + } + catch (Exception ex) + { + ErrorHandler.Error("Failed to load connection type [" + ConnectionType + "]", ex); + throw; + } + } + + #endregion // Protected Instance Methods + + #region Private Instance Methods + + /// + /// Connects to the database. + /// + private void InitializeDatabaseConnection() + { + string connectionStringContext = "Unable to determine connection string context."; + string resolvedConnectionString = string.Empty; + + try + { + DiposeConnection(); + + // Set the connection string + resolvedConnectionString = ResolveConnectionString(out connectionStringContext); + + Connection = CreateConnection(ResolveConnectionType(), resolvedConnectionString); + + using (SecurityContext.Impersonate(this)) + { + // Open the database connection + Connection.Open(); + } + } + catch (Exception e) + { + // Sadly, your connection string is bad. + ErrorHandler.Error("Could not open database connection [" + resolvedConnectionString + "]. Connection string context [" + connectionStringContext + "].", e); + + Connection = null; + } + } + + /// + /// Cleanup the existing connection. + /// + /// + /// Calls the IDbConnection's method. + /// + private void DiposeConnection() + { + if (Connection != null) + { + try + { + Connection.Close(); + } + catch (Exception ex) + { + LogLog.Warn(declaringType, "Exception while disposing cached connection object", ex); + } + Connection = null; + } + } + + #endregion // Private Instance Methods + + #region Protected Instance Fields + + /// + /// The list of objects. + /// + /// + /// + /// The list of objects. + /// + /// + protected ArrayList m_parameters; + + #endregion // Protected Instance Fields + + #region Private Instance Fields + + /// + /// The security context to use for privileged calls + /// + private SecurityContext m_securityContext; + + /// + /// The that will be used + /// to insert logging events into a database. + /// + private IDbConnection m_dbConnection; + + /// + /// Database connection string. + /// + private string m_connectionString; + + /// + /// The appSettings key from App.Config that contains the connection string. + /// + private string m_appSettingsKey; + + /// + /// The connectionStrings key from App.Config that contains the connection string. + /// + private string m_connectionStringName; + + /// + /// String type name of the type name. + /// + private string m_connectionType; + + /// + /// The text of the command. + /// + private string m_commandText; + + /// + /// The command type. + /// + private CommandType m_commandType; + + /// + /// Indicates whether to use transactions when writing to the database. + /// + private bool m_useTransactions; + + /// + /// Indicates whether to reconnect when a connection is lost. + /// + private bool m_reconnectOnError; + + #endregion // Private Instance Fields + + #region Private Static Fields + + /// + /// The fully qualified type of the AdoNetAppender class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(AdoNetAppender); + + #endregion Private Static Fields + } + + /// + /// Parameter type used by the . + /// + /// + /// + /// This class provides the basic database parameter properties + /// as defined by the interface. + /// + /// This type can be subclassed to provide database specific + /// functionality. The two methods that are called externally are + /// and . + /// + /// + public class AdoNetAppenderParameter + { + #region Public Instance Constructors + + /// + /// Initializes a new instance of the class. + /// + /// + /// Default constructor for the AdoNetAppenderParameter class. + /// + public AdoNetAppenderParameter() + { + Precision = 0; + Scale = 0; + Size = 0; + } + + #endregion // Public Instance Constructors + + #region Public Instance Properties + + /// + /// Gets or sets the name of this parameter. + /// + /// + /// The name of this parameter. + /// + /// + /// + /// The name of this parameter. The parameter name + /// must match up to a named parameter to the SQL stored procedure + /// or prepared statement. + /// + /// + public string ParameterName + { + get { return m_parameterName; } + set { m_parameterName = value; } + } + + /// + /// Gets or sets the database type for this parameter. + /// + /// + /// The database type for this parameter. + /// + /// + /// + /// The database type for this parameter. This property should + /// be set to the database type from the + /// enumeration. See . + /// + /// + /// This property is optional. If not specified the ADO.NET provider + /// will attempt to infer the type from the value. + /// + /// + /// + public DbType DbType + { + get { return m_dbType; } + set + { + m_dbType = value; + m_inferType = false; + } + } + + /// + /// Gets or sets the precision for this parameter. + /// + /// + /// The precision for this parameter. + /// + /// + /// + /// The maximum number of digits used to represent the Value. + /// + /// + /// This property is optional. If not specified the ADO.NET provider + /// will attempt to infer the precision from the value. + /// + /// + /// + public byte Precision + { + get { return m_precision; } + set { m_precision = value; } + } + + /// + /// Gets or sets the scale for this parameter. + /// + /// + /// The scale for this parameter. + /// + /// + /// + /// The number of decimal places to which Value is resolved. + /// + /// + /// This property is optional. If not specified the ADO.NET provider + /// will attempt to infer the scale from the value. + /// + /// + /// + public byte Scale + { + get { return m_scale; } + set { m_scale = value; } + } + + /// + /// Gets or sets the size for this parameter. + /// + /// + /// The size for this parameter. + /// + /// + /// + /// The maximum size, in bytes, of the data within the column. + /// + /// + /// This property is optional. If not specified the ADO.NET provider + /// will attempt to infer the size from the value. + /// + /// + /// For BLOB data types like VARCHAR(max) it may be impossible to infer the value automatically, use -1 as the size in this case. + /// + /// + /// + public int Size + { + get { return m_size; } + set { m_size = value; } + } + + /// + /// Gets or sets the to use to + /// render the logging event into an object for this + /// parameter. + /// + /// + /// The used to render the + /// logging event into an object for this parameter. + /// + /// + /// + /// The that renders the value for this + /// parameter. + /// + /// + /// The can be used to adapt + /// any into a + /// for use in the property. + /// + /// + public IRawLayout Layout + { + get { return m_layout; } + set { m_layout = value; } + } + + #endregion // Public Instance Properties + + #region Public Instance Methods + + /// + /// Prepare the specified database command object. + /// + /// The command to prepare. + /// + /// + /// Prepares the database command object by adding + /// this parameter to its collection of parameters. + /// + /// + public virtual void Prepare(IDbCommand command) + { + // Create a new parameter + IDbDataParameter param = command.CreateParameter(); + + // Set the parameter properties + param.ParameterName = ParameterName; + + if (!m_inferType) + { + param.DbType = DbType; + } + if (Precision != 0) + { + param.Precision = Precision; + } + if (Scale != 0) + { + param.Scale = Scale; + } + if (Size != 0) + { + param.Size = Size; + } + + // Add the parameter to the collection of params + command.Parameters.Add(param); + } + + /// + /// Renders the logging event and set the parameter value in the command. + /// + /// The command containing the parameter. + /// The event to be rendered. + /// + /// + /// Renders the logging event using this parameters layout + /// object. Sets the value of the parameter on the command object. + /// + /// + public virtual void FormatValue(IDbCommand command, LoggingEvent loggingEvent) + { + // Lookup the parameter + IDbDataParameter param = (IDbDataParameter)command.Parameters[ParameterName]; + + // Format the value + object formattedValue = Layout.Format(loggingEvent); + + // If the value is null then convert to a DBNull + if (formattedValue == null) + { + formattedValue = DBNull.Value; + } + + param.Value = formattedValue; + } + + #endregion // Public Instance Methods + + #region Private Instance Fields + + /// + /// The name of this parameter. + /// + private string m_parameterName; + + /// + /// The database type for this parameter. + /// + private DbType m_dbType; + + /// + /// Flag to infer type rather than use the DbType + /// + private bool m_inferType = true; + + /// + /// The precision for this parameter. + /// + private byte m_precision; + + /// + /// The scale for this parameter. + /// + private byte m_scale; + + /// + /// The size for this parameter. + /// + private int m_size; + + /// + /// The to use to render the + /// logging event into an object for this parameter. + /// + private IRawLayout m_layout; + + #endregion // Private Instance Fields + } } #endif // !SSCLI \ No newline at end of file diff --git a/src/log4net/Appender/AnsiColorTerminalAppender.cs b/src/log4net/Appender/AnsiColorTerminalAppender.cs index 50a6875c..1331833a 100644 --- a/src/log4net/Appender/AnsiColorTerminalAppender.cs +++ b/src/log4net/Appender/AnsiColorTerminalAppender.cs @@ -27,548 +27,548 @@ namespace log4net.Appender { - /// - /// Appends logging events to the terminal using ANSI color escape sequences. - /// - /// - /// - /// AnsiColorTerminalAppender appends log events to the standard output stream - /// or the error output stream using a layout specified by the - /// user. It also allows the color of a specific level of message to be set. - /// - /// - /// This appender expects the terminal to understand the VT100 control set - /// in order to interpret the color codes. If the terminal or console does not - /// understand the control codes the behavior is not defined. - /// - /// - /// By default, all output is written to the console's standard output stream. - /// The property can be set to direct the output to the - /// error stream. - /// - /// - /// NOTE: This appender writes each message to the System.Console.Out or - /// System.Console.Error that is set at the time the event is appended. - /// Therefore it is possible to programmatically redirect the output of this appender - /// (for example NUnit does this to capture program output). While this is the desired - /// behavior of this appender it may have security implications in your application. - /// - /// - /// When configuring the ANSI colored terminal appender, a mapping should be - /// specified to map a logging level to a color. For example: - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// The Level is the standard log4net logging level and ForeColor and BackColor can be any - /// of the following values: - /// - /// Blue - /// Green - /// Red - /// White - /// Yellow - /// Purple - /// Cyan - /// - /// These color values cannot be combined together to make new colors. - /// - /// - /// The attributes can be any combination of the following: - /// - /// Brightforeground is brighter - /// Dimforeground is dimmer - /// Underscoremessage is underlined - /// Blinkforeground is blinking (does not work on all terminals) - /// Reverseforeground and background are reversed - /// Hiddenoutput is hidden - /// Strikethroughmessage has a line through it - /// - /// While any of these attributes may be combined together not all combinations - /// work well together, for example setting both Bright and Dim attributes makes - /// no sense. - /// - /// - /// Patrick Wagstrom - /// Nicko Cadell - public class AnsiColorTerminalAppender : AppenderSkeleton - { - #region Colors Enum - - /// - /// The enum of possible display attributes - /// - /// - /// - /// The following flags can be combined together to - /// form the ANSI color attributes. - /// - /// - /// - [Flags] - public enum AnsiAttributes : int - { - /// - /// text is bright - /// - Bright = 1, - /// - /// text is dim - /// - Dim = 2, - - /// - /// text is underlined - /// - Underscore = 4, - - /// - /// text is blinking - /// - /// - /// Not all terminals support this attribute - /// - Blink = 8, - - /// - /// text and background colors are reversed - /// - Reverse = 16, - - /// - /// text is hidden - /// - Hidden = 32, - - /// - /// text is displayed with a strikethrough - /// - Strikethrough = 64, - - /// - /// text color is light - /// - Light = 128 - } - - /// - /// The enum of possible foreground or background color values for - /// use with the color mapping method - /// - /// - /// - /// The output can be in one for the following ANSI colors. - /// - /// - /// - public enum AnsiColor : int - { - /// - /// color is black - /// - Black = 0, - - /// - /// color is red - /// - Red = 1, - - /// - /// color is green - /// - Green = 2, - - /// - /// color is yellow - /// - Yellow = 3, - - /// - /// color is blue - /// - Blue = 4, - - /// - /// color is magenta - /// - Magenta = 5, - - /// - /// color is cyan - /// - Cyan = 6, - - /// - /// color is white - /// - White = 7 - } - - #endregion - - #region Public Instance Constructors - - /// - /// Initializes a new instance of the class. - /// - /// - /// The instance of the class is set up to write - /// to the standard output stream. - /// - public AnsiColorTerminalAppender() - { - } - - #endregion Public Instance Constructors - - #region Public Instance Properties - - /// - /// Target is the value of the console output stream. - /// - /// - /// Target is the value of the console output stream. - /// This is either "Console.Out" or "Console.Error". - /// - /// - /// - /// Target is the value of the console output stream. - /// This is either "Console.Out" or "Console.Error". - /// - /// - public virtual string Target - { - get { return m_writeToErrorStream ? ConsoleError : ConsoleOut; } - set - { - string trimmedTargetName = value.Trim(); - - if (SystemInfo.EqualsIgnoringCase(ConsoleError, trimmedTargetName)) - { - m_writeToErrorStream = true; - } - else - { - m_writeToErrorStream = false; - } - } - } - - /// - /// Add a mapping of level to color - /// - /// The mapping to add - /// - /// - /// Add a mapping to this appender. - /// Each mapping defines the foreground and background colours - /// for a level. - /// - /// - public void AddMapping(LevelColors mapping) - { - m_levelMapping.Add(mapping); - } - - #endregion Public Instance Properties - - #region Override implementation of AppenderSkeleton - - /// - /// This method is called by the method. - /// - /// The event to log. - /// - /// - /// Writes the event to the console. - /// - /// - /// The format of the output will depend on the appender's layout. - /// - /// - protected override void Append(log4net.Core.LoggingEvent loggingEvent) - { - string loggingMessage = RenderLoggingEvent(loggingEvent); - - // see if there is a specified lookup. - LevelColors levelColors = m_levelMapping.Lookup(loggingEvent.Level) as LevelColors; - if (levelColors != null) - { - // Prepend the Ansi Color code - loggingMessage = levelColors.CombinedColor + loggingMessage; - } - - // on most terminals there are weird effects if we don't clear the background color - // before the new line. This checks to see if it ends with a newline, and if - // so, inserts the clear codes before the newline, otherwise the clear codes - // are inserted afterwards. - if (loggingMessage.Length > 1) - { - if (loggingMessage.EndsWith("\r\n") || loggingMessage.EndsWith("\n\r")) - { - loggingMessage = loggingMessage.Insert(loggingMessage.Length - 2, PostEventCodes); - } - else if (loggingMessage.EndsWith("\n") || loggingMessage.EndsWith("\r")) - { - loggingMessage = loggingMessage.Insert(loggingMessage.Length - 1, PostEventCodes); - } - else - { - loggingMessage = loggingMessage + PostEventCodes; - } - } - else - { - if (loggingMessage[0] == '\n' || loggingMessage[0] == '\r') - { - loggingMessage = PostEventCodes + loggingMessage; - } - else - { - loggingMessage = loggingMessage + PostEventCodes; - } - } + /// + /// Appends logging events to the terminal using ANSI color escape sequences. + /// + /// + /// + /// AnsiColorTerminalAppender appends log events to the standard output stream + /// or the error output stream using a layout specified by the + /// user. It also allows the color of a specific level of message to be set. + /// + /// + /// This appender expects the terminal to understand the VT100 control set + /// in order to interpret the color codes. If the terminal or console does not + /// understand the control codes the behavior is not defined. + /// + /// + /// By default, all output is written to the console's standard output stream. + /// The property can be set to direct the output to the + /// error stream. + /// + /// + /// NOTE: This appender writes each message to the System.Console.Out or + /// System.Console.Error that is set at the time the event is appended. + /// Therefore it is possible to programmatically redirect the output of this appender + /// (for example NUnit does this to capture program output). While this is the desired + /// behavior of this appender it may have security implications in your application. + /// + /// + /// When configuring the ANSI colored terminal appender, a mapping should be + /// specified to map a logging level to a color. For example: + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// The Level is the standard log4net logging level and ForeColor and BackColor can be any + /// of the following values: + /// + /// Blue + /// Green + /// Red + /// White + /// Yellow + /// Purple + /// Cyan + /// + /// These color values cannot be combined together to make new colors. + /// + /// + /// The attributes can be any combination of the following: + /// + /// Brightforeground is brighter + /// Dimforeground is dimmer + /// Underscoremessage is underlined + /// Blinkforeground is blinking (does not work on all terminals) + /// Reverseforeground and background are reversed + /// Hiddenoutput is hidden + /// Strikethroughmessage has a line through it + /// + /// While any of these attributes may be combined together not all combinations + /// work well together, for example setting both Bright and Dim attributes makes + /// no sense. + /// + /// + /// Patrick Wagstrom + /// Nicko Cadell + public class AnsiColorTerminalAppender : AppenderSkeleton + { + #region Colors Enum + + /// + /// The enum of possible display attributes + /// + /// + /// + /// The following flags can be combined together to + /// form the ANSI color attributes. + /// + /// + /// + [Flags] + public enum AnsiAttributes : int + { + /// + /// text is bright + /// + Bright = 1, + /// + /// text is dim + /// + Dim = 2, + + /// + /// text is underlined + /// + Underscore = 4, + + /// + /// text is blinking + /// + /// + /// Not all terminals support this attribute + /// + Blink = 8, + + /// + /// text and background colors are reversed + /// + Reverse = 16, + + /// + /// text is hidden + /// + Hidden = 32, + + /// + /// text is displayed with a strikethrough + /// + Strikethrough = 64, + + /// + /// text color is light + /// + Light = 128 + } + + /// + /// The enum of possible foreground or background color values for + /// use with the color mapping method + /// + /// + /// + /// The output can be in one for the following ANSI colors. + /// + /// + /// + public enum AnsiColor : int + { + /// + /// color is black + /// + Black = 0, + + /// + /// color is red + /// + Red = 1, + + /// + /// color is green + /// + Green = 2, + + /// + /// color is yellow + /// + Yellow = 3, + + /// + /// color is blue + /// + Blue = 4, + + /// + /// color is magenta + /// + Magenta = 5, + + /// + /// color is cyan + /// + Cyan = 6, + + /// + /// color is white + /// + White = 7 + } + + #endregion + + #region Public Instance Constructors + + /// + /// Initializes a new instance of the class. + /// + /// + /// The instance of the class is set up to write + /// to the standard output stream. + /// + public AnsiColorTerminalAppender() + { + } + + #endregion Public Instance Constructors + + #region Public Instance Properties + + /// + /// Target is the value of the console output stream. + /// + /// + /// Target is the value of the console output stream. + /// This is either "Console.Out" or "Console.Error". + /// + /// + /// + /// Target is the value of the console output stream. + /// This is either "Console.Out" or "Console.Error". + /// + /// + public virtual string Target + { + get { return m_writeToErrorStream ? ConsoleError : ConsoleOut; } + set + { + string trimmedTargetName = value.Trim(); + + if (SystemInfo.EqualsIgnoringCase(ConsoleError, trimmedTargetName)) + { + m_writeToErrorStream = true; + } + else + { + m_writeToErrorStream = false; + } + } + } + + /// + /// Add a mapping of level to color + /// + /// The mapping to add + /// + /// + /// Add a mapping to this appender. + /// Each mapping defines the foreground and background colours + /// for a level. + /// + /// + public void AddMapping(LevelColors mapping) + { + m_levelMapping.Add(mapping); + } + + #endregion Public Instance Properties + + #region Override implementation of AppenderSkeleton + + /// + /// This method is called by the method. + /// + /// The event to log. + /// + /// + /// Writes the event to the console. + /// + /// + /// The format of the output will depend on the appender's layout. + /// + /// + protected override void Append(log4net.Core.LoggingEvent loggingEvent) + { + string loggingMessage = RenderLoggingEvent(loggingEvent); + + // see if there is a specified lookup. + LevelColors levelColors = m_levelMapping.Lookup(loggingEvent.Level) as LevelColors; + if (levelColors != null) + { + // Prepend the Ansi Color code + loggingMessage = levelColors.CombinedColor + loggingMessage; + } + + // on most terminals there are weird effects if we don't clear the background color + // before the new line. This checks to see if it ends with a newline, and if + // so, inserts the clear codes before the newline, otherwise the clear codes + // are inserted afterwards. + if (loggingMessage.Length > 1) + { + if (loggingMessage.EndsWith("\r\n") || loggingMessage.EndsWith("\n\r")) + { + loggingMessage = loggingMessage.Insert(loggingMessage.Length - 2, PostEventCodes); + } + else if (loggingMessage.EndsWith("\n") || loggingMessage.EndsWith("\r")) + { + loggingMessage = loggingMessage.Insert(loggingMessage.Length - 1, PostEventCodes); + } + else + { + loggingMessage = loggingMessage + PostEventCodes; + } + } + else + { + if (loggingMessage[0] == '\n' || loggingMessage[0] == '\r') + { + loggingMessage = PostEventCodes + loggingMessage; + } + else + { + loggingMessage = loggingMessage + PostEventCodes; + } + } #if NETCF_1_0 - // Write to the output stream - Console.Write(loggingMessage); + // Write to the output stream + Console.Write(loggingMessage); #else - if (m_writeToErrorStream) - { - // Write to the error stream - Console.Error.Write(loggingMessage); - } - else - { - // Write to the output stream - Console.Write(loggingMessage); - } + if (m_writeToErrorStream) + { + // Write to the error stream + Console.Error.Write(loggingMessage); + } + else + { + // Write to the output stream + Console.Write(loggingMessage); + } #endif - - } - - /// - /// This appender requires a to be set. - /// - /// true - /// - /// - /// This appender requires a to be set. - /// - /// - protected override bool RequiresLayout - { - get { return true; } - } - - /// - /// Initialize the options for this appender - /// - /// - /// - /// Initialize the level to color mappings set on this appender. - /// - /// - public override void ActivateOptions() - { - base.ActivateOptions(); - m_levelMapping.ActivateOptions(); - } - - #endregion Override implementation of AppenderSkeleton - - #region Public Static Fields - - /// - /// The to use when writing to the Console - /// standard output stream. - /// - /// - /// - /// The to use when writing to the Console - /// standard output stream. - /// - /// - public const string ConsoleOut = "Console.Out"; - - /// - /// The to use when writing to the Console - /// standard error output stream. - /// - /// - /// - /// The to use when writing to the Console - /// standard error output stream. - /// - /// - public const string ConsoleError = "Console.Error"; - - #endregion Public Static Fields - - #region Private Instances Fields - - /// - /// Flag to write output to the error stream rather than the standard output stream - /// - private bool m_writeToErrorStream = false; - - /// - /// Mapping from level object to color value - /// - private LevelMapping m_levelMapping = new LevelMapping(); - - /// - /// Ansi code to reset terminal - /// - private const string PostEventCodes = "\x1b[0m"; - - #endregion Private Instances Fields - - #region LevelColors LevelMapping Entry - - /// - /// A class to act as a mapping between the level that a logging call is made at and - /// the color it should be displayed as. - /// - /// - /// - /// Defines the mapping between a level and the color it should be displayed in. - /// - /// - public class LevelColors : LevelMappingEntry - { - private AnsiColor m_foreColor; - private AnsiColor m_backColor; - private AnsiAttributes m_attributes; - private string m_combinedColor = ""; - - /// - /// The mapped foreground color for the specified level - /// - /// - /// - /// Required property. - /// The mapped foreground color for the specified level - /// - /// - public AnsiColor ForeColor - { - get { return m_foreColor; } - set { m_foreColor = value; } - } - - /// - /// The mapped background color for the specified level - /// - /// - /// - /// Required property. - /// The mapped background color for the specified level - /// - /// - public AnsiColor BackColor - { - get { return m_backColor; } - set { m_backColor = value; } - } - - /// - /// The color attributes for the specified level - /// - /// - /// - /// Required property. - /// The color attributes for the specified level - /// - /// - public AnsiAttributes Attributes - { - get { return m_attributes; } - set { m_attributes = value; } - } - - /// - /// Initialize the options for the object - /// - /// - /// - /// Combine the and together - /// and append the attributes. - /// - /// - public override void ActivateOptions() - { - base.ActivateOptions(); - - StringBuilder buf = new StringBuilder(); - - // Reset any existing codes - buf.Append("\x1b[0;"); - - int lightAdjustment = ((m_attributes & AnsiAttributes.Light) > 0) ? 60 : 0; - - // set the foreground color - buf.Append(30 + lightAdjustment + (int)m_foreColor); - buf.Append(';'); - - // set the background color - buf.Append(40 + lightAdjustment + (int)m_backColor); - - // set the attributes - if ((m_attributes & AnsiAttributes.Bright) > 0) - { - buf.Append(";1"); - } - if ((m_attributes & AnsiAttributes.Dim) > 0) - { - buf.Append(";2"); - } - if ((m_attributes & AnsiAttributes.Underscore) > 0) - { - buf.Append(";4"); - } - if ((m_attributes & AnsiAttributes.Blink) > 0) - { - buf.Append(";5"); - } - if ((m_attributes & AnsiAttributes.Reverse) > 0) - { - buf.Append(";7"); - } - if ((m_attributes & AnsiAttributes.Hidden) > 0) - { - buf.Append(";8"); - } - if ((m_attributes & AnsiAttributes.Strikethrough) > 0) - { - buf.Append(";9"); - } - - buf.Append('m'); - - m_combinedColor = buf.ToString(); - } - - /// - /// The combined , and - /// suitable for setting the ansi terminal color. - /// - internal string CombinedColor - { - get { return m_combinedColor; } - } - } - - #endregion // LevelColors LevelMapping Entry - } + + } + + /// + /// This appender requires a to be set. + /// + /// true + /// + /// + /// This appender requires a to be set. + /// + /// + protected override bool RequiresLayout + { + get { return true; } + } + + /// + /// Initialize the options for this appender + /// + /// + /// + /// Initialize the level to color mappings set on this appender. + /// + /// + public override void ActivateOptions() + { + base.ActivateOptions(); + m_levelMapping.ActivateOptions(); + } + + #endregion Override implementation of AppenderSkeleton + + #region Public Static Fields + + /// + /// The to use when writing to the Console + /// standard output stream. + /// + /// + /// + /// The to use when writing to the Console + /// standard output stream. + /// + /// + public const string ConsoleOut = "Console.Out"; + + /// + /// The to use when writing to the Console + /// standard error output stream. + /// + /// + /// + /// The to use when writing to the Console + /// standard error output stream. + /// + /// + public const string ConsoleError = "Console.Error"; + + #endregion Public Static Fields + + #region Private Instances Fields + + /// + /// Flag to write output to the error stream rather than the standard output stream + /// + private bool m_writeToErrorStream = false; + + /// + /// Mapping from level object to color value + /// + private LevelMapping m_levelMapping = new LevelMapping(); + + /// + /// Ansi code to reset terminal + /// + private const string PostEventCodes = "\x1b[0m"; + + #endregion Private Instances Fields + + #region LevelColors LevelMapping Entry + + /// + /// A class to act as a mapping between the level that a logging call is made at and + /// the color it should be displayed as. + /// + /// + /// + /// Defines the mapping between a level and the color it should be displayed in. + /// + /// + public class LevelColors : LevelMappingEntry + { + private AnsiColor m_foreColor; + private AnsiColor m_backColor; + private AnsiAttributes m_attributes; + private string m_combinedColor = ""; + + /// + /// The mapped foreground color for the specified level + /// + /// + /// + /// Required property. + /// The mapped foreground color for the specified level + /// + /// + public AnsiColor ForeColor + { + get { return m_foreColor; } + set { m_foreColor = value; } + } + + /// + /// The mapped background color for the specified level + /// + /// + /// + /// Required property. + /// The mapped background color for the specified level + /// + /// + public AnsiColor BackColor + { + get { return m_backColor; } + set { m_backColor = value; } + } + + /// + /// The color attributes for the specified level + /// + /// + /// + /// Required property. + /// The color attributes for the specified level + /// + /// + public AnsiAttributes Attributes + { + get { return m_attributes; } + set { m_attributes = value; } + } + + /// + /// Initialize the options for the object + /// + /// + /// + /// Combine the and together + /// and append the attributes. + /// + /// + public override void ActivateOptions() + { + base.ActivateOptions(); + + StringBuilder buf = new StringBuilder(); + + // Reset any existing codes + buf.Append("\x1b[0;"); + + int lightAdjustment = ((m_attributes & AnsiAttributes.Light) > 0) ? 60 : 0; + + // set the foreground color + buf.Append(30 + lightAdjustment + (int)m_foreColor); + buf.Append(';'); + + // set the background color + buf.Append(40 + lightAdjustment + (int)m_backColor); + + // set the attributes + if ((m_attributes & AnsiAttributes.Bright) > 0) + { + buf.Append(";1"); + } + if ((m_attributes & AnsiAttributes.Dim) > 0) + { + buf.Append(";2"); + } + if ((m_attributes & AnsiAttributes.Underscore) > 0) + { + buf.Append(";4"); + } + if ((m_attributes & AnsiAttributes.Blink) > 0) + { + buf.Append(";5"); + } + if ((m_attributes & AnsiAttributes.Reverse) > 0) + { + buf.Append(";7"); + } + if ((m_attributes & AnsiAttributes.Hidden) > 0) + { + buf.Append(";8"); + } + if ((m_attributes & AnsiAttributes.Strikethrough) > 0) + { + buf.Append(";9"); + } + + buf.Append('m'); + + m_combinedColor = buf.ToString(); + } + + /// + /// The combined , and + /// suitable for setting the ansi terminal color. + /// + internal string CombinedColor + { + get { return m_combinedColor; } + } + } + + #endregion // LevelColors LevelMapping Entry + } } diff --git a/src/log4net/Appender/AppenderCollection.cs b/src/log4net/Appender/AppenderCollection.cs index 14f2304b..97286610 100644 --- a/src/log4net/Appender/AppenderCollection.cs +++ b/src/log4net/Appender/AppenderCollection.cs @@ -22,884 +22,884 @@ namespace log4net.Appender { - /// - /// A strongly-typed collection of objects. - /// - /// Nicko Cadell - public class AppenderCollection : ICollection, IList, IEnumerable + /// + /// A strongly-typed collection of objects. + /// + /// Nicko Cadell + public class AppenderCollection : ICollection, IList, IEnumerable #if !NETSTANDARD1_3 - , ICloneable + , ICloneable #endif - { - #region Interfaces - /// - /// Supports type-safe iteration over a . - /// - /// - public interface IAppenderCollectionEnumerator - { - /// - /// Gets the current element in the collection. - /// - IAppender Current { get; } - - /// - /// Advances the enumerator to the next element in the collection. - /// - /// - /// true if the enumerator was successfully advanced to the next element; - /// false if the enumerator has passed the end of the collection. - /// - /// - /// The collection was modified after the enumerator was created. - /// - bool MoveNext(); - - /// - /// Sets the enumerator to its initial position, before the first element in the collection. - /// - void Reset(); - } - #endregion - - private const int DEFAULT_CAPACITY = 16; - - #region Implementation (data) - - private IAppender[] m_array; - private int m_count = 0; - private int m_version = 0; - - #endregion - - #region Static Wrappers - - /// - /// Creates a read-only wrapper for a AppenderCollection instance. - /// - /// list to create a readonly wrapper arround - /// - /// An AppenderCollection wrapper that is read-only. - /// - public static AppenderCollection ReadOnly(AppenderCollection list) - { - if(list==null) throw new ArgumentNullException("list"); - - return new ReadOnlyAppenderCollection(list); - } - - #endregion - - #region Static Fields - - /// - /// An empty readonly static AppenderCollection - /// - public static readonly AppenderCollection EmptyCollection = ReadOnly(new AppenderCollection(0)); - - #endregion - - #region Constructors - - /// - /// Initializes a new instance of the AppenderCollection class - /// that is empty and has the default initial capacity. - /// - public AppenderCollection() - { - m_array = new IAppender[DEFAULT_CAPACITY]; - } - - /// - /// Initializes a new instance of the AppenderCollection class - /// that has the specified initial capacity. - /// - /// - /// The number of elements that the new AppenderCollection is initially capable of storing. - /// - public AppenderCollection(int capacity) - { - m_array = new IAppender[capacity]; - } - - /// - /// Initializes a new instance of the AppenderCollection class - /// that contains elements copied from the specified AppenderCollection. - /// - /// The AppenderCollection whose elements are copied to the new collection. - public AppenderCollection(AppenderCollection c) - { - m_array = new IAppender[c.Count]; - AddRange(c); - } - - /// - /// Initializes a new instance of the AppenderCollection class - /// that contains elements copied from the specified array. - /// - /// The array whose elements are copied to the new list. - public AppenderCollection(IAppender[] a) - { - m_array = new IAppender[a.Length]; - AddRange(a); - } - - /// - /// Initializes a new instance of the AppenderCollection class - /// that contains elements copied from the specified collection. - /// - /// The collection whose elements are copied to the new list. - public AppenderCollection(ICollection col) - { - m_array = new IAppender[col.Count]; - AddRange(col); - } - - /// - /// Type visible only to our subclasses - /// Used to access protected constructor - /// - /// - protected internal enum Tag - { - /// - /// A value - /// - Default - } - - /// - /// Allow subclasses to avoid our default constructors - /// - /// - /// - protected internal AppenderCollection(Tag tag) - { - m_array = null; - } - - #endregion - - #region Operations (type-safe ICollection) - - /// - /// Gets the number of elements actually contained in the AppenderCollection. - /// - public virtual int Count - { - get { return m_count; } - } - - /// - /// Copies the entire AppenderCollection to a one-dimensional - /// array. - /// - /// The one-dimensional array to copy to. - public virtual void CopyTo(IAppender[] array) - { - this.CopyTo(array, 0); - } - - /// - /// Copies the entire AppenderCollection to a one-dimensional - /// array, starting at the specified index of the target array. - /// - /// The one-dimensional array to copy to. - /// The zero-based index in at which copying begins. - public virtual void CopyTo(IAppender[] array, int start) - { - if (m_count > array.GetUpperBound(0) + 1 - start) - { - throw new System.ArgumentException("Destination array was not long enough."); - } - - Array.Copy(m_array, 0, array, start, m_count); - } - - /// - /// Gets a value indicating whether access to the collection is synchronized (thread-safe). - /// - /// false, because the backing type is an array, which is never thread-safe. - public virtual bool IsSynchronized - { - get { return false; } - } - - /// - /// Gets an object that can be used to synchronize access to the collection. - /// - public virtual object SyncRoot - { - get { return m_array; } - } - - #endregion - - #region Operations (type-safe IList) - - /// - /// Gets or sets the at the specified index. - /// - /// The zero-based index of the element to get or set. - /// - /// is less than zero - /// -or- - /// is equal to or greater than . - /// - public virtual IAppender this[int index] - { - get - { - ValidateIndex(index); // throws - return m_array[index]; - } - set - { - ValidateIndex(index); // throws - ++m_version; - m_array[index] = value; - } - } - - /// - /// Adds a to the end of the AppenderCollection. - /// - /// The to be added to the end of the AppenderCollection. - /// The index at which the value has been added. - public virtual int Add(IAppender item) - { - if (m_count == m_array.Length) - { - EnsureCapacity(m_count + 1); - } - - m_array[m_count] = item; - m_version++; - - return m_count++; - } - - /// - /// Removes all elements from the AppenderCollection. - /// - public virtual void Clear() - { - ++m_version; - m_array = new IAppender[DEFAULT_CAPACITY]; - m_count = 0; - } - - /// - /// Creates a shallow copy of the . - /// - /// A new with a shallow copy of the collection data. - public virtual object Clone() - { - AppenderCollection newCol = new AppenderCollection(m_count); - Array.Copy(m_array, 0, newCol.m_array, 0, m_count); - newCol.m_count = m_count; - newCol.m_version = m_version; - - return newCol; - } - - /// - /// Determines whether a given is in the AppenderCollection. - /// - /// The to check for. - /// true if is found in the AppenderCollection; otherwise, false. - public virtual bool Contains(IAppender item) - { - for (int i=0; i != m_count; ++i) - { - if (m_array[i].Equals(item)) - { - return true; - } - } - return false; - } - - /// - /// Returns the zero-based index of the first occurrence of a - /// in the AppenderCollection. - /// - /// The to locate in the AppenderCollection. - /// - /// The zero-based index of the first occurrence of - /// in the entire AppenderCollection, if found; otherwise, -1. - /// - public virtual int IndexOf(IAppender item) - { - for (int i=0; i != m_count; ++i) - { - if (m_array[i].Equals(item)) - { - return i; - } - } - return -1; - } - - /// - /// Inserts an element into the AppenderCollection at the specified index. - /// - /// The zero-based index at which should be inserted. - /// The to insert. - /// - /// is less than zero - /// -or- - /// is equal to or greater than . - /// - public virtual void Insert(int index, IAppender item) - { - ValidateIndex(index, true); // throws - - if (m_count == m_array.Length) - { - EnsureCapacity(m_count + 1); - } - - if (index < m_count) - { - Array.Copy(m_array, index, m_array, index + 1, m_count - index); - } - - m_array[index] = item; - m_count++; - m_version++; - } - - /// - /// Removes the first occurrence of a specific from the AppenderCollection. - /// - /// The to remove from the AppenderCollection. - /// - /// The specified was not found in the AppenderCollection. - /// - public virtual void Remove(IAppender item) - { - int i = IndexOf(item); - if (i < 0) - { - throw new System.ArgumentException("Cannot remove the specified item because it was not found in the specified Collection."); - } - - ++m_version; - RemoveAt(i); - } - - /// - /// Removes the element at the specified index of the AppenderCollection. - /// - /// The zero-based index of the element to remove. - /// - /// is less than zero - /// -or- - /// is equal to or greater than . - /// - public virtual void RemoveAt(int index) - { - ValidateIndex(index); // throws - - m_count--; - - if (index < m_count) - { - Array.Copy(m_array, index + 1, m_array, index, m_count - index); - } - - // We can't set the deleted entry equal to null, because it might be a value type. - // Instead, we'll create an empty single-element array of the right type and copy it - // over the entry we want to erase. - IAppender[] temp = new IAppender[1]; - Array.Copy(temp, 0, m_array, m_count, 1); - m_version++; - } - - /// - /// Gets a value indicating whether the collection has a fixed size. - /// - /// true if the collection has a fixed size; otherwise, false. The default is false - public virtual bool IsFixedSize - { - get { return false; } - } - - /// - /// Gets a value indicating whether the IList is read-only. - /// - /// true if the collection is read-only; otherwise, false. The default is false - public virtual bool IsReadOnly - { - get { return false; } - } - - #endregion - - #region Operations (type-safe IEnumerable) - - /// - /// Returns an enumerator that can iterate through the AppenderCollection. - /// - /// An for the entire AppenderCollection. - public virtual IAppenderCollectionEnumerator GetEnumerator() - { - return new Enumerator(this); - } - - #endregion - - #region Public helpers (just to mimic some nice features of ArrayList) - - /// - /// Gets or sets the number of elements the AppenderCollection can contain. - /// - public virtual int Capacity - { - get - { - return m_array.Length; - } - set - { - if (value < m_count) - { - value = m_count; - } - - if (value != m_array.Length) - { - if (value > 0) - { - IAppender[] temp = new IAppender[value]; - Array.Copy(m_array, 0, temp, 0, m_count); - m_array = temp; - } - else - { - m_array = new IAppender[DEFAULT_CAPACITY]; - } - } - } - } - - /// - /// Adds the elements of another AppenderCollection to the current AppenderCollection. - /// - /// The AppenderCollection whose elements should be added to the end of the current AppenderCollection. - /// The new of the AppenderCollection. - public virtual int AddRange(AppenderCollection x) - { - if (m_count + x.Count >= m_array.Length) - { - EnsureCapacity(m_count + x.Count); - } - - Array.Copy(x.m_array, 0, m_array, m_count, x.Count); - m_count += x.Count; - m_version++; - - return m_count; - } - - /// - /// Adds the elements of a array to the current AppenderCollection. - /// - /// The array whose elements should be added to the end of the AppenderCollection. - /// The new of the AppenderCollection. - public virtual int AddRange(IAppender[] x) - { - if (m_count + x.Length >= m_array.Length) - { - EnsureCapacity(m_count + x.Length); - } - - Array.Copy(x, 0, m_array, m_count, x.Length); - m_count += x.Length; - m_version++; - - return m_count; - } - - /// - /// Adds the elements of a collection to the current AppenderCollection. - /// - /// The collection whose elements should be added to the end of the AppenderCollection. - /// The new of the AppenderCollection. - public virtual int AddRange(ICollection col) - { - if (m_count + col.Count >= m_array.Length) - { - EnsureCapacity(m_count + col.Count); - } - - foreach(object item in col) - { - Add((IAppender)item); - } - - return m_count; - } - - /// - /// Sets the capacity to the actual number of elements. - /// - public virtual void TrimToSize() - { - this.Capacity = m_count; - } - - /// - /// Return the collection elements as an array - /// - /// the array - public virtual IAppender[] ToArray() - { - IAppender[] resultArray = new IAppender[m_count]; - if (m_count > 0) - { - Array.Copy(m_array, 0, resultArray, 0, m_count); - } - return resultArray; - } - - #endregion - - #region Implementation (helpers) - - /// - /// is less than zero - /// -or- - /// is equal to or greater than . - /// - private void ValidateIndex(int i) - { - ValidateIndex(i, false); - } - - /// - /// is less than zero - /// -or- - /// is equal to or greater than . - /// - private void ValidateIndex(int i, bool allowEqualEnd) - { - int max = (allowEqualEnd) ? (m_count) : (m_count-1); - if (i < 0 || i > max) - { - throw log4net.Util.SystemInfo.CreateArgumentOutOfRangeException("i", (object)i, "Index was out of range. Must be non-negative and less than the size of the collection. [" + (object)i + "] Specified argument was out of the range of valid values."); - } - } - - private void EnsureCapacity(int min) - { - int newCapacity = ((m_array.Length == 0) ? DEFAULT_CAPACITY : m_array.Length * 2); - if (newCapacity < min) - { - newCapacity = min; - } - - this.Capacity = newCapacity; - } - - #endregion - - #region Implementation (ICollection) - - void ICollection.CopyTo(Array array, int start) - { - if (m_count > 0) - { - Array.Copy(m_array, 0, array, start, m_count); - } - } - - #endregion - - #region Implementation (IList) - - object IList.this[int i] - { - get { return (object)this[i]; } - set { this[i] = (IAppender)value; } - } - - int IList.Add(object x) - { - return this.Add((IAppender)x); - } - - bool IList.Contains(object x) - { - return this.Contains((IAppender)x); - } - - int IList.IndexOf(object x) - { - return this.IndexOf((IAppender)x); - } - - void IList.Insert(int pos, object x) - { - this.Insert(pos, (IAppender)x); - } - - void IList.Remove(object x) - { - this.Remove((IAppender)x); - } - - void IList.RemoveAt(int pos) - { - this.RemoveAt(pos); - } - - #endregion - - #region Implementation (IEnumerable) - - IEnumerator IEnumerable.GetEnumerator() - { - return (IEnumerator)(this.GetEnumerator()); - } - - #endregion - - #region Nested enumerator class - - /// - /// Supports simple iteration over a . - /// - /// - private sealed class Enumerator : IEnumerator, IAppenderCollectionEnumerator - { - #region Implementation (data) - - private readonly AppenderCollection m_collection; - private int m_index; - private int m_version; - - #endregion - - #region Construction - - /// - /// Initializes a new instance of the Enumerator class. - /// - /// - internal Enumerator(AppenderCollection tc) - { - m_collection = tc; - m_index = -1; - m_version = tc.m_version; - } - - #endregion - - #region Operations (type-safe IEnumerator) - - /// - /// Gets the current element in the collection. - /// - public IAppender Current - { - get { return m_collection[m_index]; } - } - - /// - /// Advances the enumerator to the next element in the collection. - /// - /// - /// true if the enumerator was successfully advanced to the next element; - /// false if the enumerator has passed the end of the collection. - /// - /// - /// The collection was modified after the enumerator was created. - /// - public bool MoveNext() - { - if (m_version != m_collection.m_version) - { - throw new System.InvalidOperationException("Collection was modified; enumeration operation may not execute."); - } - - ++m_index; - return (m_index < m_collection.Count); - } - - /// - /// Sets the enumerator to its initial position, before the first element in the collection. - /// - public void Reset() - { - m_index = -1; - } - #endregion - - #region Implementation (IEnumerator) - - object IEnumerator.Current - { - get { return this.Current; } - } - - #endregion - } - - #endregion - - #region Nested Read Only Wrapper class - - /// - private sealed class ReadOnlyAppenderCollection : AppenderCollection, ICollection - { - #region Implementation (data) - - private readonly AppenderCollection m_collection; - - #endregion - - #region Construction - - internal ReadOnlyAppenderCollection(AppenderCollection list) : base(Tag.Default) - { - m_collection = list; - } - - #endregion - - #region Type-safe ICollection - - public override void CopyTo(IAppender[] array) - { - m_collection.CopyTo(array); - } - - public override void CopyTo(IAppender[] array, int start) - { - m_collection.CopyTo(array,start); - } - - void ICollection.CopyTo(Array array, int start) - { - ((ICollection)m_collection).CopyTo(array, start); - } - - public override int Count - { - get { return m_collection.Count; } - } - - public override bool IsSynchronized - { - get { return m_collection.IsSynchronized; } - } - - public override object SyncRoot - { - get { return this.m_collection.SyncRoot; } - } - - #endregion - - #region Type-safe IList - - public override IAppender this[int i] - { - get { return m_collection[i]; } - set { throw new NotSupportedException("This is a Read Only Collection and can not be modified"); } - } - - public override int Add(IAppender x) - { - throw new NotSupportedException("This is a Read Only Collection and can not be modified"); - } - - public override void Clear() - { - throw new NotSupportedException("This is a Read Only Collection and can not be modified"); - } - - public override bool Contains(IAppender x) - { - return m_collection.Contains(x); - } - - public override int IndexOf(IAppender x) - { - return m_collection.IndexOf(x); - } - - public override void Insert(int pos, IAppender x) - { - throw new NotSupportedException("This is a Read Only Collection and can not be modified"); - } - - public override void Remove(IAppender x) - { - throw new NotSupportedException("This is a Read Only Collection and can not be modified"); - } - - public override void RemoveAt(int pos) - { - throw new NotSupportedException("This is a Read Only Collection and can not be modified"); - } + { + #region Interfaces + /// + /// Supports type-safe iteration over a . + /// + /// + public interface IAppenderCollectionEnumerator + { + /// + /// Gets the current element in the collection. + /// + IAppender Current { get; } + + /// + /// Advances the enumerator to the next element in the collection. + /// + /// + /// true if the enumerator was successfully advanced to the next element; + /// false if the enumerator has passed the end of the collection. + /// + /// + /// The collection was modified after the enumerator was created. + /// + bool MoveNext(); + + /// + /// Sets the enumerator to its initial position, before the first element in the collection. + /// + void Reset(); + } + #endregion + + private const int DEFAULT_CAPACITY = 16; + + #region Implementation (data) + + private IAppender[] m_array; + private int m_count = 0; + private int m_version = 0; + + #endregion + + #region Static Wrappers + + /// + /// Creates a read-only wrapper for a AppenderCollection instance. + /// + /// list to create a readonly wrapper arround + /// + /// An AppenderCollection wrapper that is read-only. + /// + public static AppenderCollection ReadOnly(AppenderCollection list) + { + if(list==null) throw new ArgumentNullException("list"); + + return new ReadOnlyAppenderCollection(list); + } + + #endregion + + #region Static Fields + + /// + /// An empty readonly static AppenderCollection + /// + public static readonly AppenderCollection EmptyCollection = ReadOnly(new AppenderCollection(0)); + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the AppenderCollection class + /// that is empty and has the default initial capacity. + /// + public AppenderCollection() + { + m_array = new IAppender[DEFAULT_CAPACITY]; + } + + /// + /// Initializes a new instance of the AppenderCollection class + /// that has the specified initial capacity. + /// + /// + /// The number of elements that the new AppenderCollection is initially capable of storing. + /// + public AppenderCollection(int capacity) + { + m_array = new IAppender[capacity]; + } + + /// + /// Initializes a new instance of the AppenderCollection class + /// that contains elements copied from the specified AppenderCollection. + /// + /// The AppenderCollection whose elements are copied to the new collection. + public AppenderCollection(AppenderCollection c) + { + m_array = new IAppender[c.Count]; + AddRange(c); + } + + /// + /// Initializes a new instance of the AppenderCollection class + /// that contains elements copied from the specified array. + /// + /// The array whose elements are copied to the new list. + public AppenderCollection(IAppender[] a) + { + m_array = new IAppender[a.Length]; + AddRange(a); + } + + /// + /// Initializes a new instance of the AppenderCollection class + /// that contains elements copied from the specified collection. + /// + /// The collection whose elements are copied to the new list. + public AppenderCollection(ICollection col) + { + m_array = new IAppender[col.Count]; + AddRange(col); + } + + /// + /// Type visible only to our subclasses + /// Used to access protected constructor + /// + /// + protected internal enum Tag + { + /// + /// A value + /// + Default + } + + /// + /// Allow subclasses to avoid our default constructors + /// + /// + /// + protected internal AppenderCollection(Tag tag) + { + m_array = null; + } + + #endregion + + #region Operations (type-safe ICollection) + + /// + /// Gets the number of elements actually contained in the AppenderCollection. + /// + public virtual int Count + { + get { return m_count; } + } + + /// + /// Copies the entire AppenderCollection to a one-dimensional + /// array. + /// + /// The one-dimensional array to copy to. + public virtual void CopyTo(IAppender[] array) + { + this.CopyTo(array, 0); + } + + /// + /// Copies the entire AppenderCollection to a one-dimensional + /// array, starting at the specified index of the target array. + /// + /// The one-dimensional array to copy to. + /// The zero-based index in at which copying begins. + public virtual void CopyTo(IAppender[] array, int start) + { + if (m_count > array.GetUpperBound(0) + 1 - start) + { + throw new System.ArgumentException("Destination array was not long enough."); + } + + Array.Copy(m_array, 0, array, start, m_count); + } + + /// + /// Gets a value indicating whether access to the collection is synchronized (thread-safe). + /// + /// false, because the backing type is an array, which is never thread-safe. + public virtual bool IsSynchronized + { + get { return false; } + } + + /// + /// Gets an object that can be used to synchronize access to the collection. + /// + public virtual object SyncRoot + { + get { return m_array; } + } + + #endregion + + #region Operations (type-safe IList) + + /// + /// Gets or sets the at the specified index. + /// + /// The zero-based index of the element to get or set. + /// + /// is less than zero + /// -or- + /// is equal to or greater than . + /// + public virtual IAppender this[int index] + { + get + { + ValidateIndex(index); // throws + return m_array[index]; + } + set + { + ValidateIndex(index); // throws + ++m_version; + m_array[index] = value; + } + } + + /// + /// Adds a to the end of the AppenderCollection. + /// + /// The to be added to the end of the AppenderCollection. + /// The index at which the value has been added. + public virtual int Add(IAppender item) + { + if (m_count == m_array.Length) + { + EnsureCapacity(m_count + 1); + } + + m_array[m_count] = item; + m_version++; + + return m_count++; + } + + /// + /// Removes all elements from the AppenderCollection. + /// + public virtual void Clear() + { + ++m_version; + m_array = new IAppender[DEFAULT_CAPACITY]; + m_count = 0; + } + + /// + /// Creates a shallow copy of the . + /// + /// A new with a shallow copy of the collection data. + public virtual object Clone() + { + AppenderCollection newCol = new AppenderCollection(m_count); + Array.Copy(m_array, 0, newCol.m_array, 0, m_count); + newCol.m_count = m_count; + newCol.m_version = m_version; + + return newCol; + } + + /// + /// Determines whether a given is in the AppenderCollection. + /// + /// The to check for. + /// true if is found in the AppenderCollection; otherwise, false. + public virtual bool Contains(IAppender item) + { + for (int i=0; i != m_count; ++i) + { + if (m_array[i].Equals(item)) + { + return true; + } + } + return false; + } + + /// + /// Returns the zero-based index of the first occurrence of a + /// in the AppenderCollection. + /// + /// The to locate in the AppenderCollection. + /// + /// The zero-based index of the first occurrence of + /// in the entire AppenderCollection, if found; otherwise, -1. + /// + public virtual int IndexOf(IAppender item) + { + for (int i=0; i != m_count; ++i) + { + if (m_array[i].Equals(item)) + { + return i; + } + } + return -1; + } + + /// + /// Inserts an element into the AppenderCollection at the specified index. + /// + /// The zero-based index at which should be inserted. + /// The to insert. + /// + /// is less than zero + /// -or- + /// is equal to or greater than . + /// + public virtual void Insert(int index, IAppender item) + { + ValidateIndex(index, true); // throws + + if (m_count == m_array.Length) + { + EnsureCapacity(m_count + 1); + } + + if (index < m_count) + { + Array.Copy(m_array, index, m_array, index + 1, m_count - index); + } + + m_array[index] = item; + m_count++; + m_version++; + } + + /// + /// Removes the first occurrence of a specific from the AppenderCollection. + /// + /// The to remove from the AppenderCollection. + /// + /// The specified was not found in the AppenderCollection. + /// + public virtual void Remove(IAppender item) + { + int i = IndexOf(item); + if (i < 0) + { + throw new System.ArgumentException("Cannot remove the specified item because it was not found in the specified Collection."); + } + + ++m_version; + RemoveAt(i); + } + + /// + /// Removes the element at the specified index of the AppenderCollection. + /// + /// The zero-based index of the element to remove. + /// + /// is less than zero + /// -or- + /// is equal to or greater than . + /// + public virtual void RemoveAt(int index) + { + ValidateIndex(index); // throws + + m_count--; + + if (index < m_count) + { + Array.Copy(m_array, index + 1, m_array, index, m_count - index); + } + + // We can't set the deleted entry equal to null, because it might be a value type. + // Instead, we'll create an empty single-element array of the right type and copy it + // over the entry we want to erase. + IAppender[] temp = new IAppender[1]; + Array.Copy(temp, 0, m_array, m_count, 1); + m_version++; + } + + /// + /// Gets a value indicating whether the collection has a fixed size. + /// + /// true if the collection has a fixed size; otherwise, false. The default is false + public virtual bool IsFixedSize + { + get { return false; } + } + + /// + /// Gets a value indicating whether the IList is read-only. + /// + /// true if the collection is read-only; otherwise, false. The default is false + public virtual bool IsReadOnly + { + get { return false; } + } + + #endregion + + #region Operations (type-safe IEnumerable) + + /// + /// Returns an enumerator that can iterate through the AppenderCollection. + /// + /// An for the entire AppenderCollection. + public virtual IAppenderCollectionEnumerator GetEnumerator() + { + return new Enumerator(this); + } + + #endregion + + #region Public helpers (just to mimic some nice features of ArrayList) + + /// + /// Gets or sets the number of elements the AppenderCollection can contain. + /// + public virtual int Capacity + { + get + { + return m_array.Length; + } + set + { + if (value < m_count) + { + value = m_count; + } + + if (value != m_array.Length) + { + if (value > 0) + { + IAppender[] temp = new IAppender[value]; + Array.Copy(m_array, 0, temp, 0, m_count); + m_array = temp; + } + else + { + m_array = new IAppender[DEFAULT_CAPACITY]; + } + } + } + } + + /// + /// Adds the elements of another AppenderCollection to the current AppenderCollection. + /// + /// The AppenderCollection whose elements should be added to the end of the current AppenderCollection. + /// The new of the AppenderCollection. + public virtual int AddRange(AppenderCollection x) + { + if (m_count + x.Count >= m_array.Length) + { + EnsureCapacity(m_count + x.Count); + } + + Array.Copy(x.m_array, 0, m_array, m_count, x.Count); + m_count += x.Count; + m_version++; + + return m_count; + } + + /// + /// Adds the elements of a array to the current AppenderCollection. + /// + /// The array whose elements should be added to the end of the AppenderCollection. + /// The new of the AppenderCollection. + public virtual int AddRange(IAppender[] x) + { + if (m_count + x.Length >= m_array.Length) + { + EnsureCapacity(m_count + x.Length); + } + + Array.Copy(x, 0, m_array, m_count, x.Length); + m_count += x.Length; + m_version++; + + return m_count; + } + + /// + /// Adds the elements of a collection to the current AppenderCollection. + /// + /// The collection whose elements should be added to the end of the AppenderCollection. + /// The new of the AppenderCollection. + public virtual int AddRange(ICollection col) + { + if (m_count + col.Count >= m_array.Length) + { + EnsureCapacity(m_count + col.Count); + } + + foreach(object item in col) + { + Add((IAppender)item); + } + + return m_count; + } + + /// + /// Sets the capacity to the actual number of elements. + /// + public virtual void TrimToSize() + { + this.Capacity = m_count; + } + + /// + /// Return the collection elements as an array + /// + /// the array + public virtual IAppender[] ToArray() + { + IAppender[] resultArray = new IAppender[m_count]; + if (m_count > 0) + { + Array.Copy(m_array, 0, resultArray, 0, m_count); + } + return resultArray; + } + + #endregion + + #region Implementation (helpers) + + /// + /// is less than zero + /// -or- + /// is equal to or greater than . + /// + private void ValidateIndex(int i) + { + ValidateIndex(i, false); + } + + /// + /// is less than zero + /// -or- + /// is equal to or greater than . + /// + private void ValidateIndex(int i, bool allowEqualEnd) + { + int max = (allowEqualEnd) ? (m_count) : (m_count-1); + if (i < 0 || i > max) + { + throw log4net.Util.SystemInfo.CreateArgumentOutOfRangeException("i", (object)i, "Index was out of range. Must be non-negative and less than the size of the collection. [" + (object)i + "] Specified argument was out of the range of valid values."); + } + } + + private void EnsureCapacity(int min) + { + int newCapacity = ((m_array.Length == 0) ? DEFAULT_CAPACITY : m_array.Length * 2); + if (newCapacity < min) + { + newCapacity = min; + } + + this.Capacity = newCapacity; + } + + #endregion + + #region Implementation (ICollection) + + void ICollection.CopyTo(Array array, int start) + { + if (m_count > 0) + { + Array.Copy(m_array, 0, array, start, m_count); + } + } + + #endregion + + #region Implementation (IList) + + object IList.this[int i] + { + get { return (object)this[i]; } + set { this[i] = (IAppender)value; } + } + + int IList.Add(object x) + { + return this.Add((IAppender)x); + } + + bool IList.Contains(object x) + { + return this.Contains((IAppender)x); + } + + int IList.IndexOf(object x) + { + return this.IndexOf((IAppender)x); + } + + void IList.Insert(int pos, object x) + { + this.Insert(pos, (IAppender)x); + } + + void IList.Remove(object x) + { + this.Remove((IAppender)x); + } + + void IList.RemoveAt(int pos) + { + this.RemoveAt(pos); + } + + #endregion + + #region Implementation (IEnumerable) + + IEnumerator IEnumerable.GetEnumerator() + { + return (IEnumerator)(this.GetEnumerator()); + } + + #endregion + + #region Nested enumerator class + + /// + /// Supports simple iteration over a . + /// + /// + private sealed class Enumerator : IEnumerator, IAppenderCollectionEnumerator + { + #region Implementation (data) + + private readonly AppenderCollection m_collection; + private int m_index; + private int m_version; + + #endregion + + #region Construction + + /// + /// Initializes a new instance of the Enumerator class. + /// + /// + internal Enumerator(AppenderCollection tc) + { + m_collection = tc; + m_index = -1; + m_version = tc.m_version; + } + + #endregion + + #region Operations (type-safe IEnumerator) + + /// + /// Gets the current element in the collection. + /// + public IAppender Current + { + get { return m_collection[m_index]; } + } + + /// + /// Advances the enumerator to the next element in the collection. + /// + /// + /// true if the enumerator was successfully advanced to the next element; + /// false if the enumerator has passed the end of the collection. + /// + /// + /// The collection was modified after the enumerator was created. + /// + public bool MoveNext() + { + if (m_version != m_collection.m_version) + { + throw new System.InvalidOperationException("Collection was modified; enumeration operation may not execute."); + } + + ++m_index; + return (m_index < m_collection.Count); + } + + /// + /// Sets the enumerator to its initial position, before the first element in the collection. + /// + public void Reset() + { + m_index = -1; + } + #endregion + + #region Implementation (IEnumerator) + + object IEnumerator.Current + { + get { return this.Current; } + } + + #endregion + } + + #endregion + + #region Nested Read Only Wrapper class + + /// + private sealed class ReadOnlyAppenderCollection : AppenderCollection, ICollection + { + #region Implementation (data) + + private readonly AppenderCollection m_collection; + + #endregion + + #region Construction + + internal ReadOnlyAppenderCollection(AppenderCollection list) : base(Tag.Default) + { + m_collection = list; + } + + #endregion + + #region Type-safe ICollection + + public override void CopyTo(IAppender[] array) + { + m_collection.CopyTo(array); + } + + public override void CopyTo(IAppender[] array, int start) + { + m_collection.CopyTo(array,start); + } + + void ICollection.CopyTo(Array array, int start) + { + ((ICollection)m_collection).CopyTo(array, start); + } + + public override int Count + { + get { return m_collection.Count; } + } + + public override bool IsSynchronized + { + get { return m_collection.IsSynchronized; } + } + + public override object SyncRoot + { + get { return this.m_collection.SyncRoot; } + } + + #endregion + + #region Type-safe IList + + public override IAppender this[int i] + { + get { return m_collection[i]; } + set { throw new NotSupportedException("This is a Read Only Collection and can not be modified"); } + } + + public override int Add(IAppender x) + { + throw new NotSupportedException("This is a Read Only Collection and can not be modified"); + } + + public override void Clear() + { + throw new NotSupportedException("This is a Read Only Collection and can not be modified"); + } + + public override bool Contains(IAppender x) + { + return m_collection.Contains(x); + } + + public override int IndexOf(IAppender x) + { + return m_collection.IndexOf(x); + } + + public override void Insert(int pos, IAppender x) + { + throw new NotSupportedException("This is a Read Only Collection and can not be modified"); + } + + public override void Remove(IAppender x) + { + throw new NotSupportedException("This is a Read Only Collection and can not be modified"); + } + + public override void RemoveAt(int pos) + { + throw new NotSupportedException("This is a Read Only Collection and can not be modified"); + } - public override bool IsFixedSize - { - get { return true; } - } + public override bool IsFixedSize + { + get { return true; } + } - public override bool IsReadOnly - { - get { return true; } - } + public override bool IsReadOnly + { + get { return true; } + } - #endregion - - #region Type-safe IEnumerable - - public override IAppenderCollectionEnumerator GetEnumerator() - { - return m_collection.GetEnumerator(); - } - - #endregion - - #region Public Helpers - - // (just to mimic some nice features of ArrayList) - public override int Capacity - { - get { return m_collection.Capacity; } - set { throw new NotSupportedException("This is a Read Only Collection and can not be modified"); } - } - - public override int AddRange(AppenderCollection x) - { - throw new NotSupportedException("This is a Read Only Collection and can not be modified"); - } - - public override int AddRange(IAppender[] x) - { - throw new NotSupportedException("This is a Read Only Collection and can not be modified"); - } - - public override IAppender[] ToArray() - { - return m_collection.ToArray(); - } - - public override void TrimToSize() - { - throw new NotSupportedException("This is a Read Only Collection and can not be modified"); - } - - #endregion - } - - #endregion - } + #endregion + + #region Type-safe IEnumerable + + public override IAppenderCollectionEnumerator GetEnumerator() + { + return m_collection.GetEnumerator(); + } + + #endregion + + #region Public Helpers + + // (just to mimic some nice features of ArrayList) + public override int Capacity + { + get { return m_collection.Capacity; } + set { throw new NotSupportedException("This is a Read Only Collection and can not be modified"); } + } + + public override int AddRange(AppenderCollection x) + { + throw new NotSupportedException("This is a Read Only Collection and can not be modified"); + } + + public override int AddRange(IAppender[] x) + { + throw new NotSupportedException("This is a Read Only Collection and can not be modified"); + } + + public override IAppender[] ToArray() + { + return m_collection.ToArray(); + } + + public override void TrimToSize() + { + throw new NotSupportedException("This is a Read Only Collection and can not be modified"); + } + + #endregion + } + + #endregion + } } diff --git a/src/log4net/Appender/AppenderSkeleton.cs b/src/log4net/Appender/AppenderSkeleton.cs index 44b68c75..0ababc3f 100644 --- a/src/log4net/Appender/AppenderSkeleton.cs +++ b/src/log4net/Appender/AppenderSkeleton.cs @@ -28,674 +28,674 @@ namespace log4net.Appender { - /// - /// Abstract base class implementation of . - /// - /// - /// - /// This class provides the code for common functionality, such - /// as support for threshold filtering and support for general filters. - /// - /// - /// Appenders can also implement the interface. Therefore - /// they would require that the method - /// be called after the appenders properties have been configured. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public abstract class AppenderSkeleton : IAppender, IBulkAppender, IOptionHandler, IFlushable - { - #region Protected Instance Constructors - - /// - /// Default constructor - /// - /// - /// Empty default constructor - /// - protected AppenderSkeleton() - { - m_errorHandler = new OnlyOnceErrorHandler(this.GetType().Name); - } - - #endregion Protected Instance Constructors - - #region Finalizer - - /// - /// Finalizes this appender by calling the implementation's - /// method. - /// - /// - /// - /// If this appender has not been closed then the Finalize method - /// will call . - /// - /// - ~AppenderSkeleton() - { - // An appender might be closed then garbage collected. - // There is no point in closing twice. - if (!m_closed) - { - LogLog.Debug(declaringType, "Finalizing appender named ["+m_name+"]."); - Close(); - } - } - - #endregion Finalizer - - #region Public Instance Properties - - /// - /// Gets or sets the threshold of this appender. - /// - /// - /// The threshold of the appender. - /// - /// - /// - /// All log events with lower level than the threshold level are ignored - /// by the appender. - /// - /// - /// In configuration files this option is specified by setting the - /// value of the option to a level - /// string, such as "DEBUG", "INFO" and so on. - /// - /// - public Level Threshold - { - get { return m_threshold; } - set { m_threshold = value; } - } - - /// - /// Gets or sets the for this appender. - /// - /// The of the appender - /// - /// - /// The provides a default - /// implementation for the property. - /// - /// - public virtual IErrorHandler ErrorHandler - { - get { return this.m_errorHandler; } - set - { - lock(this) - { - if (value == null) - { - // We do not throw exception here since the cause is probably a - // bad config file. - LogLog.Warn(declaringType, "You have tried to set a null error-handler."); - } - else - { - m_errorHandler = value; - } - } - } - } - - /// - /// The filter chain. - /// - /// The head of the filter chain filter chain. - /// - /// - /// Returns the head Filter. The Filters are organized in a linked list - /// and so all Filters on this Appender are available through the result. - /// - /// - public virtual IFilter FilterHead - { - get { return m_headFilter; } - } - - /// - /// Gets or sets the for this appender. - /// - /// The layout of the appender. - /// - /// - /// See for more information. - /// - /// - /// - public virtual ILayout Layout - { - get { return m_layout; } - set { m_layout = value; } - } - - #endregion - - #region Implementation of IOptionHandler - - /// - /// Initialize the appender based on the options set - /// - /// - /// - /// This is part of the delayed object - /// activation scheme. The method must - /// be called on this object after the configuration properties have - /// been set. Until is called this - /// object is in an undefined state and must not be used. - /// - /// - /// If any of the configuration properties are modified then - /// must be called again. - /// - /// - public virtual void ActivateOptions() - { - } - - #endregion Implementation of IOptionHandler - - #region Implementation of IAppender - - /// - /// Gets or sets the name of this appender. - /// - /// The name of the appender. - /// - /// - /// The name uniquely identifies the appender. - /// - /// - public string Name - { - get { return m_name; } - set { m_name = value; } - } - - /// - /// Closes the appender and release resources. - /// - /// - /// - /// Release any resources allocated within the appender such as file handles, - /// network connections, etc. - /// - /// - /// It is a programming error to append to a closed appender. - /// - /// - /// This method cannot be overridden by subclasses. This method - /// delegates the closing of the appender to the - /// method which must be overridden in the subclass. - /// - /// - public void Close() - { - // This lock prevents the appender being closed while it is still appending - lock(this) - { - if (!m_closed) - { - OnClose(); - m_closed = true; - } - } - } - - /// - /// Performs threshold checks and invokes filters before - /// delegating actual logging to the subclasses specific - /// method. - /// - /// The event to log. - /// - /// - /// This method cannot be overridden by derived classes. A - /// derived class should override the method - /// which is called by this method. - /// - /// - /// The implementation of this method is as follows: - /// - /// - /// - /// - /// - /// Checks that the severity of the - /// is greater than or equal to the of this - /// appender. - /// - /// - /// - /// Checks that the chain accepts the - /// . - /// - /// - /// - /// - /// Calls and checks that - /// it returns true. - /// - /// - /// - /// - /// If all of the above steps succeed then the - /// will be passed to the abstract method. - /// - /// - public void DoAppend(LoggingEvent loggingEvent) - { - // This lock is absolutely critical for correct formatting - // of the message in a multi-threaded environment. Without - // this, the message may be broken up into elements from - // multiple thread contexts (like get the wrong thread ID). - - lock(this) - { - if (m_closed) - { - ErrorHandler.Error("Attempted to append to closed appender named ["+m_name+"]."); - return; - } - - // prevent re-entry - if (m_recursiveGuard) - { - return; - } - - try - { - m_recursiveGuard = true; - - if (FilterEvent(loggingEvent) && PreAppendCheck()) - { - this.Append(loggingEvent); - } - } - catch(Exception ex) - { - ErrorHandler.Error("Failed in DoAppend", ex); - } + /// + /// Abstract base class implementation of . + /// + /// + /// + /// This class provides the code for common functionality, such + /// as support for threshold filtering and support for general filters. + /// + /// + /// Appenders can also implement the interface. Therefore + /// they would require that the method + /// be called after the appenders properties have been configured. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public abstract class AppenderSkeleton : IAppender, IBulkAppender, IOptionHandler, IFlushable + { + #region Protected Instance Constructors + + /// + /// Default constructor + /// + /// + /// Empty default constructor + /// + protected AppenderSkeleton() + { + m_errorHandler = new OnlyOnceErrorHandler(this.GetType().Name); + } + + #endregion Protected Instance Constructors + + #region Finalizer + + /// + /// Finalizes this appender by calling the implementation's + /// method. + /// + /// + /// + /// If this appender has not been closed then the Finalize method + /// will call . + /// + /// + ~AppenderSkeleton() + { + // An appender might be closed then garbage collected. + // There is no point in closing twice. + if (!m_closed) + { + LogLog.Debug(declaringType, "Finalizing appender named ["+m_name+"]."); + Close(); + } + } + + #endregion Finalizer + + #region Public Instance Properties + + /// + /// Gets or sets the threshold of this appender. + /// + /// + /// The threshold of the appender. + /// + /// + /// + /// All log events with lower level than the threshold level are ignored + /// by the appender. + /// + /// + /// In configuration files this option is specified by setting the + /// value of the option to a level + /// string, such as "DEBUG", "INFO" and so on. + /// + /// + public Level Threshold + { + get { return m_threshold; } + set { m_threshold = value; } + } + + /// + /// Gets or sets the for this appender. + /// + /// The of the appender + /// + /// + /// The provides a default + /// implementation for the property. + /// + /// + public virtual IErrorHandler ErrorHandler + { + get { return this.m_errorHandler; } + set + { + lock(this) + { + if (value == null) + { + // We do not throw exception here since the cause is probably a + // bad config file. + LogLog.Warn(declaringType, "You have tried to set a null error-handler."); + } + else + { + m_errorHandler = value; + } + } + } + } + + /// + /// The filter chain. + /// + /// The head of the filter chain filter chain. + /// + /// + /// Returns the head Filter. The Filters are organized in a linked list + /// and so all Filters on this Appender are available through the result. + /// + /// + public virtual IFilter FilterHead + { + get { return m_headFilter; } + } + + /// + /// Gets or sets the for this appender. + /// + /// The layout of the appender. + /// + /// + /// See for more information. + /// + /// + /// + public virtual ILayout Layout + { + get { return m_layout; } + set { m_layout = value; } + } + + #endregion + + #region Implementation of IOptionHandler + + /// + /// Initialize the appender based on the options set + /// + /// + /// + /// This is part of the delayed object + /// activation scheme. The method must + /// be called on this object after the configuration properties have + /// been set. Until is called this + /// object is in an undefined state and must not be used. + /// + /// + /// If any of the configuration properties are modified then + /// must be called again. + /// + /// + public virtual void ActivateOptions() + { + } + + #endregion Implementation of IOptionHandler + + #region Implementation of IAppender + + /// + /// Gets or sets the name of this appender. + /// + /// The name of the appender. + /// + /// + /// The name uniquely identifies the appender. + /// + /// + public string Name + { + get { return m_name; } + set { m_name = value; } + } + + /// + /// Closes the appender and release resources. + /// + /// + /// + /// Release any resources allocated within the appender such as file handles, + /// network connections, etc. + /// + /// + /// It is a programming error to append to a closed appender. + /// + /// + /// This method cannot be overridden by subclasses. This method + /// delegates the closing of the appender to the + /// method which must be overridden in the subclass. + /// + /// + public void Close() + { + // This lock prevents the appender being closed while it is still appending + lock(this) + { + if (!m_closed) + { + OnClose(); + m_closed = true; + } + } + } + + /// + /// Performs threshold checks and invokes filters before + /// delegating actual logging to the subclasses specific + /// method. + /// + /// The event to log. + /// + /// + /// This method cannot be overridden by derived classes. A + /// derived class should override the method + /// which is called by this method. + /// + /// + /// The implementation of this method is as follows: + /// + /// + /// + /// + /// + /// Checks that the severity of the + /// is greater than or equal to the of this + /// appender. + /// + /// + /// + /// Checks that the chain accepts the + /// . + /// + /// + /// + /// + /// Calls and checks that + /// it returns true. + /// + /// + /// + /// + /// If all of the above steps succeed then the + /// will be passed to the abstract method. + /// + /// + public void DoAppend(LoggingEvent loggingEvent) + { + // This lock is absolutely critical for correct formatting + // of the message in a multi-threaded environment. Without + // this, the message may be broken up into elements from + // multiple thread contexts (like get the wrong thread ID). + + lock(this) + { + if (m_closed) + { + ErrorHandler.Error("Attempted to append to closed appender named ["+m_name+"]."); + return; + } + + // prevent re-entry + if (m_recursiveGuard) + { + return; + } + + try + { + m_recursiveGuard = true; + + if (FilterEvent(loggingEvent) && PreAppendCheck()) + { + this.Append(loggingEvent); + } + } + catch(Exception ex) + { + ErrorHandler.Error("Failed in DoAppend", ex); + } #if !MONO && !NET_2_0 && !NETSTANDARD - // on .NET 2.0 (and higher) and Mono (all profiles), - // exceptions that do not derive from System.Exception will be - // wrapped in a RuntimeWrappedException by the runtime, and as - // such will be catched by the catch clause above - catch - { - // Catch handler for non System.Exception types - ErrorHandler.Error("Failed in DoAppend (unknown exception)"); - } + // on .NET 2.0 (and higher) and Mono (all profiles), + // exceptions that do not derive from System.Exception will be + // wrapped in a RuntimeWrappedException by the runtime, and as + // such will be catched by the catch clause above + catch + { + // Catch handler for non System.Exception types + ErrorHandler.Error("Failed in DoAppend (unknown exception)"); + } #endif - finally - { - m_recursiveGuard = false; - } - } - } - - #endregion Implementation of IAppender - - #region Implementation of IBulkAppender - - /// - /// Performs threshold checks and invokes filters before - /// delegating actual logging to the subclasses specific - /// method. - /// - /// The array of events to log. - /// - /// - /// This method cannot be overridden by derived classes. A - /// derived class should override the method - /// which is called by this method. - /// - /// - /// The implementation of this method is as follows: - /// - /// - /// - /// - /// - /// Checks that the severity of the - /// is greater than or equal to the of this - /// appender. - /// - /// - /// - /// Checks that the chain accepts the - /// . - /// - /// - /// - /// - /// Calls and checks that - /// it returns true. - /// - /// - /// - /// - /// If all of the above steps succeed then the - /// will be passed to the method. - /// - /// - public void DoAppend(LoggingEvent[] loggingEvents) - { - // This lock is absolutely critical for correct formatting - // of the message in a multi-threaded environment. Without - // this, the message may be broken up into elements from - // multiple thread contexts (like get the wrong thread ID). - - lock(this) - { - if (m_closed) - { - ErrorHandler.Error("Attempted to append to closed appender named ["+m_name+"]."); - return; - } - - // prevent re-entry - if (m_recursiveGuard) - { - return; - } - - try - { - m_recursiveGuard = true; - - ArrayList filteredEvents = new ArrayList(loggingEvents.Length); - - foreach(LoggingEvent loggingEvent in loggingEvents) - { - if (FilterEvent(loggingEvent)) - { - filteredEvents.Add(loggingEvent); - } - } - - if (filteredEvents.Count > 0 && PreAppendCheck()) - { - this.Append((LoggingEvent[])filteredEvents.ToArray(typeof(LoggingEvent))); - } - } - catch(Exception ex) - { - ErrorHandler.Error("Failed in Bulk DoAppend", ex); - } + finally + { + m_recursiveGuard = false; + } + } + } + + #endregion Implementation of IAppender + + #region Implementation of IBulkAppender + + /// + /// Performs threshold checks and invokes filters before + /// delegating actual logging to the subclasses specific + /// method. + /// + /// The array of events to log. + /// + /// + /// This method cannot be overridden by derived classes. A + /// derived class should override the method + /// which is called by this method. + /// + /// + /// The implementation of this method is as follows: + /// + /// + /// + /// + /// + /// Checks that the severity of the + /// is greater than or equal to the of this + /// appender. + /// + /// + /// + /// Checks that the chain accepts the + /// . + /// + /// + /// + /// + /// Calls and checks that + /// it returns true. + /// + /// + /// + /// + /// If all of the above steps succeed then the + /// will be passed to the method. + /// + /// + public void DoAppend(LoggingEvent[] loggingEvents) + { + // This lock is absolutely critical for correct formatting + // of the message in a multi-threaded environment. Without + // this, the message may be broken up into elements from + // multiple thread contexts (like get the wrong thread ID). + + lock(this) + { + if (m_closed) + { + ErrorHandler.Error("Attempted to append to closed appender named ["+m_name+"]."); + return; + } + + // prevent re-entry + if (m_recursiveGuard) + { + return; + } + + try + { + m_recursiveGuard = true; + + ArrayList filteredEvents = new ArrayList(loggingEvents.Length); + + foreach(LoggingEvent loggingEvent in loggingEvents) + { + if (FilterEvent(loggingEvent)) + { + filteredEvents.Add(loggingEvent); + } + } + + if (filteredEvents.Count > 0 && PreAppendCheck()) + { + this.Append((LoggingEvent[])filteredEvents.ToArray(typeof(LoggingEvent))); + } + } + catch(Exception ex) + { + ErrorHandler.Error("Failed in Bulk DoAppend", ex); + } #if !MONO && !NET_2_0 && !NETSTANDARD - // on .NET 2.0 (and higher) and Mono (all profiles), - // exceptions that do not derive from System.Exception will be - // wrapped in a RuntimeWrappedException by the runtime, and as - // such will be catched by the catch clause above - catch - { - // Catch handler for non System.Exception types - ErrorHandler.Error("Failed in Bulk DoAppend (unknown exception)"); - } + // on .NET 2.0 (and higher) and Mono (all profiles), + // exceptions that do not derive from System.Exception will be + // wrapped in a RuntimeWrappedException by the runtime, and as + // such will be catched by the catch clause above + catch + { + // Catch handler for non System.Exception types + ErrorHandler.Error("Failed in Bulk DoAppend (unknown exception)"); + } #endif - finally - { - m_recursiveGuard = false; - } - } - } - - #endregion Implementation of IBulkAppender - - /// - /// Test if the logging event should we output by this appender - /// - /// the event to test - /// true if the event should be output, false if the event should be ignored - /// - /// - /// This method checks the logging event against the threshold level set - /// on this appender and also against the filters specified on this - /// appender. - /// - /// - /// The implementation of this method is as follows: - /// - /// - /// - /// - /// - /// Checks that the severity of the - /// is greater than or equal to the of this - /// appender. - /// - /// - /// - /// Checks that the chain accepts the - /// . - /// - /// - /// - /// - /// - protected virtual bool FilterEvent(LoggingEvent loggingEvent) - { - if (!IsAsSevereAsThreshold(loggingEvent.Level)) - { - return false; - } - - IFilter f = this.FilterHead; - - while(f != null) - { - switch(f.Decide(loggingEvent)) - { - case FilterDecision.Deny: - return false; // Return without appending - - case FilterDecision.Accept: - f = null; // Break out of the loop - break; - - case FilterDecision.Neutral: - f = f.Next; // Move to next filter - break; - } - } - - return true; - } - - #region Public Instance Methods - - /// - /// Adds a filter to the end of the filter chain. - /// - /// the filter to add to this appender - /// - /// - /// The Filters are organized in a linked list. - /// - /// - /// Setting this property causes the new filter to be pushed onto the - /// back of the filter chain. - /// - /// - public virtual void AddFilter(IFilter filter) - { - if (filter == null) - { - throw new ArgumentNullException("filter param must not be null"); - } - - if (m_headFilter == null) - { - m_headFilter = m_tailFilter = filter; - } - else - { - m_tailFilter.Next = filter; - m_tailFilter = filter; - } - } - - /// - /// Clears the filter list for this appender. - /// - /// - /// - /// Clears the filter list for this appender. - /// - /// - public virtual void ClearFilters() - { - m_headFilter = m_tailFilter = null; - } - - #endregion Public Instance Methods - - #region Protected Instance Methods - - /// - /// Checks if the message level is below this appender's threshold. - /// - /// to test against. - /// - /// - /// If there is no threshold set, then the return value is always true. - /// - /// - /// - /// true if the meets the - /// requirements of this appender. - /// - protected virtual bool IsAsSevereAsThreshold(Level level) - { - return ((m_threshold == null) || level >= m_threshold); - } - - /// - /// Is called when the appender is closed. Derived classes should override - /// this method if resources need to be released. - /// - /// - /// - /// Releases any resources allocated within the appender such as file handles, - /// network connections, etc. - /// - /// - /// It is a programming error to append to a closed appender. - /// - /// - protected virtual void OnClose() - { - // Do nothing by default - } - - /// - /// Subclasses of should implement this method - /// to perform actual logging. - /// - /// The event to append. - /// - /// - /// A subclass must implement this method to perform - /// logging of the . - /// - /// This method will be called by - /// if all the conditions listed for that method are met. - /// - /// - /// To restrict the logging of events in the appender - /// override the method. - /// - /// - protected abstract void Append(LoggingEvent loggingEvent); - - /// - /// Append a bulk array of logging events. - /// - /// the array of logging events - /// - /// - /// This base class implementation calls the - /// method for each element in the bulk array. - /// - /// - /// A sub class that can better process a bulk array of events should - /// override this method in addition to . - /// - /// - protected virtual void Append(LoggingEvent[] loggingEvents) - { - foreach(LoggingEvent loggingEvent in loggingEvents) - { - Append(loggingEvent); - } - } - - /// - /// Called before as a precondition. - /// - /// - /// - /// This method is called by - /// before the call to the abstract method. - /// - /// - /// This method can be overridden in a subclass to extend the checks - /// made before the event is passed to the method. - /// - /// - /// A subclass should ensure that they delegate this call to - /// this base class if it is overridden. - /// - /// - /// true if the call to should proceed. - protected virtual bool PreAppendCheck() - { - if ((m_layout == null) && RequiresLayout) - { - ErrorHandler.Error("AppenderSkeleton: No layout set for the appender named ["+m_name+"]."); - return false; - } - - return true; - } - - /// - /// Renders the to a string. - /// - /// The event to render. - /// The event rendered as a string. - /// - /// - /// Helper method to render a to - /// a string. This appender must have a - /// set to render the to - /// a string. - /// - /// If there is exception data in the logging event and - /// the layout does not process the exception, this method - /// will append the exception text to the rendered string. - /// - /// - /// Where possible use the alternative version of this method - /// . - /// That method streams the rendering onto an existing Writer - /// which can give better performance if the caller already has - /// a open and ready for writing. - /// - /// - protected string RenderLoggingEvent(LoggingEvent loggingEvent) - { - // Create the render writer on first use - if (m_renderWriter == null) - { - m_renderWriter = new ReusableStringWriter(System.Globalization.CultureInfo.InvariantCulture); - } + finally + { + m_recursiveGuard = false; + } + } + } + + #endregion Implementation of IBulkAppender + + /// + /// Test if the logging event should we output by this appender + /// + /// the event to test + /// true if the event should be output, false if the event should be ignored + /// + /// + /// This method checks the logging event against the threshold level set + /// on this appender and also against the filters specified on this + /// appender. + /// + /// + /// The implementation of this method is as follows: + /// + /// + /// + /// + /// + /// Checks that the severity of the + /// is greater than or equal to the of this + /// appender. + /// + /// + /// + /// Checks that the chain accepts the + /// . + /// + /// + /// + /// + /// + protected virtual bool FilterEvent(LoggingEvent loggingEvent) + { + if (!IsAsSevereAsThreshold(loggingEvent.Level)) + { + return false; + } + + IFilter f = this.FilterHead; + + while(f != null) + { + switch(f.Decide(loggingEvent)) + { + case FilterDecision.Deny: + return false; // Return without appending + + case FilterDecision.Accept: + f = null; // Break out of the loop + break; + + case FilterDecision.Neutral: + f = f.Next; // Move to next filter + break; + } + } + + return true; + } + + #region Public Instance Methods + + /// + /// Adds a filter to the end of the filter chain. + /// + /// the filter to add to this appender + /// + /// + /// The Filters are organized in a linked list. + /// + /// + /// Setting this property causes the new filter to be pushed onto the + /// back of the filter chain. + /// + /// + public virtual void AddFilter(IFilter filter) + { + if (filter == null) + { + throw new ArgumentNullException("filter param must not be null"); + } + + if (m_headFilter == null) + { + m_headFilter = m_tailFilter = filter; + } + else + { + m_tailFilter.Next = filter; + m_tailFilter = filter; + } + } + + /// + /// Clears the filter list for this appender. + /// + /// + /// + /// Clears the filter list for this appender. + /// + /// + public virtual void ClearFilters() + { + m_headFilter = m_tailFilter = null; + } + + #endregion Public Instance Methods + + #region Protected Instance Methods + + /// + /// Checks if the message level is below this appender's threshold. + /// + /// to test against. + /// + /// + /// If there is no threshold set, then the return value is always true. + /// + /// + /// + /// true if the meets the + /// requirements of this appender. + /// + protected virtual bool IsAsSevereAsThreshold(Level level) + { + return ((m_threshold == null) || level >= m_threshold); + } + + /// + /// Is called when the appender is closed. Derived classes should override + /// this method if resources need to be released. + /// + /// + /// + /// Releases any resources allocated within the appender such as file handles, + /// network connections, etc. + /// + /// + /// It is a programming error to append to a closed appender. + /// + /// + protected virtual void OnClose() + { + // Do nothing by default + } + + /// + /// Subclasses of should implement this method + /// to perform actual logging. + /// + /// The event to append. + /// + /// + /// A subclass must implement this method to perform + /// logging of the . + /// + /// This method will be called by + /// if all the conditions listed for that method are met. + /// + /// + /// To restrict the logging of events in the appender + /// override the method. + /// + /// + protected abstract void Append(LoggingEvent loggingEvent); + + /// + /// Append a bulk array of logging events. + /// + /// the array of logging events + /// + /// + /// This base class implementation calls the + /// method for each element in the bulk array. + /// + /// + /// A sub class that can better process a bulk array of events should + /// override this method in addition to . + /// + /// + protected virtual void Append(LoggingEvent[] loggingEvents) + { + foreach(LoggingEvent loggingEvent in loggingEvents) + { + Append(loggingEvent); + } + } + + /// + /// Called before as a precondition. + /// + /// + /// + /// This method is called by + /// before the call to the abstract method. + /// + /// + /// This method can be overridden in a subclass to extend the checks + /// made before the event is passed to the method. + /// + /// + /// A subclass should ensure that they delegate this call to + /// this base class if it is overridden. + /// + /// + /// true if the call to should proceed. + protected virtual bool PreAppendCheck() + { + if ((m_layout == null) && RequiresLayout) + { + ErrorHandler.Error("AppenderSkeleton: No layout set for the appender named ["+m_name+"]."); + return false; + } + + return true; + } + + /// + /// Renders the to a string. + /// + /// The event to render. + /// The event rendered as a string. + /// + /// + /// Helper method to render a to + /// a string. This appender must have a + /// set to render the to + /// a string. + /// + /// If there is exception data in the logging event and + /// the layout does not process the exception, this method + /// will append the exception text to the rendered string. + /// + /// + /// Where possible use the alternative version of this method + /// . + /// That method streams the rendering onto an existing Writer + /// which can give better performance if the caller already has + /// a open and ready for writing. + /// + /// + protected string RenderLoggingEvent(LoggingEvent loggingEvent) + { + // Create the render writer on first use + if (m_renderWriter == null) + { + m_renderWriter = new ReusableStringWriter(System.Globalization.CultureInfo.InvariantCulture); + } lock (m_renderWriter) { @@ -705,205 +705,205 @@ protected string RenderLoggingEvent(LoggingEvent loggingEvent) RenderLoggingEvent(m_renderWriter, loggingEvent); return m_renderWriter.ToString(); } - } - - /// - /// Renders the to a string. - /// - /// The event to render. - /// The TextWriter to write the formatted event to - /// - /// - /// Helper method to render a to - /// a string. This appender must have a - /// set to render the to - /// a string. - /// - /// If there is exception data in the logging event and - /// the layout does not process the exception, this method - /// will append the exception text to the rendered string. - /// - /// - /// Use this method in preference to - /// where possible. If, however, the caller needs to render the event - /// to a string then does - /// provide an efficient mechanism for doing so. - /// - /// - protected void RenderLoggingEvent(TextWriter writer, LoggingEvent loggingEvent) - { - if (m_layout == null) - { - throw new InvalidOperationException("A layout must be set"); - } - - if (m_layout.IgnoresException) - { - string exceptionStr = loggingEvent.GetExceptionString(); - if (exceptionStr != null && exceptionStr.Length > 0) - { - // render the event and the exception - m_layout.Format(writer, loggingEvent); - writer.WriteLine(exceptionStr); - } - else - { - // there is no exception to render - m_layout.Format(writer, loggingEvent); - } - } - else - { - // The layout will render the exception - m_layout.Format(writer, loggingEvent); - } - } - - /// - /// Tests if this appender requires a to be set. - /// - /// - /// - /// In the rather exceptional case, where the appender - /// implementation admits a layout but can also work without it, - /// then the appender should return true. - /// - /// - /// This default implementation always returns false. - /// - /// - /// - /// true if the appender requires a layout object, otherwise false. - /// - protected virtual bool RequiresLayout - { - get { return false; } - } - - #endregion - - /// - /// Flushes any buffered log data. - /// - /// - /// This implementation doesn't flush anything and always returns true - /// - /// True if all logging events were flushed successfully, else false. - public virtual bool Flush(int millisecondsTimeout) - { - return true; - } - - #region Private Instance Fields - - /// - /// The layout of this appender. - /// - /// - /// See for more information. - /// - private ILayout m_layout; - - /// - /// The name of this appender. - /// - /// - /// See for more information. - /// - private string m_name; - - /// - /// The level threshold of this appender. - /// - /// - /// - /// There is no level threshold filtering by default. - /// - /// - /// See for more information. - /// - /// - private Level m_threshold; - - /// - /// It is assumed and enforced that errorHandler is never null. - /// - /// - /// - /// It is assumed and enforced that errorHandler is never null. - /// - /// - /// See for more information. - /// - /// - private IErrorHandler m_errorHandler; - - /// - /// The first filter in the filter chain. - /// - /// - /// - /// Set to null initially. - /// - /// - /// See for more information. - /// - /// - private IFilter m_headFilter; - - /// - /// The last filter in the filter chain. - /// - /// - /// See for more information. - /// - private IFilter m_tailFilter; - - /// - /// Flag indicating if this appender is closed. - /// - /// - /// See for more information. - /// - private bool m_closed = false; - - /// - /// The guard prevents an appender from repeatedly calling its own DoAppend method - /// - private bool m_recursiveGuard = false; - - /// - /// StringWriter used to render events - /// - private ReusableStringWriter m_renderWriter = null; - - #endregion Private Instance Fields - - #region Constants - - /// - /// Initial buffer size - /// - private const int c_renderBufferSize = 256; - - /// - /// Maximum buffer size before it is recycled - /// - private const int c_renderBufferMaxCapacity = 1024; - - #endregion - - #region Private Static Fields - - /// - /// The fully qualified type of the AppenderSkeleton class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(AppenderSkeleton); - - #endregion Private Static Fields - } + } + + /// + /// Renders the to a string. + /// + /// The event to render. + /// The TextWriter to write the formatted event to + /// + /// + /// Helper method to render a to + /// a string. This appender must have a + /// set to render the to + /// a string. + /// + /// If there is exception data in the logging event and + /// the layout does not process the exception, this method + /// will append the exception text to the rendered string. + /// + /// + /// Use this method in preference to + /// where possible. If, however, the caller needs to render the event + /// to a string then does + /// provide an efficient mechanism for doing so. + /// + /// + protected void RenderLoggingEvent(TextWriter writer, LoggingEvent loggingEvent) + { + if (m_layout == null) + { + throw new InvalidOperationException("A layout must be set"); + } + + if (m_layout.IgnoresException) + { + string exceptionStr = loggingEvent.GetExceptionString(); + if (exceptionStr != null && exceptionStr.Length > 0) + { + // render the event and the exception + m_layout.Format(writer, loggingEvent); + writer.WriteLine(exceptionStr); + } + else + { + // there is no exception to render + m_layout.Format(writer, loggingEvent); + } + } + else + { + // The layout will render the exception + m_layout.Format(writer, loggingEvent); + } + } + + /// + /// Tests if this appender requires a to be set. + /// + /// + /// + /// In the rather exceptional case, where the appender + /// implementation admits a layout but can also work without it, + /// then the appender should return true. + /// + /// + /// This default implementation always returns false. + /// + /// + /// + /// true if the appender requires a layout object, otherwise false. + /// + protected virtual bool RequiresLayout + { + get { return false; } + } + + #endregion + + /// + /// Flushes any buffered log data. + /// + /// + /// This implementation doesn't flush anything and always returns true + /// + /// True if all logging events were flushed successfully, else false. + public virtual bool Flush(int millisecondsTimeout) + { + return true; + } + + #region Private Instance Fields + + /// + /// The layout of this appender. + /// + /// + /// See for more information. + /// + private ILayout m_layout; + + /// + /// The name of this appender. + /// + /// + /// See for more information. + /// + private string m_name; + + /// + /// The level threshold of this appender. + /// + /// + /// + /// There is no level threshold filtering by default. + /// + /// + /// See for more information. + /// + /// + private Level m_threshold; + + /// + /// It is assumed and enforced that errorHandler is never null. + /// + /// + /// + /// It is assumed and enforced that errorHandler is never null. + /// + /// + /// See for more information. + /// + /// + private IErrorHandler m_errorHandler; + + /// + /// The first filter in the filter chain. + /// + /// + /// + /// Set to null initially. + /// + /// + /// See for more information. + /// + /// + private IFilter m_headFilter; + + /// + /// The last filter in the filter chain. + /// + /// + /// See for more information. + /// + private IFilter m_tailFilter; + + /// + /// Flag indicating if this appender is closed. + /// + /// + /// See for more information. + /// + private bool m_closed = false; + + /// + /// The guard prevents an appender from repeatedly calling its own DoAppend method + /// + private bool m_recursiveGuard = false; + + /// + /// StringWriter used to render events + /// + private ReusableStringWriter m_renderWriter = null; + + #endregion Private Instance Fields + + #region Constants + + /// + /// Initial buffer size + /// + private const int c_renderBufferSize = 256; + + /// + /// Maximum buffer size before it is recycled + /// + private const int c_renderBufferMaxCapacity = 1024; + + #endregion + + #region Private Static Fields + + /// + /// The fully qualified type of the AppenderSkeleton class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(AppenderSkeleton); + + #endregion Private Static Fields + } } diff --git a/src/log4net/Appender/AspNetTraceAppender.cs b/src/log4net/Appender/AspNetTraceAppender.cs index bffa0459..addd4c14 100644 --- a/src/log4net/Appender/AspNetTraceAppender.cs +++ b/src/log4net/Appender/AspNetTraceAppender.cs @@ -29,97 +29,97 @@ namespace log4net.Appender { - /// - /// - /// Appends log events to the ASP.NET system. - /// - /// - /// - /// - /// Diagnostic information and tracing messages that you specify are appended to the output - /// of the page that is sent to the requesting browser. Optionally, you can view this information - /// from a separate trace viewer (Trace.axd) that displays trace information for every page in a - /// given application. - /// - /// - /// Trace statements are processed and displayed only when tracing is enabled. You can control - /// whether tracing is displayed to a page, to the trace viewer, or both. - /// - /// - /// The logging event is passed to the or - /// method depending on the level of the logging event. + /// + /// + /// Appends log events to the ASP.NET system. + /// + /// + /// + /// + /// Diagnostic information and tracing messages that you specify are appended to the output + /// of the page that is sent to the requesting browser. Optionally, you can view this information + /// from a separate trace viewer (Trace.axd) that displays trace information for every page in a + /// given application. + /// + /// + /// Trace statements are processed and displayed only when tracing is enabled. You can control + /// whether tracing is displayed to a page, to the trace viewer, or both. + /// + /// + /// The logging event is passed to the or + /// method depending on the level of the logging event. /// The event's logger name is the default value for the category parameter of the Write/Warn method. - /// - /// - /// Nicko Cadell - /// Gert Driesen - /// Ron Grabowski - public class AspNetTraceAppender : AppenderSkeleton - { - #region Public Instances Constructors - - /// - /// Initializes a new instance of the class. - /// - /// - /// - /// Default constructor. - /// - /// - public AspNetTraceAppender() - { - } - - #endregion // Public Instances Constructors - - #region Override implementation of AppenderSkeleton - - /// - /// Write the logging event to the ASP.NET trace - /// - /// the event to log - /// - /// - /// Write the logging event to the ASP.NET trace - /// HttpContext.Current.Trace - /// (). - /// - /// - protected override void Append(LoggingEvent loggingEvent) - { - // check if log4net is running in the context of an ASP.NET application - if (HttpContext.Current != null) - { - // check if tracing is enabled for the current context - if (HttpContext.Current.Trace.IsEnabled) - { - if (loggingEvent.Level >= Level.Warn) - { + /// + /// + /// Nicko Cadell + /// Gert Driesen + /// Ron Grabowski + public class AspNetTraceAppender : AppenderSkeleton + { + #region Public Instances Constructors + + /// + /// Initializes a new instance of the class. + /// + /// + /// + /// Default constructor. + /// + /// + public AspNetTraceAppender() + { + } + + #endregion // Public Instances Constructors + + #region Override implementation of AppenderSkeleton + + /// + /// Write the logging event to the ASP.NET trace + /// + /// the event to log + /// + /// + /// Write the logging event to the ASP.NET trace + /// HttpContext.Current.Trace + /// (). + /// + /// + protected override void Append(LoggingEvent loggingEvent) + { + // check if log4net is running in the context of an ASP.NET application + if (HttpContext.Current != null) + { + // check if tracing is enabled for the current context + if (HttpContext.Current.Trace.IsEnabled) + { + if (loggingEvent.Level >= Level.Warn) + { HttpContext.Current.Trace.Warn(m_category.Format(loggingEvent), RenderLoggingEvent(loggingEvent)); - } - else - { + } + else + { HttpContext.Current.Trace.Write(m_category.Format(loggingEvent), RenderLoggingEvent(loggingEvent)); - } - } - } - } - - /// - /// This appender requires a to be set. - /// - /// true - /// - /// - /// This appender requires a to be set. - /// - /// - protected override bool RequiresLayout - { - get { return true; } - } - - #endregion // Override implementation of AppenderSkeleton + } + } + } + } + + /// + /// This appender requires a to be set. + /// + /// true + /// + /// + /// This appender requires a to be set. + /// + /// + protected override bool RequiresLayout + { + get { return true; } + } + + #endregion // Override implementation of AppenderSkeleton #region Public Instance Properties @@ -140,17 +140,17 @@ public PatternLayout Category set { m_category = value; } } - #endregion + #endregion - #region Private Instance Fields + #region Private Instance Fields - /// - /// Defaults to %logger - /// - private PatternLayout m_category = new PatternLayout("%logger"); + /// + /// Defaults to %logger + /// + private PatternLayout m_category = new PatternLayout("%logger"); - #endregion - } + #endregion + } } #endif // !NETCF && !SSCLI diff --git a/src/log4net/Appender/BufferingAppenderSkeleton.cs b/src/log4net/Appender/BufferingAppenderSkeleton.cs index c49d8382..e8f8e496 100644 --- a/src/log4net/Appender/BufferingAppenderSkeleton.cs +++ b/src/log4net/Appender/BufferingAppenderSkeleton.cs @@ -25,242 +25,242 @@ namespace log4net.Appender { - /// - /// Abstract base class implementation of that - /// buffers events in a fixed size buffer. - /// - /// - /// - /// This base class should be used by appenders that need to buffer a - /// number of events before logging them. - /// For example the - /// buffers events and then submits the entire contents of the buffer to - /// the underlying database in one go. - /// - /// - /// Subclasses should override the - /// method to deliver the buffered events. - /// - /// The BufferingAppenderSkeleton maintains a fixed size cyclic - /// buffer of events. The size of the buffer is set using - /// the property. - /// - /// A is used to inspect - /// each event as it arrives in the appender. If the - /// triggers, then the current buffer is sent immediately - /// (see ). Otherwise the event - /// is stored in the buffer. For example, an evaluator can be used to - /// deliver the events immediately when an ERROR event arrives. - /// - /// - /// The buffering appender can be configured in a mode. - /// By default the appender is NOT lossy. When the buffer is full all - /// the buffered events are sent with . - /// If the property is set to true then the - /// buffer will not be sent when it is full, and new events arriving - /// in the appender will overwrite the oldest event in the buffer. - /// In lossy mode the buffer will only be sent when the - /// triggers. This can be useful behavior when you need to know about - /// ERROR events but not about events with a lower level, configure an - /// evaluator that will trigger when an ERROR event arrives, the whole - /// buffer will be sent which gives a history of events leading up to - /// the ERROR event. - /// - /// - /// Nicko Cadell - /// Gert Driesen + /// + /// Abstract base class implementation of that + /// buffers events in a fixed size buffer. + /// + /// + /// + /// This base class should be used by appenders that need to buffer a + /// number of events before logging them. + /// For example the + /// buffers events and then submits the entire contents of the buffer to + /// the underlying database in one go. + /// + /// + /// Subclasses should override the + /// method to deliver the buffered events. + /// + /// The BufferingAppenderSkeleton maintains a fixed size cyclic + /// buffer of events. The size of the buffer is set using + /// the property. + /// + /// A is used to inspect + /// each event as it arrives in the appender. If the + /// triggers, then the current buffer is sent immediately + /// (see ). Otherwise the event + /// is stored in the buffer. For example, an evaluator can be used to + /// deliver the events immediately when an ERROR event arrives. + /// + /// + /// The buffering appender can be configured in a mode. + /// By default the appender is NOT lossy. When the buffer is full all + /// the buffered events are sent with . + /// If the property is set to true then the + /// buffer will not be sent when it is full, and new events arriving + /// in the appender will overwrite the oldest event in the buffer. + /// In lossy mode the buffer will only be sent when the + /// triggers. This can be useful behavior when you need to know about + /// ERROR events but not about events with a lower level, configure an + /// evaluator that will trigger when an ERROR event arrives, the whole + /// buffer will be sent which gives a history of events leading up to + /// the ERROR event. + /// + /// + /// Nicko Cadell + /// Gert Driesen public abstract class BufferingAppenderSkeleton : AppenderSkeleton - { - #region Protected Instance Constructors - - /// - /// Initializes a new instance of the class. - /// - /// - /// - /// Protected default constructor to allow subclassing. - /// - /// - protected BufferingAppenderSkeleton() : this(true) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// the events passed through this appender must be - /// fixed by the time that they arrive in the derived class' SendBuffer method. - /// - /// - /// Protected constructor to allow subclassing. - /// - /// - /// The should be set if the subclass - /// expects the events delivered to be fixed even if the - /// is set to zero, i.e. when no buffering occurs. - /// - /// - protected BufferingAppenderSkeleton(bool eventMustBeFixed) : base() - { - m_eventMustBeFixed = eventMustBeFixed; - } - - #endregion Protected Instance Constructors - - #region Public Instance Properties - - /// - /// Gets or sets a value that indicates whether the appender is lossy. - /// - /// - /// true if the appender is lossy, otherwise false. The default is false. - /// - /// - /// - /// This appender uses a buffer to store logging events before - /// delivering them. A triggering event causes the whole buffer - /// to be send to the remote sink. If the buffer overruns before - /// a triggering event then logging events could be lost. Set - /// to false to prevent logging events - /// from being lost. - /// - /// If is set to true then an - /// must be specified. - /// - public bool Lossy - { - get { return m_lossy; } - set { m_lossy = value; } - } - - /// - /// Gets or sets the size of the cyclic buffer used to hold the - /// logging events. - /// - /// - /// The size of the cyclic buffer used to hold the logging events. - /// - /// - /// - /// The option takes a positive integer - /// representing the maximum number of logging events to collect in - /// a cyclic buffer. When the is reached, - /// oldest events are deleted as new events are added to the - /// buffer. By default the size of the cyclic buffer is 512 events. - /// - /// - /// If the is set to a value less than - /// or equal to 1 then no buffering will occur. The logging event - /// will be delivered synchronously (depending on the - /// and properties). Otherwise the event will - /// be buffered. - /// - /// - public int BufferSize - { - get { return m_bufferSize; } - set { m_bufferSize = value; } - } - - /// - /// Gets or sets the that causes the - /// buffer to be sent immediately. - /// - /// - /// The that causes the buffer to be - /// sent immediately. - /// - /// - /// - /// The evaluator will be called for each event that is appended to this - /// appender. If the evaluator triggers then the current buffer will - /// immediately be sent (see ). - /// - /// If is set to true then an - /// must be specified. - /// - public ITriggeringEventEvaluator Evaluator - { - get { return m_evaluator; } - set { m_evaluator = value; } - } - - /// - /// Gets or sets the value of the to use. - /// - /// - /// The value of the to use. - /// - /// - /// - /// The evaluator will be called for each event that is discarded from this - /// appender. If the evaluator triggers then the current buffer will immediately - /// be sent (see ). - /// - /// - public ITriggeringEventEvaluator LossyEvaluator - { - get { return m_lossyEvaluator; } - set { m_lossyEvaluator = value; } - } - - /// - /// Gets or sets a value indicating if only part of the logging event data - /// should be fixed. - /// - /// - /// true if the appender should only fix part of the logging event - /// data, otherwise false. The default is false. - /// - /// - /// - /// Setting this property to true will cause only part of the - /// event data to be fixed and serialized. This will improve performance. - /// - /// - /// See for more information. - /// - /// - [Obsolete("Use Fix property")] - public virtual bool OnlyFixPartialEventData - { - get { return (Fix == FixFlags.Partial); } - set - { - if (value) - { - Fix = FixFlags.Partial; - } - else - { - Fix = FixFlags.All; - } - } - } - - /// - /// Gets or sets a the fields that will be fixed in the event - /// - /// - /// The event fields that will be fixed before the event is buffered - /// - /// - /// - /// The logging event needs to have certain thread specific values - /// captured before it can be buffered. See - /// for details. - /// - /// - /// - public virtual FixFlags Fix - { - get { return m_fixFlags; } - set { m_fixFlags = value; } - } - - #endregion Public Instance Properties - - #region Public Methods + { + #region Protected Instance Constructors + + /// + /// Initializes a new instance of the class. + /// + /// + /// + /// Protected default constructor to allow subclassing. + /// + /// + protected BufferingAppenderSkeleton() : this(true) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// the events passed through this appender must be + /// fixed by the time that they arrive in the derived class' SendBuffer method. + /// + /// + /// Protected constructor to allow subclassing. + /// + /// + /// The should be set if the subclass + /// expects the events delivered to be fixed even if the + /// is set to zero, i.e. when no buffering occurs. + /// + /// + protected BufferingAppenderSkeleton(bool eventMustBeFixed) : base() + { + m_eventMustBeFixed = eventMustBeFixed; + } + + #endregion Protected Instance Constructors + + #region Public Instance Properties + + /// + /// Gets or sets a value that indicates whether the appender is lossy. + /// + /// + /// true if the appender is lossy, otherwise false. The default is false. + /// + /// + /// + /// This appender uses a buffer to store logging events before + /// delivering them. A triggering event causes the whole buffer + /// to be send to the remote sink. If the buffer overruns before + /// a triggering event then logging events could be lost. Set + /// to false to prevent logging events + /// from being lost. + /// + /// If is set to true then an + /// must be specified. + /// + public bool Lossy + { + get { return m_lossy; } + set { m_lossy = value; } + } + + /// + /// Gets or sets the size of the cyclic buffer used to hold the + /// logging events. + /// + /// + /// The size of the cyclic buffer used to hold the logging events. + /// + /// + /// + /// The option takes a positive integer + /// representing the maximum number of logging events to collect in + /// a cyclic buffer. When the is reached, + /// oldest events are deleted as new events are added to the + /// buffer. By default the size of the cyclic buffer is 512 events. + /// + /// + /// If the is set to a value less than + /// or equal to 1 then no buffering will occur. The logging event + /// will be delivered synchronously (depending on the + /// and properties). Otherwise the event will + /// be buffered. + /// + /// + public int BufferSize + { + get { return m_bufferSize; } + set { m_bufferSize = value; } + } + + /// + /// Gets or sets the that causes the + /// buffer to be sent immediately. + /// + /// + /// The that causes the buffer to be + /// sent immediately. + /// + /// + /// + /// The evaluator will be called for each event that is appended to this + /// appender. If the evaluator triggers then the current buffer will + /// immediately be sent (see ). + /// + /// If is set to true then an + /// must be specified. + /// + public ITriggeringEventEvaluator Evaluator + { + get { return m_evaluator; } + set { m_evaluator = value; } + } + + /// + /// Gets or sets the value of the to use. + /// + /// + /// The value of the to use. + /// + /// + /// + /// The evaluator will be called for each event that is discarded from this + /// appender. If the evaluator triggers then the current buffer will immediately + /// be sent (see ). + /// + /// + public ITriggeringEventEvaluator LossyEvaluator + { + get { return m_lossyEvaluator; } + set { m_lossyEvaluator = value; } + } + + /// + /// Gets or sets a value indicating if only part of the logging event data + /// should be fixed. + /// + /// + /// true if the appender should only fix part of the logging event + /// data, otherwise false. The default is false. + /// + /// + /// + /// Setting this property to true will cause only part of the + /// event data to be fixed and serialized. This will improve performance. + /// + /// + /// See for more information. + /// + /// + [Obsolete("Use Fix property")] + public virtual bool OnlyFixPartialEventData + { + get { return (Fix == FixFlags.Partial); } + set + { + if (value) + { + Fix = FixFlags.Partial; + } + else + { + Fix = FixFlags.All; + } + } + } + + /// + /// Gets or sets a the fields that will be fixed in the event + /// + /// + /// The event fields that will be fixed before the event is buffered + /// + /// + /// + /// The logging event needs to have certain thread specific values + /// captured before it can be buffered. See + /// for details. + /// + /// + /// + public virtual FixFlags Fix + { + get { return m_fixFlags; } + set { m_fixFlags = value; } + } + + #endregion Public Instance Properties + + #region Public Methods /// /// Flushes any buffered log data. @@ -273,387 +273,387 @@ public override bool Flush(int millisecondsTimeout) return true; } - /// - /// Flush the currently buffered events - /// - /// - /// - /// Flushes any events that have been buffered. - /// - /// - /// If the appender is buffering in mode then the contents - /// of the buffer will NOT be flushed to the appender. - /// - /// - public virtual void Flush() - { - Flush(false); - } - - /// - /// Flush the currently buffered events - /// - /// set to true to flush the buffer of lossy events - /// - /// - /// Flushes events that have been buffered. If is - /// false then events will only be flushed if this buffer is non-lossy mode. - /// - /// - /// If the appender is buffering in mode then the contents - /// of the buffer will only be flushed if is true. - /// In this case the contents of the buffer will be tested against the - /// and if triggering will be output. All other buffered - /// events will be discarded. - /// - /// - /// If is true then the buffer will always - /// be emptied by calling this method. - /// - /// - public virtual void Flush(bool flushLossyBuffer) - { - // This method will be called outside of the AppenderSkeleton DoAppend() method - // therefore it needs to be protected by its own lock. This will block any - // Appends while the buffer is flushed. - lock(this) - { - if (m_cb != null && m_cb.Length > 0) - { - if (m_lossy) - { - // If we are allowed to eagerly flush from the lossy buffer - if (flushLossyBuffer) - { - if (m_lossyEvaluator != null) - { - // Test the contents of the buffer against the lossy evaluator - LoggingEvent[] bufferedEvents = m_cb.PopAll(); - ArrayList filteredEvents = new ArrayList(bufferedEvents.Length); - - foreach(LoggingEvent loggingEvent in bufferedEvents) - { - if (m_lossyEvaluator.IsTriggeringEvent(loggingEvent)) - { - filteredEvents.Add(loggingEvent); - } - } - - // Send the events that meet the lossy evaluator criteria - if (filteredEvents.Count > 0) - { - SendBuffer((LoggingEvent[])filteredEvents.ToArray(typeof(LoggingEvent))); - } - } - else - { - // No lossy evaluator, all buffered events are discarded - m_cb.Clear(); - } - } - } - else - { - // Not lossy, send whole buffer - SendFromBuffer(null, m_cb); - } - } - } - } - - #endregion Public Methods - - #region Implementation of IOptionHandler - - /// - /// Initialize the appender based on the options set - /// - /// - /// - /// This is part of the delayed object - /// activation scheme. The method must - /// be called on this object after the configuration properties have - /// been set. Until is called this - /// object is in an undefined state and must not be used. - /// - /// - /// If any of the configuration properties are modified then - /// must be called again. - /// - /// - public override void ActivateOptions() - { - base.ActivateOptions(); - - // If the appender is in Lossy mode then we will - // only send the buffer when the Evaluator triggers - // therefore check we have an evaluator. - if (m_lossy && m_evaluator == null) - { - ErrorHandler.Error("Appender ["+Name+"] is Lossy but has no Evaluator. The buffer will never be sent!"); - } - - if (m_bufferSize > 1) - { - m_cb = new CyclicBuffer(m_bufferSize); - } - else - { - m_cb = null; - } - } - - #endregion Implementation of IOptionHandler - - #region Override implementation of AppenderSkeleton - - /// - /// Close this appender instance. - /// - /// - /// - /// Close this appender instance. If this appender is marked - /// as not then the remaining events in - /// the buffer must be sent when the appender is closed. - /// - /// - protected override void OnClose() - { - // Flush the buffer on close - Flush(true); - } - - /// - /// This method is called by the method. - /// - /// the event to log - /// - /// - /// Stores the in the cyclic buffer. - /// - /// - /// The buffer will be sent (i.e. passed to the - /// method) if one of the following conditions is met: - /// - /// - /// - /// The cyclic buffer is full and this appender is - /// marked as not lossy (see ) - /// - /// - /// An is set and - /// it is triggered for the - /// specified. - /// - /// - /// - /// Before the event is stored in the buffer it is fixed - /// (see ) to ensure that - /// any data referenced by the event will be valid when the buffer - /// is processed. - /// - /// - protected override void Append(LoggingEvent loggingEvent) - { - // If the buffer size is set to 1 or less then the buffer will be - // sent immediately because there is not enough space in the buffer - // to buffer up more than 1 event. Therefore as a special case - // we don't use the buffer at all. - if (m_cb == null || m_bufferSize <= 1) - { - // Only send the event if we are in non lossy mode or the event is a triggering event - if ((!m_lossy) || - (m_evaluator != null && m_evaluator.IsTriggeringEvent(loggingEvent)) || - (m_lossyEvaluator != null && m_lossyEvaluator.IsTriggeringEvent(loggingEvent))) - { - if (m_eventMustBeFixed) - { - // Derive class expects fixed events - loggingEvent.Fix = this.Fix; - } - - // Not buffering events, send immediately - SendBuffer(new LoggingEvent[] { loggingEvent } ); - } - } - else - { - // Because we are caching the LoggingEvent beyond the - // lifetime of the Append() method we must fix any - // volatile data in the event. - loggingEvent.Fix = this.Fix; - - // Add to the buffer, returns the event discarded from the buffer if there is no space remaining after the append - LoggingEvent discardedLoggingEvent = m_cb.Append(loggingEvent); - - if (discardedLoggingEvent != null) - { - // Buffer is full and has had to discard an event - if (!m_lossy) - { - // Not lossy, must send all events - SendFromBuffer(discardedLoggingEvent, m_cb); - } - else - { - // Check if the discarded event should not be logged - if (m_lossyEvaluator == null || !m_lossyEvaluator.IsTriggeringEvent(discardedLoggingEvent)) - { - // Clear the discarded event as we should not forward it - discardedLoggingEvent = null; - } - - // Check if the event should trigger the whole buffer to be sent - if (m_evaluator != null && m_evaluator.IsTriggeringEvent(loggingEvent)) - { - SendFromBuffer(discardedLoggingEvent, m_cb); - } - else if (discardedLoggingEvent != null) - { - // Just send the discarded event - SendBuffer(new LoggingEvent[] { discardedLoggingEvent } ); - } - } - } - else - { - // Buffer is not yet full - - // Check if the event should trigger the whole buffer to be sent - if (m_evaluator != null && m_evaluator.IsTriggeringEvent(loggingEvent)) - { - SendFromBuffer(null, m_cb); - } - } - } - } - - #endregion Override implementation of AppenderSkeleton - - #region Protected Instance Methods - - /// - /// Sends the contents of the buffer. - /// - /// The first logging event. - /// The buffer containing the events that need to be send. - /// - /// - /// The subclass must override . - /// - /// - protected virtual void SendFromBuffer(LoggingEvent firstLoggingEvent, CyclicBuffer buffer) - { - LoggingEvent[] bufferEvents = buffer.PopAll(); - - if (firstLoggingEvent == null) - { - SendBuffer(bufferEvents); - } - else if (bufferEvents.Length == 0) - { - SendBuffer(new LoggingEvent[] { firstLoggingEvent } ); - } - else - { - // Create new array with the firstLoggingEvent at the head - LoggingEvent[] events = new LoggingEvent[bufferEvents.Length + 1]; - Array.Copy(bufferEvents, 0, events, 1, bufferEvents.Length); - events[0] = firstLoggingEvent; - - SendBuffer(events); - } - } - - #endregion Protected Instance Methods - - /// - /// Sends the events. - /// - /// The events that need to be send. - /// - /// - /// The subclass must override this method to process the buffered events. - /// - /// - protected abstract void SendBuffer(LoggingEvent[] events); - - #region Private Static Fields - - /// - /// The default buffer size. - /// - /// - /// The default size of the cyclic buffer used to store events. - /// This is set to 512 by default. - /// - private const int DEFAULT_BUFFER_SIZE = 512; - - #endregion Private Static Fields - - #region Private Instance Fields - - /// - /// The size of the cyclic buffer used to hold the logging events. - /// - /// - /// Set to by default. - /// - private int m_bufferSize = DEFAULT_BUFFER_SIZE; - - /// - /// The cyclic buffer used to store the logging events. - /// - private CyclicBuffer m_cb; - - /// - /// The triggering event evaluator that causes the buffer to be sent immediately. - /// - /// - /// The object that is used to determine if an event causes the entire - /// buffer to be sent immediately. This field can be null, which - /// indicates that event triggering is not to be done. The evaluator - /// can be set using the property. If this appender - /// has the ( property) set to - /// true then an must be set. - /// - private ITriggeringEventEvaluator m_evaluator; - - /// - /// Indicates if the appender should overwrite events in the cyclic buffer - /// when it becomes full, or if the buffer should be flushed when the - /// buffer is full. - /// - /// - /// If this field is set to true then an must - /// be set. - /// - private bool m_lossy = false; - - /// - /// The triggering event evaluator filters discarded events. - /// - /// - /// The object that is used to determine if an event that is discarded should - /// really be discarded or if it should be sent to the appenders. - /// This field can be null, which indicates that all discarded events will - /// be discarded. - /// - private ITriggeringEventEvaluator m_lossyEvaluator; - - /// - /// Value indicating which fields in the event should be fixed - /// - /// - /// By default all fields are fixed - /// - private FixFlags m_fixFlags = FixFlags.All; - - /// - /// The events delivered to the subclass must be fixed. - /// - private readonly bool m_eventMustBeFixed; - - #endregion Private Instance Fields - } + /// + /// Flush the currently buffered events + /// + /// + /// + /// Flushes any events that have been buffered. + /// + /// + /// If the appender is buffering in mode then the contents + /// of the buffer will NOT be flushed to the appender. + /// + /// + public virtual void Flush() + { + Flush(false); + } + + /// + /// Flush the currently buffered events + /// + /// set to true to flush the buffer of lossy events + /// + /// + /// Flushes events that have been buffered. If is + /// false then events will only be flushed if this buffer is non-lossy mode. + /// + /// + /// If the appender is buffering in mode then the contents + /// of the buffer will only be flushed if is true. + /// In this case the contents of the buffer will be tested against the + /// and if triggering will be output. All other buffered + /// events will be discarded. + /// + /// + /// If is true then the buffer will always + /// be emptied by calling this method. + /// + /// + public virtual void Flush(bool flushLossyBuffer) + { + // This method will be called outside of the AppenderSkeleton DoAppend() method + // therefore it needs to be protected by its own lock. This will block any + // Appends while the buffer is flushed. + lock(this) + { + if (m_cb != null && m_cb.Length > 0) + { + if (m_lossy) + { + // If we are allowed to eagerly flush from the lossy buffer + if (flushLossyBuffer) + { + if (m_lossyEvaluator != null) + { + // Test the contents of the buffer against the lossy evaluator + LoggingEvent[] bufferedEvents = m_cb.PopAll(); + ArrayList filteredEvents = new ArrayList(bufferedEvents.Length); + + foreach(LoggingEvent loggingEvent in bufferedEvents) + { + if (m_lossyEvaluator.IsTriggeringEvent(loggingEvent)) + { + filteredEvents.Add(loggingEvent); + } + } + + // Send the events that meet the lossy evaluator criteria + if (filteredEvents.Count > 0) + { + SendBuffer((LoggingEvent[])filteredEvents.ToArray(typeof(LoggingEvent))); + } + } + else + { + // No lossy evaluator, all buffered events are discarded + m_cb.Clear(); + } + } + } + else + { + // Not lossy, send whole buffer + SendFromBuffer(null, m_cb); + } + } + } + } + + #endregion Public Methods + + #region Implementation of IOptionHandler + + /// + /// Initialize the appender based on the options set + /// + /// + /// + /// This is part of the delayed object + /// activation scheme. The method must + /// be called on this object after the configuration properties have + /// been set. Until is called this + /// object is in an undefined state and must not be used. + /// + /// + /// If any of the configuration properties are modified then + /// must be called again. + /// + /// + public override void ActivateOptions() + { + base.ActivateOptions(); + + // If the appender is in Lossy mode then we will + // only send the buffer when the Evaluator triggers + // therefore check we have an evaluator. + if (m_lossy && m_evaluator == null) + { + ErrorHandler.Error("Appender ["+Name+"] is Lossy but has no Evaluator. The buffer will never be sent!"); + } + + if (m_bufferSize > 1) + { + m_cb = new CyclicBuffer(m_bufferSize); + } + else + { + m_cb = null; + } + } + + #endregion Implementation of IOptionHandler + + #region Override implementation of AppenderSkeleton + + /// + /// Close this appender instance. + /// + /// + /// + /// Close this appender instance. If this appender is marked + /// as not then the remaining events in + /// the buffer must be sent when the appender is closed. + /// + /// + protected override void OnClose() + { + // Flush the buffer on close + Flush(true); + } + + /// + /// This method is called by the method. + /// + /// the event to log + /// + /// + /// Stores the in the cyclic buffer. + /// + /// + /// The buffer will be sent (i.e. passed to the + /// method) if one of the following conditions is met: + /// + /// + /// + /// The cyclic buffer is full and this appender is + /// marked as not lossy (see ) + /// + /// + /// An is set and + /// it is triggered for the + /// specified. + /// + /// + /// + /// Before the event is stored in the buffer it is fixed + /// (see ) to ensure that + /// any data referenced by the event will be valid when the buffer + /// is processed. + /// + /// + protected override void Append(LoggingEvent loggingEvent) + { + // If the buffer size is set to 1 or less then the buffer will be + // sent immediately because there is not enough space in the buffer + // to buffer up more than 1 event. Therefore as a special case + // we don't use the buffer at all. + if (m_cb == null || m_bufferSize <= 1) + { + // Only send the event if we are in non lossy mode or the event is a triggering event + if ((!m_lossy) || + (m_evaluator != null && m_evaluator.IsTriggeringEvent(loggingEvent)) || + (m_lossyEvaluator != null && m_lossyEvaluator.IsTriggeringEvent(loggingEvent))) + { + if (m_eventMustBeFixed) + { + // Derive class expects fixed events + loggingEvent.Fix = this.Fix; + } + + // Not buffering events, send immediately + SendBuffer(new LoggingEvent[] { loggingEvent } ); + } + } + else + { + // Because we are caching the LoggingEvent beyond the + // lifetime of the Append() method we must fix any + // volatile data in the event. + loggingEvent.Fix = this.Fix; + + // Add to the buffer, returns the event discarded from the buffer if there is no space remaining after the append + LoggingEvent discardedLoggingEvent = m_cb.Append(loggingEvent); + + if (discardedLoggingEvent != null) + { + // Buffer is full and has had to discard an event + if (!m_lossy) + { + // Not lossy, must send all events + SendFromBuffer(discardedLoggingEvent, m_cb); + } + else + { + // Check if the discarded event should not be logged + if (m_lossyEvaluator == null || !m_lossyEvaluator.IsTriggeringEvent(discardedLoggingEvent)) + { + // Clear the discarded event as we should not forward it + discardedLoggingEvent = null; + } + + // Check if the event should trigger the whole buffer to be sent + if (m_evaluator != null && m_evaluator.IsTriggeringEvent(loggingEvent)) + { + SendFromBuffer(discardedLoggingEvent, m_cb); + } + else if (discardedLoggingEvent != null) + { + // Just send the discarded event + SendBuffer(new LoggingEvent[] { discardedLoggingEvent } ); + } + } + } + else + { + // Buffer is not yet full + + // Check if the event should trigger the whole buffer to be sent + if (m_evaluator != null && m_evaluator.IsTriggeringEvent(loggingEvent)) + { + SendFromBuffer(null, m_cb); + } + } + } + } + + #endregion Override implementation of AppenderSkeleton + + #region Protected Instance Methods + + /// + /// Sends the contents of the buffer. + /// + /// The first logging event. + /// The buffer containing the events that need to be send. + /// + /// + /// The subclass must override . + /// + /// + protected virtual void SendFromBuffer(LoggingEvent firstLoggingEvent, CyclicBuffer buffer) + { + LoggingEvent[] bufferEvents = buffer.PopAll(); + + if (firstLoggingEvent == null) + { + SendBuffer(bufferEvents); + } + else if (bufferEvents.Length == 0) + { + SendBuffer(new LoggingEvent[] { firstLoggingEvent } ); + } + else + { + // Create new array with the firstLoggingEvent at the head + LoggingEvent[] events = new LoggingEvent[bufferEvents.Length + 1]; + Array.Copy(bufferEvents, 0, events, 1, bufferEvents.Length); + events[0] = firstLoggingEvent; + + SendBuffer(events); + } + } + + #endregion Protected Instance Methods + + /// + /// Sends the events. + /// + /// The events that need to be send. + /// + /// + /// The subclass must override this method to process the buffered events. + /// + /// + protected abstract void SendBuffer(LoggingEvent[] events); + + #region Private Static Fields + + /// + /// The default buffer size. + /// + /// + /// The default size of the cyclic buffer used to store events. + /// This is set to 512 by default. + /// + private const int DEFAULT_BUFFER_SIZE = 512; + + #endregion Private Static Fields + + #region Private Instance Fields + + /// + /// The size of the cyclic buffer used to hold the logging events. + /// + /// + /// Set to by default. + /// + private int m_bufferSize = DEFAULT_BUFFER_SIZE; + + /// + /// The cyclic buffer used to store the logging events. + /// + private CyclicBuffer m_cb; + + /// + /// The triggering event evaluator that causes the buffer to be sent immediately. + /// + /// + /// The object that is used to determine if an event causes the entire + /// buffer to be sent immediately. This field can be null, which + /// indicates that event triggering is not to be done. The evaluator + /// can be set using the property. If this appender + /// has the ( property) set to + /// true then an must be set. + /// + private ITriggeringEventEvaluator m_evaluator; + + /// + /// Indicates if the appender should overwrite events in the cyclic buffer + /// when it becomes full, or if the buffer should be flushed when the + /// buffer is full. + /// + /// + /// If this field is set to true then an must + /// be set. + /// + private bool m_lossy = false; + + /// + /// The triggering event evaluator filters discarded events. + /// + /// + /// The object that is used to determine if an event that is discarded should + /// really be discarded or if it should be sent to the appenders. + /// This field can be null, which indicates that all discarded events will + /// be discarded. + /// + private ITriggeringEventEvaluator m_lossyEvaluator; + + /// + /// Value indicating which fields in the event should be fixed + /// + /// + /// By default all fields are fixed + /// + private FixFlags m_fixFlags = FixFlags.All; + + /// + /// The events delivered to the subclass must be fixed. + /// + private readonly bool m_eventMustBeFixed; + + #endregion Private Instance Fields + } } diff --git a/src/log4net/Appender/BufferingForwardingAppender.cs b/src/log4net/Appender/BufferingForwardingAppender.cs index 20c36241..c228b223 100644 --- a/src/log4net/Appender/BufferingForwardingAppender.cs +++ b/src/log4net/Appender/BufferingForwardingAppender.cs @@ -25,250 +25,250 @@ namespace log4net.Appender { - /// - /// Buffers events and then forwards them to attached appenders. - /// - /// - /// - /// The events are buffered in this appender until conditions are - /// met to allow the appender to deliver the events to the attached - /// appenders. See for the - /// conditions that cause the buffer to be sent. - /// - /// The forwarding appender can be used to specify different - /// thresholds and filters for the same appender at different locations - /// within the hierarchy. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public class BufferingForwardingAppender : BufferingAppenderSkeleton, IAppenderAttachable - { - #region Public Instance Constructors + /// + /// Buffers events and then forwards them to attached appenders. + /// + /// + /// + /// The events are buffered in this appender until conditions are + /// met to allow the appender to deliver the events to the attached + /// appenders. See for the + /// conditions that cause the buffer to be sent. + /// + /// The forwarding appender can be used to specify different + /// thresholds and filters for the same appender at different locations + /// within the hierarchy. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public class BufferingForwardingAppender : BufferingAppenderSkeleton, IAppenderAttachable + { + #region Public Instance Constructors - /// - /// Initializes a new instance of the class. - /// - /// - /// - /// Default constructor. - /// - /// - public BufferingForwardingAppender() - { - } + /// + /// Initializes a new instance of the class. + /// + /// + /// + /// Default constructor. + /// + /// + public BufferingForwardingAppender() + { + } - #endregion Public Instance Constructors + #endregion Public Instance Constructors - #region Override implementation of AppenderSkeleton + #region Override implementation of AppenderSkeleton - /// - /// Closes the appender and releases resources. - /// - /// - /// - /// Releases any resources allocated within the appender such as file handles, - /// network connections, etc. - /// - /// - /// It is a programming error to append to a closed appender. - /// - /// - protected override void OnClose() - { - // Remove all the attached appenders - lock(this) - { - // Delegate to base, which will flush buffers - base.OnClose(); + /// + /// Closes the appender and releases resources. + /// + /// + /// + /// Releases any resources allocated within the appender such as file handles, + /// network connections, etc. + /// + /// + /// It is a programming error to append to a closed appender. + /// + /// + protected override void OnClose() + { + // Remove all the attached appenders + lock(this) + { + // Delegate to base, which will flush buffers + base.OnClose(); - if (m_appenderAttachedImpl != null) - { - m_appenderAttachedImpl.RemoveAllAppenders(); - } - } - } + if (m_appenderAttachedImpl != null) + { + m_appenderAttachedImpl.RemoveAllAppenders(); + } + } + } - #endregion Override implementation of AppenderSkeleton + #endregion Override implementation of AppenderSkeleton - #region Override implementation of BufferingAppenderSkeleton + #region Override implementation of BufferingAppenderSkeleton - /// - /// Send the events. - /// - /// The events that need to be send. - /// - /// - /// Forwards the events to the attached appenders. - /// - /// - protected override void SendBuffer(LoggingEvent[] events) - { - // Pass the logging event on to the attached appenders - if (m_appenderAttachedImpl != null) - { - m_appenderAttachedImpl.AppendLoopOnAppenders(events); - } - } + /// + /// Send the events. + /// + /// The events that need to be send. + /// + /// + /// Forwards the events to the attached appenders. + /// + /// + protected override void SendBuffer(LoggingEvent[] events) + { + // Pass the logging event on to the attached appenders + if (m_appenderAttachedImpl != null) + { + m_appenderAttachedImpl.AppendLoopOnAppenders(events); + } + } - #endregion Override implementation of BufferingAppenderSkeleton + #endregion Override implementation of BufferingAppenderSkeleton - #region Implementation of IAppenderAttachable + #region Implementation of IAppenderAttachable - /// - /// Adds an to the list of appenders of this - /// instance. - /// - /// The to add to this appender. - /// - /// - /// If the specified is already in the list of - /// appenders, then it won't be added again. - /// - /// - public virtual void AddAppender(IAppender newAppender) - { - if (newAppender == null) - { - throw new ArgumentNullException("newAppender"); - } - lock(this) - { - if (m_appenderAttachedImpl == null) - { - m_appenderAttachedImpl = new log4net.Util.AppenderAttachedImpl(); - } - m_appenderAttachedImpl.AddAppender(newAppender); - } - } + /// + /// Adds an to the list of appenders of this + /// instance. + /// + /// The to add to this appender. + /// + /// + /// If the specified is already in the list of + /// appenders, then it won't be added again. + /// + /// + public virtual void AddAppender(IAppender newAppender) + { + if (newAppender == null) + { + throw new ArgumentNullException("newAppender"); + } + lock(this) + { + if (m_appenderAttachedImpl == null) + { + m_appenderAttachedImpl = new log4net.Util.AppenderAttachedImpl(); + } + m_appenderAttachedImpl.AddAppender(newAppender); + } + } - /// - /// Gets the appenders contained in this appender as an - /// . - /// - /// - /// If no appenders can be found, then an - /// is returned. - /// - /// - /// A collection of the appenders in this appender. - /// - public virtual AppenderCollection Appenders - { - get - { - lock(this) - { - if (m_appenderAttachedImpl == null) - { - return AppenderCollection.EmptyCollection; - } - else - { - return m_appenderAttachedImpl.Appenders; - } - } - } - } + /// + /// Gets the appenders contained in this appender as an + /// . + /// + /// + /// If no appenders can be found, then an + /// is returned. + /// + /// + /// A collection of the appenders in this appender. + /// + public virtual AppenderCollection Appenders + { + get + { + lock(this) + { + if (m_appenderAttachedImpl == null) + { + return AppenderCollection.EmptyCollection; + } + else + { + return m_appenderAttachedImpl.Appenders; + } + } + } + } - /// - /// Looks for the appender with the specified name. - /// - /// The name of the appender to lookup. - /// - /// The appender with the specified name, or null. - /// - /// - /// - /// Get the named appender attached to this buffering appender. - /// - /// - public virtual IAppender GetAppender(string name) - { - lock(this) - { - if (m_appenderAttachedImpl == null || name == null) - { - return null; - } + /// + /// Looks for the appender with the specified name. + /// + /// The name of the appender to lookup. + /// + /// The appender with the specified name, or null. + /// + /// + /// + /// Get the named appender attached to this buffering appender. + /// + /// + public virtual IAppender GetAppender(string name) + { + lock(this) + { + if (m_appenderAttachedImpl == null || name == null) + { + return null; + } - return m_appenderAttachedImpl.GetAppender(name); - } - } + return m_appenderAttachedImpl.GetAppender(name); + } + } - /// - /// Removes all previously added appenders from this appender. - /// - /// - /// - /// This is useful when re-reading configuration information. - /// - /// - public virtual void RemoveAllAppenders() - { - lock(this) - { - if (m_appenderAttachedImpl != null) - { - m_appenderAttachedImpl.RemoveAllAppenders(); - m_appenderAttachedImpl = null; - } - } - } + /// + /// Removes all previously added appenders from this appender. + /// + /// + /// + /// This is useful when re-reading configuration information. + /// + /// + public virtual void RemoveAllAppenders() + { + lock(this) + { + if (m_appenderAttachedImpl != null) + { + m_appenderAttachedImpl.RemoveAllAppenders(); + m_appenderAttachedImpl = null; + } + } + } - /// - /// Removes the specified appender from the list of appenders. - /// - /// The appender to remove. - /// The appender removed from the list - /// - /// The appender removed is not closed. - /// If you are discarding the appender you must call - /// on the appender removed. - /// - public virtual IAppender RemoveAppender(IAppender appender) - { - lock(this) - { - if (appender != null && m_appenderAttachedImpl != null) - { - return m_appenderAttachedImpl.RemoveAppender(appender); - } - } - return null; - } + /// + /// Removes the specified appender from the list of appenders. + /// + /// The appender to remove. + /// The appender removed from the list + /// + /// The appender removed is not closed. + /// If you are discarding the appender you must call + /// on the appender removed. + /// + public virtual IAppender RemoveAppender(IAppender appender) + { + lock(this) + { + if (appender != null && m_appenderAttachedImpl != null) + { + return m_appenderAttachedImpl.RemoveAppender(appender); + } + } + return null; + } - /// - /// Removes the appender with the specified name from the list of appenders. - /// - /// The name of the appender to remove. - /// The appender removed from the list - /// - /// The appender removed is not closed. - /// If you are discarding the appender you must call - /// on the appender removed. - /// - public virtual IAppender RemoveAppender(string name) - { - lock(this) - { - if (name != null && m_appenderAttachedImpl != null) - { - return m_appenderAttachedImpl.RemoveAppender(name); - } - } - return null; - } + /// + /// Removes the appender with the specified name from the list of appenders. + /// + /// The name of the appender to remove. + /// The appender removed from the list + /// + /// The appender removed is not closed. + /// If you are discarding the appender you must call + /// on the appender removed. + /// + public virtual IAppender RemoveAppender(string name) + { + lock(this) + { + if (name != null && m_appenderAttachedImpl != null) + { + return m_appenderAttachedImpl.RemoveAppender(name); + } + } + return null; + } - #endregion Implementation of IAppenderAttachable + #endregion Implementation of IAppenderAttachable - #region Private Instance Fields + #region Private Instance Fields - /// - /// Implementation of the interface - /// - private AppenderAttachedImpl m_appenderAttachedImpl; + /// + /// Implementation of the interface + /// + private AppenderAttachedImpl m_appenderAttachedImpl; - #endregion Private Instance Fields - } + #endregion Private Instance Fields + } } diff --git a/src/log4net/Appender/ColoredConsoleAppender.cs b/src/log4net/Appender/ColoredConsoleAppender.cs index cbcc8757..c90cf5fb 100644 --- a/src/log4net/Appender/ColoredConsoleAppender.cs +++ b/src/log4net/Appender/ColoredConsoleAppender.cs @@ -38,627 +38,627 @@ namespace log4net.Appender { - /// - /// Appends logging events to the console. - /// - /// - /// - /// ColoredConsoleAppender appends log events to the standard output stream - /// or the error output stream using a layout specified by the - /// user. It also allows the color of a specific type of message to be set. - /// - /// - /// By default, all output is written to the console's standard output stream. - /// The property can be set to direct the output to the - /// error stream. - /// - /// - /// NOTE: This appender writes directly to the application's attached console - /// not to the System.Console.Out or System.Console.Error TextWriter. - /// The System.Console.Out and System.Console.Error streams can be - /// programmatically redirected (for example NUnit does this to capture program output). - /// This appender will ignore these redirections because it needs to use Win32 - /// API calls to colorize the output. To respect these redirections the - /// must be used. - /// - /// - /// When configuring the colored console appender, mapping should be - /// specified to map a logging level to a color. For example: - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// The Level is the standard log4net logging level and ForeColor and BackColor can be any - /// combination of the following values: - /// - /// Blue - /// Green - /// Red - /// White - /// Yellow - /// Purple - /// Cyan - /// HighIntensity - /// - /// - /// - /// Rick Hobbs - /// Nicko Cadell - public class ColoredConsoleAppender : AppenderSkeleton - { - #region Colors Enum - - /// - /// The enum of possible color values for use with the color mapping method - /// - /// - /// - /// The following flags can be combined together to - /// form the colors. - /// - /// - /// - [Flags] - public enum Colors : int - { - /// - /// color is blue - /// - Blue = 0x0001, - - /// - /// color is green - /// - Green = 0x0002, - - /// - /// color is red - /// - Red = 0x0004, - - /// - /// color is white - /// - White = Blue | Green | Red, - - /// - /// color is yellow - /// - Yellow = Red | Green, - - /// - /// color is purple - /// - Purple = Red | Blue, - - /// - /// color is cyan - /// - Cyan = Green | Blue, - - /// - /// color is intensified - /// - HighIntensity = 0x0008, - } - - #endregion // Colors Enum - - #region Public Instance Constructors - - /// - /// Initializes a new instance of the class. - /// - /// - /// The instance of the class is set up to write - /// to the standard output stream. - /// - public ColoredConsoleAppender() - { - } - - /// - /// Initializes a new instance of the class - /// with the specified layout. - /// - /// the layout to use for this appender - /// - /// The instance of the class is set up to write - /// to the standard output stream. - /// - [Obsolete("Instead use the default constructor and set the Layout property")] - public ColoredConsoleAppender(ILayout layout) : this(layout, false) - { - } - - /// - /// Initializes a new instance of the class - /// with the specified layout. - /// - /// the layout to use for this appender - /// flag set to true to write to the console error stream - /// - /// When is set to true, output is written to - /// the standard error output stream. Otherwise, output is written to the standard - /// output stream. - /// - [Obsolete("Instead use the default constructor and set the Layout & Target properties")] - public ColoredConsoleAppender(ILayout layout, bool writeToErrorStream) - { - Layout = layout; - m_writeToErrorStream = writeToErrorStream; - } - - #endregion // Public Instance Constructors - - #region Public Instance Properties - - /// - /// Target is the value of the console output stream. - /// This is either "Console.Out" or "Console.Error". - /// - /// - /// Target is the value of the console output stream. - /// This is either "Console.Out" or "Console.Error". - /// - /// - /// - /// Target is the value of the console output stream. - /// This is either "Console.Out" or "Console.Error". - /// - /// - public virtual string Target - { - get { return m_writeToErrorStream ? ConsoleError : ConsoleOut; } - set - { - string v = value.Trim(); - - if (string.Compare(ConsoleError, v, true, CultureInfo.InvariantCulture) == 0) - { - m_writeToErrorStream = true; - } - else - { - m_writeToErrorStream = false; - } - } - } - - /// - /// Add a mapping of level to color - done by the config file - /// - /// The mapping to add - /// - /// - /// Add a mapping to this appender. - /// Each mapping defines the foreground and background colors - /// for a level. - /// - /// - public void AddMapping(LevelColors mapping) - { - m_levelMapping.Add(mapping); - } - - #endregion // Public Instance Properties - - #region Override implementation of AppenderSkeleton - - /// - /// This method is called by the method. - /// - /// The event to log. - /// - /// - /// Writes the event to the console. - /// - /// - /// The format of the output will depend on the appender's layout. - /// - /// + /// + /// Appends logging events to the console. + /// + /// + /// + /// ColoredConsoleAppender appends log events to the standard output stream + /// or the error output stream using a layout specified by the + /// user. It also allows the color of a specific type of message to be set. + /// + /// + /// By default, all output is written to the console's standard output stream. + /// The property can be set to direct the output to the + /// error stream. + /// + /// + /// NOTE: This appender writes directly to the application's attached console + /// not to the System.Console.Out or System.Console.Error TextWriter. + /// The System.Console.Out and System.Console.Error streams can be + /// programmatically redirected (for example NUnit does this to capture program output). + /// This appender will ignore these redirections because it needs to use Win32 + /// API calls to colorize the output. To respect these redirections the + /// must be used. + /// + /// + /// When configuring the colored console appender, mapping should be + /// specified to map a logging level to a color. For example: + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// The Level is the standard log4net logging level and ForeColor and BackColor can be any + /// combination of the following values: + /// + /// Blue + /// Green + /// Red + /// White + /// Yellow + /// Purple + /// Cyan + /// HighIntensity + /// + /// + /// + /// Rick Hobbs + /// Nicko Cadell + public class ColoredConsoleAppender : AppenderSkeleton + { + #region Colors Enum + + /// + /// The enum of possible color values for use with the color mapping method + /// + /// + /// + /// The following flags can be combined together to + /// form the colors. + /// + /// + /// + [Flags] + public enum Colors : int + { + /// + /// color is blue + /// + Blue = 0x0001, + + /// + /// color is green + /// + Green = 0x0002, + + /// + /// color is red + /// + Red = 0x0004, + + /// + /// color is white + /// + White = Blue | Green | Red, + + /// + /// color is yellow + /// + Yellow = Red | Green, + + /// + /// color is purple + /// + Purple = Red | Blue, + + /// + /// color is cyan + /// + Cyan = Green | Blue, + + /// + /// color is intensified + /// + HighIntensity = 0x0008, + } + + #endregion // Colors Enum + + #region Public Instance Constructors + + /// + /// Initializes a new instance of the class. + /// + /// + /// The instance of the class is set up to write + /// to the standard output stream. + /// + public ColoredConsoleAppender() + { + } + + /// + /// Initializes a new instance of the class + /// with the specified layout. + /// + /// the layout to use for this appender + /// + /// The instance of the class is set up to write + /// to the standard output stream. + /// + [Obsolete("Instead use the default constructor and set the Layout property")] + public ColoredConsoleAppender(ILayout layout) : this(layout, false) + { + } + + /// + /// Initializes a new instance of the class + /// with the specified layout. + /// + /// the layout to use for this appender + /// flag set to true to write to the console error stream + /// + /// When is set to true, output is written to + /// the standard error output stream. Otherwise, output is written to the standard + /// output stream. + /// + [Obsolete("Instead use the default constructor and set the Layout & Target properties")] + public ColoredConsoleAppender(ILayout layout, bool writeToErrorStream) + { + Layout = layout; + m_writeToErrorStream = writeToErrorStream; + } + + #endregion // Public Instance Constructors + + #region Public Instance Properties + + /// + /// Target is the value of the console output stream. + /// This is either "Console.Out" or "Console.Error". + /// + /// + /// Target is the value of the console output stream. + /// This is either "Console.Out" or "Console.Error". + /// + /// + /// + /// Target is the value of the console output stream. + /// This is either "Console.Out" or "Console.Error". + /// + /// + public virtual string Target + { + get { return m_writeToErrorStream ? ConsoleError : ConsoleOut; } + set + { + string v = value.Trim(); + + if (string.Compare(ConsoleError, v, true, CultureInfo.InvariantCulture) == 0) + { + m_writeToErrorStream = true; + } + else + { + m_writeToErrorStream = false; + } + } + } + + /// + /// Add a mapping of level to color - done by the config file + /// + /// The mapping to add + /// + /// + /// Add a mapping to this appender. + /// Each mapping defines the foreground and background colors + /// for a level. + /// + /// + public void AddMapping(LevelColors mapping) + { + m_levelMapping.Add(mapping); + } + + #endregion // Public Instance Properties + + #region Override implementation of AppenderSkeleton + + /// + /// This method is called by the method. + /// + /// The event to log. + /// + /// + /// Writes the event to the console. + /// + /// + /// The format of the output will depend on the appender's layout. + /// + /// #if NET_4_0 || MONO_4_0 || NETSTANDARD - [System.Security.SecuritySafeCritical] + [System.Security.SecuritySafeCritical] #endif - [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, UnmanagedCode = true)] - protected override void Append(log4net.Core.LoggingEvent loggingEvent) - { - if (m_consoleOutputWriter != null) - { - IntPtr consoleHandle = IntPtr.Zero; - if (m_writeToErrorStream) - { - // Write to the error stream - consoleHandle = GetStdHandle(STD_ERROR_HANDLE); - } - else - { - // Write to the output stream - consoleHandle = GetStdHandle(STD_OUTPUT_HANDLE); - } - - // Default to white on black - ushort colorInfo = (ushort)Colors.White; - - // see if there is a specified lookup - LevelColors levelColors = m_levelMapping.Lookup(loggingEvent.Level) as LevelColors; - if (levelColors != null) - { - colorInfo = levelColors.CombinedColor; - } - - // Render the event to a string - string strLoggingMessage = RenderLoggingEvent(loggingEvent); - - // get the current console color - to restore later - CONSOLE_SCREEN_BUFFER_INFO bufferInfo; - GetConsoleScreenBufferInfo(consoleHandle, out bufferInfo); - - // set the console colors - SetConsoleTextAttribute(consoleHandle, colorInfo); - - // Using WriteConsoleW seems to be unreliable. - // If a large buffer is written, say 15,000 chars - // Followed by a larger buffer, say 20,000 chars - // then WriteConsoleW will fail, last error 8 - // 'Not enough storage is available to process this command.' - // - // Although the documentation states that the buffer must - // be less that 64KB (i.e. 32,000 WCHARs) the longest string - // that I can write out a the first call to WriteConsoleW - // is only 30,704 chars. - // - // Unlike the WriteFile API the WriteConsoleW method does not - // seem to be able to partially write out from the input buffer. - // It does have a lpNumberOfCharsWritten parameter, but this is - // either the length of the input buffer if any output was written, - // or 0 when an error occurs. - // - // All results above were observed on Windows XP SP1 running - // .NET runtime 1.1 SP1. - // - // Old call to WriteConsoleW: - // - // WriteConsoleW( - // consoleHandle, - // strLoggingMessage, - // (UInt32)strLoggingMessage.Length, - // out (UInt32)ignoreWrittenCount, - // IntPtr.Zero); - // - // Instead of calling WriteConsoleW we use WriteFile which - // handles large buffers correctly. Because WriteFile does not - // handle the codepage conversion as WriteConsoleW does we - // need to use a System.IO.StreamWriter with the appropriate - // Encoding. The WriteFile calls are wrapped up in the - // System.IO.__ConsoleStream internal class obtained through - // the System.Console.OpenStandardOutput method. - // - // See the ActivateOptions method below for the code that - // retrieves and wraps the stream. - - - // The windows console uses ScrollConsoleScreenBuffer internally to - // scroll the console buffer when the display buffer of the console - // has been used up. ScrollConsoleScreenBuffer fills the area uncovered - // by moving the current content with the background color - // currently specified on the console. This means that it fills the - // whole line in front of the cursor position with the current - // background color. - // This causes an issue when writing out text with a non default - // background color. For example; We write a message with a Blue - // background color and the scrollable area of the console is full. - // When we write the newline at the end of the message the console - // needs to scroll the buffer to make space available for the new line. - // The ScrollConsoleScreenBuffer internals will fill the newly created - // space with the current background color: Blue. - // We then change the console color back to default (White text on a - // Black background). We write some text to the console, the text is - // written correctly in White with a Black background, however the - // remainder of the line still has a Blue background. - // - // This causes a disjointed appearance to the output where the background - // colors change. - // - // This can be remedied by restoring the console colors before causing - // the buffer to scroll, i.e. before writing the last newline. This does - // assume that the rendered message will end with a newline. - // - // Therefore we identify a trailing newline in the message and don't - // write this to the output, then we restore the console color and write - // a newline. Note that we must AutoFlush before we restore the console - // color otherwise we will have no effect. - // - // There will still be a slight artefact for the last line of the message - // will have the background extended to the end of the line, however this - // is unlikely to cause any user issues. - // - // Note that none of the above is visible while the console buffer is scrollable - // within the console window viewport, the effects only arise when the actual - // buffer is full and needs to be scrolled. - - char[] messageCharArray = strLoggingMessage.ToCharArray(); - int arrayLength = messageCharArray.Length; - bool appendNewline = false; - - // Trim off last newline, if it exists - if (arrayLength > 1 && messageCharArray[arrayLength-2] == '\r' && messageCharArray[arrayLength-1] == '\n') - { - arrayLength -= 2; - appendNewline = true; - } - - // Write to the output stream - m_consoleOutputWriter.Write(messageCharArray, 0, arrayLength); - - // Restore the console back to its previous color scheme - SetConsoleTextAttribute(consoleHandle, bufferInfo.wAttributes); - - if (appendNewline) - { - // Write the newline, after changing the color scheme - m_consoleOutputWriter.Write(s_windowsNewline, 0, 2); - } - } - } - - private static readonly char[] s_windowsNewline = {'\r', '\n'}; - - /// - /// This appender requires a to be set. - /// - /// true - /// - /// - /// This appender requires a to be set. - /// - /// - protected override bool RequiresLayout - { - get { return true; } - } - - /// - /// Initialize the options for this appender - /// - /// - /// - /// Initialize the level to color mappings set on this appender. - /// - /// + [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, UnmanagedCode = true)] + protected override void Append(log4net.Core.LoggingEvent loggingEvent) + { + if (m_consoleOutputWriter != null) + { + IntPtr consoleHandle = IntPtr.Zero; + if (m_writeToErrorStream) + { + // Write to the error stream + consoleHandle = GetStdHandle(STD_ERROR_HANDLE); + } + else + { + // Write to the output stream + consoleHandle = GetStdHandle(STD_OUTPUT_HANDLE); + } + + // Default to white on black + ushort colorInfo = (ushort)Colors.White; + + // see if there is a specified lookup + LevelColors levelColors = m_levelMapping.Lookup(loggingEvent.Level) as LevelColors; + if (levelColors != null) + { + colorInfo = levelColors.CombinedColor; + } + + // Render the event to a string + string strLoggingMessage = RenderLoggingEvent(loggingEvent); + + // get the current console color - to restore later + CONSOLE_SCREEN_BUFFER_INFO bufferInfo; + GetConsoleScreenBufferInfo(consoleHandle, out bufferInfo); + + // set the console colors + SetConsoleTextAttribute(consoleHandle, colorInfo); + + // Using WriteConsoleW seems to be unreliable. + // If a large buffer is written, say 15,000 chars + // Followed by a larger buffer, say 20,000 chars + // then WriteConsoleW will fail, last error 8 + // 'Not enough storage is available to process this command.' + // + // Although the documentation states that the buffer must + // be less that 64KB (i.e. 32,000 WCHARs) the longest string + // that I can write out a the first call to WriteConsoleW + // is only 30,704 chars. + // + // Unlike the WriteFile API the WriteConsoleW method does not + // seem to be able to partially write out from the input buffer. + // It does have a lpNumberOfCharsWritten parameter, but this is + // either the length of the input buffer if any output was written, + // or 0 when an error occurs. + // + // All results above were observed on Windows XP SP1 running + // .NET runtime 1.1 SP1. + // + // Old call to WriteConsoleW: + // + // WriteConsoleW( + // consoleHandle, + // strLoggingMessage, + // (UInt32)strLoggingMessage.Length, + // out (UInt32)ignoreWrittenCount, + // IntPtr.Zero); + // + // Instead of calling WriteConsoleW we use WriteFile which + // handles large buffers correctly. Because WriteFile does not + // handle the codepage conversion as WriteConsoleW does we + // need to use a System.IO.StreamWriter with the appropriate + // Encoding. The WriteFile calls are wrapped up in the + // System.IO.__ConsoleStream internal class obtained through + // the System.Console.OpenStandardOutput method. + // + // See the ActivateOptions method below for the code that + // retrieves and wraps the stream. + + + // The windows console uses ScrollConsoleScreenBuffer internally to + // scroll the console buffer when the display buffer of the console + // has been used up. ScrollConsoleScreenBuffer fills the area uncovered + // by moving the current content with the background color + // currently specified on the console. This means that it fills the + // whole line in front of the cursor position with the current + // background color. + // This causes an issue when writing out text with a non default + // background color. For example; We write a message with a Blue + // background color and the scrollable area of the console is full. + // When we write the newline at the end of the message the console + // needs to scroll the buffer to make space available for the new line. + // The ScrollConsoleScreenBuffer internals will fill the newly created + // space with the current background color: Blue. + // We then change the console color back to default (White text on a + // Black background). We write some text to the console, the text is + // written correctly in White with a Black background, however the + // remainder of the line still has a Blue background. + // + // This causes a disjointed appearance to the output where the background + // colors change. + // + // This can be remedied by restoring the console colors before causing + // the buffer to scroll, i.e. before writing the last newline. This does + // assume that the rendered message will end with a newline. + // + // Therefore we identify a trailing newline in the message and don't + // write this to the output, then we restore the console color and write + // a newline. Note that we must AutoFlush before we restore the console + // color otherwise we will have no effect. + // + // There will still be a slight artefact for the last line of the message + // will have the background extended to the end of the line, however this + // is unlikely to cause any user issues. + // + // Note that none of the above is visible while the console buffer is scrollable + // within the console window viewport, the effects only arise when the actual + // buffer is full and needs to be scrolled. + + char[] messageCharArray = strLoggingMessage.ToCharArray(); + int arrayLength = messageCharArray.Length; + bool appendNewline = false; + + // Trim off last newline, if it exists + if (arrayLength > 1 && messageCharArray[arrayLength-2] == '\r' && messageCharArray[arrayLength-1] == '\n') + { + arrayLength -= 2; + appendNewline = true; + } + + // Write to the output stream + m_consoleOutputWriter.Write(messageCharArray, 0, arrayLength); + + // Restore the console back to its previous color scheme + SetConsoleTextAttribute(consoleHandle, bufferInfo.wAttributes); + + if (appendNewline) + { + // Write the newline, after changing the color scheme + m_consoleOutputWriter.Write(s_windowsNewline, 0, 2); + } + } + } + + private static readonly char[] s_windowsNewline = {'\r', '\n'}; + + /// + /// This appender requires a to be set. + /// + /// true + /// + /// + /// This appender requires a to be set. + /// + /// + protected override bool RequiresLayout + { + get { return true; } + } + + /// + /// Initialize the options for this appender + /// + /// + /// + /// Initialize the level to color mappings set on this appender. + /// + /// #if NET_4_0 || MONO_4_0 || NETSTANDARD - [System.Security.SecuritySafeCritical] + [System.Security.SecuritySafeCritical] #endif - [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, UnmanagedCode = true)] - public override void ActivateOptions() - { - base.ActivateOptions(); - m_levelMapping.ActivateOptions(); - - System.IO.Stream consoleOutputStream = null; - - // Use the Console methods to open a Stream over the console std handle - if (m_writeToErrorStream) - { - // Write to the error stream - consoleOutputStream = Console.OpenStandardError(); - } - else - { - // Write to the output stream - consoleOutputStream = Console.OpenStandardOutput(); - } - - // Lookup the codepage encoding for the console - System.Text.Encoding consoleEncoding = System.Text.Encoding.GetEncoding(GetConsoleOutputCP()); - - // Create a writer around the console stream - m_consoleOutputWriter = new System.IO.StreamWriter(consoleOutputStream, consoleEncoding, 0x100); - - m_consoleOutputWriter.AutoFlush = true; - - // SuppressFinalize on m_consoleOutputWriter because all it will do is flush - // and close the file handle. Because we have set AutoFlush the additional flush - // is not required. The console file handle should not be closed, so we don't call - // Dispose, Close or the finalizer. - GC.SuppressFinalize(m_consoleOutputWriter); - } - - #endregion // Override implementation of AppenderSkeleton - - #region Public Static Fields - - /// - /// The to use when writing to the Console - /// standard output stream. - /// - /// - /// - /// The to use when writing to the Console - /// standard output stream. - /// - /// - public const string ConsoleOut = "Console.Out"; - - /// - /// The to use when writing to the Console - /// standard error output stream. - /// - /// - /// - /// The to use when writing to the Console - /// standard error output stream. - /// - /// - public const string ConsoleError = "Console.Error"; - - #endregion // Public Static Fields - - #region Private Instances Fields - - /// - /// Flag to write output to the error stream rather than the standard output stream - /// - private bool m_writeToErrorStream = false; - - /// - /// Mapping from level object to color value - /// - private LevelMapping m_levelMapping = new LevelMapping(); - - /// - /// The console output stream writer to write to - /// - /// - /// - /// This writer is not thread safe. - /// - /// - private System.IO.StreamWriter m_consoleOutputWriter = null; - - #endregion // Private Instances Fields - - #region Win32 Methods - - [DllImport("Kernel32.dll", SetLastError=true, CharSet=CharSet.Auto)] - private static extern int GetConsoleOutputCP(); - - [DllImport("Kernel32.dll", SetLastError=true, CharSet=CharSet.Auto)] - private static extern bool SetConsoleTextAttribute( - IntPtr consoleHandle, - ushort attributes); - - [DllImport("Kernel32.dll", SetLastError=true, CharSet=CharSet.Auto)] - private static extern bool GetConsoleScreenBufferInfo( - IntPtr consoleHandle, - out CONSOLE_SCREEN_BUFFER_INFO bufferInfo); - -// [DllImport("Kernel32.dll", SetLastError=true, CharSet=CharSet.Unicode)] -// private static extern bool WriteConsoleW( -// IntPtr hConsoleHandle, -// [MarshalAs(UnmanagedType.LPWStr)] string strBuffer, -// UInt32 bufferLen, -// out UInt32 written, -// IntPtr reserved); - - //private const UInt32 STD_INPUT_HANDLE = unchecked((UInt32)(-10)); - private const UInt32 STD_OUTPUT_HANDLE = unchecked((UInt32)(-11)); - private const UInt32 STD_ERROR_HANDLE = unchecked((UInt32)(-12)); - - [DllImport("Kernel32.dll", SetLastError=true, CharSet=CharSet.Auto)] - private static extern IntPtr GetStdHandle( - UInt32 type); - - [StructLayout(LayoutKind.Sequential)] - private struct COORD - { - public UInt16 x; - public UInt16 y; - } - - [StructLayout(LayoutKind.Sequential)] - private struct SMALL_RECT - { - public UInt16 Left; - public UInt16 Top; - public UInt16 Right; - public UInt16 Bottom; - } - - [StructLayout(LayoutKind.Sequential)] - private struct CONSOLE_SCREEN_BUFFER_INFO - { - public COORD dwSize; - public COORD dwCursorPosition; - public ushort wAttributes; - public SMALL_RECT srWindow; - public COORD dwMaximumWindowSize; - } - - #endregion // Win32 Methods - - #region LevelColors LevelMapping Entry - - /// - /// A class to act as a mapping between the level that a logging call is made at and - /// the color it should be displayed as. - /// - /// - /// - /// Defines the mapping between a level and the color it should be displayed in. - /// - /// - public class LevelColors : LevelMappingEntry - { - private Colors m_foreColor; - private Colors m_backColor; - private ushort m_combinedColor = 0; - - /// - /// The mapped foreground color for the specified level - /// - /// - /// - /// Required property. - /// The mapped foreground color for the specified level. - /// - /// - public Colors ForeColor - { - get { return m_foreColor; } - set { m_foreColor = value; } - } - - /// - /// The mapped background color for the specified level - /// - /// - /// - /// Required property. - /// The mapped background color for the specified level. - /// - /// - public Colors BackColor - { - get { return m_backColor; } - set { m_backColor = value; } - } - - /// - /// Initialize the options for the object - /// - /// - /// - /// Combine the and together. - /// - /// - public override void ActivateOptions() - { - base.ActivateOptions(); - m_combinedColor = (ushort)( (int)m_foreColor + (((int)m_backColor) << 4) ); - } - - /// - /// The combined and suitable for - /// setting the console color. - /// - internal ushort CombinedColor - { - get { return m_combinedColor; } - } - } - - #endregion // LevelColors LevelMapping Entry - } + [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, UnmanagedCode = true)] + public override void ActivateOptions() + { + base.ActivateOptions(); + m_levelMapping.ActivateOptions(); + + System.IO.Stream consoleOutputStream = null; + + // Use the Console methods to open a Stream over the console std handle + if (m_writeToErrorStream) + { + // Write to the error stream + consoleOutputStream = Console.OpenStandardError(); + } + else + { + // Write to the output stream + consoleOutputStream = Console.OpenStandardOutput(); + } + + // Lookup the codepage encoding for the console + System.Text.Encoding consoleEncoding = System.Text.Encoding.GetEncoding(GetConsoleOutputCP()); + + // Create a writer around the console stream + m_consoleOutputWriter = new System.IO.StreamWriter(consoleOutputStream, consoleEncoding, 0x100); + + m_consoleOutputWriter.AutoFlush = true; + + // SuppressFinalize on m_consoleOutputWriter because all it will do is flush + // and close the file handle. Because we have set AutoFlush the additional flush + // is not required. The console file handle should not be closed, so we don't call + // Dispose, Close or the finalizer. + GC.SuppressFinalize(m_consoleOutputWriter); + } + + #endregion // Override implementation of AppenderSkeleton + + #region Public Static Fields + + /// + /// The to use when writing to the Console + /// standard output stream. + /// + /// + /// + /// The to use when writing to the Console + /// standard output stream. + /// + /// + public const string ConsoleOut = "Console.Out"; + + /// + /// The to use when writing to the Console + /// standard error output stream. + /// + /// + /// + /// The to use when writing to the Console + /// standard error output stream. + /// + /// + public const string ConsoleError = "Console.Error"; + + #endregion // Public Static Fields + + #region Private Instances Fields + + /// + /// Flag to write output to the error stream rather than the standard output stream + /// + private bool m_writeToErrorStream = false; + + /// + /// Mapping from level object to color value + /// + private LevelMapping m_levelMapping = new LevelMapping(); + + /// + /// The console output stream writer to write to + /// + /// + /// + /// This writer is not thread safe. + /// + /// + private System.IO.StreamWriter m_consoleOutputWriter = null; + + #endregion // Private Instances Fields + + #region Win32 Methods + + [DllImport("Kernel32.dll", SetLastError=true, CharSet=CharSet.Auto)] + private static extern int GetConsoleOutputCP(); + + [DllImport("Kernel32.dll", SetLastError=true, CharSet=CharSet.Auto)] + private static extern bool SetConsoleTextAttribute( + IntPtr consoleHandle, + ushort attributes); + + [DllImport("Kernel32.dll", SetLastError=true, CharSet=CharSet.Auto)] + private static extern bool GetConsoleScreenBufferInfo( + IntPtr consoleHandle, + out CONSOLE_SCREEN_BUFFER_INFO bufferInfo); + +// [DllImport("Kernel32.dll", SetLastError=true, CharSet=CharSet.Unicode)] +// private static extern bool WriteConsoleW( +// IntPtr hConsoleHandle, +// [MarshalAs(UnmanagedType.LPWStr)] string strBuffer, +// UInt32 bufferLen, +// out UInt32 written, +// IntPtr reserved); + + //private const UInt32 STD_INPUT_HANDLE = unchecked((UInt32)(-10)); + private const UInt32 STD_OUTPUT_HANDLE = unchecked((UInt32)(-11)); + private const UInt32 STD_ERROR_HANDLE = unchecked((UInt32)(-12)); + + [DllImport("Kernel32.dll", SetLastError=true, CharSet=CharSet.Auto)] + private static extern IntPtr GetStdHandle( + UInt32 type); + + [StructLayout(LayoutKind.Sequential)] + private struct COORD + { + public UInt16 x; + public UInt16 y; + } + + [StructLayout(LayoutKind.Sequential)] + private struct SMALL_RECT + { + public UInt16 Left; + public UInt16 Top; + public UInt16 Right; + public UInt16 Bottom; + } + + [StructLayout(LayoutKind.Sequential)] + private struct CONSOLE_SCREEN_BUFFER_INFO + { + public COORD dwSize; + public COORD dwCursorPosition; + public ushort wAttributes; + public SMALL_RECT srWindow; + public COORD dwMaximumWindowSize; + } + + #endregion // Win32 Methods + + #region LevelColors LevelMapping Entry + + /// + /// A class to act as a mapping between the level that a logging call is made at and + /// the color it should be displayed as. + /// + /// + /// + /// Defines the mapping between a level and the color it should be displayed in. + /// + /// + public class LevelColors : LevelMappingEntry + { + private Colors m_foreColor; + private Colors m_backColor; + private ushort m_combinedColor = 0; + + /// + /// The mapped foreground color for the specified level + /// + /// + /// + /// Required property. + /// The mapped foreground color for the specified level. + /// + /// + public Colors ForeColor + { + get { return m_foreColor; } + set { m_foreColor = value; } + } + + /// + /// The mapped background color for the specified level + /// + /// + /// + /// Required property. + /// The mapped background color for the specified level. + /// + /// + public Colors BackColor + { + get { return m_backColor; } + set { m_backColor = value; } + } + + /// + /// Initialize the options for the object + /// + /// + /// + /// Combine the and together. + /// + /// + public override void ActivateOptions() + { + base.ActivateOptions(); + m_combinedColor = (ushort)( (int)m_foreColor + (((int)m_backColor) << 4) ); + } + + /// + /// The combined and suitable for + /// setting the console color. + /// + internal ushort CombinedColor + { + get { return m_combinedColor; } + } + } + + #endregion // LevelColors LevelMapping Entry + } } #endif // !CLI_1_0 diff --git a/src/log4net/Appender/ConsoleAppender.cs b/src/log4net/Appender/ConsoleAppender.cs index 760aace4..79643914 100644 --- a/src/log4net/Appender/ConsoleAppender.cs +++ b/src/log4net/Appender/ConsoleAppender.cs @@ -26,196 +26,196 @@ namespace log4net.Appender { - /// - /// Appends logging events to the console. - /// - /// - /// - /// ConsoleAppender appends log events to the standard output stream - /// or the error output stream using a layout specified by the - /// user. - /// - /// - /// By default, all output is written to the console's standard output stream. - /// The property can be set to direct the output to the - /// error stream. - /// - /// - /// NOTE: This appender writes each message to the System.Console.Out or - /// System.Console.Error that is set at the time the event is appended. - /// Therefore it is possible to programmatically redirect the output of this appender - /// (for example NUnit does this to capture program output). While this is the desired - /// behavior of this appender it may have security implications in your application. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public class ConsoleAppender : AppenderSkeleton - { - #region Public Instance Constructors - - /// - /// Initializes a new instance of the class. - /// - /// - /// The instance of the class is set up to write - /// to the standard output stream. - /// - public ConsoleAppender() - { - } - - /// - /// Initializes a new instance of the class - /// with the specified layout. - /// - /// the layout to use for this appender - /// - /// The instance of the class is set up to write - /// to the standard output stream. - /// - [Obsolete("Instead use the default constructor and set the Layout property")] - public ConsoleAppender(ILayout layout) : this(layout, false) - { - } - - /// - /// Initializes a new instance of the class - /// with the specified layout. - /// - /// the layout to use for this appender - /// flag set to true to write to the console error stream - /// - /// When is set to true, output is written to - /// the standard error output stream. Otherwise, output is written to the standard - /// output stream. - /// - [Obsolete("Instead use the default constructor and set the Layout & Target properties")] - public ConsoleAppender(ILayout layout, bool writeToErrorStream) - { - Layout = layout; - m_writeToErrorStream = writeToErrorStream; - } - - #endregion Public Instance Constructors - - #region Public Instance Properties - - /// - /// Target is the value of the console output stream. - /// This is either "Console.Out" or "Console.Error". - /// - /// - /// Target is the value of the console output stream. - /// This is either "Console.Out" or "Console.Error". - /// - /// - /// - /// Target is the value of the console output stream. - /// This is either "Console.Out" or "Console.Error". - /// - /// - public virtual string Target - { - get { return m_writeToErrorStream ? ConsoleError : ConsoleOut; } - set - { - string v = value.Trim(); - - if (SystemInfo.EqualsIgnoringCase(ConsoleError, v)) - { - m_writeToErrorStream = true; - } - else - { - m_writeToErrorStream = false; - } - } - } - - #endregion Public Instance Properties - - #region Override implementation of AppenderSkeleton - - /// - /// This method is called by the method. - /// - /// The event to log. - /// - /// - /// Writes the event to the console. - /// - /// - /// The format of the output will depend on the appender's layout. - /// - /// - protected override void Append(LoggingEvent loggingEvent) - { + /// + /// Appends logging events to the console. + /// + /// + /// + /// ConsoleAppender appends log events to the standard output stream + /// or the error output stream using a layout specified by the + /// user. + /// + /// + /// By default, all output is written to the console's standard output stream. + /// The property can be set to direct the output to the + /// error stream. + /// + /// + /// NOTE: This appender writes each message to the System.Console.Out or + /// System.Console.Error that is set at the time the event is appended. + /// Therefore it is possible to programmatically redirect the output of this appender + /// (for example NUnit does this to capture program output). While this is the desired + /// behavior of this appender it may have security implications in your application. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public class ConsoleAppender : AppenderSkeleton + { + #region Public Instance Constructors + + /// + /// Initializes a new instance of the class. + /// + /// + /// The instance of the class is set up to write + /// to the standard output stream. + /// + public ConsoleAppender() + { + } + + /// + /// Initializes a new instance of the class + /// with the specified layout. + /// + /// the layout to use for this appender + /// + /// The instance of the class is set up to write + /// to the standard output stream. + /// + [Obsolete("Instead use the default constructor and set the Layout property")] + public ConsoleAppender(ILayout layout) : this(layout, false) + { + } + + /// + /// Initializes a new instance of the class + /// with the specified layout. + /// + /// the layout to use for this appender + /// flag set to true to write to the console error stream + /// + /// When is set to true, output is written to + /// the standard error output stream. Otherwise, output is written to the standard + /// output stream. + /// + [Obsolete("Instead use the default constructor and set the Layout & Target properties")] + public ConsoleAppender(ILayout layout, bool writeToErrorStream) + { + Layout = layout; + m_writeToErrorStream = writeToErrorStream; + } + + #endregion Public Instance Constructors + + #region Public Instance Properties + + /// + /// Target is the value of the console output stream. + /// This is either "Console.Out" or "Console.Error". + /// + /// + /// Target is the value of the console output stream. + /// This is either "Console.Out" or "Console.Error". + /// + /// + /// + /// Target is the value of the console output stream. + /// This is either "Console.Out" or "Console.Error". + /// + /// + public virtual string Target + { + get { return m_writeToErrorStream ? ConsoleError : ConsoleOut; } + set + { + string v = value.Trim(); + + if (SystemInfo.EqualsIgnoringCase(ConsoleError, v)) + { + m_writeToErrorStream = true; + } + else + { + m_writeToErrorStream = false; + } + } + } + + #endregion Public Instance Properties + + #region Override implementation of AppenderSkeleton + + /// + /// This method is called by the method. + /// + /// The event to log. + /// + /// + /// Writes the event to the console. + /// + /// + /// The format of the output will depend on the appender's layout. + /// + /// + protected override void Append(LoggingEvent loggingEvent) + { #if NETCF_1_0 - // Write to the output stream - Console.Write(RenderLoggingEvent(loggingEvent)); + // Write to the output stream + Console.Write(RenderLoggingEvent(loggingEvent)); #else - if (m_writeToErrorStream) - { - // Write to the error stream - Console.Error.Write(RenderLoggingEvent(loggingEvent)); - } - else - { - // Write to the output stream - Console.Write(RenderLoggingEvent(loggingEvent)); - } + if (m_writeToErrorStream) + { + // Write to the error stream + Console.Error.Write(RenderLoggingEvent(loggingEvent)); + } + else + { + // Write to the output stream + Console.Write(RenderLoggingEvent(loggingEvent)); + } #endif - } - - /// - /// This appender requires a to be set. - /// - /// true - /// - /// - /// This appender requires a to be set. - /// - /// - protected override bool RequiresLayout - { - get { return true; } - } - - #endregion Override implementation of AppenderSkeleton - - #region Public Static Fields - - /// - /// The to use when writing to the Console - /// standard output stream. - /// - /// - /// - /// The to use when writing to the Console - /// standard output stream. - /// - /// - public const string ConsoleOut = "Console.Out"; - - /// - /// The to use when writing to the Console - /// standard error output stream. - /// - /// - /// - /// The to use when writing to the Console - /// standard error output stream. - /// - /// - public const string ConsoleError = "Console.Error"; - - #endregion Public Static Fields - - #region Private Instances Fields - - private bool m_writeToErrorStream = false; - - #endregion Private Instances Fields - } + } + + /// + /// This appender requires a to be set. + /// + /// true + /// + /// + /// This appender requires a to be set. + /// + /// + protected override bool RequiresLayout + { + get { return true; } + } + + #endregion Override implementation of AppenderSkeleton + + #region Public Static Fields + + /// + /// The to use when writing to the Console + /// standard output stream. + /// + /// + /// + /// The to use when writing to the Console + /// standard output stream. + /// + /// + public const string ConsoleOut = "Console.Out"; + + /// + /// The to use when writing to the Console + /// standard error output stream. + /// + /// + /// + /// The to use when writing to the Console + /// standard error output stream. + /// + /// + public const string ConsoleError = "Console.Error"; + + #endregion Public Static Fields + + #region Private Instances Fields + + private bool m_writeToErrorStream = false; + + #endregion Private Instances Fields + } } diff --git a/src/log4net/Appender/DebugAppender.cs b/src/log4net/Appender/DebugAppender.cs index c1eda997..668d622c 100644 --- a/src/log4net/Appender/DebugAppender.cs +++ b/src/log4net/Appender/DebugAppender.cs @@ -24,82 +24,82 @@ namespace log4net.Appender { - /// - /// Appends log events to the system. - /// - /// - /// - /// The application configuration file can be used to control what listeners - /// are actually used. See the MSDN documentation for the - /// class for details on configuring the - /// debug system. - /// - /// - /// Events are written using the - /// method. The event's logger name is passed as the value for the category name to the Write method. - /// - /// - /// Nicko Cadell - public class DebugAppender : AppenderSkeleton - { - #region Public Instance Constructors - - /// - /// Initializes a new instance of the . - /// - /// - /// - /// Default constructor. - /// - /// - public DebugAppender() - { - } - - /// - /// Initializes a new instance of the - /// with a specified layout. - /// - /// The layout to use with this appender. - /// - /// - /// Obsolete constructor. - /// - /// - [System.Obsolete("Instead use the default constructor and set the Layout property")] - public DebugAppender(ILayout layout) - { - Layout = layout; - } - - #endregion Public Instance Constructors - - #region Public Instance Properties - + /// + /// Appends log events to the system. + /// + /// + /// + /// The application configuration file can be used to control what listeners + /// are actually used. See the MSDN documentation for the + /// class for details on configuring the + /// debug system. + /// + /// + /// Events are written using the + /// method. The event's logger name is passed as the value for the category name to the Write method. + /// + /// + /// Nicko Cadell + public class DebugAppender : AppenderSkeleton + { + #region Public Instance Constructors + + /// + /// Initializes a new instance of the . + /// + /// + /// + /// Default constructor. + /// + /// + public DebugAppender() + { + } + + /// + /// Initializes a new instance of the + /// with a specified layout. + /// + /// The layout to use with this appender. + /// + /// + /// Obsolete constructor. + /// + /// + [System.Obsolete("Instead use the default constructor and set the Layout property")] + public DebugAppender(ILayout layout) + { + Layout = layout; + } + + #endregion Public Instance Constructors + + #region Public Instance Properties + #if !NETSTANDARD1_3 // System.Diagnostics.Debug has no Flush() in netstandard1.3 - /// - /// Gets or sets a value that indicates whether the appender will - /// flush at the end of each write. - /// - /// - /// The default behavior is to flush at the end of each - /// write. If the option is set tofalse, then the underlying - /// stream can defer writing to physical medium to a later time. - /// - /// - /// Avoiding the flush operation at the end of each append results - /// in a performance gain of 10 to 20 percent. However, there is safety - /// trade-off involved in skipping flushing. Indeed, when flushing is - /// skipped, then it is likely that the last few log events will not - /// be recorded on disk when the application exits. This is a high - /// price to pay even for a 20% performance gain. - /// - /// - public bool ImmediateFlush - { - get { return m_immediateFlush; } - set { m_immediateFlush = value; } - } + /// + /// Gets or sets a value that indicates whether the appender will + /// flush at the end of each write. + /// + /// + /// The default behavior is to flush at the end of each + /// write. If the option is set tofalse, then the underlying + /// stream can defer writing to physical medium to a later time. + /// + /// + /// Avoiding the flush operation at the end of each append results + /// in a performance gain of 10 to 20 percent. However, there is safety + /// trade-off involved in skipping flushing. Indeed, when flushing is + /// skipped, then it is likely that the last few log events will not + /// be recorded on disk when the application exits. This is a high + /// price to pay even for a 20% performance gain. + /// + /// + public bool ImmediateFlush + { + get { return m_immediateFlush; } + set { m_immediateFlush = value; } + } #endif // !NETSTANDARD1_3 /// @@ -119,7 +119,7 @@ public PatternLayout Category set { m_category = value; } } - #endregion Public Instance Properties + #endregion Public Instance Properties #if !NETSTANDARD1_3 /// @@ -139,36 +139,36 @@ public override bool Flush(int millisecondsTimeout) } #endif - #region Override implementation of AppenderSkeleton - + #region Override implementation of AppenderSkeleton + #if NETSTANDARD1_3 - /// - /// Writes the logging event to the system. - /// - /// The event to log. - /// - /// - /// Writes the logging event to the system. - /// - /// + /// + /// Writes the logging event to the system. + /// + /// The event to log. + /// + /// + /// Writes the logging event to the system. + /// + /// #else - /// - /// Writes the logging event to the system. - /// - /// The event to log. - /// - /// - /// Writes the logging event to the system. - /// If is true then the - /// is called. - /// - /// + /// + /// Writes the logging event to the system. + /// + /// The event to log. + /// + /// + /// Writes the logging event to the system. + /// If is true then the + /// is called. + /// + /// #endif - protected override void Append(LoggingEvent loggingEvent) - { - // - // Write the string to the Debug system - // + protected override void Append(LoggingEvent loggingEvent) + { + // + // Write the string to the Debug system + // if(m_category == null) { System.Diagnostics.Debug.Write(RenderLoggingEvent(loggingEvent)); @@ -186,51 +186,51 @@ protected override void Append(LoggingEvent loggingEvent) } } #if !NETSTANDARD1_3 - // - // Flush the Debug system if needed - // - if (m_immediateFlush) - { - System.Diagnostics.Debug.Flush(); - } + // + // Flush the Debug system if needed + // + if (m_immediateFlush) + { + System.Diagnostics.Debug.Flush(); + } #endif - } - - /// - /// This appender requires a to be set. - /// - /// true - /// - /// - /// This appender requires a to be set. - /// - /// - protected override bool RequiresLayout - { - get { return true; } - } - - #endregion Override implementation of AppenderSkeleton - - #region Private Instance Fields - -#if !NETSTANDARD1_3 - /// - /// Immediate flush means that the underlying writer or output stream - /// will be flushed at the end of each append operation. - /// - /// - /// - /// Immediate flush is slower but ensures that each append request is - /// actually written. If is set to - /// false, then there is a good chance that the last few - /// logs events are not actually written to persistent media if and - /// when the application crashes. - /// - /// - /// The default value is true. - /// - private bool m_immediateFlush = true; + } + + /// + /// This appender requires a to be set. + /// + /// true + /// + /// + /// This appender requires a to be set. + /// + /// + protected override bool RequiresLayout + { + get { return true; } + } + + #endregion Override implementation of AppenderSkeleton + + #region Private Instance Fields + +#if !NETSTANDARD1_3 + /// + /// Immediate flush means that the underlying writer or output stream + /// will be flushed at the end of each append operation. + /// + /// + /// + /// Immediate flush is slower but ensures that each append request is + /// actually written. If is set to + /// false, then there is a good chance that the last few + /// logs events are not actually written to persistent media if and + /// when the application crashes. + /// + /// + /// The default value is true. + /// + private bool m_immediateFlush = true; #endif /// @@ -238,6 +238,6 @@ protected override bool RequiresLayout /// private PatternLayout m_category = new PatternLayout("%logger"); - #endregion Private Instance Fields - } + #endregion Private Instance Fields + } } diff --git a/src/log4net/Appender/EventLogAppender.cs b/src/log4net/Appender/EventLogAppender.cs index 0d1f3c89..2de708bd 100644 --- a/src/log4net/Appender/EventLogAppender.cs +++ b/src/log4net/Appender/EventLogAppender.cs @@ -36,191 +36,191 @@ namespace log4net.Appender { - /// - /// Writes events to the system event log. - /// - /// + /// + /// Writes events to the system event log. + /// + /// /// /// The appender will fail if you try to write using an event source that doesn't exist unless it is running with local administrator privileges. /// See also http://logging.apache.org/log4net/release/faq.html#trouble-EventLog /// - /// - /// The EventID of the event log entry can be - /// set using the EventID property () - /// on the . - /// + /// + /// The EventID of the event log entry can be + /// set using the EventID property () + /// on the . + /// /// /// The Category of the event log entry can be - /// set using the Category property () - /// on the . - /// - /// - /// There is a limit of 32K characters for an event log message - /// - /// - /// When configuring the EventLogAppender a mapping can be - /// specified to map a logging level to an event log entry type. For example: - /// - /// - /// <mapping> - /// <level value="ERROR" /> - /// <eventLogEntryType value="Error" /> - /// </mapping> - /// <mapping> - /// <level value="DEBUG" /> - /// <eventLogEntryType value="Information" /> - /// </mapping> - /// - /// - /// The Level is the standard log4net logging level and eventLogEntryType can be any value - /// from the enum, i.e.: - /// - /// Erroran error event - /// Warninga warning event - /// Informationan informational event - /// - /// - /// - /// Aspi Havewala - /// Douglas de la Torre - /// Nicko Cadell - /// Gert Driesen - /// Thomas Voss - public class EventLogAppender : AppenderSkeleton - { - #region Public Instance Constructors - - /// - /// Initializes a new instance of the class. - /// - /// - /// - /// Default constructor. - /// - /// - public EventLogAppender() - { - m_applicationName = System.Threading.Thread.GetDomain().FriendlyName; - m_logName = "Application"; // Defaults to application log - m_machineName = "."; // Only log on the local machine - } - - /// - /// Initializes a new instance of the class - /// with the specified . - /// - /// The to use with this appender. - /// - /// - /// Obsolete constructor. - /// - /// - [Obsolete("Instead use the default constructor and set the Layout property")] - public EventLogAppender(ILayout layout) : this() - { - Layout = layout; - } - - #endregion // Public Instance Constructors - - #region Public Instance Properties - - /// - /// The name of the log where messages will be stored. - /// - /// - /// The string name of the log where messages will be stored. - /// - /// - /// This is the name of the log as it appears in the Event Viewer - /// tree. The default value is to log into the Application - /// log, this is where most applications write their events. However - /// if you need a separate log for your application (or applications) - /// then you should set the appropriately. - /// This should not be used to distinguish your event log messages - /// from those of other applications, the - /// property should be used to distinguish events. This property should be - /// used to group together events into a single log. - /// - /// - public string LogName - { - get { return m_logName; } - set { m_logName = value; } - } - - /// - /// Property used to set the Application name. This appears in the - /// event logs when logging. - /// - /// - /// The string used to distinguish events from different sources. - /// - /// - /// Sets the event log source property. - /// - public string ApplicationName - { - get { return m_applicationName; } - set { m_applicationName = value; } - } - - /// - /// This property is used to return the name of the computer to use - /// when accessing the event logs. Currently, this is the current - /// computer, denoted by a dot "." - /// - /// - /// The string name of the machine holding the event log that - /// will be logged into. - /// - /// - /// This property cannot be changed. It is currently set to '.' - /// i.e. the local machine. This may be changed in future. - /// - public string MachineName - { - get { return m_machineName; } - set { /* Currently we do not allow the machine name to be changed */; } - } - - /// - /// Add a mapping of level to - done by the config file - /// - /// The mapping to add - /// - /// - /// Add a mapping to this appender. - /// Each mapping defines the event log entry type for a level. - /// - /// - public void AddMapping(Level2EventLogEntryType mapping) - { - m_levelMapping.Add(mapping); - } - - /// - /// Gets or sets the used to write to the EventLog. - /// - /// - /// The used to write to the EventLog. - /// - /// - /// - /// The system security context used to write to the EventLog. - /// - /// - /// Unless a specified here for this appender - /// the is queried for the - /// security context to use. The default behavior is to use the security context - /// of the current thread. - /// - /// - public SecurityContext SecurityContext - { - get { return m_securityContext; } - set { m_securityContext = value; } - } + /// set using the Category property () + /// on the . + /// + /// + /// There is a limit of 32K characters for an event log message + /// + /// + /// When configuring the EventLogAppender a mapping can be + /// specified to map a logging level to an event log entry type. For example: + /// + /// + /// <mapping> + /// <level value="ERROR" /> + /// <eventLogEntryType value="Error" /> + /// </mapping> + /// <mapping> + /// <level value="DEBUG" /> + /// <eventLogEntryType value="Information" /> + /// </mapping> + /// + /// + /// The Level is the standard log4net logging level and eventLogEntryType can be any value + /// from the enum, i.e.: + /// + /// Erroran error event + /// Warninga warning event + /// Informationan informational event + /// + /// + /// + /// Aspi Havewala + /// Douglas de la Torre + /// Nicko Cadell + /// Gert Driesen + /// Thomas Voss + public class EventLogAppender : AppenderSkeleton + { + #region Public Instance Constructors + + /// + /// Initializes a new instance of the class. + /// + /// + /// + /// Default constructor. + /// + /// + public EventLogAppender() + { + m_applicationName = System.Threading.Thread.GetDomain().FriendlyName; + m_logName = "Application"; // Defaults to application log + m_machineName = "."; // Only log on the local machine + } + + /// + /// Initializes a new instance of the class + /// with the specified . + /// + /// The to use with this appender. + /// + /// + /// Obsolete constructor. + /// + /// + [Obsolete("Instead use the default constructor and set the Layout property")] + public EventLogAppender(ILayout layout) : this() + { + Layout = layout; + } + + #endregion // Public Instance Constructors + + #region Public Instance Properties + + /// + /// The name of the log where messages will be stored. + /// + /// + /// The string name of the log where messages will be stored. + /// + /// + /// This is the name of the log as it appears in the Event Viewer + /// tree. The default value is to log into the Application + /// log, this is where most applications write their events. However + /// if you need a separate log for your application (or applications) + /// then you should set the appropriately. + /// This should not be used to distinguish your event log messages + /// from those of other applications, the + /// property should be used to distinguish events. This property should be + /// used to group together events into a single log. + /// + /// + public string LogName + { + get { return m_logName; } + set { m_logName = value; } + } + + /// + /// Property used to set the Application name. This appears in the + /// event logs when logging. + /// + /// + /// The string used to distinguish events from different sources. + /// + /// + /// Sets the event log source property. + /// + public string ApplicationName + { + get { return m_applicationName; } + set { m_applicationName = value; } + } + + /// + /// This property is used to return the name of the computer to use + /// when accessing the event logs. Currently, this is the current + /// computer, denoted by a dot "." + /// + /// + /// The string name of the machine holding the event log that + /// will be logged into. + /// + /// + /// This property cannot be changed. It is currently set to '.' + /// i.e. the local machine. This may be changed in future. + /// + public string MachineName + { + get { return m_machineName; } + set { /* Currently we do not allow the machine name to be changed */; } + } + + /// + /// Add a mapping of level to - done by the config file + /// + /// The mapping to add + /// + /// + /// Add a mapping to this appender. + /// Each mapping defines the event log entry type for a level. + /// + /// + public void AddMapping(Level2EventLogEntryType mapping) + { + m_levelMapping.Add(mapping); + } + + /// + /// Gets or sets the used to write to the EventLog. + /// + /// + /// The used to write to the EventLog. + /// + /// + /// + /// The system security context used to write to the EventLog. + /// + /// + /// Unless a specified here for this appender + /// the is queried for the + /// security context to use. The default behavior is to use the security context + /// of the current thread. + /// + /// + public SecurityContext SecurityContext + { + get { return m_securityContext; } + set { m_securityContext = value; } + } /// /// Gets or sets the EventId to use unless one is explicitly specified via the LoggingEvent's properties. @@ -228,8 +228,8 @@ public SecurityContext SecurityContext /// /// /// The EventID of the event log entry will normally be - /// set using the EventID property () - /// on the . + /// set using the EventID property () + /// on the . /// This property provides the fallback value which defaults to 0. /// /// @@ -245,8 +245,8 @@ public int EventId { /// /// /// The Category of the event log entry will normally be - /// set using the Category property () - /// on the . + /// set using the Category property () + /// on the . /// This property provides the fallback value which defaults to 0. /// /// @@ -257,26 +257,26 @@ public short Category } #endregion // Public Instance Properties - #region Implementation of IOptionHandler - - /// - /// Initialize the appender based on the options set - /// - /// - /// - /// This is part of the delayed object - /// activation scheme. The method must - /// be called on this object after the configuration properties have - /// been set. Until is called this - /// object is in an undefined state and must not be used. - /// - /// - /// If any of the configuration properties are modified then - /// must be called again. - /// - /// - public override void ActivateOptions() - { + #region Implementation of IOptionHandler + + /// + /// Initialize the appender based on the options set + /// + /// + /// + /// This is part of the delayed object + /// activation scheme. The method must + /// be called on this object after the configuration properties have + /// been set. Until is called this + /// object is in an undefined state and must not be used. + /// + /// + /// If any of the configuration properties are modified then + /// must be called again. + /// + /// + public override void ActivateOptions() + { try { base.ActivateOptions(); @@ -342,82 +342,82 @@ public override void ActivateOptions() ex); Threshold = Level.Off; } - } - - #endregion // Implementation of IOptionHandler - - /// - /// Create an event log source - /// - /// - /// Uses different API calls under NET_2_0 - /// - private static void CreateEventSource(string source, string logName, string machineName) - { + } + + #endregion // Implementation of IOptionHandler + + /// + /// Create an event log source + /// + /// + /// Uses different API calls under NET_2_0 + /// + private static void CreateEventSource(string source, string logName, string machineName) + { #if NET_2_0 - EventSourceCreationData eventSourceCreationData = new EventSourceCreationData(source, logName); - eventSourceCreationData.MachineName = machineName; - EventLog.CreateEventSource(eventSourceCreationData); + EventSourceCreationData eventSourceCreationData = new EventSourceCreationData(source, logName); + eventSourceCreationData.MachineName = machineName; + EventLog.CreateEventSource(eventSourceCreationData); #else - EventLog.CreateEventSource(source, logName, machineName); + EventLog.CreateEventSource(source, logName, machineName); #endif - } + } - #region Override implementation of AppenderSkeleton - - /// - /// This method is called by the - /// method. - /// - /// the event to log - /// - /// Writes the event to the system event log using the - /// . - /// - /// If the event has an EventID property (see ) - /// set then this integer will be used as the event log event id. - /// - /// - /// There is a limit of 32K characters for an event log message - /// - /// - protected override void Append(LoggingEvent loggingEvent) - { - // - // Write the resulting string to the event log system - // - int eventID = m_eventId; - - // Look for the EventID property - object eventIDPropertyObj = loggingEvent.LookupProperty("EventID"); - if (eventIDPropertyObj != null) - { - if (eventIDPropertyObj is int) - { - eventID = (int)eventIDPropertyObj; - } - else - { - string eventIDPropertyString = eventIDPropertyObj as string; + #region Override implementation of AppenderSkeleton + + /// + /// This method is called by the + /// method. + /// + /// the event to log + /// + /// Writes the event to the system event log using the + /// . + /// + /// If the event has an EventID property (see ) + /// set then this integer will be used as the event log event id. + /// + /// + /// There is a limit of 32K characters for an event log message + /// + /// + protected override void Append(LoggingEvent loggingEvent) + { + // + // Write the resulting string to the event log system + // + int eventID = m_eventId; + + // Look for the EventID property + object eventIDPropertyObj = loggingEvent.LookupProperty("EventID"); + if (eventIDPropertyObj != null) + { + if (eventIDPropertyObj is int) + { + eventID = (int)eventIDPropertyObj; + } + else + { + string eventIDPropertyString = eventIDPropertyObj as string; if (eventIDPropertyString == null) { eventIDPropertyString = eventIDPropertyObj.ToString(); } - if (eventIDPropertyString != null && eventIDPropertyString.Length > 0) - { - // Read the string property into a number - int intVal; - if (SystemInfo.TryParse(eventIDPropertyString, out intVal)) - { - eventID = intVal; - } - else - { - ErrorHandler.Error("Unable to parse event ID property [" + eventIDPropertyString + "]."); - } - } - } - } + if (eventIDPropertyString != null && eventIDPropertyString.Length > 0) + { + // Read the string property into a number + int intVal; + if (SystemInfo.TryParse(eventIDPropertyString, out intVal)) + { + eventID = intVal; + } + else + { + ErrorHandler.Error("Unable to parse event ID property [" + eventIDPropertyString + "]."); + } + } + } + } short category = m_category; // Look for the Category property @@ -451,114 +451,114 @@ protected override void Append(LoggingEvent loggingEvent) } } - // Write to the event log - try - { - string eventTxt = RenderLoggingEvent(loggingEvent); - - // There is a limit of about 32K characters for an event log message - if (eventTxt.Length > MAX_EVENTLOG_MESSAGE_SIZE) - { - eventTxt = eventTxt.Substring(0, MAX_EVENTLOG_MESSAGE_SIZE); - } - - EventLogEntryType entryType = GetEntryType(loggingEvent.Level); - - using(SecurityContext.Impersonate(this)) - { - EventLog.WriteEntry(m_applicationName, eventTxt, entryType, eventID, category); - } - } - catch(Exception ex) - { - ErrorHandler.Error("Unable to write to event log [" + m_logName + "] using source [" + m_applicationName + "]", ex); - } - } - - /// - /// This appender requires a to be set. - /// - /// true - /// - /// - /// This appender requires a to be set. - /// - /// - protected override bool RequiresLayout - { - get { return true; } - } - - #endregion // Override implementation of AppenderSkeleton - - #region Protected Instance Methods - - /// - /// Get the equivalent for a - /// - /// the Level to convert to an EventLogEntryType - /// The equivalent for a - /// - /// Because there are fewer applicable - /// values to use in logging levels than there are in the - /// this is a one way mapping. There is - /// a loss of information during the conversion. - /// - protected virtual EventLogEntryType GetEntryType(Level level) - { - // see if there is a specified lookup. - Level2EventLogEntryType entryType = m_levelMapping.Lookup(level) as Level2EventLogEntryType; - if (entryType != null) - { - return entryType.EventLogEntryType; - } - - // Use default behavior - - if (level >= Level.Error) - { - return EventLogEntryType.Error; - } - else if (level == Level.Warn) - { - return EventLogEntryType.Warning; - } - - // Default setting - return EventLogEntryType.Information; - } - - #endregion // Protected Instance Methods - - #region Private Instance Fields - - /// - /// The log name is the section in the event logs where the messages - /// are stored. - /// - private string m_logName; - - /// - /// Name of the application to use when logging. This appears in the - /// application column of the event log named by . - /// - private string m_applicationName; - - /// - /// The name of the machine which holds the event log. This is - /// currently only allowed to be '.' i.e. the current machine. - /// - private string m_machineName; - - /// - /// Mapping from level object to EventLogEntryType - /// - private LevelMapping m_levelMapping = new LevelMapping(); - - /// - /// The security context to use for privileged calls - /// - private SecurityContext m_securityContext; + // Write to the event log + try + { + string eventTxt = RenderLoggingEvent(loggingEvent); + + // There is a limit of about 32K characters for an event log message + if (eventTxt.Length > MAX_EVENTLOG_MESSAGE_SIZE) + { + eventTxt = eventTxt.Substring(0, MAX_EVENTLOG_MESSAGE_SIZE); + } + + EventLogEntryType entryType = GetEntryType(loggingEvent.Level); + + using(SecurityContext.Impersonate(this)) + { + EventLog.WriteEntry(m_applicationName, eventTxt, entryType, eventID, category); + } + } + catch(Exception ex) + { + ErrorHandler.Error("Unable to write to event log [" + m_logName + "] using source [" + m_applicationName + "]", ex); + } + } + + /// + /// This appender requires a to be set. + /// + /// true + /// + /// + /// This appender requires a to be set. + /// + /// + protected override bool RequiresLayout + { + get { return true; } + } + + #endregion // Override implementation of AppenderSkeleton + + #region Protected Instance Methods + + /// + /// Get the equivalent for a + /// + /// the Level to convert to an EventLogEntryType + /// The equivalent for a + /// + /// Because there are fewer applicable + /// values to use in logging levels than there are in the + /// this is a one way mapping. There is + /// a loss of information during the conversion. + /// + protected virtual EventLogEntryType GetEntryType(Level level) + { + // see if there is a specified lookup. + Level2EventLogEntryType entryType = m_levelMapping.Lookup(level) as Level2EventLogEntryType; + if (entryType != null) + { + return entryType.EventLogEntryType; + } + + // Use default behavior + + if (level >= Level.Error) + { + return EventLogEntryType.Error; + } + else if (level == Level.Warn) + { + return EventLogEntryType.Warning; + } + + // Default setting + return EventLogEntryType.Information; + } + + #endregion // Protected Instance Methods + + #region Private Instance Fields + + /// + /// The log name is the section in the event logs where the messages + /// are stored. + /// + private string m_logName; + + /// + /// Name of the application to use when logging. This appears in the + /// application column of the event log named by . + /// + private string m_applicationName; + + /// + /// The name of the machine which holds the event log. This is + /// currently only allowed to be '.' i.e. the current machine. + /// + private string m_machineName; + + /// + /// Mapping from level object to EventLogEntryType + /// + private LevelMapping m_levelMapping = new LevelMapping(); + + /// + /// The security context to use for privileged calls + /// + private SecurityContext m_securityContext; /// /// The event ID to use unless one is explicitly specified via the LoggingEvent's properties. @@ -572,120 +572,120 @@ protected virtual EventLogEntryType GetEntryType(Level level) #endregion // Private Instance Fields - #region Level2EventLogEntryType LevelMapping Entry - - /// - /// A class to act as a mapping between the level that a logging call is made at and - /// the color it should be displayed as. - /// - /// - /// - /// Defines the mapping between a level and its event log entry type. - /// - /// - public class Level2EventLogEntryType : LevelMappingEntry - { - private EventLogEntryType m_entryType; - - /// - /// The for this entry - /// - /// - /// - /// Required property. - /// The for this entry - /// - /// - public EventLogEntryType EventLogEntryType - { - get { return m_entryType; } - set { m_entryType = value; } - } - } - - #endregion // LevelColors LevelMapping Entry - - #region Private Static Fields - - /// - /// The fully qualified type of the EventLogAppender class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(EventLogAppender); - - /// - /// The maximum size supported by default. - /// - /// - /// http://msdn.microsoft.com/en-us/library/xzwc042w(v=vs.100).aspx - /// The 32766 documented max size is two bytes shy of 32K (I'm assuming 32766 - /// may leave space for a two byte null terminator of #0#0). The 32766 max - /// length is what the .NET 4.0 source code checks for, but this is WRONG! - /// Strings with a length > 31839 on Windows Vista or higher can CORRUPT - /// the event log! See: System.Diagnostics.EventLogInternal.InternalWriteEvent() - /// for the use of the 32766 max size. - /// - private static readonly int MAX_EVENTLOG_MESSAGE_SIZE_DEFAULT = 32766; - - /// - /// The maximum size supported by a windows operating system that is vista - /// or newer. - /// - /// - /// See ReportEvent API: - /// http://msdn.microsoft.com/en-us/library/aa363679(VS.85).aspx - /// ReportEvent's lpStrings parameter: - /// "A pointer to a buffer containing an array of - /// null-terminated strings that are merged into the message before Event Viewer - /// displays the string to the user. This parameter must be a valid pointer - /// (or NULL), even if wNumStrings is zero. Each string is limited to 31,839 characters." - /// - /// Going beyond the size of 31839 will (at some point) corrupt the event log on Windows - /// Vista or higher! It may succeed for a while...but you will eventually run into the - /// error: "System.ComponentModel.Win32Exception : A device attached to the system is - /// not functioning", and the event log will then be corrupt (I was able to corrupt - /// an event log using a length of 31877 on Windows 7). - /// - /// The max size for Windows Vista or higher is documented here: - /// http://msdn.microsoft.com/en-us/library/xzwc042w(v=vs.100).aspx. - /// Going over this size may succeed a few times but the buffer will overrun and - /// eventually corrupt the log (based on testing). - /// - /// The maxEventMsgSize size is based on the max buffer size of the lpStrings parameter of the ReportEvent API. - /// The documented max size for EventLog.WriteEntry for Windows Vista and higher is 31839, but I'm leaving room for a - /// terminator of #0#0, as we cannot see the source of ReportEvent (though we could use an API monitor to examine the - /// buffer, given enough time). - /// - private static readonly int MAX_EVENTLOG_MESSAGE_SIZE_VISTA_OR_NEWER = 31839 - 2; - - /// - /// The maximum size that the operating system supports for - /// a event log message. - /// - /// - /// Used to determine the maximum string length that can be written - /// to the operating system event log and eventually truncate a string - /// that exceeds the limits. - /// - private static readonly int MAX_EVENTLOG_MESSAGE_SIZE = GetMaxEventLogMessageSize(); - - /// - /// This method determines the maximum event log message size allowed for - /// the current environment. - /// - /// - private static int GetMaxEventLogMessageSize() - { - if (Environment.OSVersion.Platform == PlatformID.Win32NT && Environment.OSVersion.Version.Major >= 6) - return MAX_EVENTLOG_MESSAGE_SIZE_VISTA_OR_NEWER; - return MAX_EVENTLOG_MESSAGE_SIZE_DEFAULT; - } - - #endregion Private Static Fields - } + #region Level2EventLogEntryType LevelMapping Entry + + /// + /// A class to act as a mapping between the level that a logging call is made at and + /// the color it should be displayed as. + /// + /// + /// + /// Defines the mapping between a level and its event log entry type. + /// + /// + public class Level2EventLogEntryType : LevelMappingEntry + { + private EventLogEntryType m_entryType; + + /// + /// The for this entry + /// + /// + /// + /// Required property. + /// The for this entry + /// + /// + public EventLogEntryType EventLogEntryType + { + get { return m_entryType; } + set { m_entryType = value; } + } + } + + #endregion // LevelColors LevelMapping Entry + + #region Private Static Fields + + /// + /// The fully qualified type of the EventLogAppender class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(EventLogAppender); + + /// + /// The maximum size supported by default. + /// + /// + /// http://msdn.microsoft.com/en-us/library/xzwc042w(v=vs.100).aspx + /// The 32766 documented max size is two bytes shy of 32K (I'm assuming 32766 + /// may leave space for a two byte null terminator of #0#0). The 32766 max + /// length is what the .NET 4.0 source code checks for, but this is WRONG! + /// Strings with a length > 31839 on Windows Vista or higher can CORRUPT + /// the event log! See: System.Diagnostics.EventLogInternal.InternalWriteEvent() + /// for the use of the 32766 max size. + /// + private static readonly int MAX_EVENTLOG_MESSAGE_SIZE_DEFAULT = 32766; + + /// + /// The maximum size supported by a windows operating system that is vista + /// or newer. + /// + /// + /// See ReportEvent API: + /// http://msdn.microsoft.com/en-us/library/aa363679(VS.85).aspx + /// ReportEvent's lpStrings parameter: + /// "A pointer to a buffer containing an array of + /// null-terminated strings that are merged into the message before Event Viewer + /// displays the string to the user. This parameter must be a valid pointer + /// (or NULL), even if wNumStrings is zero. Each string is limited to 31,839 characters." + /// + /// Going beyond the size of 31839 will (at some point) corrupt the event log on Windows + /// Vista or higher! It may succeed for a while...but you will eventually run into the + /// error: "System.ComponentModel.Win32Exception : A device attached to the system is + /// not functioning", and the event log will then be corrupt (I was able to corrupt + /// an event log using a length of 31877 on Windows 7). + /// + /// The max size for Windows Vista or higher is documented here: + /// http://msdn.microsoft.com/en-us/library/xzwc042w(v=vs.100).aspx. + /// Going over this size may succeed a few times but the buffer will overrun and + /// eventually corrupt the log (based on testing). + /// + /// The maxEventMsgSize size is based on the max buffer size of the lpStrings parameter of the ReportEvent API. + /// The documented max size for EventLog.WriteEntry for Windows Vista and higher is 31839, but I'm leaving room for a + /// terminator of #0#0, as we cannot see the source of ReportEvent (though we could use an API monitor to examine the + /// buffer, given enough time). + /// + private static readonly int MAX_EVENTLOG_MESSAGE_SIZE_VISTA_OR_NEWER = 31839 - 2; + + /// + /// The maximum size that the operating system supports for + /// a event log message. + /// + /// + /// Used to determine the maximum string length that can be written + /// to the operating system event log and eventually truncate a string + /// that exceeds the limits. + /// + private static readonly int MAX_EVENTLOG_MESSAGE_SIZE = GetMaxEventLogMessageSize(); + + /// + /// This method determines the maximum event log message size allowed for + /// the current environment. + /// + /// + private static int GetMaxEventLogMessageSize() + { + if (Environment.OSVersion.Platform == PlatformID.Win32NT && Environment.OSVersion.Version.Major >= 6) + return MAX_EVENTLOG_MESSAGE_SIZE_VISTA_OR_NEWER; + return MAX_EVENTLOG_MESSAGE_SIZE_DEFAULT; + } + + #endregion Private Static Fields + } } #endif // !SSCLI diff --git a/src/log4net/Appender/FileAppender.cs b/src/log4net/Appender/FileAppender.cs index af0b387b..a9cce8e9 100644 --- a/src/log4net/Appender/FileAppender.cs +++ b/src/log4net/Appender/FileAppender.cs @@ -85,53 +85,53 @@ namespace log4net.Appender /// Douglas de la Torre /// Niall Daley #else - /// - /// Appends logging events to a file. - /// - /// - /// - /// Logging events are sent to the file specified by - /// the property. - /// - /// - /// The file can be opened in either append or overwrite mode - /// by specifying the property. - /// If the file path is relative it is taken as relative from - /// the application base directory. The file encoding can be - /// specified by setting the property. - /// - /// - /// The layout's and - /// values will be written each time the file is opened and closed - /// respectively. If the property is - /// then the file may contain multiple copies of the header and footer. - /// - /// - /// This appender will first try to open the file for writing when - /// is called. This will typically be during configuration. - /// If the file cannot be opened for writing the appender will attempt - /// to open the file again each time a message is logged to the appender. - /// If the file cannot be opened for writing when a message is logged then - /// the message will be discarded by this appender. - /// - /// - /// The supports pluggable file locking models via - /// the property. - /// The default behavior, implemented by - /// is to obtain an exclusive write lock on the file until this appender is closed. - /// The alternative model only holds a - /// write lock while the appender is writing a logging event (). - /// - /// - /// All locking strategies have issues and you should seriously consider using a different strategy that - /// avoids having multiple processes logging to the same file. - /// - /// - /// Nicko Cadell - /// Gert Driesen - /// Rodrigo B. de Oliveira - /// Douglas de la Torre - /// Niall Daley + /// + /// Appends logging events to a file. + /// + /// + /// + /// Logging events are sent to the file specified by + /// the property. + /// + /// + /// The file can be opened in either append or overwrite mode + /// by specifying the property. + /// If the file path is relative it is taken as relative from + /// the application base directory. The file encoding can be + /// specified by setting the property. + /// + /// + /// The layout's and + /// values will be written each time the file is opened and closed + /// respectively. If the property is + /// then the file may contain multiple copies of the header and footer. + /// + /// + /// This appender will first try to open the file for writing when + /// is called. This will typically be during configuration. + /// If the file cannot be opened for writing the appender will attempt + /// to open the file again each time a message is logged to the appender. + /// If the file cannot be opened for writing when a message is logged then + /// the message will be discarded by this appender. + /// + /// + /// The supports pluggable file locking models via + /// the property. + /// The default behavior, implemented by + /// is to obtain an exclusive write lock on the file until this appender is closed. + /// The alternative model only holds a + /// write lock while the appender is writing a logging event (). + /// + /// + /// All locking strategies have issues and you should seriously consider using a different strategy that + /// avoids having multiple processes logging to the same file. + /// + /// + /// Nicko Cadell + /// Gert Driesen + /// Rodrigo B. de Oliveira + /// Douglas de la Torre + /// Niall Daley #endif public class FileAppender : TextWriterAppender { @@ -186,11 +186,11 @@ public LockingStream(LockingModelBase locking) #region Override Implementation of Stream #if NETSTANDARD - protected override void Dispose(bool disposing) - { - m_lockingModel.CloseFile(); - base.Dispose(disposing); - } + protected override void Dispose(bool disposing) + { + m_lockingModel.CloseFile(); + base.Dispose(disposing); + } #else private int m_readTotal = -1; @@ -241,17 +241,17 @@ public override void EndWrite(IAsyncResult asyncResult) #endif #if NET_4_5 || NETSTANDARD - public override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) - { - AssertLocked(); - return m_realStream.ReadAsync(buffer, offset, count, cancellationToken); - } - - public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) - { - AssertLocked(); - return base.WriteAsync(buffer, offset, count, cancellationToken); - } + public override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) + { + AssertLocked(); + return m_realStream.ReadAsync(buffer, offset, count, cancellationToken); + } + + public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) + { + AssertLocked(); + return base.WriteAsync(buffer, offset, count, cancellationToken); + } #endif public override void Flush() @@ -285,7 +285,7 @@ public override void SetLength(long value) void IDisposable.Dispose() { #if NETSTANDARD - Dispose(true); + Dispose(true); #else Close(); #endif @@ -792,7 +792,7 @@ public class InterProcessLock : LockingModelBase /// /// #if NET_4_0 || MONO_4_0 || NETSTANDARD - [System.Security.SecuritySafeCritical] + [System.Security.SecuritySafeCritical] #endif public override void OpenFile(string filename, bool append, Encoding encoding) { @@ -916,7 +916,7 @@ public override void OnClose() if (m_mutex != null) { #if NET_4_0 || MONO_4_0 || NETSTANDARD - m_mutex.Dispose(); + m_mutex.Dispose(); #else m_mutex.Close(); #endif @@ -1178,26 +1178,26 @@ public SecurityContext SecurityContext } #if NETCF - /// - /// Gets or sets the used to handle locking of the file. - /// - /// - /// The used to lock the file. - /// - /// - /// - /// Gets or sets the used to handle locking of the file. - /// - /// - /// There are two built in locking models, and . - /// The first locks the file from the start of logging to the end, the - /// second locks only for the minimal amount of time when logging each message - /// and the last synchronizes processes using a named system wide Mutex. - /// - /// - /// The default locking model is the . - /// - /// + /// + /// Gets or sets the used to handle locking of the file. + /// + /// + /// The used to lock the file. + /// + /// + /// + /// Gets or sets the used to handle locking of the file. + /// + /// + /// There are two built in locking models, and . + /// The first locks the file from the start of logging to the end, the + /// second locks only for the minimal amount of time when logging each message + /// and the last synchronizes processes using a named system wide Mutex. + /// + /// + /// The default locking model is the . + /// + /// #else /// /// Gets or sets the used to handle locking of the file. diff --git a/src/log4net/Appender/ForwardingAppender.cs b/src/log4net/Appender/ForwardingAppender.cs index 20a99ccc..f1a13964 100644 --- a/src/log4net/Appender/ForwardingAppender.cs +++ b/src/log4net/Appender/ForwardingAppender.cs @@ -25,255 +25,255 @@ namespace log4net.Appender { - /// - /// This appender forwards logging events to attached appenders. - /// - /// - /// - /// The forwarding appender can be used to specify different thresholds - /// and filters for the same appender at different locations within the hierarchy. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public class ForwardingAppender : AppenderSkeleton, IAppenderAttachable - { - #region Public Instance Constructors + /// + /// This appender forwards logging events to attached appenders. + /// + /// + /// + /// The forwarding appender can be used to specify different thresholds + /// and filters for the same appender at different locations within the hierarchy. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public class ForwardingAppender : AppenderSkeleton, IAppenderAttachable + { + #region Public Instance Constructors - /// - /// Initializes a new instance of the class. - /// - /// - /// - /// Default constructor. - /// - /// - public ForwardingAppender() - { - } + /// + /// Initializes a new instance of the class. + /// + /// + /// + /// Default constructor. + /// + /// + public ForwardingAppender() + { + } - #endregion Public Instance Constructors + #endregion Public Instance Constructors - #region Override implementation of AppenderSkeleton + #region Override implementation of AppenderSkeleton - /// - /// Closes the appender and releases resources. - /// - /// - /// - /// Releases any resources allocated within the appender such as file handles, - /// network connections, etc. - /// - /// - /// It is a programming error to append to a closed appender. - /// - /// - protected override void OnClose() - { - // Remove all the attached appenders - lock(this) - { - if (m_appenderAttachedImpl != null) - { - m_appenderAttachedImpl.RemoveAllAppenders(); - } - } - } + /// + /// Closes the appender and releases resources. + /// + /// + /// + /// Releases any resources allocated within the appender such as file handles, + /// network connections, etc. + /// + /// + /// It is a programming error to append to a closed appender. + /// + /// + protected override void OnClose() + { + // Remove all the attached appenders + lock(this) + { + if (m_appenderAttachedImpl != null) + { + m_appenderAttachedImpl.RemoveAllAppenders(); + } + } + } - /// - /// Forward the logging event to the attached appenders - /// - /// The event to log. - /// - /// - /// Delivers the logging event to all the attached appenders. - /// - /// - protected override void Append(LoggingEvent loggingEvent) - { - // Pass the logging event on the the attached appenders - if (m_appenderAttachedImpl != null) - { - m_appenderAttachedImpl.AppendLoopOnAppenders(loggingEvent); - } - } + /// + /// Forward the logging event to the attached appenders + /// + /// The event to log. + /// + /// + /// Delivers the logging event to all the attached appenders. + /// + /// + protected override void Append(LoggingEvent loggingEvent) + { + // Pass the logging event on the the attached appenders + if (m_appenderAttachedImpl != null) + { + m_appenderAttachedImpl.AppendLoopOnAppenders(loggingEvent); + } + } - /// - /// Forward the logging events to the attached appenders - /// - /// The array of events to log. - /// - /// - /// Delivers the logging events to all the attached appenders. - /// - /// - protected override void Append(LoggingEvent[] loggingEvents) - { - // Pass the logging event on the the attached appenders - if (m_appenderAttachedImpl != null) - { - m_appenderAttachedImpl.AppendLoopOnAppenders(loggingEvents); - } - } + /// + /// Forward the logging events to the attached appenders + /// + /// The array of events to log. + /// + /// + /// Delivers the logging events to all the attached appenders. + /// + /// + protected override void Append(LoggingEvent[] loggingEvents) + { + // Pass the logging event on the the attached appenders + if (m_appenderAttachedImpl != null) + { + m_appenderAttachedImpl.AppendLoopOnAppenders(loggingEvents); + } + } - #endregion Override implementation of AppenderSkeleton + #endregion Override implementation of AppenderSkeleton - #region Implementation of IAppenderAttachable + #region Implementation of IAppenderAttachable - /// - /// Adds an to the list of appenders of this - /// instance. - /// - /// The to add to this appender. - /// - /// - /// If the specified is already in the list of - /// appenders, then it won't be added again. - /// - /// - public virtual void AddAppender(IAppender newAppender) - { - if (newAppender == null) - { - throw new ArgumentNullException("newAppender"); - } - lock(this) - { - if (m_appenderAttachedImpl == null) - { - m_appenderAttachedImpl = new log4net.Util.AppenderAttachedImpl(); - } - m_appenderAttachedImpl.AddAppender(newAppender); - } - } + /// + /// Adds an to the list of appenders of this + /// instance. + /// + /// The to add to this appender. + /// + /// + /// If the specified is already in the list of + /// appenders, then it won't be added again. + /// + /// + public virtual void AddAppender(IAppender newAppender) + { + if (newAppender == null) + { + throw new ArgumentNullException("newAppender"); + } + lock(this) + { + if (m_appenderAttachedImpl == null) + { + m_appenderAttachedImpl = new log4net.Util.AppenderAttachedImpl(); + } + m_appenderAttachedImpl.AddAppender(newAppender); + } + } - /// - /// Gets the appenders contained in this appender as an - /// . - /// - /// - /// If no appenders can be found, then an - /// is returned. - /// - /// - /// A collection of the appenders in this appender. - /// - public virtual AppenderCollection Appenders - { - get - { - lock(this) - { - if (m_appenderAttachedImpl == null) - { - return AppenderCollection.EmptyCollection; - } - else - { - return m_appenderAttachedImpl.Appenders; - } - } - } - } + /// + /// Gets the appenders contained in this appender as an + /// . + /// + /// + /// If no appenders can be found, then an + /// is returned. + /// + /// + /// A collection of the appenders in this appender. + /// + public virtual AppenderCollection Appenders + { + get + { + lock(this) + { + if (m_appenderAttachedImpl == null) + { + return AppenderCollection.EmptyCollection; + } + else + { + return m_appenderAttachedImpl.Appenders; + } + } + } + } - /// - /// Looks for the appender with the specified name. - /// - /// The name of the appender to lookup. - /// - /// The appender with the specified name, or null. - /// - /// - /// - /// Get the named appender attached to this appender. - /// - /// - public virtual IAppender GetAppender(string name) - { - lock(this) - { - if (m_appenderAttachedImpl == null || name == null) - { - return null; - } + /// + /// Looks for the appender with the specified name. + /// + /// The name of the appender to lookup. + /// + /// The appender with the specified name, or null. + /// + /// + /// + /// Get the named appender attached to this appender. + /// + /// + public virtual IAppender GetAppender(string name) + { + lock(this) + { + if (m_appenderAttachedImpl == null || name == null) + { + return null; + } - return m_appenderAttachedImpl.GetAppender(name); - } - } + return m_appenderAttachedImpl.GetAppender(name); + } + } - /// - /// Removes all previously added appenders from this appender. - /// - /// - /// - /// This is useful when re-reading configuration information. - /// - /// - public virtual void RemoveAllAppenders() - { - lock(this) - { - if (m_appenderAttachedImpl != null) - { - m_appenderAttachedImpl.RemoveAllAppenders(); - m_appenderAttachedImpl = null; - } - } - } + /// + /// Removes all previously added appenders from this appender. + /// + /// + /// + /// This is useful when re-reading configuration information. + /// + /// + public virtual void RemoveAllAppenders() + { + lock(this) + { + if (m_appenderAttachedImpl != null) + { + m_appenderAttachedImpl.RemoveAllAppenders(); + m_appenderAttachedImpl = null; + } + } + } - /// - /// Removes the specified appender from the list of appenders. - /// - /// The appender to remove. - /// The appender removed from the list - /// - /// The appender removed is not closed. - /// If you are discarding the appender you must call - /// on the appender removed. - /// - public virtual IAppender RemoveAppender(IAppender appender) - { - lock(this) - { - if (appender != null && m_appenderAttachedImpl != null) - { - return m_appenderAttachedImpl.RemoveAppender(appender); - } - } - return null; - } + /// + /// Removes the specified appender from the list of appenders. + /// + /// The appender to remove. + /// The appender removed from the list + /// + /// The appender removed is not closed. + /// If you are discarding the appender you must call + /// on the appender removed. + /// + public virtual IAppender RemoveAppender(IAppender appender) + { + lock(this) + { + if (appender != null && m_appenderAttachedImpl != null) + { + return m_appenderAttachedImpl.RemoveAppender(appender); + } + } + return null; + } - /// - /// Removes the appender with the specified name from the list of appenders. - /// - /// The name of the appender to remove. - /// The appender removed from the list - /// - /// The appender removed is not closed. - /// If you are discarding the appender you must call - /// on the appender removed. - /// - public virtual IAppender RemoveAppender(string name) - { - lock(this) - { - if (name != null && m_appenderAttachedImpl != null) - { - return m_appenderAttachedImpl.RemoveAppender(name); - } - } - return null; - } + /// + /// Removes the appender with the specified name from the list of appenders. + /// + /// The name of the appender to remove. + /// The appender removed from the list + /// + /// The appender removed is not closed. + /// If you are discarding the appender you must call + /// on the appender removed. + /// + public virtual IAppender RemoveAppender(string name) + { + lock(this) + { + if (name != null && m_appenderAttachedImpl != null) + { + return m_appenderAttachedImpl.RemoveAppender(name); + } + } + return null; + } - #endregion Implementation of IAppenderAttachable + #endregion Implementation of IAppenderAttachable - #region Private Instance Fields + #region Private Instance Fields - /// - /// Implementation of the interface - /// - private AppenderAttachedImpl m_appenderAttachedImpl; + /// + /// Implementation of the interface + /// + private AppenderAttachedImpl m_appenderAttachedImpl; - #endregion Private Instance Fields - } + #endregion Private Instance Fields + } } diff --git a/src/log4net/Appender/IAppender.cs b/src/log4net/Appender/IAppender.cs index a644f072..3f2fb0bd 100644 --- a/src/log4net/Appender/IAppender.cs +++ b/src/log4net/Appender/IAppender.cs @@ -23,56 +23,56 @@ namespace log4net.Appender { - /// - /// Implement this interface for your own strategies for printing log statements. - /// - /// - /// - /// Implementors should consider extending the - /// class which provides a default implementation of this interface. - /// - /// - /// Appenders can also implement the interface. Therefore - /// they would require that the method - /// be called after the appenders properties have been configured. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public interface IAppender - { - /// - /// Closes the appender and releases resources. - /// - /// - /// - /// Releases any resources allocated within the appender such as file handles, - /// network connections, etc. - /// - /// - /// It is a programming error to append to a closed appender. - /// - /// - void Close(); + /// + /// Implement this interface for your own strategies for printing log statements. + /// + /// + /// + /// Implementors should consider extending the + /// class which provides a default implementation of this interface. + /// + /// + /// Appenders can also implement the interface. Therefore + /// they would require that the method + /// be called after the appenders properties have been configured. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public interface IAppender + { + /// + /// Closes the appender and releases resources. + /// + /// + /// + /// Releases any resources allocated within the appender such as file handles, + /// network connections, etc. + /// + /// + /// It is a programming error to append to a closed appender. + /// + /// + void Close(); - /// - /// Log the logging event in Appender specific way. - /// - /// The event to log - /// - /// - /// This method is called to log a message into this appender. - /// - /// - void DoAppend(LoggingEvent loggingEvent); + /// + /// Log the logging event in Appender specific way. + /// + /// The event to log + /// + /// + /// This method is called to log a message into this appender. + /// + /// + void DoAppend(LoggingEvent loggingEvent); - /// - /// Gets or sets the name of this appender. - /// - /// The name of the appender. - /// - /// The name uniquely identifies the appender. - /// - string Name { get; set; } - } + /// + /// Gets or sets the name of this appender. + /// + /// The name of the appender. + /// + /// The name uniquely identifies the appender. + /// + string Name { get; set; } + } } diff --git a/src/log4net/Appender/IBulkAppender.cs b/src/log4net/Appender/IBulkAppender.cs index 469eb85a..9ccb1e87 100644 --- a/src/log4net/Appender/IBulkAppender.cs +++ b/src/log4net/Appender/IBulkAppender.cs @@ -21,28 +21,28 @@ namespace log4net.Appender { - /// - /// Interface for appenders that support bulk logging. - /// - /// - /// - /// This interface extends the interface to - /// support bulk logging of objects. Appenders - /// should only implement this interface if they can bulk log efficiently. - /// - /// - /// Nicko Cadell - public interface IBulkAppender : IAppender - { - /// - /// Log the array of logging events in Appender specific way. - /// - /// The events to log - /// - /// - /// This method is called to log an array of events into this appender. - /// - /// - void DoAppend(LoggingEvent[] loggingEvents); - } + /// + /// Interface for appenders that support bulk logging. + /// + /// + /// + /// This interface extends the interface to + /// support bulk logging of objects. Appenders + /// should only implement this interface if they can bulk log efficiently. + /// + /// + /// Nicko Cadell + public interface IBulkAppender : IAppender + { + /// + /// Log the array of logging events in Appender specific way. + /// + /// The events to log + /// + /// + /// This method is called to log an array of events into this appender. + /// + /// + void DoAppend(LoggingEvent[] loggingEvents); + } } diff --git a/src/log4net/Appender/LocalSyslogAppender.cs b/src/log4net/Appender/LocalSyslogAppender.cs index ad31b5df..3cd0c16d 100644 --- a/src/log4net/Appender/LocalSyslogAppender.cs +++ b/src/log4net/Appender/LocalSyslogAppender.cs @@ -29,577 +29,577 @@ namespace log4net.Appender { - /// - /// Logs events to a local syslog service. - /// - /// - /// - /// This appender uses the POSIX libc library functions openlog, syslog, and closelog. - /// If these functions are not available on the local system then this appender will not work! - /// - /// - /// The functions openlog, syslog, and closelog are specified in SUSv2 and - /// POSIX 1003.1-2001 standards. These are used to log messages to the local syslog service. - /// - /// - /// This appender talks to a local syslog service. If you need to log to a remote syslog - /// daemon and you cannot configure your local syslog service to do this you may be - /// able to use the to log via UDP. - /// - /// - /// Syslog messages must have a facility and and a severity. The severity - /// is derived from the Level of the logging event. - /// The facility must be chosen from the set of defined syslog - /// values. The facilities list is predefined - /// and cannot be extended. - /// - /// - /// An identifier is specified with each log message. This can be specified - /// by setting the property. The identity (also know - /// as the tag) must not contain white space. The default value for the - /// identity is the application name (from ). - /// - /// - /// Rob Lyon - /// Nicko Cadell - public class LocalSyslogAppender : AppenderSkeleton - { - #region Enumerations - - /// - /// syslog severities - /// - /// - /// - /// The log4net Level maps to a syslog severity using the - /// method and the - /// class. The severity is set on . - /// - /// - public enum SyslogSeverity - { - /// - /// system is unusable - /// - Emergency = 0, - - /// - /// action must be taken immediately - /// - Alert = 1, - - /// - /// critical conditions - /// - Critical = 2, - - /// - /// error conditions - /// - Error = 3, - - /// - /// warning conditions - /// - Warning = 4, - - /// - /// normal but significant condition - /// - Notice = 5, - - /// - /// informational - /// - Informational = 6, - - /// - /// debug-level messages - /// - Debug = 7 - }; - - /// - /// syslog facilities - /// - /// - /// - /// The syslog facility defines which subsystem the logging comes from. - /// This is set on the property. - /// - /// - public enum SyslogFacility - { - /// - /// kernel messages - /// - Kernel = 0, - - /// - /// random user-level messages - /// - User = 1, - - /// - /// mail system - /// - Mail = 2, - - /// - /// system daemons - /// - Daemons = 3, - - /// - /// security/authorization messages - /// - Authorization = 4, - - /// - /// messages generated internally by syslogd - /// - Syslog = 5, - - /// - /// line printer subsystem - /// - Printer = 6, - - /// - /// network news subsystem - /// - News = 7, - - /// - /// UUCP subsystem - /// - Uucp = 8, - - /// - /// clock (cron/at) daemon - /// - Clock = 9, - - /// - /// security/authorization messages (private) - /// - Authorization2 = 10, - - /// - /// ftp daemon - /// - Ftp = 11, - - /// - /// NTP subsystem - /// - Ntp = 12, - - /// - /// log audit - /// - Audit = 13, - - /// - /// log alert - /// - Alert = 14, - - /// - /// clock daemon - /// - Clock2 = 15, - - /// - /// reserved for local use - /// - Local0 = 16, - - /// - /// reserved for local use - /// - Local1 = 17, - - /// - /// reserved for local use - /// - Local2 = 18, - - /// - /// reserved for local use - /// - Local3 = 19, - - /// - /// reserved for local use - /// - Local4 = 20, - - /// - /// reserved for local use - /// - Local5 = 21, - - /// - /// reserved for local use - /// - Local6 = 22, - - /// - /// reserved for local use - /// - Local7 = 23 - } - - #endregion // Enumerations - - #region Public Instance Constructors - - /// - /// Initializes a new instance of the class. - /// - /// - /// This instance of the class is set up to write - /// to a local syslog service. - /// - public LocalSyslogAppender() - { - } - - #endregion // Public Instance Constructors - - #region Public Instance Properties - - /// - /// Message identity - /// - /// - /// - /// An identifier is specified with each log message. This can be specified - /// by setting the property. The identity (also know - /// as the tag) must not contain white space. The default value for the - /// identity is the application name (from ). - /// - /// - public string Identity - { - get { return m_identity; } - set { m_identity = value; } - } - - /// - /// Syslog facility - /// - /// - /// Set to one of the values. The list of - /// facilities is predefined and cannot be extended. The default value - /// is . - /// - public SyslogFacility Facility - { - get { return m_facility; } - set { m_facility = value; } - } - - #endregion // Public Instance Properties - - /// - /// Add a mapping of level to severity - /// - /// The mapping to add - /// - /// - /// Adds a to this appender. - /// - /// - public void AddMapping(LevelSeverity mapping) - { - m_levelMapping.Add(mapping); - } - - #region IOptionHandler Implementation - - /// - /// Initialize the appender based on the options set. - /// - /// - /// - /// This is part of the delayed object - /// activation scheme. The method must - /// be called on this object after the configuration properties have - /// been set. Until is called this - /// object is in an undefined state and must not be used. - /// - /// - /// If any of the configuration properties are modified then - /// must be called again. - /// - /// + /// + /// Logs events to a local syslog service. + /// + /// + /// + /// This appender uses the POSIX libc library functions openlog, syslog, and closelog. + /// If these functions are not available on the local system then this appender will not work! + /// + /// + /// The functions openlog, syslog, and closelog are specified in SUSv2 and + /// POSIX 1003.1-2001 standards. These are used to log messages to the local syslog service. + /// + /// + /// This appender talks to a local syslog service. If you need to log to a remote syslog + /// daemon and you cannot configure your local syslog service to do this you may be + /// able to use the to log via UDP. + /// + /// + /// Syslog messages must have a facility and and a severity. The severity + /// is derived from the Level of the logging event. + /// The facility must be chosen from the set of defined syslog + /// values. The facilities list is predefined + /// and cannot be extended. + /// + /// + /// An identifier is specified with each log message. This can be specified + /// by setting the property. The identity (also know + /// as the tag) must not contain white space. The default value for the + /// identity is the application name (from ). + /// + /// + /// Rob Lyon + /// Nicko Cadell + public class LocalSyslogAppender : AppenderSkeleton + { + #region Enumerations + + /// + /// syslog severities + /// + /// + /// + /// The log4net Level maps to a syslog severity using the + /// method and the + /// class. The severity is set on . + /// + /// + public enum SyslogSeverity + { + /// + /// system is unusable + /// + Emergency = 0, + + /// + /// action must be taken immediately + /// + Alert = 1, + + /// + /// critical conditions + /// + Critical = 2, + + /// + /// error conditions + /// + Error = 3, + + /// + /// warning conditions + /// + Warning = 4, + + /// + /// normal but significant condition + /// + Notice = 5, + + /// + /// informational + /// + Informational = 6, + + /// + /// debug-level messages + /// + Debug = 7 + }; + + /// + /// syslog facilities + /// + /// + /// + /// The syslog facility defines which subsystem the logging comes from. + /// This is set on the property. + /// + /// + public enum SyslogFacility + { + /// + /// kernel messages + /// + Kernel = 0, + + /// + /// random user-level messages + /// + User = 1, + + /// + /// mail system + /// + Mail = 2, + + /// + /// system daemons + /// + Daemons = 3, + + /// + /// security/authorization messages + /// + Authorization = 4, + + /// + /// messages generated internally by syslogd + /// + Syslog = 5, + + /// + /// line printer subsystem + /// + Printer = 6, + + /// + /// network news subsystem + /// + News = 7, + + /// + /// UUCP subsystem + /// + Uucp = 8, + + /// + /// clock (cron/at) daemon + /// + Clock = 9, + + /// + /// security/authorization messages (private) + /// + Authorization2 = 10, + + /// + /// ftp daemon + /// + Ftp = 11, + + /// + /// NTP subsystem + /// + Ntp = 12, + + /// + /// log audit + /// + Audit = 13, + + /// + /// log alert + /// + Alert = 14, + + /// + /// clock daemon + /// + Clock2 = 15, + + /// + /// reserved for local use + /// + Local0 = 16, + + /// + /// reserved for local use + /// + Local1 = 17, + + /// + /// reserved for local use + /// + Local2 = 18, + + /// + /// reserved for local use + /// + Local3 = 19, + + /// + /// reserved for local use + /// + Local4 = 20, + + /// + /// reserved for local use + /// + Local5 = 21, + + /// + /// reserved for local use + /// + Local6 = 22, + + /// + /// reserved for local use + /// + Local7 = 23 + } + + #endregion // Enumerations + + #region Public Instance Constructors + + /// + /// Initializes a new instance of the class. + /// + /// + /// This instance of the class is set up to write + /// to a local syslog service. + /// + public LocalSyslogAppender() + { + } + + #endregion // Public Instance Constructors + + #region Public Instance Properties + + /// + /// Message identity + /// + /// + /// + /// An identifier is specified with each log message. This can be specified + /// by setting the property. The identity (also know + /// as the tag) must not contain white space. The default value for the + /// identity is the application name (from ). + /// + /// + public string Identity + { + get { return m_identity; } + set { m_identity = value; } + } + + /// + /// Syslog facility + /// + /// + /// Set to one of the values. The list of + /// facilities is predefined and cannot be extended. The default value + /// is . + /// + public SyslogFacility Facility + { + get { return m_facility; } + set { m_facility = value; } + } + + #endregion // Public Instance Properties + + /// + /// Add a mapping of level to severity + /// + /// The mapping to add + /// + /// + /// Adds a to this appender. + /// + /// + public void AddMapping(LevelSeverity mapping) + { + m_levelMapping.Add(mapping); + } + + #region IOptionHandler Implementation + + /// + /// Initialize the appender based on the options set. + /// + /// + /// + /// This is part of the delayed object + /// activation scheme. The method must + /// be called on this object after the configuration properties have + /// been set. Until is called this + /// object is in an undefined state and must not be used. + /// + /// + /// If any of the configuration properties are modified then + /// must be called again. + /// + /// #if NET_4_0 || MONO_4_0 || NETSTANDARD - [System.Security.SecuritySafeCritical] + [System.Security.SecuritySafeCritical] #endif - public override void ActivateOptions() - { - base.ActivateOptions(); - - m_levelMapping.ActivateOptions(); - - string identString = m_identity; - if (identString == null) - { - // Set to app name by default - identString = SystemInfo.ApplicationFriendlyName; - } - - // create the native heap ansi string. Note this is a copy of our string - // so we do not need to hold on to the string itself, holding on to the - // handle will keep the heap ansi string alive. - m_handleToIdentity = Marshal.StringToHGlobalAnsi(identString); - - // open syslog - openlog(m_handleToIdentity, 1, m_facility); - } - - #endregion // IOptionHandler Implementation - - #region AppenderSkeleton Implementation - - /// - /// This method is called by the method. - /// - /// The event to log. - /// - /// - /// Writes the event to a remote syslog daemon. - /// - /// - /// The format of the output will depend on the appender's layout. - /// - /// + public override void ActivateOptions() + { + base.ActivateOptions(); + + m_levelMapping.ActivateOptions(); + + string identString = m_identity; + if (identString == null) + { + // Set to app name by default + identString = SystemInfo.ApplicationFriendlyName; + } + + // create the native heap ansi string. Note this is a copy of our string + // so we do not need to hold on to the string itself, holding on to the + // handle will keep the heap ansi string alive. + m_handleToIdentity = Marshal.StringToHGlobalAnsi(identString); + + // open syslog + openlog(m_handleToIdentity, 1, m_facility); + } + + #endregion // IOptionHandler Implementation + + #region AppenderSkeleton Implementation + + /// + /// This method is called by the method. + /// + /// The event to log. + /// + /// + /// Writes the event to a remote syslog daemon. + /// + /// + /// The format of the output will depend on the appender's layout. + /// + /// #if NET_4_0 || MONO_4_0 || NETSTANDARD - [System.Security.SecuritySafeCritical] + [System.Security.SecuritySafeCritical] #endif #if !NETSTANDARD1_3 - [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, UnmanagedCode = true)] + [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, UnmanagedCode = true)] #endif - protected override void Append(LoggingEvent loggingEvent) - { - int priority = GeneratePriority(m_facility, GetSeverity(loggingEvent.Level)); - string message = RenderLoggingEvent(loggingEvent); - - // Call the local libc syslog method - // The second argument is a printf style format string - syslog(priority, "%s", message); - } - - /// - /// Close the syslog when the appender is closed - /// - /// - /// - /// Close the syslog when the appender is closed - /// - /// + protected override void Append(LoggingEvent loggingEvent) + { + int priority = GeneratePriority(m_facility, GetSeverity(loggingEvent.Level)); + string message = RenderLoggingEvent(loggingEvent); + + // Call the local libc syslog method + // The second argument is a printf style format string + syslog(priority, "%s", message); + } + + /// + /// Close the syslog when the appender is closed + /// + /// + /// + /// Close the syslog when the appender is closed + /// + /// #if NET_4_0 || MONO_4_0 || NETSTANDARD - [System.Security.SecuritySafeCritical] + [System.Security.SecuritySafeCritical] #endif - protected override void OnClose() - { - base.OnClose(); - - try - { - // close syslog - closelog(); - } - catch(DllNotFoundException) - { - // Ignore dll not found at this point - } - - if (m_handleToIdentity != IntPtr.Zero) - { - // free global ident - Marshal.FreeHGlobal(m_handleToIdentity); - } - } - - /// - /// This appender requires a to be set. - /// - /// true - /// - /// - /// This appender requires a to be set. - /// - /// - protected override bool RequiresLayout - { - get { return true; } - } - - #endregion // AppenderSkeleton Implementation - - #region Protected Members - - /// - /// Translates a log4net level to a syslog severity. - /// - /// A log4net level. - /// A syslog severity. - /// - /// - /// Translates a log4net level to a syslog severity. - /// - /// - protected virtual SyslogSeverity GetSeverity(Level level) - { - LevelSeverity levelSeverity = m_levelMapping.Lookup(level) as LevelSeverity; - if (levelSeverity != null) - { - return levelSeverity.Severity; - } - - // - // Fallback to sensible default values - // - - if (level >= Level.Alert) - { - return SyslogSeverity.Alert; - } - else if (level >= Level.Critical) - { - return SyslogSeverity.Critical; - } - else if (level >= Level.Error) - { - return SyslogSeverity.Error; - } - else if (level >= Level.Warn) - { - return SyslogSeverity.Warning; - } - else if (level >= Level.Notice) - { - return SyslogSeverity.Notice; - } - else if (level >= Level.Info) - { - return SyslogSeverity.Informational; - } - // Default setting - return SyslogSeverity.Debug; - } - - #endregion // Protected Members - - #region Public Static Members - - /// - /// Generate a syslog priority. - /// - /// The syslog facility. - /// The syslog severity. - /// A syslog priority. - private static int GeneratePriority(SyslogFacility facility, SyslogSeverity severity) - { - return ((int)facility * 8) + (int)severity; - } - - #endregion // Public Static Members - - #region Private Instances Fields - - /// - /// The facility. The default facility is . - /// - private SyslogFacility m_facility = SyslogFacility.User; - - /// - /// The message identity - /// - private string m_identity; - - /// - /// Marshaled handle to the identity string. We have to hold on to the - /// string as the openlog and syslog APIs just hold the - /// pointer to the ident and dereference it for each log message. - /// - private IntPtr m_handleToIdentity = IntPtr.Zero; - - /// - /// Mapping from level object to syslog severity - /// - private LevelMapping m_levelMapping = new LevelMapping(); - - #endregion // Private Instances Fields - - #region External Members - - /// - /// Open connection to system logger. - /// - [DllImport("libc")] - private static extern void openlog(IntPtr ident, int option, SyslogFacility facility); - - /// - /// Generate a log message. - /// - /// - /// - /// The libc syslog method takes a format string and a variable argument list similar - /// to the classic printf function. As this type of vararg list is not supported - /// by C# we need to specify the arguments explicitly. Here we have specified the - /// format string with a single message argument. The caller must set the format - /// string to "%s". - /// - /// - [DllImport("libc", CharSet=CharSet.Ansi, CallingConvention=CallingConvention.Cdecl)] - private static extern void syslog(int priority, string format, string message); - - /// - /// Close descriptor used to write to system logger. - /// - [DllImport("libc")] - private static extern void closelog(); - - #endregion // External Members - - #region LevelSeverity LevelMapping Entry - - /// - /// A class to act as a mapping between the level that a logging call is made at and - /// the syslog severity that is should be logged at. - /// - /// - /// - /// A class to act as a mapping between the level that a logging call is made at and - /// the syslog severity that is should be logged at. - /// - /// - public class LevelSeverity : LevelMappingEntry - { - private SyslogSeverity m_severity; - - /// - /// The mapped syslog severity for the specified level - /// - /// - /// - /// Required property. - /// The mapped syslog severity for the specified level - /// - /// - public SyslogSeverity Severity - { - get { return m_severity; } - set { m_severity = value; } - } - } - - #endregion // LevelSeverity LevelMapping Entry - } + protected override void OnClose() + { + base.OnClose(); + + try + { + // close syslog + closelog(); + } + catch(DllNotFoundException) + { + // Ignore dll not found at this point + } + + if (m_handleToIdentity != IntPtr.Zero) + { + // free global ident + Marshal.FreeHGlobal(m_handleToIdentity); + } + } + + /// + /// This appender requires a to be set. + /// + /// true + /// + /// + /// This appender requires a to be set. + /// + /// + protected override bool RequiresLayout + { + get { return true; } + } + + #endregion // AppenderSkeleton Implementation + + #region Protected Members + + /// + /// Translates a log4net level to a syslog severity. + /// + /// A log4net level. + /// A syslog severity. + /// + /// + /// Translates a log4net level to a syslog severity. + /// + /// + protected virtual SyslogSeverity GetSeverity(Level level) + { + LevelSeverity levelSeverity = m_levelMapping.Lookup(level) as LevelSeverity; + if (levelSeverity != null) + { + return levelSeverity.Severity; + } + + // + // Fallback to sensible default values + // + + if (level >= Level.Alert) + { + return SyslogSeverity.Alert; + } + else if (level >= Level.Critical) + { + return SyslogSeverity.Critical; + } + else if (level >= Level.Error) + { + return SyslogSeverity.Error; + } + else if (level >= Level.Warn) + { + return SyslogSeverity.Warning; + } + else if (level >= Level.Notice) + { + return SyslogSeverity.Notice; + } + else if (level >= Level.Info) + { + return SyslogSeverity.Informational; + } + // Default setting + return SyslogSeverity.Debug; + } + + #endregion // Protected Members + + #region Public Static Members + + /// + /// Generate a syslog priority. + /// + /// The syslog facility. + /// The syslog severity. + /// A syslog priority. + private static int GeneratePriority(SyslogFacility facility, SyslogSeverity severity) + { + return ((int)facility * 8) + (int)severity; + } + + #endregion // Public Static Members + + #region Private Instances Fields + + /// + /// The facility. The default facility is . + /// + private SyslogFacility m_facility = SyslogFacility.User; + + /// + /// The message identity + /// + private string m_identity; + + /// + /// Marshaled handle to the identity string. We have to hold on to the + /// string as the openlog and syslog APIs just hold the + /// pointer to the ident and dereference it for each log message. + /// + private IntPtr m_handleToIdentity = IntPtr.Zero; + + /// + /// Mapping from level object to syslog severity + /// + private LevelMapping m_levelMapping = new LevelMapping(); + + #endregion // Private Instances Fields + + #region External Members + + /// + /// Open connection to system logger. + /// + [DllImport("libc")] + private static extern void openlog(IntPtr ident, int option, SyslogFacility facility); + + /// + /// Generate a log message. + /// + /// + /// + /// The libc syslog method takes a format string and a variable argument list similar + /// to the classic printf function. As this type of vararg list is not supported + /// by C# we need to specify the arguments explicitly. Here we have specified the + /// format string with a single message argument. The caller must set the format + /// string to "%s". + /// + /// + [DllImport("libc", CharSet=CharSet.Ansi, CallingConvention=CallingConvention.Cdecl)] + private static extern void syslog(int priority, string format, string message); + + /// + /// Close descriptor used to write to system logger. + /// + [DllImport("libc")] + private static extern void closelog(); + + #endregion // External Members + + #region LevelSeverity LevelMapping Entry + + /// + /// A class to act as a mapping between the level that a logging call is made at and + /// the syslog severity that is should be logged at. + /// + /// + /// + /// A class to act as a mapping between the level that a logging call is made at and + /// the syslog severity that is should be logged at. + /// + /// + public class LevelSeverity : LevelMappingEntry + { + private SyslogSeverity m_severity; + + /// + /// The mapped syslog severity for the specified level + /// + /// + /// + /// Required property. + /// The mapped syslog severity for the specified level + /// + /// + public SyslogSeverity Severity + { + get { return m_severity; } + set { m_severity = value; } + } + } + + #endregion // LevelSeverity LevelMapping Entry + } } #endif diff --git a/src/log4net/Appender/ManagedColoredConsoleAppender.cs b/src/log4net/Appender/ManagedColoredConsoleAppender.cs index 9edfce50..ecc69490 100644 --- a/src/log4net/Appender/ManagedColoredConsoleAppender.cs +++ b/src/log4net/Appender/ManagedColoredConsoleAppender.cs @@ -18,7 +18,7 @@ #endregion // Compatibility: -// http://msdn.microsoft.com/en-us/library/system.console.foregroundcolor.aspx +// http://msdn.microsoft.com/en-us/library/system.console.foregroundcolor.aspx // Disable for unsupported targets #if !NETCF #if !SSCLI @@ -48,294 +48,294 @@ namespace log4net.Appender { - /// - /// Appends colorful logging events to the console, using the .NET 2 - /// built-in capabilities. - /// - /// - /// - /// ManagedColoredConsoleAppender appends log events to the standard output stream - /// or the error output stream using a layout specified by the - /// user. It also allows the color of a specific type of message to be set. - /// - /// - /// By default, all output is written to the console's standard output stream. - /// The property can be set to direct the output to the - /// error stream. - /// - /// - /// When configuring the colored console appender, mappings should be - /// specified to map logging levels to colors. For example: - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// The Level is the standard log4net logging level while - /// ForeColor and BackColor are the values of - /// enumeration. - /// - /// - /// Based on the ColoredConsoleAppender - /// - /// - /// Rick Hobbs - /// Nicko Cadell - /// Pavlos Touboulidis - public class ManagedColoredConsoleAppender: AppenderSkeleton - { - /// - /// Initializes a new instance of the class. - /// - /// - /// The instance of the class is set up to write - /// to the standard output stream. - /// - public ManagedColoredConsoleAppender() - { - } - - #region Public Instance Properties - /// - /// Target is the value of the console output stream. - /// This is either "Console.Out" or "Console.Error". - /// - /// - /// Target is the value of the console output stream. - /// This is either "Console.Out" or "Console.Error". - /// - /// - /// - /// Target is the value of the console output stream. - /// This is either "Console.Out" or "Console.Error". - /// - /// - public virtual string Target - { - get { return m_writeToErrorStream ? ConsoleError : ConsoleOut; } - set - { - string v = value.Trim(); + /// + /// Appends colorful logging events to the console, using the .NET 2 + /// built-in capabilities. + /// + /// + /// + /// ManagedColoredConsoleAppender appends log events to the standard output stream + /// or the error output stream using a layout specified by the + /// user. It also allows the color of a specific type of message to be set. + /// + /// + /// By default, all output is written to the console's standard output stream. + /// The property can be set to direct the output to the + /// error stream. + /// + /// + /// When configuring the colored console appender, mappings should be + /// specified to map logging levels to colors. For example: + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// The Level is the standard log4net logging level while + /// ForeColor and BackColor are the values of + /// enumeration. + /// + /// + /// Based on the ColoredConsoleAppender + /// + /// + /// Rick Hobbs + /// Nicko Cadell + /// Pavlos Touboulidis + public class ManagedColoredConsoleAppender: AppenderSkeleton + { + /// + /// Initializes a new instance of the class. + /// + /// + /// The instance of the class is set up to write + /// to the standard output stream. + /// + public ManagedColoredConsoleAppender() + { + } + + #region Public Instance Properties + /// + /// Target is the value of the console output stream. + /// This is either "Console.Out" or "Console.Error". + /// + /// + /// Target is the value of the console output stream. + /// This is either "Console.Out" or "Console.Error". + /// + /// + /// + /// Target is the value of the console output stream. + /// This is either "Console.Out" or "Console.Error". + /// + /// + public virtual string Target + { + get { return m_writeToErrorStream ? ConsoleError : ConsoleOut; } + set + { + string v = value.Trim(); - if (SystemInfo.EqualsIgnoringCase(ConsoleError, v)) - { - m_writeToErrorStream = true; - } - else - { - m_writeToErrorStream = false; - } - } - } + if (SystemInfo.EqualsIgnoringCase(ConsoleError, v)) + { + m_writeToErrorStream = true; + } + else + { + m_writeToErrorStream = false; + } + } + } - /// - /// Add a mapping of level to color - done by the config file - /// - /// The mapping to add - /// - /// - /// Add a mapping to this appender. - /// Each mapping defines the foreground and background colors - /// for a level. - /// - /// - public void AddMapping(LevelColors mapping) - { - m_levelMapping.Add(mapping); - } - #endregion // Public Instance Properties + /// + /// Add a mapping of level to color - done by the config file + /// + /// The mapping to add + /// + /// + /// Add a mapping to this appender. + /// Each mapping defines the foreground and background colors + /// for a level. + /// + /// + public void AddMapping(LevelColors mapping) + { + m_levelMapping.Add(mapping); + } + #endregion // Public Instance Properties - #region Override implementation of AppenderSkeleton - /// - /// This method is called by the method. - /// - /// The event to log. - /// - /// - /// Writes the event to the console. - /// - /// - /// The format of the output will depend on the appender's layout. - /// - /// - protected override void Append(log4net.Core.LoggingEvent loggingEvent) - { - System.IO.TextWriter writer; - - if (m_writeToErrorStream) - writer = Console.Error; - else - writer = Console.Out; - - // Reset color - Console.ResetColor(); - - // see if there is a specified lookup - LevelColors levelColors = m_levelMapping.Lookup(loggingEvent.Level) as LevelColors; - if (levelColors != null) - { - // if the backColor has been explicitly set - if (levelColors.HasBackColor) - Console.BackgroundColor = levelColors.BackColor; - // if the foreColor has been explicitly set - if (levelColors.HasForeColor) - Console.ForegroundColor = levelColors.ForeColor; - } - - // Render the event to a string - string strLoggingMessage = RenderLoggingEvent(loggingEvent); - // and write it - writer.Write(strLoggingMessage); + #region Override implementation of AppenderSkeleton + /// + /// This method is called by the method. + /// + /// The event to log. + /// + /// + /// Writes the event to the console. + /// + /// + /// The format of the output will depend on the appender's layout. + /// + /// + protected override void Append(log4net.Core.LoggingEvent loggingEvent) + { + System.IO.TextWriter writer; + + if (m_writeToErrorStream) + writer = Console.Error; + else + writer = Console.Out; + + // Reset color + Console.ResetColor(); + + // see if there is a specified lookup + LevelColors levelColors = m_levelMapping.Lookup(loggingEvent.Level) as LevelColors; + if (levelColors != null) + { + // if the backColor has been explicitly set + if (levelColors.HasBackColor) + Console.BackgroundColor = levelColors.BackColor; + // if the foreColor has been explicitly set + if (levelColors.HasForeColor) + Console.ForegroundColor = levelColors.ForeColor; + } + + // Render the event to a string + string strLoggingMessage = RenderLoggingEvent(loggingEvent); + // and write it + writer.Write(strLoggingMessage); - // Reset color again - Console.ResetColor(); - } + // Reset color again + Console.ResetColor(); + } - /// - /// This appender requires a to be set. - /// - /// true - /// - /// - /// This appender requires a to be set. - /// - /// - protected override bool RequiresLayout - { - get { return true; } - } + /// + /// This appender requires a to be set. + /// + /// true + /// + /// + /// This appender requires a to be set. + /// + /// + protected override bool RequiresLayout + { + get { return true; } + } - /// - /// Initialize the options for this appender - /// - /// - /// - /// Initialize the level to color mappings set on this appender. - /// - /// - public override void ActivateOptions() - { - base.ActivateOptions(); - m_levelMapping.ActivateOptions(); - } - #endregion // Override implementation of AppenderSkeleton + /// + /// Initialize the options for this appender + /// + /// + /// + /// Initialize the level to color mappings set on this appender. + /// + /// + public override void ActivateOptions() + { + base.ActivateOptions(); + m_levelMapping.ActivateOptions(); + } + #endregion // Override implementation of AppenderSkeleton - #region Public Static Fields - /// - /// The to use when writing to the Console - /// standard output stream. - /// - /// - /// - /// The to use when writing to the Console - /// standard output stream. - /// - /// - public const string ConsoleOut = "Console.Out"; + #region Public Static Fields + /// + /// The to use when writing to the Console + /// standard output stream. + /// + /// + /// + /// The to use when writing to the Console + /// standard output stream. + /// + /// + public const string ConsoleOut = "Console.Out"; - /// - /// The to use when writing to the Console - /// standard error output stream. - /// - /// - /// - /// The to use when writing to the Console - /// standard error output stream. - /// - /// - public const string ConsoleError = "Console.Error"; - #endregion // Public Static Fields + /// + /// The to use when writing to the Console + /// standard error output stream. + /// + /// + /// + /// The to use when writing to the Console + /// standard error output stream. + /// + /// + public const string ConsoleError = "Console.Error"; + #endregion // Public Static Fields - #region Private Instances Fields - /// - /// Flag to write output to the error stream rather than the standard output stream - /// - private bool m_writeToErrorStream = false; + #region Private Instances Fields + /// + /// Flag to write output to the error stream rather than the standard output stream + /// + private bool m_writeToErrorStream = false; - /// - /// Mapping from level object to color value - /// - private LevelMapping m_levelMapping = new LevelMapping(); - #endregion // Private Instances Fields + /// + /// Mapping from level object to color value + /// + private LevelMapping m_levelMapping = new LevelMapping(); + #endregion // Private Instances Fields - #region LevelColors LevelMapping Entry - /// - /// A class to act as a mapping between the level that a logging call is made at and - /// the color it should be displayed as. - /// - /// - /// - /// Defines the mapping between a level and the color it should be displayed in. - /// - /// - public class LevelColors : LevelMappingEntry - { - /// - /// The mapped foreground color for the specified level - /// - /// - /// - /// Required property. - /// The mapped foreground color for the specified level. - /// - /// - public ConsoleColor ForeColor - { - get { return (this.foreColor); } - // Keep a flag that the color has been set - // and is no longer the default. - set { this.foreColor = value; this.hasForeColor = true; } - } - private ConsoleColor foreColor; - private bool hasForeColor; + #region LevelColors LevelMapping Entry + /// + /// A class to act as a mapping between the level that a logging call is made at and + /// the color it should be displayed as. + /// + /// + /// + /// Defines the mapping between a level and the color it should be displayed in. + /// + /// + public class LevelColors : LevelMappingEntry + { + /// + /// The mapped foreground color for the specified level + /// + /// + /// + /// Required property. + /// The mapped foreground color for the specified level. + /// + /// + public ConsoleColor ForeColor + { + get { return (this.foreColor); } + // Keep a flag that the color has been set + // and is no longer the default. + set { this.foreColor = value; this.hasForeColor = true; } + } + private ConsoleColor foreColor; + private bool hasForeColor; internal bool HasForeColor { get { return hasForeColor; } } - /// - /// The mapped background color for the specified level - /// - /// - /// - /// Required property. - /// The mapped background color for the specified level. - /// - /// - public ConsoleColor BackColor - { - get { return (this.backColor); } - // Keep a flag that the color has been set - // and is no longer the default. - set { this.backColor = value; this.hasBackColor = true; } - } - private ConsoleColor backColor; + /// + /// The mapped background color for the specified level + /// + /// + /// + /// Required property. + /// The mapped background color for the specified level. + /// + /// + public ConsoleColor BackColor + { + get { return (this.backColor); } + // Keep a flag that the color has been set + // and is no longer the default. + set { this.backColor = value; this.hasBackColor = true; } + } + private ConsoleColor backColor; private bool hasBackColor; internal bool HasBackColor { get { return hasBackColor; } } - } - #endregion // LevelColors LevelMapping Entry - } + } + #endregion // LevelColors LevelMapping Entry + } } #endif diff --git a/src/log4net/Appender/MemoryAppender.cs b/src/log4net/Appender/MemoryAppender.cs index 441569ce..5c30c2ba 100644 --- a/src/log4net/Appender/MemoryAppender.cs +++ b/src/log4net/Appender/MemoryAppender.cs @@ -24,165 +24,165 @@ namespace log4net.Appender { - /// - /// Stores logging events in an array. - /// - /// - /// - /// The memory appender stores all the logging events - /// that are appended in an in-memory array. - /// - /// - /// Use the method to get - /// and clear the current list of events that have been appended. - /// - /// - /// Use the method to get the current - /// list of events that have been appended. Note there is a - /// race-condition when calling and - /// in pairs, you better use in that case. - /// - /// - /// Use the method to clear the - /// current list of events. Note there is a - /// race-condition when calling and - /// in pairs, you better use in that case. - /// - /// - /// Julian Biddle - /// Nicko Cadell - /// Gert Driesen - public class MemoryAppender : AppenderSkeleton - { - #region Public Instance Constructors - - /// - /// Initializes a new instance of the class. - /// - /// - /// - /// Default constructor. - /// - /// - public MemoryAppender() : base() - { - m_eventsList = new ArrayList(); - } - - #endregion Protected Instance Constructors - - #region Public Instance Properties - - /// - /// Gets the events that have been logged. - /// - /// The events that have been logged - /// - /// - /// Gets the events that have been logged. - /// - /// - public virtual LoggingEvent[] GetEvents() - { + /// + /// Stores logging events in an array. + /// + /// + /// + /// The memory appender stores all the logging events + /// that are appended in an in-memory array. + /// + /// + /// Use the method to get + /// and clear the current list of events that have been appended. + /// + /// + /// Use the method to get the current + /// list of events that have been appended. Note there is a + /// race-condition when calling and + /// in pairs, you better use in that case. + /// + /// + /// Use the method to clear the + /// current list of events. Note there is a + /// race-condition when calling and + /// in pairs, you better use in that case. + /// + /// + /// Julian Biddle + /// Nicko Cadell + /// Gert Driesen + public class MemoryAppender : AppenderSkeleton + { + #region Public Instance Constructors + + /// + /// Initializes a new instance of the class. + /// + /// + /// + /// Default constructor. + /// + /// + public MemoryAppender() : base() + { + m_eventsList = new ArrayList(); + } + + #endregion Protected Instance Constructors + + #region Public Instance Properties + + /// + /// Gets the events that have been logged. + /// + /// The events that have been logged + /// + /// + /// Gets the events that have been logged. + /// + /// + public virtual LoggingEvent[] GetEvents() + { lock (m_eventsList.SyncRoot) { return (LoggingEvent[]) m_eventsList.ToArray(typeof(LoggingEvent)); } - } - - /// - /// Gets or sets a value indicating whether only part of the logging event - /// data should be fixed. - /// - /// - /// true if the appender should only fix part of the logging event - /// data, otherwise false. The default is false. - /// - /// - /// - /// Setting this property to true will cause only part of the event - /// data to be fixed and stored in the appender, hereby improving performance. - /// - /// - /// See for more information. - /// - /// - [Obsolete("Use Fix property")] - public virtual bool OnlyFixPartialEventData - { - get { return (Fix == FixFlags.Partial); } - set - { - if (value) - { - Fix = FixFlags.Partial; - } - else - { - Fix = FixFlags.All; - } - } - } - - /// - /// Gets or sets the fields that will be fixed in the event - /// - /// - /// - /// The logging event needs to have certain thread specific values - /// captured before it can be buffered. See - /// for details. - /// - /// - public virtual FixFlags Fix - { - get { return m_fixFlags; } - set { m_fixFlags = value; } - } - - #endregion Public Instance Properties - - #region Override implementation of AppenderSkeleton - - /// - /// This method is called by the method. - /// - /// the event to log - /// - /// Stores the in the events list. - /// - protected override void Append(LoggingEvent loggingEvent) - { - // Because we are caching the LoggingEvent beyond the - // lifetime of the Append() method we must fix any - // volatile data in the event. - loggingEvent.Fix = this.Fix; + } + + /// + /// Gets or sets a value indicating whether only part of the logging event + /// data should be fixed. + /// + /// + /// true if the appender should only fix part of the logging event + /// data, otherwise false. The default is false. + /// + /// + /// + /// Setting this property to true will cause only part of the event + /// data to be fixed and stored in the appender, hereby improving performance. + /// + /// + /// See for more information. + /// + /// + [Obsolete("Use Fix property")] + public virtual bool OnlyFixPartialEventData + { + get { return (Fix == FixFlags.Partial); } + set + { + if (value) + { + Fix = FixFlags.Partial; + } + else + { + Fix = FixFlags.All; + } + } + } + + /// + /// Gets or sets the fields that will be fixed in the event + /// + /// + /// + /// The logging event needs to have certain thread specific values + /// captured before it can be buffered. See + /// for details. + /// + /// + public virtual FixFlags Fix + { + get { return m_fixFlags; } + set { m_fixFlags = value; } + } + + #endregion Public Instance Properties + + #region Override implementation of AppenderSkeleton + + /// + /// This method is called by the method. + /// + /// the event to log + /// + /// Stores the in the events list. + /// + protected override void Append(LoggingEvent loggingEvent) + { + // Because we are caching the LoggingEvent beyond the + // lifetime of the Append() method we must fix any + // volatile data in the event. + loggingEvent.Fix = this.Fix; lock (m_eventsList.SyncRoot) { m_eventsList.Add(loggingEvent); } - } + } - #endregion Override implementation of AppenderSkeleton + #endregion Override implementation of AppenderSkeleton - #region Public Instance Methods + #region Public Instance Methods - /// - /// Clear the list of events - /// - /// - /// Clear the list of events - /// - public virtual void Clear() - { + /// + /// Clear the list of events + /// + /// + /// Clear the list of events + /// + public virtual void Clear() + { lock (m_eventsList.SyncRoot) { m_eventsList.Clear(); } - } + } /// /// Gets the events that have been logged and clears the list of events. @@ -203,23 +203,23 @@ public virtual LoggingEvent[] PopAllEvents() } } - #endregion Public Instance Methods + #endregion Public Instance Methods - #region Protected Instance Fields + #region Protected Instance Fields - /// - /// The list of events that have been appended. - /// - protected ArrayList m_eventsList; + /// + /// The list of events that have been appended. + /// + protected ArrayList m_eventsList; - /// - /// Value indicating which fields in the event should be fixed - /// - /// - /// By default all fields are fixed - /// - protected FixFlags m_fixFlags = FixFlags.All; + /// + /// Value indicating which fields in the event should be fixed + /// + /// + /// By default all fields are fixed + /// + protected FixFlags m_fixFlags = FixFlags.All; - #endregion Protected Instance Fields - } + #endregion Protected Instance Fields + } } diff --git a/src/log4net/Appender/NetSendAppender.cs b/src/log4net/Appender/NetSendAppender.cs index b03d21d6..f6fdbb55 100644 --- a/src/log4net/Appender/NetSendAppender.cs +++ b/src/log4net/Appender/NetSendAppender.cs @@ -37,386 +37,386 @@ namespace log4net.Appender { - /// - /// Logs entries by sending network messages using the - /// native function. - /// - /// - /// - /// You can send messages only to names that are active - /// on the network. If you send the message to a user name, - /// that user must be logged on and running the Messenger - /// service to receive the message. - /// - /// - /// The receiver will get a top most window displaying the - /// messages one at a time, therefore this appender should - /// not be used to deliver a high volume of messages. - /// - /// - /// The following table lists some possible uses for this appender : - /// - /// - /// - /// - /// Action - /// Property Value(s) - /// - /// - /// Send a message to a user account on the local machine - /// - /// - /// = <name of the local machine> - /// - /// - /// = <user name> - /// - /// - /// - /// - /// Send a message to a user account on a remote machine - /// - /// - /// = <name of the remote machine> - /// - /// - /// = <user name> - /// - /// - /// - /// - /// Send a message to a domain user account - /// - /// - /// = <name of a domain controller | uninitialized> - /// - /// - /// = <user name> - /// - /// - /// - /// - /// Send a message to all the names in a workgroup or domain - /// - /// - /// = <workgroup name | domain name>* - /// - /// - /// - /// - /// Send a message from the local machine to a remote machine - /// - /// - /// = <name of the local machine | uninitialized> - /// - /// - /// = <name of the remote machine> - /// - /// - /// - /// - /// - /// - /// Note : security restrictions apply for sending - /// network messages, see - /// for more information. - /// - /// - /// - /// - /// An example configuration section to log information - /// using this appender from the local machine, named - /// LOCAL_PC, to machine OPERATOR_PC : - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// Nicko Cadell - /// Gert Driesen - public class NetSendAppender : AppenderSkeleton - { - #region Member Variables - - /// - /// The DNS or NetBIOS name of the server on which the function is to execute. - /// - private string m_server; - - /// - /// The sender of the network message. - /// - private string m_sender; - - /// - /// The message alias to which the message should be sent. - /// - private string m_recipient; - - /// - /// The security context to use for privileged calls - /// - private SecurityContext m_securityContext; - - #endregion - - #region Constructors - - /// - /// Initializes the appender. - /// - /// - /// The default constructor initializes all fields to their default values. - /// - public NetSendAppender() - { - } - - #endregion - - #region Properties - - /// - /// Gets or sets the sender of the message. - /// - /// - /// The sender of the message. - /// - /// - /// If this property is not specified, the message is sent from the local computer. - /// - public string Sender - { - get { return m_sender; } - set { m_sender = value; } - } - - /// - /// Gets or sets the message alias to which the message should be sent. - /// - /// - /// The recipient of the message. - /// - /// - /// This property should always be specified in order to send a message. - /// - public string Recipient - { - get { return m_recipient; } - set { m_recipient = value; } - } - - /// - /// Gets or sets the DNS or NetBIOS name of the remote server on which the function is to execute. - /// - /// - /// DNS or NetBIOS name of the remote server on which the function is to execute. - /// - /// - /// - /// For Windows NT 4.0 and earlier, the string should begin with \\. - /// - /// - /// If this property is not specified, the local computer is used. - /// - /// - public string Server - { - get { return m_server; } - set { m_server = value; } - } - - /// - /// Gets or sets the used to call the NetSend method. - /// - /// - /// The used to call the NetSend method. - /// - /// - /// - /// Unless a specified here for this appender - /// the is queried for the - /// security context to use. The default behavior is to use the security context - /// of the current thread. - /// - /// - public SecurityContext SecurityContext - { - get { return m_securityContext; } - set { m_securityContext = value; } - } - - #endregion - - #region Implementation of IOptionHandler - - /// - /// Initialize the appender based on the options set. - /// - /// - /// - /// This is part of the delayed object - /// activation scheme. The method must - /// be called on this object after the configuration properties have - /// been set. Until is called this - /// object is in an undefined state and must not be used. - /// - /// - /// If any of the configuration properties are modified then - /// must be called again. - /// - /// - /// The appender will be ignored if no was specified. - /// - /// - /// The required property was not specified. - public override void ActivateOptions() - { - base.ActivateOptions(); - - if (this.Recipient == null) - { - throw new ArgumentNullException("Recipient", "The required property 'Recipient' was not specified."); - } - - if (m_securityContext == null) - { - m_securityContext = SecurityContextProvider.DefaultProvider.CreateSecurityContext(this); - } - } - - #endregion - - #region Override implementation of AppenderSkeleton - - /// - /// This method is called by the method. - /// - /// The event to log. - /// - /// - /// Sends the event using a network message. - /// - /// + /// + /// Logs entries by sending network messages using the + /// native function. + /// + /// + /// + /// You can send messages only to names that are active + /// on the network. If you send the message to a user name, + /// that user must be logged on and running the Messenger + /// service to receive the message. + /// + /// + /// The receiver will get a top most window displaying the + /// messages one at a time, therefore this appender should + /// not be used to deliver a high volume of messages. + /// + /// + /// The following table lists some possible uses for this appender : + /// + /// + /// + /// + /// Action + /// Property Value(s) + /// + /// + /// Send a message to a user account on the local machine + /// + /// + /// = <name of the local machine> + /// + /// + /// = <user name> + /// + /// + /// + /// + /// Send a message to a user account on a remote machine + /// + /// + /// = <name of the remote machine> + /// + /// + /// = <user name> + /// + /// + /// + /// + /// Send a message to a domain user account + /// + /// + /// = <name of a domain controller | uninitialized> + /// + /// + /// = <user name> + /// + /// + /// + /// + /// Send a message to all the names in a workgroup or domain + /// + /// + /// = <workgroup name | domain name>* + /// + /// + /// + /// + /// Send a message from the local machine to a remote machine + /// + /// + /// = <name of the local machine | uninitialized> + /// + /// + /// = <name of the remote machine> + /// + /// + /// + /// + /// + /// + /// Note : security restrictions apply for sending + /// network messages, see + /// for more information. + /// + /// + /// + /// + /// An example configuration section to log information + /// using this appender from the local machine, named + /// LOCAL_PC, to machine OPERATOR_PC : + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// Nicko Cadell + /// Gert Driesen + public class NetSendAppender : AppenderSkeleton + { + #region Member Variables + + /// + /// The DNS or NetBIOS name of the server on which the function is to execute. + /// + private string m_server; + + /// + /// The sender of the network message. + /// + private string m_sender; + + /// + /// The message alias to which the message should be sent. + /// + private string m_recipient; + + /// + /// The security context to use for privileged calls + /// + private SecurityContext m_securityContext; + + #endregion + + #region Constructors + + /// + /// Initializes the appender. + /// + /// + /// The default constructor initializes all fields to their default values. + /// + public NetSendAppender() + { + } + + #endregion + + #region Properties + + /// + /// Gets or sets the sender of the message. + /// + /// + /// The sender of the message. + /// + /// + /// If this property is not specified, the message is sent from the local computer. + /// + public string Sender + { + get { return m_sender; } + set { m_sender = value; } + } + + /// + /// Gets or sets the message alias to which the message should be sent. + /// + /// + /// The recipient of the message. + /// + /// + /// This property should always be specified in order to send a message. + /// + public string Recipient + { + get { return m_recipient; } + set { m_recipient = value; } + } + + /// + /// Gets or sets the DNS or NetBIOS name of the remote server on which the function is to execute. + /// + /// + /// DNS or NetBIOS name of the remote server on which the function is to execute. + /// + /// + /// + /// For Windows NT 4.0 and earlier, the string should begin with \\. + /// + /// + /// If this property is not specified, the local computer is used. + /// + /// + public string Server + { + get { return m_server; } + set { m_server = value; } + } + + /// + /// Gets or sets the used to call the NetSend method. + /// + /// + /// The used to call the NetSend method. + /// + /// + /// + /// Unless a specified here for this appender + /// the is queried for the + /// security context to use. The default behavior is to use the security context + /// of the current thread. + /// + /// + public SecurityContext SecurityContext + { + get { return m_securityContext; } + set { m_securityContext = value; } + } + + #endregion + + #region Implementation of IOptionHandler + + /// + /// Initialize the appender based on the options set. + /// + /// + /// + /// This is part of the delayed object + /// activation scheme. The method must + /// be called on this object after the configuration properties have + /// been set. Until is called this + /// object is in an undefined state and must not be used. + /// + /// + /// If any of the configuration properties are modified then + /// must be called again. + /// + /// + /// The appender will be ignored if no was specified. + /// + /// + /// The required property was not specified. + public override void ActivateOptions() + { + base.ActivateOptions(); + + if (this.Recipient == null) + { + throw new ArgumentNullException("Recipient", "The required property 'Recipient' was not specified."); + } + + if (m_securityContext == null) + { + m_securityContext = SecurityContextProvider.DefaultProvider.CreateSecurityContext(this); + } + } + + #endregion + + #region Override implementation of AppenderSkeleton + + /// + /// This method is called by the method. + /// + /// The event to log. + /// + /// + /// Sends the event using a network message. + /// + /// #if NET_4_0 || MONO_4_0 || NETSTANDARD - [System.Security.SecuritySafeCritical] + [System.Security.SecuritySafeCritical] #endif #if !NETSTANDARD1_3 - [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, UnmanagedCode = true)] + [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, UnmanagedCode = true)] #endif - protected override void Append(LoggingEvent loggingEvent) - { - NativeError nativeError = null; - - // Render the event in the callers security context - string renderedLoggingEvent = RenderLoggingEvent(loggingEvent); - - using(m_securityContext.Impersonate(this)) - { - // Send the message - int returnValue = NetMessageBufferSend(this.Server, this.Recipient, this.Sender, renderedLoggingEvent, renderedLoggingEvent.Length * Marshal.SystemDefaultCharSize); - - // Log the error if the message could not be sent - if (returnValue != 0) - { - // Lookup the native error - nativeError = NativeError.GetError(returnValue); - } - } - - if (nativeError != null) - { - // Handle the error over to the ErrorHandler - ErrorHandler.Error(nativeError.ToString() + " (Params: Server=" + this.Server + ", Recipient=" + this.Recipient + ", Sender=" + this.Sender + ")"); - } - } - - /// - /// This appender requires a to be set. - /// - /// true - /// - /// - /// This appender requires a to be set. - /// - /// - protected override bool RequiresLayout - { - get { return true; } - } - - #endregion - - #region Stubs For Native Function Calls - - /// - /// Sends a buffer of information to a registered message alias. - /// - /// The DNS or NetBIOS name of the server on which the function is to execute. - /// The message alias to which the message buffer should be sent - /// The originator of the message. - /// The message text. - /// The length, in bytes, of the message text. - /// - /// - /// The following restrictions apply for sending network messages: - /// - /// - /// - /// - /// Platform - /// Requirements - /// - /// - /// Windows NT - /// - /// - /// No special group membership is required to send a network message. - /// - /// - /// Admin, Accounts, Print, or Server Operator group membership is required to - /// successfully send a network message on a remote server. - /// - /// - /// - /// - /// Windows 2000 or later - /// - /// - /// If you send a message on a domain controller that is running Active Directory, - /// access is allowed or denied based on the access control list (ACL) for the securable - /// object. The default ACL permits only Domain Admins and Account Operators to send a network message. - /// - /// - /// On a member server or workstation, only Administrators and Server Operators can send a network message. - /// - /// - /// - /// - /// - /// - /// For more information see Security Requirements for the Network Management Functions. - /// - /// - /// - /// - /// If the function succeeds, the return value is zero. - /// - /// - [DllImport("netapi32.dll", SetLastError=true)] - protected static extern int NetMessageBufferSend( - [MarshalAs(UnmanagedType.LPWStr)] string serverName, - [MarshalAs(UnmanagedType.LPWStr)] string msgName, - [MarshalAs(UnmanagedType.LPWStr)] string fromName, - [MarshalAs(UnmanagedType.LPWStr)] string buffer, - int bufferSize); - - #endregion - } + protected override void Append(LoggingEvent loggingEvent) + { + NativeError nativeError = null; + + // Render the event in the callers security context + string renderedLoggingEvent = RenderLoggingEvent(loggingEvent); + + using(m_securityContext.Impersonate(this)) + { + // Send the message + int returnValue = NetMessageBufferSend(this.Server, this.Recipient, this.Sender, renderedLoggingEvent, renderedLoggingEvent.Length * Marshal.SystemDefaultCharSize); + + // Log the error if the message could not be sent + if (returnValue != 0) + { + // Lookup the native error + nativeError = NativeError.GetError(returnValue); + } + } + + if (nativeError != null) + { + // Handle the error over to the ErrorHandler + ErrorHandler.Error(nativeError.ToString() + " (Params: Server=" + this.Server + ", Recipient=" + this.Recipient + ", Sender=" + this.Sender + ")"); + } + } + + /// + /// This appender requires a to be set. + /// + /// true + /// + /// + /// This appender requires a to be set. + /// + /// + protected override bool RequiresLayout + { + get { return true; } + } + + #endregion + + #region Stubs For Native Function Calls + + /// + /// Sends a buffer of information to a registered message alias. + /// + /// The DNS or NetBIOS name of the server on which the function is to execute. + /// The message alias to which the message buffer should be sent + /// The originator of the message. + /// The message text. + /// The length, in bytes, of the message text. + /// + /// + /// The following restrictions apply for sending network messages: + /// + /// + /// + /// + /// Platform + /// Requirements + /// + /// + /// Windows NT + /// + /// + /// No special group membership is required to send a network message. + /// + /// + /// Admin, Accounts, Print, or Server Operator group membership is required to + /// successfully send a network message on a remote server. + /// + /// + /// + /// + /// Windows 2000 or later + /// + /// + /// If you send a message on a domain controller that is running Active Directory, + /// access is allowed or denied based on the access control list (ACL) for the securable + /// object. The default ACL permits only Domain Admins and Account Operators to send a network message. + /// + /// + /// On a member server or workstation, only Administrators and Server Operators can send a network message. + /// + /// + /// + /// + /// + /// + /// For more information see Security Requirements for the Network Management Functions. + /// + /// + /// + /// + /// If the function succeeds, the return value is zero. + /// + /// + [DllImport("netapi32.dll", SetLastError=true)] + protected static extern int NetMessageBufferSend( + [MarshalAs(UnmanagedType.LPWStr)] string serverName, + [MarshalAs(UnmanagedType.LPWStr)] string msgName, + [MarshalAs(UnmanagedType.LPWStr)] string fromName, + [MarshalAs(UnmanagedType.LPWStr)] string buffer, + int bufferSize); + + #endregion + } } #endif // !CLI_1_0 diff --git a/src/log4net/Appender/OutputDebugStringAppender.cs b/src/log4net/Appender/OutputDebugStringAppender.cs index 1a13512b..7a074f0e 100644 --- a/src/log4net/Appender/OutputDebugStringAppender.cs +++ b/src/log4net/Appender/OutputDebugStringAppender.cs @@ -30,104 +30,104 @@ namespace log4net.Appender { - /// - /// Appends log events to the OutputDebugString system. - /// - /// - /// - /// OutputDebugStringAppender appends log events to the - /// OutputDebugString system. - /// - /// - /// The string is passed to the native OutputDebugString - /// function. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public class OutputDebugStringAppender : AppenderSkeleton - { - #region Public Instance Constructors + /// + /// Appends log events to the OutputDebugString system. + /// + /// + /// + /// OutputDebugStringAppender appends log events to the + /// OutputDebugString system. + /// + /// + /// The string is passed to the native OutputDebugString + /// function. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public class OutputDebugStringAppender : AppenderSkeleton + { + #region Public Instance Constructors - /// - /// Initializes a new instance of the class. - /// - /// - /// - /// Default constructor. - /// - /// - public OutputDebugStringAppender() - { - } + /// + /// Initializes a new instance of the class. + /// + /// + /// + /// Default constructor. + /// + /// + public OutputDebugStringAppender() + { + } - #endregion // Public Instance Constructors + #endregion // Public Instance Constructors - #region Override implementation of AppenderSkeleton + #region Override implementation of AppenderSkeleton - /// - /// Write the logging event to the output debug string API - /// - /// the event to log - /// - /// - /// Write the logging event to the output debug string API - /// - /// + /// + /// Write the logging event to the output debug string API + /// + /// the event to log + /// + /// + /// Write the logging event to the output debug string API + /// + /// #if NET_4_0 || MONO_4_0 || NETSTANDARD - [System.Security.SecuritySafeCritical] + [System.Security.SecuritySafeCritical] #endif #if !NETCF && !NETSTANDARD1_3 - [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, UnmanagedCode = true)] + [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, UnmanagedCode = true)] #endif - protected override void Append(LoggingEvent loggingEvent) - { + protected override void Append(LoggingEvent loggingEvent) + { #if NETSTANDARD - if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - throw new System.PlatformNotSupportedException("OutputDebugString is only available on Windows"); - } + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + throw new System.PlatformNotSupportedException("OutputDebugString is only available on Windows"); + } #endif - OutputDebugString(RenderLoggingEvent(loggingEvent)); - } + OutputDebugString(RenderLoggingEvent(loggingEvent)); + } - /// - /// This appender requires a to be set. - /// - /// true - /// - /// - /// This appender requires a to be set. - /// - /// - protected override bool RequiresLayout - { - get { return true; } - } + /// + /// This appender requires a to be set. + /// + /// true + /// + /// + /// This appender requires a to be set. + /// + /// + protected override bool RequiresLayout + { + get { return true; } + } - #endregion // Override implementation of AppenderSkeleton + #endregion // Override implementation of AppenderSkeleton - #region Protected Static Methods + #region Protected Static Methods - /// - /// Stub for OutputDebugString native method - /// - /// the string to output - /// - /// - /// Stub for OutputDebugString native method - /// - /// + /// + /// Stub for OutputDebugString native method + /// + /// the string to output + /// + /// + /// Stub for OutputDebugString native method + /// + /// #if NETCF || NETSTANDARD - [DllImport("CoreDll.dll")] + [DllImport("CoreDll.dll")] #else - [DllImport("Kernel32.dll")] + [DllImport("Kernel32.dll")] #endif - protected static extern void OutputDebugString(string message); + protected static extern void OutputDebugString(string message); - #endregion // Protected Static Methods - } + #endregion // Protected Static Methods + } } #endif // !CLI_1_0 diff --git a/src/log4net/Appender/RemoteSyslogAppender.cs b/src/log4net/Appender/RemoteSyslogAppender.cs index b67abd32..83e8de03 100644 --- a/src/log4net/Appender/RemoteSyslogAppender.cs +++ b/src/log4net/Appender/RemoteSyslogAppender.cs @@ -27,580 +27,580 @@ namespace log4net.Appender { - /// - /// Logs events to a remote syslog daemon. - /// - /// - /// - /// The BSD syslog protocol is used to remotely log to - /// a syslog daemon. The syslogd listens for for messages - /// on UDP port 514. - /// - /// - /// The syslog UDP protocol is not authenticated. Most syslog daemons - /// do not accept remote log messages because of the security implications. - /// You may be able to use the LocalSyslogAppender to talk to a local - /// syslog service. - /// - /// - /// There is an RFC 3164 that claims to document the BSD Syslog Protocol. - /// This RFC can be seen here: http://www.faqs.org/rfcs/rfc3164.html. - /// This appender generates what the RFC calls an "Original Device Message", - /// i.e. does not include the TIMESTAMP or HOSTNAME fields. By observation - /// this format of message will be accepted by all current syslog daemon - /// implementations. The daemon will attach the current time and the source - /// hostname or IP address to any messages received. - /// - /// - /// Syslog messages must have a facility and and a severity. The severity - /// is derived from the Level of the logging event. - /// The facility must be chosen from the set of defined syslog - /// values. The facilities list is predefined - /// and cannot be extended. - /// - /// - /// An identifier is specified with each log message. This can be specified - /// by setting the property. The identity (also know - /// as the tag) must not contain white space. The default value for the - /// identity is the application name (from ). - /// - /// - /// Rob Lyon - /// Nicko Cadell - public class RemoteSyslogAppender : UdpAppender - { - /// - /// Syslog port 514 - /// - private const int DefaultSyslogPort = 514; - - #region Enumerations - - /// - /// syslog severities - /// - /// - /// - /// The syslog severities. - /// - /// - public enum SyslogSeverity - { - /// - /// system is unusable - /// - Emergency = 0, - - /// - /// action must be taken immediately - /// - Alert = 1, - - /// - /// critical conditions - /// - Critical = 2, - - /// - /// error conditions - /// - Error = 3, - - /// - /// warning conditions - /// - Warning = 4, - - /// - /// normal but significant condition - /// - Notice = 5, - - /// - /// informational - /// - Informational = 6, - - /// - /// debug-level messages - /// - Debug = 7 - }; - - /// - /// syslog facilities - /// - /// - /// - /// The syslog facilities - /// - /// - public enum SyslogFacility - { - /// - /// kernel messages - /// - Kernel = 0, - - /// - /// random user-level messages - /// - User = 1, - - /// - /// mail system - /// - Mail = 2, - - /// - /// system daemons - /// - Daemons = 3, - - /// - /// security/authorization messages - /// - Authorization = 4, - - /// - /// messages generated internally by syslogd - /// - Syslog = 5, - - /// - /// line printer subsystem - /// - Printer = 6, - - /// - /// network news subsystem - /// - News = 7, - - /// - /// UUCP subsystem - /// - Uucp = 8, - - /// - /// clock (cron/at) daemon - /// - Clock = 9, - - /// - /// security/authorization messages (private) - /// - Authorization2 = 10, - - /// - /// ftp daemon - /// - Ftp = 11, - - /// - /// NTP subsystem - /// - Ntp = 12, - - /// - /// log audit - /// - Audit = 13, - - /// - /// log alert - /// - Alert = 14, - - /// - /// clock daemon - /// - Clock2 = 15, - - /// - /// reserved for local use - /// - Local0 = 16, - - /// - /// reserved for local use - /// - Local1 = 17, - - /// - /// reserved for local use - /// - Local2 = 18, - - /// - /// reserved for local use - /// - Local3 = 19, - - /// - /// reserved for local use - /// - Local4 = 20, - - /// - /// reserved for local use - /// - Local5 = 21, - - /// - /// reserved for local use - /// - Local6 = 22, - - /// - /// reserved for local use - /// - Local7 = 23 - } - - #endregion Enumerations - - #region Public Instance Constructors - - /// - /// Initializes a new instance of the class. - /// - /// - /// This instance of the class is set up to write - /// to a remote syslog daemon. - /// - public RemoteSyslogAppender() - { - // syslog udp defaults - this.RemotePort = DefaultSyslogPort; - this.RemoteAddress = System.Net.IPAddress.Parse("127.0.0.1"); - this.Encoding = System.Text.Encoding.ASCII; - } - - #endregion Public Instance Constructors - - #region Public Instance Properties - - /// - /// Message identity - /// - /// - /// - /// An identifier is specified with each log message. This can be specified - /// by setting the property. The identity (also know - /// as the tag) must not contain white space. The default value for the - /// identity is the application name (from ). - /// - /// - public PatternLayout Identity - { - get { return m_identity; } - set { m_identity = value; } - } - - /// - /// Syslog facility - /// - /// - /// Set to one of the values. The list of - /// facilities is predefined and cannot be extended. The default value - /// is . - /// - public SyslogFacility Facility - { - get { return m_facility; } - set { m_facility = value; } - } - - #endregion Public Instance Properties - - /// - /// Add a mapping of level to severity - /// - /// The mapping to add - /// - /// - /// Add a mapping to this appender. - /// - /// - public void AddMapping(LevelSeverity mapping) - { - m_levelMapping.Add(mapping); - } - - #region AppenderSkeleton Implementation - - /// - /// This method is called by the method. - /// - /// The event to log. - /// - /// - /// Writes the event to a remote syslog daemon. - /// - /// - /// The format of the output will depend on the appender's layout. - /// - /// - protected override void Append(LoggingEvent loggingEvent) - { - try - { - // Priority - int priority = GeneratePriority(m_facility, GetSeverity(loggingEvent.Level)); - - // Identity - string identity; - - if (m_identity != null) - { - identity = m_identity.Format(loggingEvent); - } - else - { - identity = loggingEvent.Domain; - } - - // Message. The message goes after the tag/identity - string message = RenderLoggingEvent(loggingEvent); - - byte[] buffer; - int i = 0; - - StringBuilder builder = new StringBuilder(); - - while (i < message.Length) - { - // Clear StringBuilder - builder.Length = 0; - - // Write priority - builder.Append('<'); - builder.Append(priority); - builder.Append('>'); - - // Write identity - builder.Append(identity); - builder.Append(": "); - - AppendMessage(message, ref i, builder); - - // Grab as a byte array - buffer = this.Encoding.GetBytes(builder.ToString()); + /// + /// Logs events to a remote syslog daemon. + /// + /// + /// + /// The BSD syslog protocol is used to remotely log to + /// a syslog daemon. The syslogd listens for for messages + /// on UDP port 514. + /// + /// + /// The syslog UDP protocol is not authenticated. Most syslog daemons + /// do not accept remote log messages because of the security implications. + /// You may be able to use the LocalSyslogAppender to talk to a local + /// syslog service. + /// + /// + /// There is an RFC 3164 that claims to document the BSD Syslog Protocol. + /// This RFC can be seen here: http://www.faqs.org/rfcs/rfc3164.html. + /// This appender generates what the RFC calls an "Original Device Message", + /// i.e. does not include the TIMESTAMP or HOSTNAME fields. By observation + /// this format of message will be accepted by all current syslog daemon + /// implementations. The daemon will attach the current time and the source + /// hostname or IP address to any messages received. + /// + /// + /// Syslog messages must have a facility and and a severity. The severity + /// is derived from the Level of the logging event. + /// The facility must be chosen from the set of defined syslog + /// values. The facilities list is predefined + /// and cannot be extended. + /// + /// + /// An identifier is specified with each log message. This can be specified + /// by setting the property. The identity (also know + /// as the tag) must not contain white space. The default value for the + /// identity is the application name (from ). + /// + /// + /// Rob Lyon + /// Nicko Cadell + public class RemoteSyslogAppender : UdpAppender + { + /// + /// Syslog port 514 + /// + private const int DefaultSyslogPort = 514; + + #region Enumerations + + /// + /// syslog severities + /// + /// + /// + /// The syslog severities. + /// + /// + public enum SyslogSeverity + { + /// + /// system is unusable + /// + Emergency = 0, + + /// + /// action must be taken immediately + /// + Alert = 1, + + /// + /// critical conditions + /// + Critical = 2, + + /// + /// error conditions + /// + Error = 3, + + /// + /// warning conditions + /// + Warning = 4, + + /// + /// normal but significant condition + /// + Notice = 5, + + /// + /// informational + /// + Informational = 6, + + /// + /// debug-level messages + /// + Debug = 7 + }; + + /// + /// syslog facilities + /// + /// + /// + /// The syslog facilities + /// + /// + public enum SyslogFacility + { + /// + /// kernel messages + /// + Kernel = 0, + + /// + /// random user-level messages + /// + User = 1, + + /// + /// mail system + /// + Mail = 2, + + /// + /// system daemons + /// + Daemons = 3, + + /// + /// security/authorization messages + /// + Authorization = 4, + + /// + /// messages generated internally by syslogd + /// + Syslog = 5, + + /// + /// line printer subsystem + /// + Printer = 6, + + /// + /// network news subsystem + /// + News = 7, + + /// + /// UUCP subsystem + /// + Uucp = 8, + + /// + /// clock (cron/at) daemon + /// + Clock = 9, + + /// + /// security/authorization messages (private) + /// + Authorization2 = 10, + + /// + /// ftp daemon + /// + Ftp = 11, + + /// + /// NTP subsystem + /// + Ntp = 12, + + /// + /// log audit + /// + Audit = 13, + + /// + /// log alert + /// + Alert = 14, + + /// + /// clock daemon + /// + Clock2 = 15, + + /// + /// reserved for local use + /// + Local0 = 16, + + /// + /// reserved for local use + /// + Local1 = 17, + + /// + /// reserved for local use + /// + Local2 = 18, + + /// + /// reserved for local use + /// + Local3 = 19, + + /// + /// reserved for local use + /// + Local4 = 20, + + /// + /// reserved for local use + /// + Local5 = 21, + + /// + /// reserved for local use + /// + Local6 = 22, + + /// + /// reserved for local use + /// + Local7 = 23 + } + + #endregion Enumerations + + #region Public Instance Constructors + + /// + /// Initializes a new instance of the class. + /// + /// + /// This instance of the class is set up to write + /// to a remote syslog daemon. + /// + public RemoteSyslogAppender() + { + // syslog udp defaults + this.RemotePort = DefaultSyslogPort; + this.RemoteAddress = System.Net.IPAddress.Parse("127.0.0.1"); + this.Encoding = System.Text.Encoding.ASCII; + } + + #endregion Public Instance Constructors + + #region Public Instance Properties + + /// + /// Message identity + /// + /// + /// + /// An identifier is specified with each log message. This can be specified + /// by setting the property. The identity (also know + /// as the tag) must not contain white space. The default value for the + /// identity is the application name (from ). + /// + /// + public PatternLayout Identity + { + get { return m_identity; } + set { m_identity = value; } + } + + /// + /// Syslog facility + /// + /// + /// Set to one of the values. The list of + /// facilities is predefined and cannot be extended. The default value + /// is . + /// + public SyslogFacility Facility + { + get { return m_facility; } + set { m_facility = value; } + } + + #endregion Public Instance Properties + + /// + /// Add a mapping of level to severity + /// + /// The mapping to add + /// + /// + /// Add a mapping to this appender. + /// + /// + public void AddMapping(LevelSeverity mapping) + { + m_levelMapping.Add(mapping); + } + + #region AppenderSkeleton Implementation + + /// + /// This method is called by the method. + /// + /// The event to log. + /// + /// + /// Writes the event to a remote syslog daemon. + /// + /// + /// The format of the output will depend on the appender's layout. + /// + /// + protected override void Append(LoggingEvent loggingEvent) + { + try + { + // Priority + int priority = GeneratePriority(m_facility, GetSeverity(loggingEvent.Level)); + + // Identity + string identity; + + if (m_identity != null) + { + identity = m_identity.Format(loggingEvent); + } + else + { + identity = loggingEvent.Domain; + } + + // Message. The message goes after the tag/identity + string message = RenderLoggingEvent(loggingEvent); + + byte[] buffer; + int i = 0; + + StringBuilder builder = new StringBuilder(); + + while (i < message.Length) + { + // Clear StringBuilder + builder.Length = 0; + + // Write priority + builder.Append('<'); + builder.Append(priority); + builder.Append('>'); + + // Write identity + builder.Append(identity); + builder.Append(": "); + + AppendMessage(message, ref i, builder); + + // Grab as a byte array + buffer = this.Encoding.GetBytes(builder.ToString()); #if NET_4_5 || NETSTANDARD - Client.SendAsync(buffer, buffer.Length, RemoteEndPoint).Wait(); + Client.SendAsync(buffer, buffer.Length, RemoteEndPoint).Wait(); #else - this.Client.Send(buffer, buffer.Length, this.RemoteEndPoint); + this.Client.Send(buffer, buffer.Length, this.RemoteEndPoint); #endif - } - } - catch (Exception e) - { - ErrorHandler.Error( - "Unable to send logging event to remote syslog " + - this.RemoteAddress.ToString() + - " on port " + - this.RemotePort + ".", - e, - ErrorCode.WriteFailure); - } - } - - /// - /// Appends the rendered message to the buffer - /// - /// rendered message - /// index of the current character in the message - /// buffer - protected virtual void AppendMessage(string message, ref int characterIndex, StringBuilder builder) - { - for (; characterIndex < message.Length; characterIndex++) - { - char c = message[characterIndex]; - - // Accept only visible ASCII characters and space. See RFC 3164 section 4.1.3 - if (((int)c >= 32) && ((int)c <= 126)) - { - builder.Append(c); - } - // If character is newline, break and send the current line - else if ((c == '\r') || (c == '\n')) - { - // Check the next character to handle \r\n or \n\r - if ((message.Length > characterIndex + 1) && ((message[characterIndex + 1] == '\r') || (message[characterIndex + 1] == '\n'))) - { - characterIndex++; - } - characterIndex++; - break; - } - } - } - - /// - /// Initialize the options for this appender - /// - /// - /// - /// Initialize the level to syslog severity mappings set on this appender. - /// - /// - public override void ActivateOptions() - { - base.ActivateOptions(); - m_levelMapping.ActivateOptions(); - } - - #endregion AppenderSkeleton Implementation - - #region Protected Members - - /// - /// Translates a log4net level to a syslog severity. - /// - /// A log4net level. - /// A syslog severity. - /// - /// - /// Translates a log4net level to a syslog severity. - /// - /// - protected virtual SyslogSeverity GetSeverity(Level level) - { - LevelSeverity levelSeverity = m_levelMapping.Lookup(level) as LevelSeverity; - if (levelSeverity != null) - { - return levelSeverity.Severity; - } - - // - // Fallback to sensible default values - // - - if (level >= Level.Alert) - { - return SyslogSeverity.Alert; - } - else if (level >= Level.Critical) - { - return SyslogSeverity.Critical; - } - else if (level >= Level.Error) - { - return SyslogSeverity.Error; - } - else if (level >= Level.Warn) - { - return SyslogSeverity.Warning; - } - else if (level >= Level.Notice) - { - return SyslogSeverity.Notice; - } - else if (level >= Level.Info) - { - return SyslogSeverity.Informational; - } - // Default setting - return SyslogSeverity.Debug; - } - - #endregion Protected Members - - #region Public Static Members - - /// - /// Generate a syslog priority. - /// - /// The syslog facility. - /// The syslog severity. - /// A syslog priority. - /// - /// - /// Generate a syslog priority. - /// - /// - public static int GeneratePriority(SyslogFacility facility, SyslogSeverity severity) - { - if (facility < SyslogFacility.Kernel || facility > SyslogFacility.Local7) - { - throw new ArgumentException("SyslogFacility out of range", "facility"); - } - - if (severity < SyslogSeverity.Emergency || severity > SyslogSeverity.Debug) - { - throw new ArgumentException("SyslogSeverity out of range", "severity"); - } - - unchecked - { - return ((int)facility * 8) + (int)severity; - } - } - - #endregion Public Static Members - - #region Private Instances Fields - - /// - /// The facility. The default facility is . - /// - private SyslogFacility m_facility = SyslogFacility.User; - - /// - /// The message identity - /// - private PatternLayout m_identity; - - /// - /// Mapping from level object to syslog severity - /// - private LevelMapping m_levelMapping = new LevelMapping(); - - /// - /// Initial buffer size - /// - private const int c_renderBufferSize = 256; - - /// - /// Maximum buffer size before it is recycled - /// - private const int c_renderBufferMaxCapacity = 1024; - - #endregion Private Instances Fields - - #region LevelSeverity LevelMapping Entry - /// - /// A class to act as a mapping between the level that a logging call is made at and - /// the syslog severity that is should be logged at. - /// - /// - /// - /// A class to act as a mapping between the level that a logging call is made at and - /// the syslog severity that is should be logged at. - /// - /// - public class LevelSeverity : LevelMappingEntry - { - private SyslogSeverity m_severity; - - /// - /// The mapped syslog severity for the specified level - /// - /// - /// - /// Required property. - /// The mapped syslog severity for the specified level - /// - /// - public SyslogSeverity Severity - { - get { return m_severity; } - set { m_severity = value; } - } - } - - #endregion // LevelSeverity LevelMapping Entry - } + } + } + catch (Exception e) + { + ErrorHandler.Error( + "Unable to send logging event to remote syslog " + + this.RemoteAddress.ToString() + + " on port " + + this.RemotePort + ".", + e, + ErrorCode.WriteFailure); + } + } + + /// + /// Appends the rendered message to the buffer + /// + /// rendered message + /// index of the current character in the message + /// buffer + protected virtual void AppendMessage(string message, ref int characterIndex, StringBuilder builder) + { + for (; characterIndex < message.Length; characterIndex++) + { + char c = message[characterIndex]; + + // Accept only visible ASCII characters and space. See RFC 3164 section 4.1.3 + if (((int)c >= 32) && ((int)c <= 126)) + { + builder.Append(c); + } + // If character is newline, break and send the current line + else if ((c == '\r') || (c == '\n')) + { + // Check the next character to handle \r\n or \n\r + if ((message.Length > characterIndex + 1) && ((message[characterIndex + 1] == '\r') || (message[characterIndex + 1] == '\n'))) + { + characterIndex++; + } + characterIndex++; + break; + } + } + } + + /// + /// Initialize the options for this appender + /// + /// + /// + /// Initialize the level to syslog severity mappings set on this appender. + /// + /// + public override void ActivateOptions() + { + base.ActivateOptions(); + m_levelMapping.ActivateOptions(); + } + + #endregion AppenderSkeleton Implementation + + #region Protected Members + + /// + /// Translates a log4net level to a syslog severity. + /// + /// A log4net level. + /// A syslog severity. + /// + /// + /// Translates a log4net level to a syslog severity. + /// + /// + protected virtual SyslogSeverity GetSeverity(Level level) + { + LevelSeverity levelSeverity = m_levelMapping.Lookup(level) as LevelSeverity; + if (levelSeverity != null) + { + return levelSeverity.Severity; + } + + // + // Fallback to sensible default values + // + + if (level >= Level.Alert) + { + return SyslogSeverity.Alert; + } + else if (level >= Level.Critical) + { + return SyslogSeverity.Critical; + } + else if (level >= Level.Error) + { + return SyslogSeverity.Error; + } + else if (level >= Level.Warn) + { + return SyslogSeverity.Warning; + } + else if (level >= Level.Notice) + { + return SyslogSeverity.Notice; + } + else if (level >= Level.Info) + { + return SyslogSeverity.Informational; + } + // Default setting + return SyslogSeverity.Debug; + } + + #endregion Protected Members + + #region Public Static Members + + /// + /// Generate a syslog priority. + /// + /// The syslog facility. + /// The syslog severity. + /// A syslog priority. + /// + /// + /// Generate a syslog priority. + /// + /// + public static int GeneratePriority(SyslogFacility facility, SyslogSeverity severity) + { + if (facility < SyslogFacility.Kernel || facility > SyslogFacility.Local7) + { + throw new ArgumentException("SyslogFacility out of range", "facility"); + } + + if (severity < SyslogSeverity.Emergency || severity > SyslogSeverity.Debug) + { + throw new ArgumentException("SyslogSeverity out of range", "severity"); + } + + unchecked + { + return ((int)facility * 8) + (int)severity; + } + } + + #endregion Public Static Members + + #region Private Instances Fields + + /// + /// The facility. The default facility is . + /// + private SyslogFacility m_facility = SyslogFacility.User; + + /// + /// The message identity + /// + private PatternLayout m_identity; + + /// + /// Mapping from level object to syslog severity + /// + private LevelMapping m_levelMapping = new LevelMapping(); + + /// + /// Initial buffer size + /// + private const int c_renderBufferSize = 256; + + /// + /// Maximum buffer size before it is recycled + /// + private const int c_renderBufferMaxCapacity = 1024; + + #endregion Private Instances Fields + + #region LevelSeverity LevelMapping Entry + /// + /// A class to act as a mapping between the level that a logging call is made at and + /// the syslog severity that is should be logged at. + /// + /// + /// + /// A class to act as a mapping between the level that a logging call is made at and + /// the syslog severity that is should be logged at. + /// + /// + public class LevelSeverity : LevelMappingEntry + { + private SyslogSeverity m_severity; + + /// + /// The mapped syslog severity for the specified level + /// + /// + /// + /// Required property. + /// The mapped syslog severity for the specified level + /// + /// + public SyslogSeverity Severity + { + get { return m_severity; } + set { m_severity = value; } + } + } + + #endregion // LevelSeverity LevelMapping Entry + } } diff --git a/src/log4net/Appender/RemotingAppender.cs b/src/log4net/Appender/RemotingAppender.cs index 7c095f89..7a9fd773 100644 --- a/src/log4net/Appender/RemotingAppender.cs +++ b/src/log4net/Appender/RemotingAppender.cs @@ -32,308 +32,308 @@ namespace log4net.Appender { - /// - /// Delivers logging events to a remote logging sink. - /// - /// - /// - /// This Appender is designed to deliver events to a remote sink. - /// That is any object that implements the - /// interface. It delivers the events using .NET remoting. The - /// object to deliver events to is specified by setting the - /// appenders property. - /// - /// The RemotingAppender buffers events before sending them. This allows it to - /// make more efficient use of the remoting infrastructure. - /// - /// Once the buffer is full the events are still not sent immediately. - /// They are scheduled to be sent using a pool thread. The effect is that - /// the send occurs asynchronously. This is very important for a - /// number of non obvious reasons. The remoting infrastructure will - /// flow thread local variables (stored in the ), - /// if they are marked as , across the - /// remoting boundary. If the server is not contactable then - /// the remoting infrastructure will clear the - /// objects from the . To prevent a logging failure from - /// having side effects on the calling application the remoting call must be made - /// from a separate thread to the one used by the application. A - /// thread is used for this. If no thread is available then - /// the events will block in the thread pool manager until a thread is available. - /// - /// Because the events are sent asynchronously using pool threads it is possible to close - /// this appender before all the queued events have been sent. - /// When closing the appender attempts to wait until all the queued events have been sent, but - /// this will timeout after 30 seconds regardless. - /// - /// If this appender is being closed because the - /// event has fired it may not be possible to send all the queued events. During process - /// exit the runtime limits the time that a - /// event handler is allowed to run for. If the runtime terminates the threads before - /// the queued events have been sent then they will be lost. To ensure that all events - /// are sent the appender must be closed before the application exits. See - /// for details on how to shutdown - /// log4net programmatically. - /// - /// - /// Nicko Cadell - /// Gert Driesen - /// Daniel Cazzulino - public class RemotingAppender : BufferingAppenderSkeleton - { - #region Public Instance Constructors - - /// - /// Initializes a new instance of the class. - /// - /// - /// - /// Default constructor. - /// - /// - public RemotingAppender() - { - } - - #endregion Public Instance Constructors - - #region Public Instance Properties - - /// - /// Gets or sets the URL of the well-known object that will accept - /// the logging events. - /// - /// - /// The well-known URL of the remote sink. - /// - /// - /// - /// The URL of the remoting sink that will accept logging events. - /// The sink must implement the - /// interface. - /// - /// - public string Sink - { - get { return m_sinkUrl; } - set { m_sinkUrl = value; } - } - - #endregion Public Instance Properties - - #region Implementation of IOptionHandler - - /// - /// Initialize the appender based on the options set - /// - /// - /// - /// This is part of the delayed object - /// activation scheme. The method must - /// be called on this object after the configuration properties have - /// been set. Until is called this - /// object is in an undefined state and must not be used. - /// - /// - /// If any of the configuration properties are modified then - /// must be called again. - /// - /// + /// + /// Delivers logging events to a remote logging sink. + /// + /// + /// + /// This Appender is designed to deliver events to a remote sink. + /// That is any object that implements the + /// interface. It delivers the events using .NET remoting. The + /// object to deliver events to is specified by setting the + /// appenders property. + /// + /// The RemotingAppender buffers events before sending them. This allows it to + /// make more efficient use of the remoting infrastructure. + /// + /// Once the buffer is full the events are still not sent immediately. + /// They are scheduled to be sent using a pool thread. The effect is that + /// the send occurs asynchronously. This is very important for a + /// number of non obvious reasons. The remoting infrastructure will + /// flow thread local variables (stored in the ), + /// if they are marked as , across the + /// remoting boundary. If the server is not contactable then + /// the remoting infrastructure will clear the + /// objects from the . To prevent a logging failure from + /// having side effects on the calling application the remoting call must be made + /// from a separate thread to the one used by the application. A + /// thread is used for this. If no thread is available then + /// the events will block in the thread pool manager until a thread is available. + /// + /// Because the events are sent asynchronously using pool threads it is possible to close + /// this appender before all the queued events have been sent. + /// When closing the appender attempts to wait until all the queued events have been sent, but + /// this will timeout after 30 seconds regardless. + /// + /// If this appender is being closed because the + /// event has fired it may not be possible to send all the queued events. During process + /// exit the runtime limits the time that a + /// event handler is allowed to run for. If the runtime terminates the threads before + /// the queued events have been sent then they will be lost. To ensure that all events + /// are sent the appender must be closed before the application exits. See + /// for details on how to shutdown + /// log4net programmatically. + /// + /// + /// Nicko Cadell + /// Gert Driesen + /// Daniel Cazzulino + public class RemotingAppender : BufferingAppenderSkeleton + { + #region Public Instance Constructors + + /// + /// Initializes a new instance of the class. + /// + /// + /// + /// Default constructor. + /// + /// + public RemotingAppender() + { + } + + #endregion Public Instance Constructors + + #region Public Instance Properties + + /// + /// Gets or sets the URL of the well-known object that will accept + /// the logging events. + /// + /// + /// The well-known URL of the remote sink. + /// + /// + /// + /// The URL of the remoting sink that will accept logging events. + /// The sink must implement the + /// interface. + /// + /// + public string Sink + { + get { return m_sinkUrl; } + set { m_sinkUrl = value; } + } + + #endregion Public Instance Properties + + #region Implementation of IOptionHandler + + /// + /// Initialize the appender based on the options set + /// + /// + /// + /// This is part of the delayed object + /// activation scheme. The method must + /// be called on this object after the configuration properties have + /// been set. Until is called this + /// object is in an undefined state and must not be used. + /// + /// + /// If any of the configuration properties are modified then + /// must be called again. + /// + /// #if NET_4_0 || MONO_4_0 [System.Security.SecuritySafeCritical] #endif public override void ActivateOptions() - { - base.ActivateOptions(); - - IDictionary channelProperties = new Hashtable(); - channelProperties["typeFilterLevel"] = "Full"; - - m_sinkObj = (IRemoteLoggingSink)Activator.GetObject(typeof(IRemoteLoggingSink), m_sinkUrl, channelProperties); - } - - #endregion - - #region Override implementation of BufferingAppenderSkeleton - - /// - /// Send the contents of the buffer to the remote sink. - /// - /// - /// The events are not sent immediately. They are scheduled to be sent - /// using a pool thread. The effect is that the send occurs asynchronously. - /// This is very important for a number of non obvious reasons. The remoting - /// infrastructure will flow thread local variables (stored in the ), - /// if they are marked as , across the - /// remoting boundary. If the server is not contactable then - /// the remoting infrastructure will clear the - /// objects from the . To prevent a logging failure from - /// having side effects on the calling application the remoting call must be made - /// from a separate thread to the one used by the application. A - /// thread is used for this. If no thread is available then - /// the events will block in the thread pool manager until a thread is available. - /// - /// The events to send. - protected override void SendBuffer(LoggingEvent[] events) - { - // Setup for an async send - BeginAsyncSend(); - - // Send the events - if (!ThreadPool.QueueUserWorkItem(new WaitCallback(SendBufferCallback), events)) - { - // Cancel the async send - EndAsyncSend(); - - ErrorHandler.Error("RemotingAppender ["+Name+"] failed to ThreadPool.QueueUserWorkItem logging events in SendBuffer."); - } - } - - /// - /// Override base class close. - /// - /// - /// - /// This method waits while there are queued work items. The events are - /// sent asynchronously using work items. These items - /// will be sent once a thread pool thread is available to send them, therefore - /// it is possible to close the appender before all the queued events have been - /// sent. - /// - /// This method attempts to wait until all the queued events have been sent, but this - /// method will timeout after 30 seconds regardless. - /// - /// If the appender is being closed because the - /// event has fired it may not be possible to send all the queued events. During process - /// exit the runtime limits the time that a - /// event handler is allowed to run for. - /// - protected override void OnClose() - { - base.OnClose(); - - // Wait for the work queue to become empty before closing, timeout 30 seconds - if (!m_workQueueEmptyEvent.WaitOne(30 * 1000, false)) - { - ErrorHandler.Error("RemotingAppender ["+Name+"] failed to send all queued events before close, in OnClose."); - } - } - - /// - /// Flushes any buffered log data. - /// - /// The maximum time to wait for logging events to be flushed. - /// True if all logging events were flushed successfully, else false. - public override bool Flush(int millisecondsTimeout) - { - base.Flush(); - return m_workQueueEmptyEvent.WaitOne(millisecondsTimeout, false); - } - - #endregion - - /// - /// A work item is being queued into the thread pool - /// - private void BeginAsyncSend() - { - // The work queue is not empty - m_workQueueEmptyEvent.Reset(); - - // Increment the queued count - Interlocked.Increment(ref m_queuedCallbackCount); - } - - /// - /// A work item from the thread pool has completed - /// - private void EndAsyncSend() - { - // Decrement the queued count - if (Interlocked.Decrement(ref m_queuedCallbackCount) <= 0) - { - // If the work queue is empty then set the event - m_workQueueEmptyEvent.Set(); - } - } - - /// - /// Send the contents of the buffer to the remote sink. - /// - /// - /// This method is designed to be used with the . - /// This method expects to be passed an array of - /// objects in the state param. - /// - /// the logging events to send - private void SendBufferCallback(object state) - { - try - { - LoggingEvent[] events = (LoggingEvent[])state; - - // Send the events - m_sinkObj.LogEvents(events); - } - catch(Exception ex) - { - ErrorHandler.Error("Failed in SendBufferCallback", ex); - } - finally - { - EndAsyncSend(); - } - } - - #region Private Instance Fields - - /// - /// The URL of the remote sink. - /// - private string m_sinkUrl; - - /// - /// The local proxy (.NET remoting) for the remote logging sink. - /// - private IRemoteLoggingSink m_sinkObj; - - /// - /// The number of queued callbacks currently waiting or executing - /// - private int m_queuedCallbackCount = 0; - - /// - /// Event used to signal when there are no queued work items - /// - /// - /// This event is set when there are no queued work items. In this - /// state it is safe to close the appender. - /// - private ManualResetEvent m_workQueueEmptyEvent = new ManualResetEvent(true); - - #endregion Private Instance Fields - - /// - /// Interface used to deliver objects to a remote sink. - /// - /// - /// This interface must be implemented by a remoting sink - /// if the is to be used - /// to deliver logging events to the sink. - /// - public interface IRemoteLoggingSink - { - /// - /// Delivers logging events to the remote sink - /// - /// Array of events to log. - /// - /// - /// Delivers logging events to the remote sink - /// - /// - void LogEvents(LoggingEvent[] events); - } - } + { + base.ActivateOptions(); + + IDictionary channelProperties = new Hashtable(); + channelProperties["typeFilterLevel"] = "Full"; + + m_sinkObj = (IRemoteLoggingSink)Activator.GetObject(typeof(IRemoteLoggingSink), m_sinkUrl, channelProperties); + } + + #endregion + + #region Override implementation of BufferingAppenderSkeleton + + /// + /// Send the contents of the buffer to the remote sink. + /// + /// + /// The events are not sent immediately. They are scheduled to be sent + /// using a pool thread. The effect is that the send occurs asynchronously. + /// This is very important for a number of non obvious reasons. The remoting + /// infrastructure will flow thread local variables (stored in the ), + /// if they are marked as , across the + /// remoting boundary. If the server is not contactable then + /// the remoting infrastructure will clear the + /// objects from the . To prevent a logging failure from + /// having side effects on the calling application the remoting call must be made + /// from a separate thread to the one used by the application. A + /// thread is used for this. If no thread is available then + /// the events will block in the thread pool manager until a thread is available. + /// + /// The events to send. + protected override void SendBuffer(LoggingEvent[] events) + { + // Setup for an async send + BeginAsyncSend(); + + // Send the events + if (!ThreadPool.QueueUserWorkItem(new WaitCallback(SendBufferCallback), events)) + { + // Cancel the async send + EndAsyncSend(); + + ErrorHandler.Error("RemotingAppender ["+Name+"] failed to ThreadPool.QueueUserWorkItem logging events in SendBuffer."); + } + } + + /// + /// Override base class close. + /// + /// + /// + /// This method waits while there are queued work items. The events are + /// sent asynchronously using work items. These items + /// will be sent once a thread pool thread is available to send them, therefore + /// it is possible to close the appender before all the queued events have been + /// sent. + /// + /// This method attempts to wait until all the queued events have been sent, but this + /// method will timeout after 30 seconds regardless. + /// + /// If the appender is being closed because the + /// event has fired it may not be possible to send all the queued events. During process + /// exit the runtime limits the time that a + /// event handler is allowed to run for. + /// + protected override void OnClose() + { + base.OnClose(); + + // Wait for the work queue to become empty before closing, timeout 30 seconds + if (!m_workQueueEmptyEvent.WaitOne(30 * 1000, false)) + { + ErrorHandler.Error("RemotingAppender ["+Name+"] failed to send all queued events before close, in OnClose."); + } + } + + /// + /// Flushes any buffered log data. + /// + /// The maximum time to wait for logging events to be flushed. + /// True if all logging events were flushed successfully, else false. + public override bool Flush(int millisecondsTimeout) + { + base.Flush(); + return m_workQueueEmptyEvent.WaitOne(millisecondsTimeout, false); + } + + #endregion + + /// + /// A work item is being queued into the thread pool + /// + private void BeginAsyncSend() + { + // The work queue is not empty + m_workQueueEmptyEvent.Reset(); + + // Increment the queued count + Interlocked.Increment(ref m_queuedCallbackCount); + } + + /// + /// A work item from the thread pool has completed + /// + private void EndAsyncSend() + { + // Decrement the queued count + if (Interlocked.Decrement(ref m_queuedCallbackCount) <= 0) + { + // If the work queue is empty then set the event + m_workQueueEmptyEvent.Set(); + } + } + + /// + /// Send the contents of the buffer to the remote sink. + /// + /// + /// This method is designed to be used with the . + /// This method expects to be passed an array of + /// objects in the state param. + /// + /// the logging events to send + private void SendBufferCallback(object state) + { + try + { + LoggingEvent[] events = (LoggingEvent[])state; + + // Send the events + m_sinkObj.LogEvents(events); + } + catch(Exception ex) + { + ErrorHandler.Error("Failed in SendBufferCallback", ex); + } + finally + { + EndAsyncSend(); + } + } + + #region Private Instance Fields + + /// + /// The URL of the remote sink. + /// + private string m_sinkUrl; + + /// + /// The local proxy (.NET remoting) for the remote logging sink. + /// + private IRemoteLoggingSink m_sinkObj; + + /// + /// The number of queued callbacks currently waiting or executing + /// + private int m_queuedCallbackCount = 0; + + /// + /// Event used to signal when there are no queued work items + /// + /// + /// This event is set when there are no queued work items. In this + /// state it is safe to close the appender. + /// + private ManualResetEvent m_workQueueEmptyEvent = new ManualResetEvent(true); + + #endregion Private Instance Fields + + /// + /// Interface used to deliver objects to a remote sink. + /// + /// + /// This interface must be implemented by a remoting sink + /// if the is to be used + /// to deliver logging events to the sink. + /// + public interface IRemoteLoggingSink + { + /// + /// Delivers logging events to the remote sink + /// + /// Array of events to log. + /// + /// + /// Delivers logging events to the remote sink + /// + /// + void LogEvents(LoggingEvent[] events); + } + } } #endif // NET_2_0 \ No newline at end of file diff --git a/src/log4net/Appender/RollingFileAppender.cs b/src/log4net/Appender/RollingFileAppender.cs index d6aef101..b1943d70 100644 --- a/src/log4net/Appender/RollingFileAppender.cs +++ b/src/log4net/Appender/RollingFileAppender.cs @@ -29,467 +29,467 @@ namespace log4net.Appender { #if CONFIRM_WIN32_FILE_SHAREMODES - // The following sounds good, and I though it was the case, but after - // further testing on Windows I have not been able to confirm it. - - /// On the Windows platform if another process has a write lock on the file - /// that is to be deleted, but allows shared read access to the file then the - /// file can be moved, but cannot be deleted. If the other process also allows - /// shared delete access to the file then the file will be deleted once that - /// process closes the file. If it is necessary to open the log file or any - /// of the backup files outside of this appender for either read or - /// write access please ensure that read and delete share modes are enabled. + // The following sounds good, and I though it was the case, but after + // further testing on Windows I have not been able to confirm it. + + /// On the Windows platform if another process has a write lock on the file + /// that is to be deleted, but allows shared read access to the file then the + /// file can be moved, but cannot be deleted. If the other process also allows + /// shared delete access to the file then the file will be deleted once that + /// process closes the file. If it is necessary to open the log file or any + /// of the backup files outside of this appender for either read or + /// write access please ensure that read and delete share modes are enabled. #endif - /// - /// Appender that rolls log files based on size or date or both. - /// - /// - /// - /// RollingFileAppender can roll log files based on size or date or both - /// depending on the setting of the property. - /// When set to the log file will be rolled - /// once its size exceeds the . - /// When set to the log file will be rolled - /// once the date boundary specified in the property - /// is crossed. - /// When set to the log file will be - /// rolled once the date boundary specified in the property - /// is crossed, but within a date boundary the file will also be rolled - /// once its size exceeds the . - /// When set to the log file will be rolled when - /// the appender is configured. This effectively means that the log file can be - /// rolled once per program execution. - /// - /// - /// A of few additional optional features have been added: - /// - /// Attach date pattern for current log file - /// Backup number increments for newer files - /// Infinite number of backups by file size - /// - /// - /// - /// - /// - /// For large or infinite numbers of backup files a - /// greater than zero is highly recommended, otherwise all the backup files need - /// to be renamed each time a new backup is created. - /// - /// - /// When Date/Time based rolling is used setting - /// to will reduce the number of file renamings to few or none. - /// - /// - /// - /// - /// - /// Changing or without clearing - /// the log file directory of backup files will cause unexpected and unwanted side effects. - /// - /// - /// - /// - /// If Date/Time based rolling is enabled this appender will attempt to roll existing files - /// in the directory without a Date/Time tag based on the last write date of the base log file. - /// The appender only rolls the log file when a message is logged. If Date/Time based rolling - /// is enabled then the appender will not roll the log file at the Date/Time boundary but - /// at the point when the next message is logged after the boundary has been crossed. - /// - /// - /// - /// The extends the and - /// has the same behavior when opening the log file. - /// The appender will first try to open the file for writing when - /// is called. This will typically be during configuration. - /// If the file cannot be opened for writing the appender will attempt - /// to open the file again each time a message is logged to the appender. - /// If the file cannot be opened for writing when a message is logged then - /// the message will be discarded by this appender. - /// - /// - /// When rolling a backup file necessitates deleting an older backup file the - /// file to be deleted is moved to a temporary name before being deleted. - /// - /// - /// - /// - /// A maximum number of backup files when rolling on date/time boundaries is not supported. - /// - /// - /// - /// Nicko Cadell - /// Gert Driesen - /// Aspi Havewala - /// Douglas de la Torre - /// Edward Smit - public class RollingFileAppender : FileAppender + /// + /// Appender that rolls log files based on size or date or both. + /// + /// + /// + /// RollingFileAppender can roll log files based on size or date or both + /// depending on the setting of the property. + /// When set to the log file will be rolled + /// once its size exceeds the . + /// When set to the log file will be rolled + /// once the date boundary specified in the property + /// is crossed. + /// When set to the log file will be + /// rolled once the date boundary specified in the property + /// is crossed, but within a date boundary the file will also be rolled + /// once its size exceeds the . + /// When set to the log file will be rolled when + /// the appender is configured. This effectively means that the log file can be + /// rolled once per program execution. + /// + /// + /// A of few additional optional features have been added: + /// + /// Attach date pattern for current log file + /// Backup number increments for newer files + /// Infinite number of backups by file size + /// + /// + /// + /// + /// + /// For large or infinite numbers of backup files a + /// greater than zero is highly recommended, otherwise all the backup files need + /// to be renamed each time a new backup is created. + /// + /// + /// When Date/Time based rolling is used setting + /// to will reduce the number of file renamings to few or none. + /// + /// + /// + /// + /// + /// Changing or without clearing + /// the log file directory of backup files will cause unexpected and unwanted side effects. + /// + /// + /// + /// + /// If Date/Time based rolling is enabled this appender will attempt to roll existing files + /// in the directory without a Date/Time tag based on the last write date of the base log file. + /// The appender only rolls the log file when a message is logged. If Date/Time based rolling + /// is enabled then the appender will not roll the log file at the Date/Time boundary but + /// at the point when the next message is logged after the boundary has been crossed. + /// + /// + /// + /// The extends the and + /// has the same behavior when opening the log file. + /// The appender will first try to open the file for writing when + /// is called. This will typically be during configuration. + /// If the file cannot be opened for writing the appender will attempt + /// to open the file again each time a message is logged to the appender. + /// If the file cannot be opened for writing when a message is logged then + /// the message will be discarded by this appender. + /// + /// + /// When rolling a backup file necessitates deleting an older backup file the + /// file to be deleted is moved to a temporary name before being deleted. + /// + /// + /// + /// + /// A maximum number of backup files when rolling on date/time boundaries is not supported. + /// + /// + /// + /// Nicko Cadell + /// Gert Driesen + /// Aspi Havewala + /// Douglas de la Torre + /// Edward Smit + public class RollingFileAppender : FileAppender { #region Public Enums /// - /// Style of rolling to use - /// - /// - /// - /// Style of rolling to use - /// - /// - public enum RollingMode - { - /// - /// Roll files once per program execution - /// - /// - /// - /// Roll files once per program execution. - /// Well really once each time this appender is - /// configured. - /// - /// - /// Setting this option also sets AppendToFile to - /// false on the RollingFileAppender, otherwise - /// this appender would just be a normal file appender. - /// - /// - Once = 0, - - /// - /// Roll files based only on the size of the file - /// - Size = 1, - - /// - /// Roll files based only on the date - /// - Date = 2, - - /// - /// Roll files based on both the size and date of the file - /// - Composite = 3 - } - - #endregion - - #region Protected Enums - - /// - /// The code assumes that the following 'time' constants are in a increasing sequence. - /// - /// - /// - /// The code assumes that the following 'time' constants are in a increasing sequence. - /// - /// - protected enum RollPoint - { - /// - /// Roll the log not based on the date - /// - InvalidRollPoint =-1, - - /// - /// Roll the log for each minute - /// - TopOfMinute = 0, - - /// - /// Roll the log for each hour - /// - TopOfHour = 1, - - /// - /// Roll the log twice a day (midday and midnight) - /// - HalfDay = 2, - - /// - /// Roll the log each day (midnight) - /// - TopOfDay = 3, - - /// - /// Roll the log each week - /// - TopOfWeek = 4, - - /// - /// Roll the log each month - /// - TopOfMonth = 5 - } - - #endregion Protected Enums - - #region Public Instance Constructors - - /// - /// Initializes a new instance of the class. - /// - /// - /// - /// Default constructor. - /// - /// - public RollingFileAppender() - { - } - - /// - /// Cleans up all resources used by this appender. - /// - ~RollingFileAppender() - { + /// Style of rolling to use + /// + /// + /// + /// Style of rolling to use + /// + /// + public enum RollingMode + { + /// + /// Roll files once per program execution + /// + /// + /// + /// Roll files once per program execution. + /// Well really once each time this appender is + /// configured. + /// + /// + /// Setting this option also sets AppendToFile to + /// false on the RollingFileAppender, otherwise + /// this appender would just be a normal file appender. + /// + /// + Once = 0, + + /// + /// Roll files based only on the size of the file + /// + Size = 1, + + /// + /// Roll files based only on the date + /// + Date = 2, + + /// + /// Roll files based on both the size and date of the file + /// + Composite = 3 + } + + #endregion + + #region Protected Enums + + /// + /// The code assumes that the following 'time' constants are in a increasing sequence. + /// + /// + /// + /// The code assumes that the following 'time' constants are in a increasing sequence. + /// + /// + protected enum RollPoint + { + /// + /// Roll the log not based on the date + /// + InvalidRollPoint =-1, + + /// + /// Roll the log for each minute + /// + TopOfMinute = 0, + + /// + /// Roll the log for each hour + /// + TopOfHour = 1, + + /// + /// Roll the log twice a day (midday and midnight) + /// + HalfDay = 2, + + /// + /// Roll the log each day (midnight) + /// + TopOfDay = 3, + + /// + /// Roll the log each week + /// + TopOfWeek = 4, + + /// + /// Roll the log each month + /// + TopOfMonth = 5 + } + + #endregion Protected Enums + + #region Public Instance Constructors + + /// + /// Initializes a new instance of the class. + /// + /// + /// + /// Default constructor. + /// + /// + public RollingFileAppender() + { + } + + /// + /// Cleans up all resources used by this appender. + /// + ~RollingFileAppender() + { #if !NETCF - if (m_mutexForRolling != null) - { + if (m_mutexForRolling != null) + { #if NET_4_0 || MONO_4_0 || NETSTANDARD - m_mutexForRolling.Dispose(); + m_mutexForRolling.Dispose(); #else - m_mutexForRolling.Close(); + m_mutexForRolling.Close(); #endif - m_mutexForRolling = null; - } + m_mutexForRolling = null; + } #endif - } + } - #endregion Public Instance Constructors + #endregion Public Instance Constructors - #region Public Instance Properties + #region Public Instance Properties #if !NET_1_0 && !CLI_1_0 && !NETCF /// - /// Gets or sets the strategy for determining the current date and time. The default - /// implementation is to use LocalDateTime which internally calls through to DateTime.Now. - /// DateTime.UtcNow may be used on frameworks newer than .NET 1.0 by specifying - /// . - /// - /// - /// An implementation of the interface which returns the current date and time. - /// - /// - /// - /// Gets or sets the used to return the current date and time. - /// + /// Gets or sets the strategy for determining the current date and time. The default + /// implementation is to use LocalDateTime which internally calls through to DateTime.Now. + /// DateTime.UtcNow may be used on frameworks newer than .NET 1.0 by specifying + /// . + /// + /// + /// An implementation of the interface which returns the current date and time. + /// + /// + /// + /// Gets or sets the used to return the current date and time. + /// /// /// There are two built strategies for determining the current date and time, - /// + /// /// and . /// /// - /// The default strategy is . - /// - /// + /// The default strategy is . + /// + /// #else /// - /// Gets or sets the strategy for determining the current date and time. The default - /// implementation is to use LocalDateTime which internally calls through to DateTime.Now. - /// - /// - /// An implementation of the interface which returns the current date and time. - /// - /// - /// - /// Gets or sets the used to return the current date and time. - /// + /// Gets or sets the strategy for determining the current date and time. The default + /// implementation is to use LocalDateTime which internally calls through to DateTime.Now. + /// + /// + /// An implementation of the interface which returns the current date and time. + /// + /// + /// + /// Gets or sets the used to return the current date and time. + /// /// - /// The default strategy is . - /// - /// + /// The default strategy is . + /// + /// #endif public IDateTime DateTimeStrategy - { - get { return m_dateTime; } - set { m_dateTime = value; } - } - - /// - /// Gets or sets the date pattern to be used for generating file names - /// when rolling over on date. - /// - /// - /// The date pattern to be used for generating file names when rolling - /// over on date. - /// - /// - /// - /// Takes a string in the same format as expected by - /// . - /// - /// - /// This property determines the rollover schedule when rolling over - /// on date. - /// - /// - public string DatePattern - { - get { return m_datePattern; } - set { m_datePattern = value; } - } + { + get { return m_dateTime; } + set { m_dateTime = value; } + } + + /// + /// Gets or sets the date pattern to be used for generating file names + /// when rolling over on date. + /// + /// + /// The date pattern to be used for generating file names when rolling + /// over on date. + /// + /// + /// + /// Takes a string in the same format as expected by + /// . + /// + /// + /// This property determines the rollover schedule when rolling over + /// on date. + /// + /// + public string DatePattern + { + get { return m_datePattern; } + set { m_datePattern = value; } + } - /// - /// Gets or sets the maximum number of backup files that are kept before - /// the oldest is erased. - /// - /// - /// The maximum number of backup files that are kept before the oldest is - /// erased. - /// - /// - /// - /// If set to zero, then there will be no backup files and the log file - /// will be truncated when it reaches . - /// - /// - /// If a negative number is supplied then no deletions will be made. Note - /// that this could result in very slow performance as a large number of - /// files are rolled over unless is used. - /// - /// - /// The maximum applies to each time based group of files and - /// not the total. - /// - /// - public int MaxSizeRollBackups - { - get { return m_maxSizeRollBackups; } - set { m_maxSizeRollBackups = value; } - } + /// + /// Gets or sets the maximum number of backup files that are kept before + /// the oldest is erased. + /// + /// + /// The maximum number of backup files that are kept before the oldest is + /// erased. + /// + /// + /// + /// If set to zero, then there will be no backup files and the log file + /// will be truncated when it reaches . + /// + /// + /// If a negative number is supplied then no deletions will be made. Note + /// that this could result in very slow performance as a large number of + /// files are rolled over unless is used. + /// + /// + /// The maximum applies to each time based group of files and + /// not the total. + /// + /// + public int MaxSizeRollBackups + { + get { return m_maxSizeRollBackups; } + set { m_maxSizeRollBackups = value; } + } - /// - /// Gets or sets the maximum size that the output file is allowed to reach - /// before being rolled over to backup files. - /// - /// - /// The maximum size in bytes that the output file is allowed to reach before being - /// rolled over to backup files. - /// - /// - /// - /// This property is equivalent to except - /// that it is required for differentiating the setter taking a - /// argument from the setter taking a - /// argument. - /// - /// - /// The default maximum file size is 10MB (10*1024*1024). - /// - /// - public long MaxFileSize - { - get { return m_maxFileSize; } - set { m_maxFileSize = value; } - } + /// + /// Gets or sets the maximum size that the output file is allowed to reach + /// before being rolled over to backup files. + /// + /// + /// The maximum size in bytes that the output file is allowed to reach before being + /// rolled over to backup files. + /// + /// + /// + /// This property is equivalent to except + /// that it is required for differentiating the setter taking a + /// argument from the setter taking a + /// argument. + /// + /// + /// The default maximum file size is 10MB (10*1024*1024). + /// + /// + public long MaxFileSize + { + get { return m_maxFileSize; } + set { m_maxFileSize = value; } + } - /// - /// Gets or sets the maximum size that the output file is allowed to reach - /// before being rolled over to backup files. - /// - /// - /// The maximum size that the output file is allowed to reach before being - /// rolled over to backup files. - /// - /// - /// - /// This property allows you to specify the maximum size with the - /// suffixes "KB", "MB" or "GB" so that the size is interpreted being - /// expressed respectively in kilobytes, megabytes or gigabytes. - /// - /// - /// For example, the value "10KB" will be interpreted as 10240 bytes. - /// - /// - /// The default maximum file size is 10MB. - /// - /// - /// If you have the option to set the maximum file size programmatically - /// consider using the property instead as this - /// allows you to set the size in bytes as a . - /// - /// - public string MaximumFileSize - { - get { return m_maxFileSize.ToString(NumberFormatInfo.InvariantInfo); } - set { m_maxFileSize = OptionConverter.ToFileSize(value, m_maxFileSize + 1); } - } - - /// - /// Gets or sets the rolling file count direction. - /// - /// - /// The rolling file count direction. - /// - /// - /// - /// Indicates if the current file is the lowest numbered file or the - /// highest numbered file. - /// - /// - /// By default newer files have lower numbers ( < 0), - /// i.e. log.1 is most recent, log.5 is the 5th backup, etc... - /// - /// - /// >= 0 does the opposite i.e. - /// log.1 is the first backup made, log.5 is the 5th backup made, etc. - /// For infinite backups use >= 0 to reduce - /// rollover costs. - /// - /// The default file count direction is -1. - /// - public int CountDirection - { - get { return m_countDirection; } - set { m_countDirection = value; } - } + /// + /// Gets or sets the maximum size that the output file is allowed to reach + /// before being rolled over to backup files. + /// + /// + /// The maximum size that the output file is allowed to reach before being + /// rolled over to backup files. + /// + /// + /// + /// This property allows you to specify the maximum size with the + /// suffixes "KB", "MB" or "GB" so that the size is interpreted being + /// expressed respectively in kilobytes, megabytes or gigabytes. + /// + /// + /// For example, the value "10KB" will be interpreted as 10240 bytes. + /// + /// + /// The default maximum file size is 10MB. + /// + /// + /// If you have the option to set the maximum file size programmatically + /// consider using the property instead as this + /// allows you to set the size in bytes as a . + /// + /// + public string MaximumFileSize + { + get { return m_maxFileSize.ToString(NumberFormatInfo.InvariantInfo); } + set { m_maxFileSize = OptionConverter.ToFileSize(value, m_maxFileSize + 1); } + } + + /// + /// Gets or sets the rolling file count direction. + /// + /// + /// The rolling file count direction. + /// + /// + /// + /// Indicates if the current file is the lowest numbered file or the + /// highest numbered file. + /// + /// + /// By default newer files have lower numbers ( < 0), + /// i.e. log.1 is most recent, log.5 is the 5th backup, etc... + /// + /// + /// >= 0 does the opposite i.e. + /// log.1 is the first backup made, log.5 is the 5th backup made, etc. + /// For infinite backups use >= 0 to reduce + /// rollover costs. + /// + /// The default file count direction is -1. + /// + public int CountDirection + { + get { return m_countDirection; } + set { m_countDirection = value; } + } - /// - /// Gets or sets the rolling style. - /// - /// The rolling style. - /// - /// - /// The default rolling style is . - /// - /// - /// When set to this appender's - /// property is set to false, otherwise - /// the appender would append to a single file rather than rolling - /// the file each time it is opened. - /// - /// - public RollingMode RollingStyle - { - get { return m_rollingStyle; } - set - { - m_rollingStyle = value; - switch (m_rollingStyle) - { - case RollingMode.Once: - m_rollDate = false; - m_rollSize = false; - - AppendToFile = false; - break; - - case RollingMode.Size: - m_rollDate = false; - m_rollSize = true; - break; - - case RollingMode.Date: - m_rollDate = true; - m_rollSize = false; - break; - - case RollingMode.Composite: - m_rollDate = true; - m_rollSize = true; - break; - } - } - } + /// + /// Gets or sets the rolling style. + /// + /// The rolling style. + /// + /// + /// The default rolling style is . + /// + /// + /// When set to this appender's + /// property is set to false, otherwise + /// the appender would append to a single file rather than rolling + /// the file each time it is opened. + /// + /// + public RollingMode RollingStyle + { + get { return m_rollingStyle; } + set + { + m_rollingStyle = value; + switch (m_rollingStyle) + { + case RollingMode.Once: + m_rollDate = false; + m_rollSize = false; + + AppendToFile = false; + break; + + case RollingMode.Size: + m_rollDate = false; + m_rollSize = true; + break; + + case RollingMode.Date: + m_rollDate = true; + m_rollSize = false; + break; + + case RollingMode.Composite: + m_rollDate = true; + m_rollSize = true; + break; + } + } + } /// /// Gets or sets a value indicating whether to preserve the file name extension when rolling. @@ -511,270 +511,270 @@ public bool PreserveLogFileNameExtension set { m_preserveLogFileNameExtension = value; } } - /// - /// Gets or sets a value indicating whether to always log to - /// the same file. - /// - /// - /// true if always should be logged to the same file, otherwise false. - /// - /// - /// - /// By default file.log is always the current file. Optionally - /// file.log.yyyy-mm-dd for current formatted datePattern can by the currently - /// logging file (or file.log.curSizeRollBackup or even - /// file.log.yyyy-mm-dd.curSizeRollBackup). - /// - /// - /// This will make time based rollovers with a large number of backups - /// much faster as the appender it won't have to rename all the backups! - /// - /// - public bool StaticLogFileName - { - get { return m_staticLogFileName; } - set { m_staticLogFileName = value; } - } - - #endregion Public Instance Properties - - #region Private Static Fields - - /// - /// The fully qualified type of the RollingFileAppender class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(RollingFileAppender); - - #endregion Private Static Fields - - #region Override implementation of FileAppender + /// + /// Gets or sets a value indicating whether to always log to + /// the same file. + /// + /// + /// true if always should be logged to the same file, otherwise false. + /// + /// + /// + /// By default file.log is always the current file. Optionally + /// file.log.yyyy-mm-dd for current formatted datePattern can by the currently + /// logging file (or file.log.curSizeRollBackup or even + /// file.log.yyyy-mm-dd.curSizeRollBackup). + /// + /// + /// This will make time based rollovers with a large number of backups + /// much faster as the appender it won't have to rename all the backups! + /// + /// + public bool StaticLogFileName + { + get { return m_staticLogFileName; } + set { m_staticLogFileName = value; } + } + + #endregion Public Instance Properties + + #region Private Static Fields + + /// + /// The fully qualified type of the RollingFileAppender class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(RollingFileAppender); + + #endregion Private Static Fields + + #region Override implementation of FileAppender - /// - /// Sets the quiet writer being used. - /// - /// - /// This method can be overridden by sub classes. - /// - /// the writer to set - protected override void SetQWForFiles(TextWriter writer) - { - QuietWriter = new CountingQuietTextWriter(writer, ErrorHandler); - } - - /// - /// Write out a logging event. - /// - /// the event to write to file. - /// - /// - /// Handles append time behavior for RollingFileAppender. This checks - /// if a roll over either by date (checked first) or time (checked second) - /// is need and then appends to the file last. - /// - /// - protected override void Append(LoggingEvent loggingEvent) - { - AdjustFileBeforeAppend(); - base.Append(loggingEvent); - } + /// + /// Sets the quiet writer being used. + /// + /// + /// This method can be overridden by sub classes. + /// + /// the writer to set + protected override void SetQWForFiles(TextWriter writer) + { + QuietWriter = new CountingQuietTextWriter(writer, ErrorHandler); + } + + /// + /// Write out a logging event. + /// + /// the event to write to file. + /// + /// + /// Handles append time behavior for RollingFileAppender. This checks + /// if a roll over either by date (checked first) or time (checked second) + /// is need and then appends to the file last. + /// + /// + protected override void Append(LoggingEvent loggingEvent) + { + AdjustFileBeforeAppend(); + base.Append(loggingEvent); + } - /// - /// Write out an array of logging events. - /// - /// the events to write to file. - /// - /// - /// Handles append time behavior for RollingFileAppender. This checks - /// if a roll over either by date (checked first) or time (checked second) - /// is need and then appends to the file last. - /// - /// - protected override void Append(LoggingEvent[] loggingEvents) - { - AdjustFileBeforeAppend(); - base.Append(loggingEvents); - } - - /// - /// Performs any required rolling before outputting the next event - /// - /// - /// - /// Handles append time behavior for RollingFileAppender. This checks - /// if a roll over either by date (checked first) or time (checked second) - /// is need and then appends to the file last. - /// - /// - protected virtual void AdjustFileBeforeAppend() - { - // reuse the file appenders locking model to lock the rolling + /// + /// Write out an array of logging events. + /// + /// the events to write to file. + /// + /// + /// Handles append time behavior for RollingFileAppender. This checks + /// if a roll over either by date (checked first) or time (checked second) + /// is need and then appends to the file last. + /// + /// + protected override void Append(LoggingEvent[] loggingEvents) + { + AdjustFileBeforeAppend(); + base.Append(loggingEvents); + } + + /// + /// Performs any required rolling before outputting the next event + /// + /// + /// + /// Handles append time behavior for RollingFileAppender. This checks + /// if a roll over either by date (checked first) or time (checked second) + /// is need and then appends to the file last. + /// + /// + protected virtual void AdjustFileBeforeAppend() + { + // reuse the file appenders locking model to lock the rolling #if !NETCF - try - { - // if rolling should be locked, acquire the lock - if (m_mutexForRolling != null) - { - m_mutexForRolling.WaitOne(); - } + try + { + // if rolling should be locked, acquire the lock + if (m_mutexForRolling != null) + { + m_mutexForRolling.WaitOne(); + } #endif - if (m_rollDate) - { - var n = m_dateTime.Now; - if (n >= m_nextCheck) - { - m_now = n; - m_nextCheck = NextCheckDate(m_now, m_rollPoint); - - RollOverTime(true); - } - } - - if (m_rollSize) - { - if ((File != null) && ((CountingQuietTextWriter)QuietWriter).Count >= m_maxFileSize) - { - RollOverSize(); - } - } + if (m_rollDate) + { + var n = m_dateTime.Now; + if (n >= m_nextCheck) + { + m_now = n; + m_nextCheck = NextCheckDate(m_now, m_rollPoint); + + RollOverTime(true); + } + } + + if (m_rollSize) + { + if ((File != null) && ((CountingQuietTextWriter)QuietWriter).Count >= m_maxFileSize) + { + RollOverSize(); + } + } #if !NETCF - } - finally - { - // if rolling should be locked, release the lock - if (m_mutexForRolling != null) - { - m_mutexForRolling.ReleaseMutex(); - } - } + } + finally + { + // if rolling should be locked, release the lock + if (m_mutexForRolling != null) + { + m_mutexForRolling.ReleaseMutex(); + } + } #endif - } - - /// - /// Creates and opens the file for logging. If - /// is false then the fully qualified name is determined and used. - /// - /// the name of the file to open - /// true to append to existing file - /// - /// This method will ensure that the directory structure - /// for the specified exists. - /// - protected override void OpenFile(string fileName, bool append) - { - lock(this) - { - fileName = GetNextOutputFileName(fileName); - - // Calculate the current size of the file - long currentCount = 0; - if (append) - { - using(SecurityContext.Impersonate(this)) - { - if (System.IO.File.Exists(fileName)) - { - currentCount = (new FileInfo(fileName)).Length; - } - } - } - else - { - if (LogLog.IsErrorEnabled) - { - // Internal check that the file is not being overwritten - // If not Appending to an existing file we should have rolled the file out of the - // way. Therefore we should not be over-writing an existing file. - // The only exception is if we are not allowed to roll the existing file away. - if (m_maxSizeRollBackups != 0 && FileExists(fileName)) - { - LogLog.Error(declaringType, "RollingFileAppender: INTERNAL ERROR. Append is False but OutputFile ["+fileName+"] already exists."); - } - } - } - - if (!m_staticLogFileName) - { - m_scheduledFilename = fileName; - } - - // Open the file (call the base class to do it) - base.OpenFile(fileName, append); - - // Set the file size onto the counting writer - ((CountingQuietTextWriter)QuietWriter).Count = currentCount; - } - } - - /// - /// Get the current output file name - /// - /// the base file name - /// the output file name - /// - /// The output file name is based on the base fileName specified. - /// If is set then the output - /// file name is the same as the base file passed in. Otherwise - /// the output file depends on the date pattern, on the count - /// direction or both. - /// - protected string GetNextOutputFileName(string fileName) - { - if (!m_staticLogFileName) - { - fileName = fileName.Trim(); - - if (m_rollDate) - { + } + + /// + /// Creates and opens the file for logging. If + /// is false then the fully qualified name is determined and used. + /// + /// the name of the file to open + /// true to append to existing file + /// + /// This method will ensure that the directory structure + /// for the specified exists. + /// + protected override void OpenFile(string fileName, bool append) + { + lock(this) + { + fileName = GetNextOutputFileName(fileName); + + // Calculate the current size of the file + long currentCount = 0; + if (append) + { + using(SecurityContext.Impersonate(this)) + { + if (System.IO.File.Exists(fileName)) + { + currentCount = (new FileInfo(fileName)).Length; + } + } + } + else + { + if (LogLog.IsErrorEnabled) + { + // Internal check that the file is not being overwritten + // If not Appending to an existing file we should have rolled the file out of the + // way. Therefore we should not be over-writing an existing file. + // The only exception is if we are not allowed to roll the existing file away. + if (m_maxSizeRollBackups != 0 && FileExists(fileName)) + { + LogLog.Error(declaringType, "RollingFileAppender: INTERNAL ERROR. Append is False but OutputFile ["+fileName+"] already exists."); + } + } + } + + if (!m_staticLogFileName) + { + m_scheduledFilename = fileName; + } + + // Open the file (call the base class to do it) + base.OpenFile(fileName, append); + + // Set the file size onto the counting writer + ((CountingQuietTextWriter)QuietWriter).Count = currentCount; + } + } + + /// + /// Get the current output file name + /// + /// the base file name + /// the output file name + /// + /// The output file name is based on the base fileName specified. + /// If is set then the output + /// file name is the same as the base file passed in. Otherwise + /// the output file depends on the date pattern, on the count + /// direction or both. + /// + protected string GetNextOutputFileName(string fileName) + { + if (!m_staticLogFileName) + { + fileName = fileName.Trim(); + + if (m_rollDate) + { fileName = CombinePath(fileName, m_now.ToString(m_datePattern, DateTimeFormatInfo.InvariantInfo)); - } + } - if (m_countDirection >= 0) - { + if (m_countDirection >= 0) + { fileName = CombinePath(fileName, "." + m_curSizeRollBackups); - } - } - - return fileName; - } - - #endregion - - #region Initialize Options - - /// - /// Determines curSizeRollBackups (only within the current roll point) - /// - private void DetermineCurSizeRollBackups() - { - m_curSizeRollBackups = 0; - - string fullPath = null; - string fileName = null; - - using(SecurityContext.Impersonate(this)) - { - fullPath = Path.GetFullPath(m_baseFileName); - fileName = Path.GetFileName(fullPath); - } - - var arrayFiles = GetExistingFiles(fullPath); - InitializeRollBackups(fileName, arrayFiles); - - LogLog.Debug(declaringType, "curSizeRollBackups starts at ["+m_curSizeRollBackups+"]"); - } - - /// - /// Generates a wildcard pattern that can be used to find all files - /// that are similar to the base file name. - /// - /// - /// - private string GetWildcardPatternForFile(string baseFileName) - { + } + } + + return fileName; + } + + #endregion + + #region Initialize Options + + /// + /// Determines curSizeRollBackups (only within the current roll point) + /// + private void DetermineCurSizeRollBackups() + { + m_curSizeRollBackups = 0; + + string fullPath = null; + string fileName = null; + + using(SecurityContext.Impersonate(this)) + { + fullPath = Path.GetFullPath(m_baseFileName); + fileName = Path.GetFileName(fullPath); + } + + var arrayFiles = GetExistingFiles(fullPath); + InitializeRollBackups(fileName, arrayFiles); + + LogLog.Debug(declaringType, "curSizeRollBackups starts at ["+m_curSizeRollBackups+"]"); + } + + /// + /// Generates a wildcard pattern that can be used to find all files + /// that are similar to the base file name. + /// + /// + /// + private string GetWildcardPatternForFile(string baseFileName) + { if (m_preserveLogFileNameExtension) { return Path.GetFileNameWithoutExtension(baseFileName) + "*" + Path.GetExtension(baseFileName); @@ -783,178 +783,178 @@ private string GetWildcardPatternForFile(string baseFileName) { return baseFileName + '*'; } - } - - /// - /// Builds a list of filenames for all files matching the base filename plus a file - /// pattern. - /// - /// - /// - private ArrayList GetExistingFiles(string baseFilePath) - { - var alFiles = new ArrayList(); - - string directory = null; - - using(SecurityContext.Impersonate(this)) - { - var fullPath = Path.GetFullPath(baseFilePath); - - directory = Path.GetDirectoryName(fullPath); - if (Directory.Exists(directory)) - { - var baseFileName = Path.GetFileName(fullPath); - - var files = Directory.GetFiles(directory, GetWildcardPatternForFile(baseFileName)); - - if (files != null) - { - for (var i = 0; i < files.Length; i++) - { - var curFileName = Path.GetFileName(files[i]); - if (curFileName.StartsWith(Path.GetFileNameWithoutExtension(baseFileName))) - { - alFiles.Add(curFileName); - } - } - } - } - } - LogLog.Debug(declaringType, "Searched for existing files in ["+directory+"]"); - return alFiles; - } - - /// - /// Initiates a roll over if needed for crossing a date boundary since the last run. - /// - private void RollOverIfDateBoundaryCrossing() - { - if (m_staticLogFileName && m_rollDate) - { - if (FileExists(m_baseFileName)) - { - DateTime last; - using(SecurityContext.Impersonate(this)) { + } + + /// + /// Builds a list of filenames for all files matching the base filename plus a file + /// pattern. + /// + /// + /// + private ArrayList GetExistingFiles(string baseFilePath) + { + var alFiles = new ArrayList(); + + string directory = null; + + using(SecurityContext.Impersonate(this)) + { + var fullPath = Path.GetFullPath(baseFilePath); + + directory = Path.GetDirectoryName(fullPath); + if (Directory.Exists(directory)) + { + var baseFileName = Path.GetFileName(fullPath); + + var files = Directory.GetFiles(directory, GetWildcardPatternForFile(baseFileName)); + + if (files != null) + { + for (var i = 0; i < files.Length; i++) + { + var curFileName = Path.GetFileName(files[i]); + if (curFileName.StartsWith(Path.GetFileNameWithoutExtension(baseFileName))) + { + alFiles.Add(curFileName); + } + } + } + } + } + LogLog.Debug(declaringType, "Searched for existing files in ["+directory+"]"); + return alFiles; + } + + /// + /// Initiates a roll over if needed for crossing a date boundary since the last run. + /// + private void RollOverIfDateBoundaryCrossing() + { + if (m_staticLogFileName && m_rollDate) + { + if (FileExists(m_baseFileName)) + { + DateTime last; + using(SecurityContext.Impersonate(this)) { #if !NET_1_0 && !CLI_1_0 && !NETCF if (DateTimeStrategy is UniversalDateTime) - { - last = System.IO.File.GetLastWriteTimeUtc(m_baseFileName); - } - else - { + { + last = System.IO.File.GetLastWriteTimeUtc(m_baseFileName); + } + else + { #endif - last = System.IO.File.GetLastWriteTime(m_baseFileName); + last = System.IO.File.GetLastWriteTime(m_baseFileName); #if !NET_1_0 && !CLI_1_0 && !NETCF } #endif } - LogLog.Debug(declaringType, "["+last.ToString(m_datePattern,DateTimeFormatInfo.InvariantInfo)+"] vs. ["+m_now.ToString(m_datePattern,DateTimeFormatInfo.InvariantInfo)+"]"); - - if (!(last.ToString(m_datePattern,DateTimeFormatInfo.InvariantInfo).Equals(m_now.ToString(m_datePattern, DateTimeFormatInfo.InvariantInfo)))) - { - m_scheduledFilename = CombinePath(m_baseFileName, last.ToString(m_datePattern, DateTimeFormatInfo.InvariantInfo)); - LogLog.Debug(declaringType, "Initial roll over to ["+m_scheduledFilename+"]"); - RollOverTime(false); - LogLog.Debug(declaringType, "curSizeRollBackups after rollOver at ["+m_curSizeRollBackups+"]"); - } - } - } - } - - /// - /// Initializes based on existing conditions at time of . - /// - /// - /// - /// Initializes based on existing conditions at time of . - /// The following is done - /// - /// determine curSizeRollBackups (only within the current roll point) - /// initiates a roll over if needed for crossing a date boundary since the last run. - /// - /// - /// - protected void ExistingInit() - { - DetermineCurSizeRollBackups(); - RollOverIfDateBoundaryCrossing(); - - // If file exists and we are not appending then roll it out of the way - if (AppendToFile != false) - { - return; - } - - bool fileExists; - var fileName = GetNextOutputFileName(m_baseFileName); - - using(SecurityContext.Impersonate(this)) - { - fileExists = System.IO.File.Exists(fileName); - } - - if (!fileExists) - { - return; - } - - if (m_maxSizeRollBackups == 0) - { - LogLog.Debug(declaringType, "Output file ["+fileName+"] already exists. MaxSizeRollBackups is 0; cannot roll. Overwriting existing file."); - } - else - { - LogLog.Debug(declaringType, "Output file ["+fileName+"] already exists. Not appending to file. Rolling existing file out of the way."); - - RollOverRenameFiles(fileName); - } - } - - /// - /// Does the work of bumping the 'current' file counter higher - /// to the highest count when an incremental file name is seen. - /// The highest count is either the first file (when count direction - /// is greater than 0) or the last file (when count direction less than 0). - /// In either case, we want to know the highest count that is present. - /// - /// - /// - private void InitializeFromOneFile(string baseFile, string curFileName) - { - curFileName = curFileName.ToLower(); - baseFile = baseFile.ToLower(); + LogLog.Debug(declaringType, "["+last.ToString(m_datePattern,DateTimeFormatInfo.InvariantInfo)+"] vs. ["+m_now.ToString(m_datePattern,DateTimeFormatInfo.InvariantInfo)+"]"); + + if (!(last.ToString(m_datePattern,DateTimeFormatInfo.InvariantInfo).Equals(m_now.ToString(m_datePattern, DateTimeFormatInfo.InvariantInfo)))) + { + m_scheduledFilename = CombinePath(m_baseFileName, last.ToString(m_datePattern, DateTimeFormatInfo.InvariantInfo)); + LogLog.Debug(declaringType, "Initial roll over to ["+m_scheduledFilename+"]"); + RollOverTime(false); + LogLog.Debug(declaringType, "curSizeRollBackups after rollOver at ["+m_curSizeRollBackups+"]"); + } + } + } + } + + /// + /// Initializes based on existing conditions at time of . + /// + /// + /// + /// Initializes based on existing conditions at time of . + /// The following is done + /// + /// determine curSizeRollBackups (only within the current roll point) + /// initiates a roll over if needed for crossing a date boundary since the last run. + /// + /// + /// + protected void ExistingInit() + { + DetermineCurSizeRollBackups(); + RollOverIfDateBoundaryCrossing(); + + // If file exists and we are not appending then roll it out of the way + if (AppendToFile != false) + { + return; + } + + bool fileExists; + var fileName = GetNextOutputFileName(m_baseFileName); + + using(SecurityContext.Impersonate(this)) + { + fileExists = System.IO.File.Exists(fileName); + } + + if (!fileExists) + { + return; + } + + if (m_maxSizeRollBackups == 0) + { + LogLog.Debug(declaringType, "Output file ["+fileName+"] already exists. MaxSizeRollBackups is 0; cannot roll. Overwriting existing file."); + } + else + { + LogLog.Debug(declaringType, "Output file ["+fileName+"] already exists. Not appending to file. Rolling existing file out of the way."); + + RollOverRenameFiles(fileName); + } + } + + /// + /// Does the work of bumping the 'current' file counter higher + /// to the highest count when an incremental file name is seen. + /// The highest count is either the first file (when count direction + /// is greater than 0) or the last file (when count direction less than 0). + /// In either case, we want to know the highest count that is present. + /// + /// + /// + private void InitializeFromOneFile(string baseFile, string curFileName) + { + curFileName = curFileName.ToLower(); + baseFile = baseFile.ToLower(); if (curFileName.StartsWith(Path.GetFileNameWithoutExtension(baseFile)) == false) - { - // This is not a log file, so ignore - return; - } - if (curFileName.Equals(baseFile)) - { - // Base log file is not an incremented logfile (.1 or .2, etc) - return; - } - - // Only look for files in the current roll point - if (m_rollDate && !m_staticLogFileName) - { - var date = m_dateTime.Now.ToString(m_datePattern, DateTimeFormatInfo.InvariantInfo).ToLower(); - var prefix = (m_preserveLogFileNameExtension - ? Path.GetFileNameWithoutExtension(baseFile) + date - : baseFile + date).ToLower(); - var suffix = m_preserveLogFileNameExtension - ? Path.GetExtension(baseFile).ToLower() - : ""; - if (!curFileName.StartsWith(prefix) || !curFileName.EndsWith(suffix)) - { - LogLog.Debug(declaringType, "Ignoring file ["+curFileName+"] because it is from a different date period"); - return; - } - } + { + // This is not a log file, so ignore + return; + } + if (curFileName.Equals(baseFile)) + { + // Base log file is not an incremented logfile (.1 or .2, etc) + return; + } + + // Only look for files in the current roll point + if (m_rollDate && !m_staticLogFileName) + { + var date = m_dateTime.Now.ToString(m_datePattern, DateTimeFormatInfo.InvariantInfo).ToLower(); + var prefix = (m_preserveLogFileNameExtension + ? Path.GetFileNameWithoutExtension(baseFile) + date + : baseFile + date).ToLower(); + var suffix = m_preserveLogFileNameExtension + ? Path.GetExtension(baseFile).ToLower() + : ""; + if (!curFileName.StartsWith(prefix) || !curFileName.EndsWith(suffix)) + { + LogLog.Debug(declaringType, "Ignoring file ["+curFileName+"] because it is from a different date period"); + return; + } + } - try - { - // Bump the counter up to the highest count seen so far + try + { + // Bump the counter up to the highest count seen so far var backup = GetBackUpIndex(curFileName); // caution: we might get a false positive when certain @@ -991,14 +991,14 @@ private void InitializeFromOneFile(string baseFile, string curFileName) } LogLog.Debug(declaringType, "File name [" + curFileName + "] moves current count to [" + m_curSizeRollBackups + "]"); } - } - catch(FormatException) - { - //this happens when file.log -> file.log.yyyy-MM-dd which is normal - //when staticLogFileName == false - LogLog.Debug(declaringType, "Encountered a backup file not ending in .x ["+curFileName+"]"); - } - } + } + catch(FormatException) + { + //this happens when file.log -> file.log.yyyy-MM-dd which is normal + //when staticLogFileName == false + LogLog.Debug(declaringType, "Encountered a backup file not ending in .x ["+curFileName+"]"); + } + } /// /// Attempts to extract a number from the end of the file name that indicates @@ -1009,8 +1009,8 @@ private void InitializeFromOneFile(string baseFile, string curFileName) /// /// /// - private int GetBackUpIndex(string curFileName) - { + private int GetBackUpIndex(string curFileName) + { var backUpIndex = -1; var fileName = curFileName; @@ -1028,156 +1028,156 @@ private int GetBackUpIndex(string curFileName) } return backUpIndex; - } - - /// - /// Takes a list of files and a base file name, and looks for - /// 'incremented' versions of the base file. Bumps the max - /// count up to the highest count seen. - /// - /// - /// - private void InitializeRollBackups(string baseFile, ArrayList arrayFiles) - { - if (null != arrayFiles) - { - var baseFileLower = baseFile.ToLowerInvariant(); - - foreach(string curFileName in arrayFiles) - { - InitializeFromOneFile(baseFileLower, curFileName.ToLowerInvariant()); - } - } - } - - /// - /// Calculates the RollPoint for the datePattern supplied. - /// - /// the date pattern to calculate the check period for - /// The RollPoint that is most accurate for the date pattern supplied - /// - /// Essentially the date pattern is examined to determine what the - /// most suitable roll point is. The roll point chosen is the roll point - /// with the smallest period that can be detected using the date pattern - /// supplied. i.e. if the date pattern only outputs the year, month, day - /// and hour then the smallest roll point that can be detected would be - /// and hourly roll point as minutes could not be detected. - /// - private RollPoint ComputeCheckPeriod(string datePattern) - { - // s_date1970 is 1970-01-01 00:00:00 this is UniversalSortableDateTimePattern - // (based on ISO 8601) using universal time. This date is used for reference - // purposes to calculate the resolution of the date pattern. - - // Get string representation of base line date - var r0 = s_date1970.ToString(datePattern, DateTimeFormatInfo.InvariantInfo); - - // Check each type of rolling mode starting with the smallest increment. - for(var i = (int)RollPoint.TopOfMinute; i <= (int)RollPoint.TopOfMonth; i++) - { - // Get string representation of next pattern - var r1 = NextCheckDate(s_date1970, (RollPoint)i).ToString(datePattern, DateTimeFormatInfo.InvariantInfo); - - LogLog.Debug(declaringType, "Type = ["+i+"], r0 = ["+r0+"], r1 = ["+r1+"]"); - - // Check if the string representations are different - if (r0 != null && r1 != null && !r0.Equals(r1)) - { - // Found highest precision roll point - return (RollPoint)i; - } - } - - return RollPoint.InvalidRollPoint; // Deliberately head for trouble... - } - - /// - /// Initialize the appender based on the options set - /// - /// - /// - /// This is part of the delayed object - /// activation scheme. The method must - /// be called on this object after the configuration properties have - /// been set. Until is called this - /// object is in an undefined state and must not be used. - /// - /// - /// If any of the configuration properties are modified then - /// must be called again. - /// - /// - /// Sets initial conditions including date/time roll over information, first check, - /// scheduledFilename, and calls to initialize - /// the current number of backups. - /// - /// - public override void ActivateOptions() - { - if (m_dateTime == null) - { - m_dateTime = new LocalDateTime(); - } - - if (m_rollDate && m_datePattern != null) - { - m_now = m_dateTime.Now; - m_rollPoint = ComputeCheckPeriod(m_datePattern); - - if (m_rollPoint == RollPoint.InvalidRollPoint) - { - throw new ArgumentException("Invalid RollPoint, unable to parse ["+m_datePattern+"]"); - } - - // next line added as this removes the name check in rollOver - m_nextCheck = NextCheckDate(m_now, m_rollPoint); - } - else - { - if (m_rollDate) - { - ErrorHandler.Error("Either DatePattern or rollingStyle options are not set for ["+Name+"]."); - } - } - - if (SecurityContext == null) - { - SecurityContext = SecurityContextProvider.DefaultProvider.CreateSecurityContext(this); - } - - using(SecurityContext.Impersonate(this)) - { - // Must convert the FileAppender's m_filePath to an absolute path before we - // call ExistingInit(). This will be done by the base.ActivateOptions() but - // we need to duplicate that functionality here first. - base.File = ConvertToFullPath(base.File.Trim()); - - // Store fully qualified base file name - m_baseFileName = base.File; - } + } + + /// + /// Takes a list of files and a base file name, and looks for + /// 'incremented' versions of the base file. Bumps the max + /// count up to the highest count seen. + /// + /// + /// + private void InitializeRollBackups(string baseFile, ArrayList arrayFiles) + { + if (null != arrayFiles) + { + var baseFileLower = baseFile.ToLowerInvariant(); + + foreach(string curFileName in arrayFiles) + { + InitializeFromOneFile(baseFileLower, curFileName.ToLowerInvariant()); + } + } + } + + /// + /// Calculates the RollPoint for the datePattern supplied. + /// + /// the date pattern to calculate the check period for + /// The RollPoint that is most accurate for the date pattern supplied + /// + /// Essentially the date pattern is examined to determine what the + /// most suitable roll point is. The roll point chosen is the roll point + /// with the smallest period that can be detected using the date pattern + /// supplied. i.e. if the date pattern only outputs the year, month, day + /// and hour then the smallest roll point that can be detected would be + /// and hourly roll point as minutes could not be detected. + /// + private RollPoint ComputeCheckPeriod(string datePattern) + { + // s_date1970 is 1970-01-01 00:00:00 this is UniversalSortableDateTimePattern + // (based on ISO 8601) using universal time. This date is used for reference + // purposes to calculate the resolution of the date pattern. + + // Get string representation of base line date + var r0 = s_date1970.ToString(datePattern, DateTimeFormatInfo.InvariantInfo); + + // Check each type of rolling mode starting with the smallest increment. + for(var i = (int)RollPoint.TopOfMinute; i <= (int)RollPoint.TopOfMonth; i++) + { + // Get string representation of next pattern + var r1 = NextCheckDate(s_date1970, (RollPoint)i).ToString(datePattern, DateTimeFormatInfo.InvariantInfo); + + LogLog.Debug(declaringType, "Type = ["+i+"], r0 = ["+r0+"], r1 = ["+r1+"]"); + + // Check if the string representations are different + if (r0 != null && r1 != null && !r0.Equals(r1)) + { + // Found highest precision roll point + return (RollPoint)i; + } + } + + return RollPoint.InvalidRollPoint; // Deliberately head for trouble... + } + + /// + /// Initialize the appender based on the options set + /// + /// + /// + /// This is part of the delayed object + /// activation scheme. The method must + /// be called on this object after the configuration properties have + /// been set. Until is called this + /// object is in an undefined state and must not be used. + /// + /// + /// If any of the configuration properties are modified then + /// must be called again. + /// + /// + /// Sets initial conditions including date/time roll over information, first check, + /// scheduledFilename, and calls to initialize + /// the current number of backups. + /// + /// + public override void ActivateOptions() + { + if (m_dateTime == null) + { + m_dateTime = new LocalDateTime(); + } + + if (m_rollDate && m_datePattern != null) + { + m_now = m_dateTime.Now; + m_rollPoint = ComputeCheckPeriod(m_datePattern); + + if (m_rollPoint == RollPoint.InvalidRollPoint) + { + throw new ArgumentException("Invalid RollPoint, unable to parse ["+m_datePattern+"]"); + } + + // next line added as this removes the name check in rollOver + m_nextCheck = NextCheckDate(m_now, m_rollPoint); + } + else + { + if (m_rollDate) + { + ErrorHandler.Error("Either DatePattern or rollingStyle options are not set for ["+Name+"]."); + } + } + + if (SecurityContext == null) + { + SecurityContext = SecurityContextProvider.DefaultProvider.CreateSecurityContext(this); + } + + using(SecurityContext.Impersonate(this)) + { + // Must convert the FileAppender's m_filePath to an absolute path before we + // call ExistingInit(). This will be done by the base.ActivateOptions() but + // we need to duplicate that functionality here first. + base.File = ConvertToFullPath(base.File.Trim()); + + // Store fully qualified base file name + m_baseFileName = base.File; + } #if !NETCF - // initialize the mutex that is used to lock rolling - m_mutexForRolling = new Mutex(false, m_baseFileName - .Replace("\\", "_") - .Replace(":", "_") - .Replace("/", "_") + "_rolling" - ); + // initialize the mutex that is used to lock rolling + m_mutexForRolling = new Mutex(false, m_baseFileName + .Replace("\\", "_") + .Replace(":", "_") + .Replace("/", "_") + "_rolling" + ); #endif - if (m_rollDate && File != null && m_scheduledFilename == null) - { + if (m_rollDate && File != null && m_scheduledFilename == null) + { m_scheduledFilename = CombinePath(File, m_now.ToString(m_datePattern, DateTimeFormatInfo.InvariantInfo)); - } + } - ExistingInit(); - - base.ActivateOptions(); - } + ExistingInit(); + + base.ActivateOptions(); + } - #endregion + #endregion - #region Roll File + #region Roll File /// /// @@ -1198,596 +1198,596 @@ private string CombinePath(string path1, string path2) } } - /// - /// Rollover the file(s) to date/time tagged file(s). - /// - /// set to true if the file to be rolled is currently open - /// - /// - /// Rollover the file(s) to date/time tagged file(s). - /// Resets curSizeRollBackups. - /// If fileIsOpen is set then the new file is opened (through SafeOpenFile). - /// - /// - protected void RollOverTime(bool fileIsOpen) - { - if (m_staticLogFileName) - { - // Compute filename, but only if datePattern is specified - if (m_datePattern == null) - { - ErrorHandler.Error("Missing DatePattern option in rollOver()."); - return; - } - - //is the new file name equivalent to the 'current' one - //something has gone wrong if we hit this -- we should only - //roll over if the new file will be different from the old - var dateFormat = m_now.ToString(m_datePattern, DateTimeFormatInfo.InvariantInfo); + /// + /// Rollover the file(s) to date/time tagged file(s). + /// + /// set to true if the file to be rolled is currently open + /// + /// + /// Rollover the file(s) to date/time tagged file(s). + /// Resets curSizeRollBackups. + /// If fileIsOpen is set then the new file is opened (through SafeOpenFile). + /// + /// + protected void RollOverTime(bool fileIsOpen) + { + if (m_staticLogFileName) + { + // Compute filename, but only if datePattern is specified + if (m_datePattern == null) + { + ErrorHandler.Error("Missing DatePattern option in rollOver()."); + return; + } + + //is the new file name equivalent to the 'current' one + //something has gone wrong if we hit this -- we should only + //roll over if the new file will be different from the old + var dateFormat = m_now.ToString(m_datePattern, DateTimeFormatInfo.InvariantInfo); if (m_scheduledFilename.Equals(CombinePath(File, dateFormat))) - { + { ErrorHandler.Error("Compare " + m_scheduledFilename + " : " + CombinePath(File, dateFormat)); - return; - } - - if (fileIsOpen) - { - // close current file, and rename it to datedFilename - CloseFile(); - } - - //we may have to roll over a large number of backups here - for (var i = 1; i <= m_curSizeRollBackups; i++) - { + return; + } + + if (fileIsOpen) + { + // close current file, and rename it to datedFilename + CloseFile(); + } + + //we may have to roll over a large number of backups here + for (var i = 1; i <= m_curSizeRollBackups; i++) + { var from = CombinePath(File, "." + i); var to = CombinePath(m_scheduledFilename, "." + i); - RollFile(from, to); - } - - RollFile(File, m_scheduledFilename); - } - - //We've cleared out the old date and are ready for the new - m_curSizeRollBackups = 0; - - //new scheduled name + RollFile(from, to); + } + + RollFile(File, m_scheduledFilename); + } + + //We've cleared out the old date and are ready for the new + m_curSizeRollBackups = 0; + + //new scheduled name m_scheduledFilename = CombinePath(File, m_now.ToString(m_datePattern, DateTimeFormatInfo.InvariantInfo)); - if (fileIsOpen) - { - // This will also close the file. This is OK since multiple close operations are safe. - SafeOpenFile(m_baseFileName, false); - } - } + if (fileIsOpen) + { + // This will also close the file. This is OK since multiple close operations are safe. + SafeOpenFile(m_baseFileName, false); + } + } + + /// + /// Renames file to file . + /// + /// Name of existing file to roll. + /// New name for file. + /// + /// + /// Renames file to file . It + /// also checks for existence of target file and deletes if it does. + /// + /// + protected void RollFile(string fromFile, string toFile) + { + if (FileExists(fromFile)) + { + // Delete the toFile if it exists + DeleteFile(toFile); + + // We may not have permission to move the file, or the file may be locked + try + { + LogLog.Debug(declaringType, "Moving [" + fromFile + "] -> [" + toFile + "]"); + using(SecurityContext.Impersonate(this)) + { + System.IO.File.Move(fromFile, toFile); + } + } + catch(Exception moveEx) + { + ErrorHandler.Error("Exception while rolling file [" + fromFile + "] -> [" + toFile + "]", moveEx, ErrorCode.GenericFailure); + } + } + else + { + LogLog.Warn(declaringType, "Cannot RollFile [" + fromFile + "] -> [" + toFile + "]. Source does not exist"); + } + } + + /// + /// Test if a file exists at a specified path + /// + /// the path to the file + /// true if the file exists + /// + /// + /// Test if a file exists at a specified path + /// + /// + protected bool FileExists(string path) + { + using(SecurityContext.Impersonate(this)) + { + return System.IO.File.Exists(path); + } + } + + /// + /// Deletes the specified file if it exists. + /// + /// The file to delete. + /// + /// + /// Delete a file if is exists. + /// The file is first moved to a new filename then deleted. + /// This allows the file to be removed even when it cannot + /// be deleted, but it still can be moved. + /// + /// + protected void DeleteFile(string fileName) + { + if (FileExists(fileName)) + { + // We may not have permission to delete the file, or the file may be locked + + var fileToDelete = fileName; + + // Try to move the file to temp name. + // If the file is locked we may still be able to move it + var tempFileName = fileName + "." + Environment.TickCount + ".DeletePending"; + try + { + using(SecurityContext.Impersonate(this)) + { + System.IO.File.Move(fileName, tempFileName); + } + fileToDelete = tempFileName; + } + catch(Exception moveEx) + { + LogLog.Debug(declaringType, "Exception while moving file to be deleted [" + fileName + "] -> [" + tempFileName + "]", moveEx); + } + + // Try to delete the file (either the original or the moved file) + try + { + using(SecurityContext.Impersonate(this)) + { + System.IO.File.Delete(fileToDelete); + } + LogLog.Debug(declaringType, "Deleted file [" + fileName + "]"); + } + catch(Exception deleteEx) + { + if (fileToDelete == fileName) + { + // Unable to move or delete the file + ErrorHandler.Error("Exception while deleting file [" + fileToDelete + "]", deleteEx, ErrorCode.GenericFailure); + } + else + { + // Moved the file, but the delete failed. File is probably locked. + // The file should automatically be deleted when the lock is released. + LogLog.Debug(declaringType, "Exception while deleting temp file [" + fileToDelete + "]", deleteEx); + } + } + } + } - /// - /// Renames file to file . - /// - /// Name of existing file to roll. - /// New name for file. - /// - /// - /// Renames file to file . It - /// also checks for existence of target file and deletes if it does. - /// - /// - protected void RollFile(string fromFile, string toFile) - { - if (FileExists(fromFile)) - { - // Delete the toFile if it exists - DeleteFile(toFile); - - // We may not have permission to move the file, or the file may be locked - try - { - LogLog.Debug(declaringType, "Moving [" + fromFile + "] -> [" + toFile + "]"); - using(SecurityContext.Impersonate(this)) - { - System.IO.File.Move(fromFile, toFile); - } - } - catch(Exception moveEx) - { - ErrorHandler.Error("Exception while rolling file [" + fromFile + "] -> [" + toFile + "]", moveEx, ErrorCode.GenericFailure); - } - } - else - { - LogLog.Warn(declaringType, "Cannot RollFile [" + fromFile + "] -> [" + toFile + "]. Source does not exist"); - } - } - - /// - /// Test if a file exists at a specified path - /// - /// the path to the file - /// true if the file exists - /// - /// - /// Test if a file exists at a specified path - /// - /// - protected bool FileExists(string path) - { - using(SecurityContext.Impersonate(this)) - { - return System.IO.File.Exists(path); - } - } + /// + /// Implements file roll base on file size. + /// + /// + /// + /// If the maximum number of size based backups is reached + /// (curSizeRollBackups == maxSizeRollBackups) then the oldest + /// file is deleted -- its index determined by the sign of countDirection. + /// If countDirection < 0, then files + /// {File.1, ..., File.curSizeRollBackups -1} + /// are renamed to {File.2, ..., + /// File.curSizeRollBackups}. Moreover, File is + /// renamed File.1 and closed. + /// + /// + /// A new file is created to receive further log output. + /// + /// + /// If maxSizeRollBackups is equal to zero, then the + /// File is truncated with no backup files created. + /// + /// + /// If maxSizeRollBackups < 0, then File is + /// renamed if needed and no files are deleted. + /// + /// + protected void RollOverSize() + { + CloseFile(); // keep windows happy. - /// - /// Deletes the specified file if it exists. - /// - /// The file to delete. - /// - /// - /// Delete a file if is exists. - /// The file is first moved to a new filename then deleted. - /// This allows the file to be removed even when it cannot - /// be deleted, but it still can be moved. - /// - /// - protected void DeleteFile(string fileName) - { - if (FileExists(fileName)) - { - // We may not have permission to delete the file, or the file may be locked - - var fileToDelete = fileName; - - // Try to move the file to temp name. - // If the file is locked we may still be able to move it - var tempFileName = fileName + "." + Environment.TickCount + ".DeletePending"; - try - { - using(SecurityContext.Impersonate(this)) - { - System.IO.File.Move(fileName, tempFileName); - } - fileToDelete = tempFileName; - } - catch(Exception moveEx) - { - LogLog.Debug(declaringType, "Exception while moving file to be deleted [" + fileName + "] -> [" + tempFileName + "]", moveEx); - } - - // Try to delete the file (either the original or the moved file) - try - { - using(SecurityContext.Impersonate(this)) - { - System.IO.File.Delete(fileToDelete); - } - LogLog.Debug(declaringType, "Deleted file [" + fileName + "]"); - } - catch(Exception deleteEx) - { - if (fileToDelete == fileName) - { - // Unable to move or delete the file - ErrorHandler.Error("Exception while deleting file [" + fileToDelete + "]", deleteEx, ErrorCode.GenericFailure); - } - else - { - // Moved the file, but the delete failed. File is probably locked. - // The file should automatically be deleted when the lock is released. - LogLog.Debug(declaringType, "Exception while deleting temp file [" + fileToDelete + "]", deleteEx); - } - } - } - } + LogLog.Debug(declaringType, "rolling over count ["+((CountingQuietTextWriter)QuietWriter).Count+"]"); + LogLog.Debug(declaringType, "maxSizeRollBackups ["+m_maxSizeRollBackups+"]"); + LogLog.Debug(declaringType, "curSizeRollBackups ["+m_curSizeRollBackups+"]"); + LogLog.Debug(declaringType, "countDirection ["+m_countDirection+"]"); + + RollOverRenameFiles(File); - /// - /// Implements file roll base on file size. - /// - /// - /// - /// If the maximum number of size based backups is reached - /// (curSizeRollBackups == maxSizeRollBackups) then the oldest - /// file is deleted -- its index determined by the sign of countDirection. - /// If countDirection < 0, then files - /// {File.1, ..., File.curSizeRollBackups -1} - /// are renamed to {File.2, ..., - /// File.curSizeRollBackups}. Moreover, File is - /// renamed File.1 and closed. - /// - /// - /// A new file is created to receive further log output. - /// - /// - /// If maxSizeRollBackups is equal to zero, then the - /// File is truncated with no backup files created. - /// - /// - /// If maxSizeRollBackups < 0, then File is - /// renamed if needed and no files are deleted. - /// - /// - protected void RollOverSize() - { - CloseFile(); // keep windows happy. - - LogLog.Debug(declaringType, "rolling over count ["+((CountingQuietTextWriter)QuietWriter).Count+"]"); - LogLog.Debug(declaringType, "maxSizeRollBackups ["+m_maxSizeRollBackups+"]"); - LogLog.Debug(declaringType, "curSizeRollBackups ["+m_curSizeRollBackups+"]"); - LogLog.Debug(declaringType, "countDirection ["+m_countDirection+"]"); - - RollOverRenameFiles(File); - - if (!m_staticLogFileName && m_countDirection >= 0) - { - m_curSizeRollBackups++; - } - - // This will also close the file. This is OK since multiple close operations are safe. - SafeOpenFile(m_baseFileName, false); - } - - /// - /// Implements file roll. - /// - /// the base name to rename - /// - /// - /// If the maximum number of size based backups is reached - /// (curSizeRollBackups == maxSizeRollBackups) then the oldest - /// file is deleted -- its index determined by the sign of countDirection. - /// If countDirection < 0, then files - /// {File.1, ..., File.curSizeRollBackups -1} - /// are renamed to {File.2, ..., - /// File.curSizeRollBackups}. - /// - /// - /// If maxSizeRollBackups is equal to zero, then the - /// File is truncated with no backup files created. - /// - /// - /// If maxSizeRollBackups < 0, then File is - /// renamed if needed and no files are deleted. - /// - /// - /// This is called by to rename the files. - /// - /// - protected void RollOverRenameFiles(string baseFileName) - { - // If maxBackups <= 0, then there is no file renaming to be done. - if (m_maxSizeRollBackups != 0) - { - if (m_countDirection < 0) - { - // Delete the oldest file, to keep Windows happy. - if (m_curSizeRollBackups == m_maxSizeRollBackups) - { + if (!m_staticLogFileName && m_countDirection >= 0) + { + m_curSizeRollBackups++; + } + + // This will also close the file. This is OK since multiple close operations are safe. + SafeOpenFile(m_baseFileName, false); + } + + /// + /// Implements file roll. + /// + /// the base name to rename + /// + /// + /// If the maximum number of size based backups is reached + /// (curSizeRollBackups == maxSizeRollBackups) then the oldest + /// file is deleted -- its index determined by the sign of countDirection. + /// If countDirection < 0, then files + /// {File.1, ..., File.curSizeRollBackups -1} + /// are renamed to {File.2, ..., + /// File.curSizeRollBackups}. + /// + /// + /// If maxSizeRollBackups is equal to zero, then the + /// File is truncated with no backup files created. + /// + /// + /// If maxSizeRollBackups < 0, then File is + /// renamed if needed and no files are deleted. + /// + /// + /// This is called by to rename the files. + /// + /// + protected void RollOverRenameFiles(string baseFileName) + { + // If maxBackups <= 0, then there is no file renaming to be done. + if (m_maxSizeRollBackups != 0) + { + if (m_countDirection < 0) + { + // Delete the oldest file, to keep Windows happy. + if (m_curSizeRollBackups == m_maxSizeRollBackups) + { DeleteFile(CombinePath(baseFileName, "." + m_maxSizeRollBackups)); - m_curSizeRollBackups--; - } - - // Map {(maxBackupIndex - 1), ..., 2, 1} to {maxBackupIndex, ..., 3, 2} - for (var i = m_curSizeRollBackups; i >= 1; i--) - { + m_curSizeRollBackups--; + } + + // Map {(maxBackupIndex - 1), ..., 2, 1} to {maxBackupIndex, ..., 3, 2} + for (var i = m_curSizeRollBackups; i >= 1; i--) + { RollFile((CombinePath(baseFileName, "." + i)), (CombinePath(baseFileName, "." + (i + 1)))); - } - - m_curSizeRollBackups++; + } + + m_curSizeRollBackups++; - // Rename fileName to fileName.1 + // Rename fileName to fileName.1 RollFile(baseFileName, CombinePath(baseFileName, ".1")); - } - else - { - //countDirection >= 0 - if (m_curSizeRollBackups >= m_maxSizeRollBackups && m_maxSizeRollBackups > 0) - { - //delete the first and keep counting up. - var oldestFileIndex = m_curSizeRollBackups - m_maxSizeRollBackups; - - // If static then there is 1 file without a number, therefore 1 less archive - if (m_staticLogFileName) - { - oldestFileIndex++; - } - - // If using a static log file then the base for the numbered sequence is the baseFileName passed in - // If not using a static log file then the baseFileName will already have a numbered postfix which - // we must remove, however it may have a date postfix which we must keep! - var archiveFileBaseName = baseFileName; - if (!m_staticLogFileName) - { + } + else + { + //countDirection >= 0 + if (m_curSizeRollBackups >= m_maxSizeRollBackups && m_maxSizeRollBackups > 0) + { + //delete the first and keep counting up. + var oldestFileIndex = m_curSizeRollBackups - m_maxSizeRollBackups; + + // If static then there is 1 file without a number, therefore 1 less archive + if (m_staticLogFileName) + { + oldestFileIndex++; + } + + // If using a static log file then the base for the numbered sequence is the baseFileName passed in + // If not using a static log file then the baseFileName will already have a numbered postfix which + // we must remove, however it may have a date postfix which we must keep! + var archiveFileBaseName = baseFileName; + if (!m_staticLogFileName) + { if (m_preserveLogFileNameExtension) { var extension = Path.GetExtension(archiveFileBaseName); var baseName = Path.GetFileNameWithoutExtension(archiveFileBaseName); - var lastDotIndex = baseName.LastIndexOf("."); - if (lastDotIndex >= 0) - { - archiveFileBaseName = baseName.Substring(0, lastDotIndex) + extension; - } + var lastDotIndex = baseName.LastIndexOf("."); + if (lastDotIndex >= 0) + { + archiveFileBaseName = baseName.Substring(0, lastDotIndex) + extension; + } } else { - var lastDotIndex = archiveFileBaseName.LastIndexOf("."); - if (lastDotIndex >= 0) - { - archiveFileBaseName = archiveFileBaseName.Substring(0, lastDotIndex); - } + var lastDotIndex = archiveFileBaseName.LastIndexOf("."); + if (lastDotIndex >= 0) + { + archiveFileBaseName = archiveFileBaseName.Substring(0, lastDotIndex); + } } - } + } - // Delete the archive file + // Delete the archive file DeleteFile(CombinePath(archiveFileBaseName, "." + oldestFileIndex)); - } - - if (m_staticLogFileName) - { - m_curSizeRollBackups++; + } + + if (m_staticLogFileName) + { + m_curSizeRollBackups++; RollFile(baseFileName, CombinePath(baseFileName, "." + m_curSizeRollBackups)); - } - } - } - } - - #endregion - - #region NextCheckDate - - /// - /// Get the start time of the next window for the current rollpoint - /// - /// the current date - /// the type of roll point we are working with - /// the start time for the next roll point an interval after the currentDateTime date - /// - /// - /// Returns the date of the next roll point after the currentDateTime date passed to the method. - /// - /// - /// The basic strategy is to subtract the time parts that are less significant - /// than the rollpoint from the current time. This should roll the time back to - /// the start of the time window for the current rollpoint. Then we add 1 window - /// worth of time and get the start time of the next window for the rollpoint. - /// - /// - protected DateTime NextCheckDate(DateTime currentDateTime, RollPoint rollPoint) - { - // Local variable to work on (this does not look very efficient) - var current = currentDateTime; - - // Do slightly different things depending on what the type of roll point we want. - switch(rollPoint) - { - case RollPoint.TopOfMinute: - current = current.AddMilliseconds(-current.Millisecond); - current = current.AddSeconds(-current.Second); - current = current.AddMinutes(1); - break; - - case RollPoint.TopOfHour: - current = current.AddMilliseconds(-current.Millisecond); - current = current.AddSeconds(-current.Second); - current = current.AddMinutes(-current.Minute); - current = current.AddHours(1); - break; - - case RollPoint.HalfDay: - current = current.AddMilliseconds(-current.Millisecond); - current = current.AddSeconds(-current.Second); - current = current.AddMinutes(-current.Minute); - - if (current.Hour < 12) - { - current = current.AddHours(12 - current.Hour); - } - else - { - current = current.AddHours(-current.Hour); - current = current.AddDays(1); - } - break; - - case RollPoint.TopOfDay: - current = current.AddMilliseconds(-current.Millisecond); - current = current.AddSeconds(-current.Second); - current = current.AddMinutes(-current.Minute); - current = current.AddHours(-current.Hour); - current = current.AddDays(1); - break; - - case RollPoint.TopOfWeek: - current = current.AddMilliseconds(-current.Millisecond); - current = current.AddSeconds(-current.Second); - current = current.AddMinutes(-current.Minute); - current = current.AddHours(-current.Hour); - current = current.AddDays(7 - (int)current.DayOfWeek); - break; - - case RollPoint.TopOfMonth: - current = current.AddMilliseconds(-current.Millisecond); - current = current.AddSeconds(-current.Second); - current = current.AddMinutes(-current.Minute); - current = current.AddHours(-current.Hour); - current = current.AddDays(1 - current.Day); /* first day of month is 1 not 0 */ - current = current.AddMonths(1); - break; - } - return current; - } - - #endregion - - #region Private Instance Fields - - /// - /// This object supplies the current date/time. Allows test code to plug in - /// a method to control this class when testing date/time based rolling. The default - /// implementation uses the underlying value of DateTime.Now. - /// - private IDateTime m_dateTime = null; - - /// - /// The date pattern. By default, the pattern is set to ".yyyy-MM-dd" - /// meaning daily rollover. - /// - private string m_datePattern = ".yyyy-MM-dd"; + } + } + } + } + + #endregion + + #region NextCheckDate + + /// + /// Get the start time of the next window for the current rollpoint + /// + /// the current date + /// the type of roll point we are working with + /// the start time for the next roll point an interval after the currentDateTime date + /// + /// + /// Returns the date of the next roll point after the currentDateTime date passed to the method. + /// + /// + /// The basic strategy is to subtract the time parts that are less significant + /// than the rollpoint from the current time. This should roll the time back to + /// the start of the time window for the current rollpoint. Then we add 1 window + /// worth of time and get the start time of the next window for the rollpoint. + /// + /// + protected DateTime NextCheckDate(DateTime currentDateTime, RollPoint rollPoint) + { + // Local variable to work on (this does not look very efficient) + var current = currentDateTime; + + // Do slightly different things depending on what the type of roll point we want. + switch(rollPoint) + { + case RollPoint.TopOfMinute: + current = current.AddMilliseconds(-current.Millisecond); + current = current.AddSeconds(-current.Second); + current = current.AddMinutes(1); + break; + + case RollPoint.TopOfHour: + current = current.AddMilliseconds(-current.Millisecond); + current = current.AddSeconds(-current.Second); + current = current.AddMinutes(-current.Minute); + current = current.AddHours(1); + break; + + case RollPoint.HalfDay: + current = current.AddMilliseconds(-current.Millisecond); + current = current.AddSeconds(-current.Second); + current = current.AddMinutes(-current.Minute); + + if (current.Hour < 12) + { + current = current.AddHours(12 - current.Hour); + } + else + { + current = current.AddHours(-current.Hour); + current = current.AddDays(1); + } + break; + + case RollPoint.TopOfDay: + current = current.AddMilliseconds(-current.Millisecond); + current = current.AddSeconds(-current.Second); + current = current.AddMinutes(-current.Minute); + current = current.AddHours(-current.Hour); + current = current.AddDays(1); + break; + + case RollPoint.TopOfWeek: + current = current.AddMilliseconds(-current.Millisecond); + current = current.AddSeconds(-current.Second); + current = current.AddMinutes(-current.Minute); + current = current.AddHours(-current.Hour); + current = current.AddDays(7 - (int)current.DayOfWeek); + break; + + case RollPoint.TopOfMonth: + current = current.AddMilliseconds(-current.Millisecond); + current = current.AddSeconds(-current.Second); + current = current.AddMinutes(-current.Minute); + current = current.AddHours(-current.Hour); + current = current.AddDays(1 - current.Day); /* first day of month is 1 not 0 */ + current = current.AddMonths(1); + break; + } + return current; + } + + #endregion + + #region Private Instance Fields + + /// + /// This object supplies the current date/time. Allows test code to plug in + /// a method to control this class when testing date/time based rolling. The default + /// implementation uses the underlying value of DateTime.Now. + /// + private IDateTime m_dateTime = null; + + /// + /// The date pattern. By default, the pattern is set to ".yyyy-MM-dd" + /// meaning daily rollover. + /// + private string m_datePattern = ".yyyy-MM-dd"; - /// - /// The actual formatted filename that is currently being written to - /// or will be the file transferred to on roll over - /// (based on staticLogFileName). - /// - private string m_scheduledFilename = null; + /// + /// The actual formatted filename that is currently being written to + /// or will be the file transferred to on roll over + /// (based on staticLogFileName). + /// + private string m_scheduledFilename = null; - /// - /// The timestamp when we shall next recompute the filename. - /// - private DateTime m_nextCheck = DateTime.MaxValue; + /// + /// The timestamp when we shall next recompute the filename. + /// + private DateTime m_nextCheck = DateTime.MaxValue; - /// - /// Holds date of last roll over - /// - private DateTime m_now; + /// + /// Holds date of last roll over + /// + private DateTime m_now; - /// - /// The type of rolling done - /// - private RollPoint m_rollPoint; + /// + /// The type of rolling done + /// + private RollPoint m_rollPoint; - /// - /// The default maximum file size is 10MB - /// - private long m_maxFileSize = 10*1024*1024; + /// + /// The default maximum file size is 10MB + /// + private long m_maxFileSize = 10*1024*1024; - /// - /// There is zero backup files by default - /// - private int m_maxSizeRollBackups = 0; - - /// - /// How many sized based backups have been made so far - /// - private int m_curSizeRollBackups = 0; + /// + /// There is zero backup files by default + /// + private int m_maxSizeRollBackups = 0; + + /// + /// How many sized based backups have been made so far + /// + private int m_curSizeRollBackups = 0; - /// - /// The rolling file count direction. - /// - private int m_countDirection = -1; + /// + /// The rolling file count direction. + /// + private int m_countDirection = -1; - /// - /// The rolling mode used in this appender. - /// - private RollingMode m_rollingStyle = RollingMode.Composite; - - /// - /// Cache flag set if we are rolling by date. - /// - private bool m_rollDate = true; - - /// - /// Cache flag set if we are rolling by size. - /// - private bool m_rollSize = true; + /// + /// The rolling mode used in this appender. + /// + private RollingMode m_rollingStyle = RollingMode.Composite; + + /// + /// Cache flag set if we are rolling by date. + /// + private bool m_rollDate = true; + + /// + /// Cache flag set if we are rolling by size. + /// + private bool m_rollSize = true; - /// - /// Value indicating whether to always log to the same file. - /// - private bool m_staticLogFileName = true; + /// + /// Value indicating whether to always log to the same file. + /// + private bool m_staticLogFileName = true; - /// - /// Value indicating whether to preserve the file name extension when rolling. - /// - private bool m_preserveLogFileNameExtension = false; + /// + /// Value indicating whether to preserve the file name extension when rolling. + /// + private bool m_preserveLogFileNameExtension = false; - /// - /// FileName provided in configuration. Used for rolling properly - /// - private string m_baseFileName; + /// + /// FileName provided in configuration. Used for rolling properly + /// + private string m_baseFileName; #if !NETCF - /// - /// A mutex that is used to lock rolling of files. - /// - private Mutex m_mutexForRolling; + /// + /// A mutex that is used to lock rolling of files. + /// + private Mutex m_mutexForRolling; #endif - #endregion Private Instance Fields - - #region Static Members - - /// - /// The 1st of January 1970 in UTC - /// - private static readonly DateTime s_date1970 = new DateTime(1970, 1, 1); - - #endregion - - #region DateTime - - /// - /// This interface is used to supply Date/Time information to the . - /// - /// - /// This interface is used to supply Date/Time information to the . - /// Used primarily to allow test classes to plug themselves in so they can - /// supply test date/times. - /// - public interface IDateTime - { - /// - /// Gets the current time. - /// - /// The current time. - /// - /// - /// Gets the current time. - /// - /// - DateTime Now { get; } - } - - /// - /// Default implementation of that returns the current time. - /// - private class LocalDateTime : IDateTime - { - /// - /// Gets the current time. - /// - /// The current time. - /// - /// - /// Gets the current time. - /// - /// - public DateTime Now - { - get { return DateTime.Now; } - } - } + #endregion Private Instance Fields + + #region Static Members + + /// + /// The 1st of January 1970 in UTC + /// + private static readonly DateTime s_date1970 = new DateTime(1970, 1, 1); + + #endregion + + #region DateTime + + /// + /// This interface is used to supply Date/Time information to the . + /// + /// + /// This interface is used to supply Date/Time information to the . + /// Used primarily to allow test classes to plug themselves in so they can + /// supply test date/times. + /// + public interface IDateTime + { + /// + /// Gets the current time. + /// + /// The current time. + /// + /// + /// Gets the current time. + /// + /// + DateTime Now { get; } + } + + /// + /// Default implementation of that returns the current time. + /// + private class LocalDateTime : IDateTime + { + /// + /// Gets the current time. + /// + /// The current time. + /// + /// + /// Gets the current time. + /// + /// + public DateTime Now + { + get { return DateTime.Now; } + } + } #if !NET_1_0 && !CLI_1_0 && !NETCF /// - /// Implementation of that returns the current time as the coordinated universal time (UTC). - /// - private class UniversalDateTime : IDateTime - { - /// - /// Gets the current time. - /// - /// The current time. - /// - /// - /// Gets the current time. - /// - /// - public DateTime Now - { - get { return DateTime.UtcNow; } - } - } + /// Implementation of that returns the current time as the coordinated universal time (UTC). + /// + private class UniversalDateTime : IDateTime + { + /// + /// Gets the current time. + /// + /// The current time. + /// + /// + /// Gets the current time. + /// + /// + public DateTime Now + { + get { return DateTime.UtcNow; } + } + } #endif #endregion DateTime - } + } } diff --git a/src/log4net/Appender/SmtpAppender.cs b/src/log4net/Appender/SmtpAppender.cs index 98b6bb61..c0d12462 100644 --- a/src/log4net/Appender/SmtpAppender.cs +++ b/src/log4net/Appender/SmtpAppender.cs @@ -36,633 +36,633 @@ namespace log4net.Appender { - /// - /// Send an e-mail when a specific logging event occurs, typically on errors - /// or fatal errors. - /// - /// - /// - /// The number of logging events delivered in this e-mail depend on - /// the value of option. The - /// keeps only the last - /// logging events in its - /// cyclic buffer. This keeps memory requirements at a reasonable level while - /// still delivering useful application context. - /// - /// - /// Authentication and setting the server Port are only available on the MS .NET 1.1 runtime. - /// For these features to be enabled you need to ensure that you are using a version of - /// the log4net assembly that is built against the MS .NET 1.1 framework and that you are - /// running the your application on the MS .NET 1.1 runtime. On all other platforms only sending - /// unauthenticated messages to a server listening on port 25 (the default) is supported. - /// - /// - /// Authentication is supported by setting the property to - /// either or . - /// If using authentication then the - /// and properties must also be set. - /// - /// - /// To set the SMTP server port use the property. The default port is 25. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public class SmtpAppender : BufferingAppenderSkeleton - { - #region Public Instance Constructors - - /// - /// Default constructor - /// - /// - /// - /// Default constructor - /// - /// - public SmtpAppender() - { - } - - #endregion // Public Instance Constructors - - #region Public Instance Properties - - /// - /// Gets or sets a comma- or semicolon-delimited list of recipient e-mail addresses (use semicolon on .NET 1.1 and comma for later versions). - /// - /// - /// - /// For .NET 1.1 (System.Web.Mail): A semicolon-delimited list of e-mail addresses. - /// - /// - /// For .NET 2.0 (System.Net.Mail): A comma-delimited list of e-mail addresses. - /// - /// - /// - /// - /// For .NET 1.1 (System.Web.Mail): A semicolon-delimited list of e-mail addresses. - /// - /// - /// For .NET 2.0 (System.Net.Mail): A comma-delimited list of e-mail addresses. - /// - /// - public string To - { - get { return m_to; } - set { m_to = MaybeTrimSeparators(value); } - } - - /// - /// Gets or sets a comma- or semicolon-delimited list of recipient e-mail addresses - /// that will be carbon copied (use semicolon on .NET 1.1 and comma for later versions). - /// - /// - /// - /// For .NET 1.1 (System.Web.Mail): A semicolon-delimited list of e-mail addresses. - /// - /// - /// For .NET 2.0 (System.Net.Mail): A comma-delimited list of e-mail addresses. - /// - /// - /// - /// - /// For .NET 1.1 (System.Web.Mail): A semicolon-delimited list of e-mail addresses. - /// - /// - /// For .NET 2.0 (System.Net.Mail): A comma-delimited list of e-mail addresses. - /// - /// - public string Cc - { - get { return m_cc; } - set { m_cc = MaybeTrimSeparators(value); } - } - - /// - /// Gets or sets a semicolon-delimited list of recipient e-mail addresses - /// that will be blind carbon copied. - /// - /// - /// A semicolon-delimited list of e-mail addresses. - /// - /// - /// - /// A semicolon-delimited list of recipient e-mail addresses. - /// - /// - public string Bcc - { - get { return m_bcc; } - set { m_bcc = MaybeTrimSeparators(value); } - } - - /// - /// Gets or sets the e-mail address of the sender. - /// - /// - /// The e-mail address of the sender. - /// - /// - /// - /// The e-mail address of the sender. - /// - /// - public string From - { - get { return m_from; } - set { m_from = value; } - } - - /// - /// Gets or sets the subject line of the e-mail message. - /// - /// - /// The subject line of the e-mail message. - /// - /// - /// - /// The subject line of the e-mail message. - /// - /// - public string Subject - { - get { return m_subject; } - set { m_subject = value; } - } + /// + /// Send an e-mail when a specific logging event occurs, typically on errors + /// or fatal errors. + /// + /// + /// + /// The number of logging events delivered in this e-mail depend on + /// the value of option. The + /// keeps only the last + /// logging events in its + /// cyclic buffer. This keeps memory requirements at a reasonable level while + /// still delivering useful application context. + /// + /// + /// Authentication and setting the server Port are only available on the MS .NET 1.1 runtime. + /// For these features to be enabled you need to ensure that you are using a version of + /// the log4net assembly that is built against the MS .NET 1.1 framework and that you are + /// running the your application on the MS .NET 1.1 runtime. On all other platforms only sending + /// unauthenticated messages to a server listening on port 25 (the default) is supported. + /// + /// + /// Authentication is supported by setting the property to + /// either or . + /// If using authentication then the + /// and properties must also be set. + /// + /// + /// To set the SMTP server port use the property. The default port is 25. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public class SmtpAppender : BufferingAppenderSkeleton + { + #region Public Instance Constructors + + /// + /// Default constructor + /// + /// + /// + /// Default constructor + /// + /// + public SmtpAppender() + { + } + + #endregion // Public Instance Constructors + + #region Public Instance Properties + + /// + /// Gets or sets a comma- or semicolon-delimited list of recipient e-mail addresses (use semicolon on .NET 1.1 and comma for later versions). + /// + /// + /// + /// For .NET 1.1 (System.Web.Mail): A semicolon-delimited list of e-mail addresses. + /// + /// + /// For .NET 2.0 (System.Net.Mail): A comma-delimited list of e-mail addresses. + /// + /// + /// + /// + /// For .NET 1.1 (System.Web.Mail): A semicolon-delimited list of e-mail addresses. + /// + /// + /// For .NET 2.0 (System.Net.Mail): A comma-delimited list of e-mail addresses. + /// + /// + public string To + { + get { return m_to; } + set { m_to = MaybeTrimSeparators(value); } + } + + /// + /// Gets or sets a comma- or semicolon-delimited list of recipient e-mail addresses + /// that will be carbon copied (use semicolon on .NET 1.1 and comma for later versions). + /// + /// + /// + /// For .NET 1.1 (System.Web.Mail): A semicolon-delimited list of e-mail addresses. + /// + /// + /// For .NET 2.0 (System.Net.Mail): A comma-delimited list of e-mail addresses. + /// + /// + /// + /// + /// For .NET 1.1 (System.Web.Mail): A semicolon-delimited list of e-mail addresses. + /// + /// + /// For .NET 2.0 (System.Net.Mail): A comma-delimited list of e-mail addresses. + /// + /// + public string Cc + { + get { return m_cc; } + set { m_cc = MaybeTrimSeparators(value); } + } + + /// + /// Gets or sets a semicolon-delimited list of recipient e-mail addresses + /// that will be blind carbon copied. + /// + /// + /// A semicolon-delimited list of e-mail addresses. + /// + /// + /// + /// A semicolon-delimited list of recipient e-mail addresses. + /// + /// + public string Bcc + { + get { return m_bcc; } + set { m_bcc = MaybeTrimSeparators(value); } + } + + /// + /// Gets or sets the e-mail address of the sender. + /// + /// + /// The e-mail address of the sender. + /// + /// + /// + /// The e-mail address of the sender. + /// + /// + public string From + { + get { return m_from; } + set { m_from = value; } + } + + /// + /// Gets or sets the subject line of the e-mail message. + /// + /// + /// The subject line of the e-mail message. + /// + /// + /// + /// The subject line of the e-mail message. + /// + /// + public string Subject + { + get { return m_subject; } + set { m_subject = value; } + } - /// - /// Gets or sets the name of the SMTP relay mail server to use to send - /// the e-mail messages. - /// - /// - /// The name of the e-mail relay server. If SmtpServer is not set, the - /// name of the local SMTP server is used. - /// - /// - /// - /// The name of the e-mail relay server. If SmtpServer is not set, the - /// name of the local SMTP server is used. - /// - /// - public string SmtpHost - { - get { return m_smtpHost; } - set { m_smtpHost = value; } - } - - /// - /// Obsolete - /// - /// - /// Use the BufferingAppenderSkeleton Fix methods instead - /// - /// - /// - /// Obsolete property. - /// - /// - [Obsolete("Use the BufferingAppenderSkeleton Fix methods")] - public bool LocationInfo - { - get { return false; } - set { ; } - } - - /// - /// The mode to use to authentication with the SMTP server - /// - /// - /// Authentication is only available on the MS .NET 1.1 runtime. - /// - /// Valid Authentication mode values are: , - /// , and . - /// The default value is . When using - /// you must specify the - /// and to use to authenticate. - /// When using the Windows credentials for the current - /// thread, if impersonating, or the process will be used to authenticate. - /// - /// - public SmtpAuthentication Authentication - { - get { return m_authentication; } - set { m_authentication = value; } - } - - /// - /// The username to use to authenticate with the SMTP server - /// - /// - /// Authentication is only available on the MS .NET 1.1 runtime. - /// - /// A and must be specified when - /// is set to , - /// otherwise the username will be ignored. - /// - /// - public string Username - { - get { return m_username; } - set { m_username = value; } - } - - /// - /// The password to use to authenticate with the SMTP server - /// - /// - /// Authentication is only available on the MS .NET 1.1 runtime. - /// - /// A and must be specified when - /// is set to , - /// otherwise the password will be ignored. - /// - /// - public string Password - { - get { return m_password; } - set { m_password = value; } - } - - /// - /// The port on which the SMTP server is listening - /// - /// - /// Server Port is only available on the MS .NET 1.1 runtime. - /// - /// The port on which the SMTP server is listening. The default - /// port is 25. The Port can only be changed when running on - /// the MS .NET 1.1 runtime. - /// - /// - public int Port - { - get { return m_port; } - set { m_port = value; } - } - - /// - /// Gets or sets the priority of the e-mail message - /// - /// - /// One of the values. - /// - /// - /// - /// Sets the priority of the e-mails generated by this - /// appender. The default priority is . - /// - /// - /// If you are using this appender to report errors then - /// you may want to set the priority to . - /// - /// - public MailPriority Priority - { - get { return m_mailPriority; } - set { m_mailPriority = value; } - } + /// + /// Gets or sets the name of the SMTP relay mail server to use to send + /// the e-mail messages. + /// + /// + /// The name of the e-mail relay server. If SmtpServer is not set, the + /// name of the local SMTP server is used. + /// + /// + /// + /// The name of the e-mail relay server. If SmtpServer is not set, the + /// name of the local SMTP server is used. + /// + /// + public string SmtpHost + { + get { return m_smtpHost; } + set { m_smtpHost = value; } + } + + /// + /// Obsolete + /// + /// + /// Use the BufferingAppenderSkeleton Fix methods instead + /// + /// + /// + /// Obsolete property. + /// + /// + [Obsolete("Use the BufferingAppenderSkeleton Fix methods")] + public bool LocationInfo + { + get { return false; } + set { ; } + } + + /// + /// The mode to use to authentication with the SMTP server + /// + /// + /// Authentication is only available on the MS .NET 1.1 runtime. + /// + /// Valid Authentication mode values are: , + /// , and . + /// The default value is . When using + /// you must specify the + /// and to use to authenticate. + /// When using the Windows credentials for the current + /// thread, if impersonating, or the process will be used to authenticate. + /// + /// + public SmtpAuthentication Authentication + { + get { return m_authentication; } + set { m_authentication = value; } + } + + /// + /// The username to use to authenticate with the SMTP server + /// + /// + /// Authentication is only available on the MS .NET 1.1 runtime. + /// + /// A and must be specified when + /// is set to , + /// otherwise the username will be ignored. + /// + /// + public string Username + { + get { return m_username; } + set { m_username = value; } + } + + /// + /// The password to use to authenticate with the SMTP server + /// + /// + /// Authentication is only available on the MS .NET 1.1 runtime. + /// + /// A and must be specified when + /// is set to , + /// otherwise the password will be ignored. + /// + /// + public string Password + { + get { return m_password; } + set { m_password = value; } + } + + /// + /// The port on which the SMTP server is listening + /// + /// + /// Server Port is only available on the MS .NET 1.1 runtime. + /// + /// The port on which the SMTP server is listening. The default + /// port is 25. The Port can only be changed when running on + /// the MS .NET 1.1 runtime. + /// + /// + public int Port + { + get { return m_port; } + set { m_port = value; } + } + + /// + /// Gets or sets the priority of the e-mail message + /// + /// + /// One of the values. + /// + /// + /// + /// Sets the priority of the e-mails generated by this + /// appender. The default priority is . + /// + /// + /// If you are using this appender to report errors then + /// you may want to set the priority to . + /// + /// + public MailPriority Priority + { + get { return m_mailPriority; } + set { m_mailPriority = value; } + } #if NET_2_0 || MONO_2_0 || NETSTANDARD2_0 - /// - /// Enable or disable use of SSL when sending e-mail message - /// - /// - /// This is available on MS .NET 2.0 runtime and higher - /// - public bool EnableSsl - { - get { return m_enableSsl; } - set { m_enableSsl = value; } - } - - /// - /// Gets or sets the reply-to e-mail address. - /// - /// - /// This is available on MS .NET 2.0 runtime and higher - /// - public string ReplyTo - { - get { return m_replyTo; } - set { m_replyTo = value; } - } + /// + /// Enable or disable use of SSL when sending e-mail message + /// + /// + /// This is available on MS .NET 2.0 runtime and higher + /// + public bool EnableSsl + { + get { return m_enableSsl; } + set { m_enableSsl = value; } + } + + /// + /// Gets or sets the reply-to e-mail address. + /// + /// + /// This is available on MS .NET 2.0 runtime and higher + /// + public string ReplyTo + { + get { return m_replyTo; } + set { m_replyTo = value; } + } #endif - /// - /// Gets or sets the subject encoding to be used. - /// - /// - /// The default encoding is the operating system's current ANSI codepage. - /// - public Encoding SubjectEncoding - { - get { return m_subjectEncoding; } - set { m_subjectEncoding = value; } - } - - /// - /// Gets or sets the body encoding to be used. - /// - /// - /// The default encoding is the operating system's current ANSI codepage. - /// - public Encoding BodyEncoding - { - get { return m_bodyEncoding; } - set { m_bodyEncoding = value; } - } - - #endregion // Public Instance Properties - - #region Override implementation of BufferingAppenderSkeleton - - /// - /// Sends the contents of the cyclic buffer as an e-mail message. - /// - /// The logging events to send. - protected override void SendBuffer(LoggingEvent[] events) - { - // Note: this code already owns the monitor for this - // appender. This frees us from needing to synchronize again. - try - { - using StringWriter writer = new StringWriter(System.Globalization.CultureInfo.InvariantCulture); - - string t = Layout.Header; - if (t != null) - { - writer.Write(t); - } - - for(int i = 0; i < events.Length; i++) - { - // Render the event and append the text to the buffer - RenderLoggingEvent(writer, events[i]); - } - - t = Layout.Footer; - if (t != null) - { - writer.Write(t); - } - - SendEmail(writer.ToString()); - } - catch(Exception e) - { - ErrorHandler.Error("Error occurred while sending e-mail notification.", e); - } - } - - #endregion // Override implementation of BufferingAppenderSkeleton - - #region Override implementation of AppenderSkeleton - - /// - /// This appender requires a to be set. - /// - /// true - /// - /// - /// This appender requires a to be set. - /// - /// - protected override bool RequiresLayout - { - get { return true; } - } - - #endregion // Override implementation of AppenderSkeleton - - #region Protected Methods - - /// - /// Send the email message - /// - /// the body text to include in the mail - protected virtual void SendEmail(string messageBody) - { + /// + /// Gets or sets the subject encoding to be used. + /// + /// + /// The default encoding is the operating system's current ANSI codepage. + /// + public Encoding SubjectEncoding + { + get { return m_subjectEncoding; } + set { m_subjectEncoding = value; } + } + + /// + /// Gets or sets the body encoding to be used. + /// + /// + /// The default encoding is the operating system's current ANSI codepage. + /// + public Encoding BodyEncoding + { + get { return m_bodyEncoding; } + set { m_bodyEncoding = value; } + } + + #endregion // Public Instance Properties + + #region Override implementation of BufferingAppenderSkeleton + + /// + /// Sends the contents of the cyclic buffer as an e-mail message. + /// + /// The logging events to send. + protected override void SendBuffer(LoggingEvent[] events) + { + // Note: this code already owns the monitor for this + // appender. This frees us from needing to synchronize again. + try + { + using StringWriter writer = new StringWriter(System.Globalization.CultureInfo.InvariantCulture); + + string t = Layout.Header; + if (t != null) + { + writer.Write(t); + } + + for(int i = 0; i < events.Length; i++) + { + // Render the event and append the text to the buffer + RenderLoggingEvent(writer, events[i]); + } + + t = Layout.Footer; + if (t != null) + { + writer.Write(t); + } + + SendEmail(writer.ToString()); + } + catch(Exception e) + { + ErrorHandler.Error("Error occurred while sending e-mail notification.", e); + } + } + + #endregion // Override implementation of BufferingAppenderSkeleton + + #region Override implementation of AppenderSkeleton + + /// + /// This appender requires a to be set. + /// + /// true + /// + /// + /// This appender requires a to be set. + /// + /// + protected override bool RequiresLayout + { + get { return true; } + } + + #endregion // Override implementation of AppenderSkeleton + + #region Protected Methods + + /// + /// Send the email message + /// + /// the body text to include in the mail + protected virtual void SendEmail(string messageBody) + { #if NET_2_0 || MONO_2_0 || NETSTANDARD2_0 - // .NET 2.0 has a new API for SMTP email System.Net.Mail - // This API supports credentials and multiple hosts correctly. - // The old API is deprecated. + // .NET 2.0 has a new API for SMTP email System.Net.Mail + // This API supports credentials and multiple hosts correctly. + // The old API is deprecated. - // Create and configure the smtp client + // Create and configure the smtp client #if NET_4_0 || MONO_4_0 || NETSTANDARD2_0 - using SmtpClient smtpClient = new SmtpClient(); + using SmtpClient smtpClient = new SmtpClient(); #else - SmtpClient smtpClient = new SmtpClient(); + SmtpClient smtpClient = new SmtpClient(); #endif - if (!String.IsNullOrEmpty(m_smtpHost)) - { - smtpClient.Host = m_smtpHost; - } - smtpClient.Port = m_port; - smtpClient.DeliveryMethod = SmtpDeliveryMethod.Network; - smtpClient.EnableSsl = m_enableSsl; - - if (m_authentication == SmtpAuthentication.Basic) - { - // Perform basic authentication - smtpClient.Credentials = new System.Net.NetworkCredential(m_username, m_password); - } - else if (m_authentication == SmtpAuthentication.Ntlm) - { - // Perform integrated authentication (NTLM) - smtpClient.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials; - } - - using (MailMessage mailMessage = new MailMessage()) - { - mailMessage.Body = messageBody; - mailMessage.BodyEncoding = m_bodyEncoding; - mailMessage.From = new MailAddress(m_from); - mailMessage.To.Add(m_to); - if (!String.IsNullOrEmpty(m_cc)) - { - mailMessage.CC.Add(m_cc); - } - if (!String.IsNullOrEmpty(m_bcc)) - { - mailMessage.Bcc.Add(m_bcc); - } - if (!String.IsNullOrEmpty(m_replyTo)) - { - // .NET 4.0 warning CS0618: 'System.Net.Mail.MailMessage.ReplyTo' is obsolete: - // 'ReplyTo is obsoleted for this type. Please use ReplyToList instead which can accept multiple addresses. http://go.microsoft.com/fwlink/?linkid=14202' + if (!String.IsNullOrEmpty(m_smtpHost)) + { + smtpClient.Host = m_smtpHost; + } + smtpClient.Port = m_port; + smtpClient.DeliveryMethod = SmtpDeliveryMethod.Network; + smtpClient.EnableSsl = m_enableSsl; + + if (m_authentication == SmtpAuthentication.Basic) + { + // Perform basic authentication + smtpClient.Credentials = new System.Net.NetworkCredential(m_username, m_password); + } + else if (m_authentication == SmtpAuthentication.Ntlm) + { + // Perform integrated authentication (NTLM) + smtpClient.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials; + } + + using (MailMessage mailMessage = new MailMessage()) + { + mailMessage.Body = messageBody; + mailMessage.BodyEncoding = m_bodyEncoding; + mailMessage.From = new MailAddress(m_from); + mailMessage.To.Add(m_to); + if (!String.IsNullOrEmpty(m_cc)) + { + mailMessage.CC.Add(m_cc); + } + if (!String.IsNullOrEmpty(m_bcc)) + { + mailMessage.Bcc.Add(m_bcc); + } + if (!String.IsNullOrEmpty(m_replyTo)) + { + // .NET 4.0 warning CS0618: 'System.Net.Mail.MailMessage.ReplyTo' is obsolete: + // 'ReplyTo is obsoleted for this type. Please use ReplyToList instead which can accept multiple addresses. http://go.microsoft.com/fwlink/?linkid=14202' #if !NET_4_0 && !MONO_4_0 && !NETSTANDARD2_0 - mailMessage.ReplyTo = new MailAddress(m_replyTo); + mailMessage.ReplyTo = new MailAddress(m_replyTo); #else - mailMessage.ReplyToList.Add(new MailAddress(m_replyTo)); + mailMessage.ReplyToList.Add(new MailAddress(m_replyTo)); #endif - } - mailMessage.Subject = m_subject; - mailMessage.SubjectEncoding = m_subjectEncoding; - mailMessage.Priority = m_mailPriority; - - // TODO: Consider using SendAsync to send the message without blocking. This would be a change in - // behaviour compared to .NET 1.x. We would need a SendCompletedCallback to log errors. - smtpClient.Send(mailMessage); - } + } + mailMessage.Subject = m_subject; + mailMessage.SubjectEncoding = m_subjectEncoding; + mailMessage.Priority = m_mailPriority; + + // TODO: Consider using SendAsync to send the message without blocking. This would be a change in + // behaviour compared to .NET 1.x. We would need a SendCompletedCallback to log errors. + smtpClient.Send(mailMessage); + } #else - // .NET 1.x uses the System.Web.Mail API for sending Mail - - MailMessage mailMessage = new MailMessage(); - mailMessage.Body = messageBody; - mailMessage.BodyEncoding = m_bodyEncoding; - mailMessage.From = m_from; - mailMessage.To = m_to; - if (m_cc != null && m_cc.Length > 0) - { - mailMessage.Cc = m_cc; - } - if (m_bcc != null && m_bcc.Length > 0) - { - mailMessage.Bcc = m_bcc; - } - mailMessage.Subject = m_subject; + // .NET 1.x uses the System.Web.Mail API for sending Mail + + MailMessage mailMessage = new MailMessage(); + mailMessage.Body = messageBody; + mailMessage.BodyEncoding = m_bodyEncoding; + mailMessage.From = m_from; + mailMessage.To = m_to; + if (m_cc != null && m_cc.Length > 0) + { + mailMessage.Cc = m_cc; + } + if (m_bcc != null && m_bcc.Length > 0) + { + mailMessage.Bcc = m_bcc; + } + mailMessage.Subject = m_subject; #if !MONO && !NET_1_0 && !NET_1_1 && !CLI_1_0 - mailMessage.SubjectEncoding = m_subjectEncoding; + mailMessage.SubjectEncoding = m_subjectEncoding; #endif - mailMessage.Priority = m_mailPriority; + mailMessage.Priority = m_mailPriority; #if NET_1_1 - // The Fields property on the MailMessage allows the CDO properties to be set directly. - // This property is only available on .NET Framework 1.1 and the implementation must understand - // the CDO properties. For details of the fields available in CDO see: - // - // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cdosys/html/_cdosys_configuration_coclass.asp - // - - try - { - if (m_authentication == SmtpAuthentication.Basic) - { - // Perform basic authentication - mailMessage.Fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate", 1); - mailMessage.Fields.Add("http://schemas.microsoft.com/cdo/configuration/sendusername", m_username); - mailMessage.Fields.Add("http://schemas.microsoft.com/cdo/configuration/sendpassword", m_password); - } - else if (m_authentication == SmtpAuthentication.Ntlm) - { - // Perform integrated authentication (NTLM) - mailMessage.Fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate", 2); - } - - // Set the port if not the default value - if (m_port != 25) - { - mailMessage.Fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpserverport", m_port); - } - } - catch(MissingMethodException missingMethodException) - { - // If we were compiled against .NET 1.1 but are running against .NET 1.0 then - // we will get a MissingMethodException when accessing the MailMessage.Fields property. - - ErrorHandler.Error("SmtpAppender: Authentication and server Port are only supported when running on the MS .NET 1.1 framework", missingMethodException); - } + // The Fields property on the MailMessage allows the CDO properties to be set directly. + // This property is only available on .NET Framework 1.1 and the implementation must understand + // the CDO properties. For details of the fields available in CDO see: + // + // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cdosys/html/_cdosys_configuration_coclass.asp + // + + try + { + if (m_authentication == SmtpAuthentication.Basic) + { + // Perform basic authentication + mailMessage.Fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate", 1); + mailMessage.Fields.Add("http://schemas.microsoft.com/cdo/configuration/sendusername", m_username); + mailMessage.Fields.Add("http://schemas.microsoft.com/cdo/configuration/sendpassword", m_password); + } + else if (m_authentication == SmtpAuthentication.Ntlm) + { + // Perform integrated authentication (NTLM) + mailMessage.Fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate", 2); + } + + // Set the port if not the default value + if (m_port != 25) + { + mailMessage.Fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpserverport", m_port); + } + } + catch(MissingMethodException missingMethodException) + { + // If we were compiled against .NET 1.1 but are running against .NET 1.0 then + // we will get a MissingMethodException when accessing the MailMessage.Fields property. + + ErrorHandler.Error("SmtpAppender: Authentication and server Port are only supported when running on the MS .NET 1.1 framework", missingMethodException); + } #else - if (m_authentication != SmtpAuthentication.None) - { - ErrorHandler.Error("SmtpAppender: Authentication is only supported on the MS .NET 1.1 or MS .NET 2.0 builds of log4net"); - } - - if (m_port != 25) - { - ErrorHandler.Error("SmtpAppender: Server Port is only supported on the MS .NET 1.1 or MS .NET 2.0 builds of log4net"); - } + if (m_authentication != SmtpAuthentication.None) + { + ErrorHandler.Error("SmtpAppender: Authentication is only supported on the MS .NET 1.1 or MS .NET 2.0 builds of log4net"); + } + + if (m_port != 25) + { + ErrorHandler.Error("SmtpAppender: Server Port is only supported on the MS .NET 1.1 or MS .NET 2.0 builds of log4net"); + } #endif // if NET_1_1 - if (m_smtpHost != null && m_smtpHost.Length > 0) - { - SmtpMail.SmtpServer = m_smtpHost; - } + if (m_smtpHost != null && m_smtpHost.Length > 0) + { + SmtpMail.SmtpServer = m_smtpHost; + } - SmtpMail.Send(mailMessage); + SmtpMail.Send(mailMessage); #endif // if NET_2_0 - } + } - #endregion // Protected Methods + #endregion // Protected Methods - #region Private Instance Fields + #region Private Instance Fields - private string m_to; - private string m_cc; - private string m_bcc; - private string m_from; - private string m_subject; - private string m_smtpHost; - private Encoding m_subjectEncoding = Encoding.UTF8; - private Encoding m_bodyEncoding = Encoding.UTF8; + private string m_to; + private string m_cc; + private string m_bcc; + private string m_from; + private string m_subject; + private string m_smtpHost; + private Encoding m_subjectEncoding = Encoding.UTF8; + private Encoding m_bodyEncoding = Encoding.UTF8; - // authentication fields - private SmtpAuthentication m_authentication = SmtpAuthentication.None; - private string m_username; - private string m_password; + // authentication fields + private SmtpAuthentication m_authentication = SmtpAuthentication.None; + private string m_username; + private string m_password; - // server port, default port 25 - private int m_port = 25; + // server port, default port 25 + private int m_port = 25; - private MailPriority m_mailPriority = MailPriority.Normal; + private MailPriority m_mailPriority = MailPriority.Normal; #if NET_2_0 || MONO_2_0 || NETSTANDARD2_0 - private bool m_enableSsl = false; - private string m_replyTo; + private bool m_enableSsl = false; + private string m_replyTo; #endif - #endregion // Private Instance Fields - - #region SmtpAuthentication Enum - - /// - /// Values for the property. - /// - /// - /// - /// SMTP authentication modes. - /// - /// - public enum SmtpAuthentication - { - /// - /// No authentication - /// - None, - - /// - /// Basic authentication. - /// - /// - /// Requires a username and password to be supplied - /// - Basic, - - /// - /// Integrated authentication - /// - /// - /// Uses the Windows credentials from the current thread or process to authenticate. - /// - Ntlm - } - - #endregion // SmtpAuthentication Enum - - private static readonly char[] ADDRESS_DELIMITERS = new char[] { ',', ';' }; - - /// - /// trims leading and trailing commas or semicolons - /// - private static string MaybeTrimSeparators(string s) { + #endregion // Private Instance Fields + + #region SmtpAuthentication Enum + + /// + /// Values for the property. + /// + /// + /// + /// SMTP authentication modes. + /// + /// + public enum SmtpAuthentication + { + /// + /// No authentication + /// + None, + + /// + /// Basic authentication. + /// + /// + /// Requires a username and password to be supplied + /// + Basic, + + /// + /// Integrated authentication + /// + /// + /// Uses the Windows credentials from the current thread or process to authenticate. + /// + Ntlm + } + + #endregion // SmtpAuthentication Enum + + private static readonly char[] ADDRESS_DELIMITERS = new char[] { ',', ';' }; + + /// + /// trims leading and trailing commas or semicolons + /// + private static string MaybeTrimSeparators(string s) { #if NET_2_0 || MONO_2_0 || NETSTANDARD2_0 - return string.IsNullOrEmpty(s) ? s : s.Trim(ADDRESS_DELIMITERS); + return string.IsNullOrEmpty(s) ? s : s.Trim(ADDRESS_DELIMITERS); #else - return s != null && s.Length > 0 ? s : s.Trim(ADDRESS_DELIMITERS); + return s != null && s.Length > 0 ? s : s.Trim(ADDRESS_DELIMITERS); #endif - } - } + } + } } #endif // !NETCF && !SSCLI diff --git a/src/log4net/Appender/SmtpPickupDirAppender.cs b/src/log4net/Appender/SmtpPickupDirAppender.cs index 17a6af4e..f3f3aa05 100644 --- a/src/log4net/Appender/SmtpPickupDirAppender.cs +++ b/src/log4net/Appender/SmtpPickupDirAppender.cs @@ -25,327 +25,327 @@ namespace log4net.Appender { - /// - /// Send an email when a specific logging event occurs, typically on errors - /// or fatal errors. Rather than sending via smtp it writes a file into the - /// directory specified by . This allows services such - /// as the IIS SMTP agent to manage sending the messages. - /// - /// - /// - /// The configuration for this appender is identical to that of the SMTPAppender, - /// except that instead of specifying the SMTPAppender.SMTPHost you specify - /// . - /// - /// - /// The number of logging events delivered in this e-mail depend on - /// the value of option. The - /// keeps only the last - /// logging events in its - /// cyclic buffer. This keeps memory requirements at a reasonable level while - /// still delivering useful application context. - /// - /// - /// Niall Daley - /// Nicko Cadell - public class SmtpPickupDirAppender : BufferingAppenderSkeleton - { - #region Public Instance Constructors - - /// - /// Default constructor - /// - /// - /// - /// Default constructor - /// - /// - public SmtpPickupDirAppender() - { - m_fileExtension = string.Empty; // Default to empty string, not null - } - - #endregion Public Instance Constructors - - #region Public Instance Properties - - /// - /// Gets or sets a semicolon-delimited list of recipient e-mail addresses. - /// - /// - /// A semicolon-delimited list of e-mail addresses. - /// - /// - /// - /// A semicolon-delimited list of e-mail addresses. - /// - /// - public string To - { - get { return m_to; } - set { m_to = value; } - } - - /// - /// Gets or sets the e-mail address of the sender. - /// - /// - /// The e-mail address of the sender. - /// - /// - /// - /// The e-mail address of the sender. - /// - /// - public string From - { - get { return m_from; } - set { m_from = value; } - } - - /// - /// Gets or sets the subject line of the e-mail message. - /// - /// - /// The subject line of the e-mail message. - /// - /// - /// - /// The subject line of the e-mail message. - /// - /// - public string Subject - { - get { return m_subject; } - set { m_subject = value; } - } + /// + /// Send an email when a specific logging event occurs, typically on errors + /// or fatal errors. Rather than sending via smtp it writes a file into the + /// directory specified by . This allows services such + /// as the IIS SMTP agent to manage sending the messages. + /// + /// + /// + /// The configuration for this appender is identical to that of the SMTPAppender, + /// except that instead of specifying the SMTPAppender.SMTPHost you specify + /// . + /// + /// + /// The number of logging events delivered in this e-mail depend on + /// the value of option. The + /// keeps only the last + /// logging events in its + /// cyclic buffer. This keeps memory requirements at a reasonable level while + /// still delivering useful application context. + /// + /// + /// Niall Daley + /// Nicko Cadell + public class SmtpPickupDirAppender : BufferingAppenderSkeleton + { + #region Public Instance Constructors + + /// + /// Default constructor + /// + /// + /// + /// Default constructor + /// + /// + public SmtpPickupDirAppender() + { + m_fileExtension = string.Empty; // Default to empty string, not null + } + + #endregion Public Instance Constructors + + #region Public Instance Properties + + /// + /// Gets or sets a semicolon-delimited list of recipient e-mail addresses. + /// + /// + /// A semicolon-delimited list of e-mail addresses. + /// + /// + /// + /// A semicolon-delimited list of e-mail addresses. + /// + /// + public string To + { + get { return m_to; } + set { m_to = value; } + } + + /// + /// Gets or sets the e-mail address of the sender. + /// + /// + /// The e-mail address of the sender. + /// + /// + /// + /// The e-mail address of the sender. + /// + /// + public string From + { + get { return m_from; } + set { m_from = value; } + } + + /// + /// Gets or sets the subject line of the e-mail message. + /// + /// + /// The subject line of the e-mail message. + /// + /// + /// + /// The subject line of the e-mail message. + /// + /// + public string Subject + { + get { return m_subject; } + set { m_subject = value; } + } - /// - /// Gets or sets the path to write the messages to. - /// - /// - /// - /// Gets or sets the path to write the messages to. This should be the same - /// as that used by the agent sending the messages. - /// - /// - public string PickupDir - { - get { return m_pickupDir; } - set { m_pickupDir = value; } - } - - /// - /// Gets or sets the file extension for the generated files - /// - /// - /// The file extension for the generated files - /// - /// - /// - /// The file extension for the generated files - /// - /// - public string FileExtension - { - get { return m_fileExtension; } - set - { - m_fileExtension = value; - if (m_fileExtension == null) - { - m_fileExtension = string.Empty; - } - // Make sure any non empty extension starts with a dot + /// + /// Gets or sets the path to write the messages to. + /// + /// + /// + /// Gets or sets the path to write the messages to. This should be the same + /// as that used by the agent sending the messages. + /// + /// + public string PickupDir + { + get { return m_pickupDir; } + set { m_pickupDir = value; } + } + + /// + /// Gets or sets the file extension for the generated files + /// + /// + /// The file extension for the generated files + /// + /// + /// + /// The file extension for the generated files + /// + /// + public string FileExtension + { + get { return m_fileExtension; } + set + { + m_fileExtension = value; + if (m_fileExtension == null) + { + m_fileExtension = string.Empty; + } + // Make sure any non empty extension starts with a dot #if NET_2_0 || MONO_2_0 || NETSTANDARD - if (!string.IsNullOrEmpty(m_fileExtension) && !m_fileExtension.StartsWith(".")) + if (!string.IsNullOrEmpty(m_fileExtension) && !m_fileExtension.StartsWith(".")) #else - if (m_fileExtension != null && m_fileExtension.Length > 0 && !m_fileExtension.StartsWith(".")) + if (m_fileExtension != null && m_fileExtension.Length > 0 && !m_fileExtension.StartsWith(".")) #endif - { - m_fileExtension = "." + m_fileExtension; - } - } - } - - /// - /// Gets or sets the used to write to the pickup directory. - /// - /// - /// The used to write to the pickup directory. - /// - /// - /// - /// Unless a specified here for this appender - /// the is queried for the - /// security context to use. The default behavior is to use the security context - /// of the current thread. - /// - /// - public SecurityContext SecurityContext - { - get { return m_securityContext; } - set { m_securityContext = value; } - } - - #endregion Public Instance Properties - - #region Override implementation of BufferingAppenderSkeleton - - /// - /// Sends the contents of the cyclic buffer as an e-mail message. - /// - /// The logging events to send. - /// - /// - /// Sends the contents of the cyclic buffer as an e-mail message. - /// - /// - protected override void SendBuffer(LoggingEvent[] events) - { - // Note: this code already owns the monitor for this - // appender. This frees us from needing to synchronize again. - try - { - string filePath = null; - StreamWriter writer = null; - - // Impersonate to open the file - using(SecurityContext.Impersonate(this)) - { - filePath = Path.Combine(m_pickupDir, SystemInfo.NewGuid().ToString("N") + m_fileExtension); - writer = File.CreateText(filePath); - } - - if (writer == null) - { - ErrorHandler.Error("Failed to create output file for writing ["+filePath+"]", null, ErrorCode.FileOpenFailure); - } - else - { - using(writer) - { - writer.WriteLine("To: " + m_to); - writer.WriteLine("From: " + m_from); - writer.WriteLine("Subject: " + m_subject); - writer.WriteLine("Date: " + DateTime.UtcNow.ToString("r")); - writer.WriteLine(""); - - string t = Layout.Header; - if (t != null) - { - writer.Write(t); - } - - for(int i = 0; i < events.Length; i++) - { - // Render the event and append the text to the buffer - RenderLoggingEvent(writer, events[i]); - } - - t = Layout.Footer; - if (t != null) - { - writer.Write(t); - } - - writer.WriteLine(""); - writer.WriteLine("."); - } - } - } - catch(Exception e) - { - ErrorHandler.Error("Error occurred while sending e-mail notification.", e); - } - } - - #endregion Override implementation of BufferingAppenderSkeleton - - #region Override implementation of AppenderSkeleton - - /// - /// Activate the options on this appender. - /// - /// - /// - /// This is part of the delayed object - /// activation scheme. The method must - /// be called on this object after the configuration properties have - /// been set. Until is called this - /// object is in an undefined state and must not be used. - /// - /// - /// If any of the configuration properties are modified then - /// must be called again. - /// - /// - public override void ActivateOptions() - { - base.ActivateOptions(); - - if (m_securityContext == null) - { - m_securityContext = SecurityContextProvider.DefaultProvider.CreateSecurityContext(this); - } - - using(SecurityContext.Impersonate(this)) - { - m_pickupDir = ConvertToFullPath(m_pickupDir.Trim()); - } - } - - /// - /// This appender requires a to be set. - /// - /// true - /// - /// - /// This appender requires a to be set. - /// - /// - protected override bool RequiresLayout - { - get { return true; } - } - - #endregion Override implementation of AppenderSkeleton - - #region Protected Static Methods - - /// - /// Convert a path into a fully qualified path. - /// - /// The path to convert. - /// The fully qualified path. - /// - /// - /// Converts the path specified to a fully - /// qualified path. If the path is relative it is - /// taken as relative from the application base - /// directory. - /// - /// - protected static string ConvertToFullPath(string path) - { - return SystemInfo.ConvertToFullPath(path); - } - - #endregion Protected Static Methods - - #region Private Instance Fields - - private string m_to; - private string m_from; - private string m_subject; - private string m_pickupDir; - private string m_fileExtension; - - /// - /// The security context to use for privileged calls - /// - private SecurityContext m_securityContext; - - #endregion Private Instance Fields - } + { + m_fileExtension = "." + m_fileExtension; + } + } + } + + /// + /// Gets or sets the used to write to the pickup directory. + /// + /// + /// The used to write to the pickup directory. + /// + /// + /// + /// Unless a specified here for this appender + /// the is queried for the + /// security context to use. The default behavior is to use the security context + /// of the current thread. + /// + /// + public SecurityContext SecurityContext + { + get { return m_securityContext; } + set { m_securityContext = value; } + } + + #endregion Public Instance Properties + + #region Override implementation of BufferingAppenderSkeleton + + /// + /// Sends the contents of the cyclic buffer as an e-mail message. + /// + /// The logging events to send. + /// + /// + /// Sends the contents of the cyclic buffer as an e-mail message. + /// + /// + protected override void SendBuffer(LoggingEvent[] events) + { + // Note: this code already owns the monitor for this + // appender. This frees us from needing to synchronize again. + try + { + string filePath = null; + StreamWriter writer = null; + + // Impersonate to open the file + using(SecurityContext.Impersonate(this)) + { + filePath = Path.Combine(m_pickupDir, SystemInfo.NewGuid().ToString("N") + m_fileExtension); + writer = File.CreateText(filePath); + } + + if (writer == null) + { + ErrorHandler.Error("Failed to create output file for writing ["+filePath+"]", null, ErrorCode.FileOpenFailure); + } + else + { + using(writer) + { + writer.WriteLine("To: " + m_to); + writer.WriteLine("From: " + m_from); + writer.WriteLine("Subject: " + m_subject); + writer.WriteLine("Date: " + DateTime.UtcNow.ToString("r")); + writer.WriteLine(""); + + string t = Layout.Header; + if (t != null) + { + writer.Write(t); + } + + for(int i = 0; i < events.Length; i++) + { + // Render the event and append the text to the buffer + RenderLoggingEvent(writer, events[i]); + } + + t = Layout.Footer; + if (t != null) + { + writer.Write(t); + } + + writer.WriteLine(""); + writer.WriteLine("."); + } + } + } + catch(Exception e) + { + ErrorHandler.Error("Error occurred while sending e-mail notification.", e); + } + } + + #endregion Override implementation of BufferingAppenderSkeleton + + #region Override implementation of AppenderSkeleton + + /// + /// Activate the options on this appender. + /// + /// + /// + /// This is part of the delayed object + /// activation scheme. The method must + /// be called on this object after the configuration properties have + /// been set. Until is called this + /// object is in an undefined state and must not be used. + /// + /// + /// If any of the configuration properties are modified then + /// must be called again. + /// + /// + public override void ActivateOptions() + { + base.ActivateOptions(); + + if (m_securityContext == null) + { + m_securityContext = SecurityContextProvider.DefaultProvider.CreateSecurityContext(this); + } + + using(SecurityContext.Impersonate(this)) + { + m_pickupDir = ConvertToFullPath(m_pickupDir.Trim()); + } + } + + /// + /// This appender requires a to be set. + /// + /// true + /// + /// + /// This appender requires a to be set. + /// + /// + protected override bool RequiresLayout + { + get { return true; } + } + + #endregion Override implementation of AppenderSkeleton + + #region Protected Static Methods + + /// + /// Convert a path into a fully qualified path. + /// + /// The path to convert. + /// The fully qualified path. + /// + /// + /// Converts the path specified to a fully + /// qualified path. If the path is relative it is + /// taken as relative from the application base + /// directory. + /// + /// + protected static string ConvertToFullPath(string path) + { + return SystemInfo.ConvertToFullPath(path); + } + + #endregion Protected Static Methods + + #region Private Instance Fields + + private string m_to; + private string m_from; + private string m_subject; + private string m_pickupDir; + private string m_fileExtension; + + /// + /// The security context to use for privileged calls + /// + private SecurityContext m_securityContext; + + #endregion Private Instance Fields + } } diff --git a/src/log4net/Appender/TelnetAppender.cs b/src/log4net/Appender/TelnetAppender.cs index 0d61a002..9aa503e0 100644 --- a/src/log4net/Appender/TelnetAppender.cs +++ b/src/log4net/Appender/TelnetAppender.cs @@ -32,511 +32,511 @@ namespace log4net.Appender { - /// - /// Appender that allows clients to connect via Telnet to receive log messages - /// - /// - /// - /// The TelnetAppender accepts socket connections and streams logging messages - /// back to the client. - /// The output is provided in a telnet-friendly way so that a log can be monitored - /// over a TCP/IP socket. - /// This allows simple remote monitoring of application logging. - /// - /// - /// The default is 23 (the telnet port). - /// - /// - /// Keith Long - /// Nicko Cadell - public class TelnetAppender : AppenderSkeleton - { - private SocketHandler m_handler; - private int m_listeningPort = 23; - - #region Constructor - - /// - /// Default constructor - /// - /// - /// - /// Default constructor - /// - /// - public TelnetAppender() - { - } - - #endregion - - #region Private Static Fields - - /// - /// The fully qualified type of the TelnetAppender class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(TelnetAppender); - - #endregion Private Static Fields - - /// - /// Gets or sets the TCP port number on which this will listen for connections. - /// - /// - /// An integer value in the range to - /// indicating the TCP port number on which this will listen for connections. - /// - /// - /// - /// The default value is 23 (the telnet port). - /// - /// - /// The value specified is less than - /// or greater than . - public int Port - { - get - { - return m_listeningPort; - } - set - { - if (value < IPEndPoint.MinPort || value > IPEndPoint.MaxPort) - { - throw log4net.Util.SystemInfo.CreateArgumentOutOfRangeException("value", (object)value, - "The value specified for Port is less than " + - IPEndPoint.MinPort.ToString(NumberFormatInfo.InvariantInfo) + - " or greater than " + - IPEndPoint.MaxPort.ToString(NumberFormatInfo.InvariantInfo) + "."); - } - else - { - m_listeningPort = value; - } - } - } - - #region Override implementation of AppenderSkeleton - - /// - /// Overrides the parent method to close the socket handler - /// - /// - /// - /// Closes all the outstanding connections. - /// - /// - protected override void OnClose() - { - base.OnClose(); - - if (m_handler != null) - { - m_handler.Dispose(); - m_handler = null; - } - } - - /// - /// This appender requires a to be set. - /// - /// true - /// - /// - /// This appender requires a to be set. - /// - /// - protected override bool RequiresLayout - { - get { return true; } - } - - /// - /// Initialize the appender based on the options set. - /// - /// - /// - /// This is part of the delayed object - /// activation scheme. The method must - /// be called on this object after the configuration properties have - /// been set. Until is called this - /// object is in an undefined state and must not be used. - /// - /// - /// If any of the configuration properties are modified then - /// must be called again. - /// - /// - /// Create the socket handler and wait for connections - /// - /// - public override void ActivateOptions() - { - base.ActivateOptions(); - try - { - LogLog.Debug(declaringType, "Creating SocketHandler to listen on port ["+m_listeningPort+"]"); - m_handler = new SocketHandler(m_listeningPort); - } - catch(Exception ex) - { - LogLog.Error(declaringType, "Failed to create SocketHandler", ex); - throw; - } - } - - /// - /// Writes the logging event to each connected client. - /// - /// The event to log. - /// - /// - /// Writes the logging event to each connected client. - /// - /// - protected override void Append(LoggingEvent loggingEvent) - { - if (m_handler != null && m_handler.HasConnections) - { - m_handler.Send(RenderLoggingEvent(loggingEvent)); - } - } - - #endregion - - #region SocketHandler helper class - - /// - /// Helper class to manage connected clients - /// - /// - /// - /// The SocketHandler class is used to accept connections from - /// clients. It is threaded so that clients can connect/disconnect - /// asynchronously. - /// - /// - protected class SocketHandler : IDisposable - { - private const int MAX_CONNECTIONS = 20; - - private Socket m_serverSocket; - private ArrayList m_clients = new ArrayList(); - - /// - /// Class that represents a client connected to this handler - /// - /// - /// - /// Class that represents a client connected to this handler - /// - /// - protected class SocketClient : IDisposable - { - private Socket m_socket; - private StreamWriter m_writer; - - /// - /// Create this for the specified - /// - /// the client's socket - /// - /// - /// Opens a stream writer on the socket. - /// - /// - public SocketClient(Socket socket) - { - m_socket = socket; - - try - { - m_writer = new StreamWriter(new NetworkStream(socket)); - } - catch - { - Dispose(); - throw; - } - } - - /// - /// Write a string to the client - /// - /// string to send - /// - /// - /// Write a string to the client - /// - /// - public void Send(String message) - { - m_writer.Write(message); - m_writer.Flush(); - } - - #region IDisposable Members - - /// - /// Cleanup the clients connection - /// - /// - /// - /// Close the socket connection. - /// - /// - public void Dispose() - { - try - { - if (m_writer != null) - { - m_writer.Dispose(); - m_writer = null; - } - } - catch { } - - if (m_socket != null) - { - try - { - m_socket.Shutdown(SocketShutdown.Both); - } - catch { } - - try - { + /// + /// Appender that allows clients to connect via Telnet to receive log messages + /// + /// + /// + /// The TelnetAppender accepts socket connections and streams logging messages + /// back to the client. + /// The output is provided in a telnet-friendly way so that a log can be monitored + /// over a TCP/IP socket. + /// This allows simple remote monitoring of application logging. + /// + /// + /// The default is 23 (the telnet port). + /// + /// + /// Keith Long + /// Nicko Cadell + public class TelnetAppender : AppenderSkeleton + { + private SocketHandler m_handler; + private int m_listeningPort = 23; + + #region Constructor + + /// + /// Default constructor + /// + /// + /// + /// Default constructor + /// + /// + public TelnetAppender() + { + } + + #endregion + + #region Private Static Fields + + /// + /// The fully qualified type of the TelnetAppender class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(TelnetAppender); + + #endregion Private Static Fields + + /// + /// Gets or sets the TCP port number on which this will listen for connections. + /// + /// + /// An integer value in the range to + /// indicating the TCP port number on which this will listen for connections. + /// + /// + /// + /// The default value is 23 (the telnet port). + /// + /// + /// The value specified is less than + /// or greater than . + public int Port + { + get + { + return m_listeningPort; + } + set + { + if (value < IPEndPoint.MinPort || value > IPEndPoint.MaxPort) + { + throw log4net.Util.SystemInfo.CreateArgumentOutOfRangeException("value", (object)value, + "The value specified for Port is less than " + + IPEndPoint.MinPort.ToString(NumberFormatInfo.InvariantInfo) + + " or greater than " + + IPEndPoint.MaxPort.ToString(NumberFormatInfo.InvariantInfo) + "."); + } + else + { + m_listeningPort = value; + } + } + } + + #region Override implementation of AppenderSkeleton + + /// + /// Overrides the parent method to close the socket handler + /// + /// + /// + /// Closes all the outstanding connections. + /// + /// + protected override void OnClose() + { + base.OnClose(); + + if (m_handler != null) + { + m_handler.Dispose(); + m_handler = null; + } + } + + /// + /// This appender requires a to be set. + /// + /// true + /// + /// + /// This appender requires a to be set. + /// + /// + protected override bool RequiresLayout + { + get { return true; } + } + + /// + /// Initialize the appender based on the options set. + /// + /// + /// + /// This is part of the delayed object + /// activation scheme. The method must + /// be called on this object after the configuration properties have + /// been set. Until is called this + /// object is in an undefined state and must not be used. + /// + /// + /// If any of the configuration properties are modified then + /// must be called again. + /// + /// + /// Create the socket handler and wait for connections + /// + /// + public override void ActivateOptions() + { + base.ActivateOptions(); + try + { + LogLog.Debug(declaringType, "Creating SocketHandler to listen on port ["+m_listeningPort+"]"); + m_handler = new SocketHandler(m_listeningPort); + } + catch(Exception ex) + { + LogLog.Error(declaringType, "Failed to create SocketHandler", ex); + throw; + } + } + + /// + /// Writes the logging event to each connected client. + /// + /// The event to log. + /// + /// + /// Writes the logging event to each connected client. + /// + /// + protected override void Append(LoggingEvent loggingEvent) + { + if (m_handler != null && m_handler.HasConnections) + { + m_handler.Send(RenderLoggingEvent(loggingEvent)); + } + } + + #endregion + + #region SocketHandler helper class + + /// + /// Helper class to manage connected clients + /// + /// + /// + /// The SocketHandler class is used to accept connections from + /// clients. It is threaded so that clients can connect/disconnect + /// asynchronously. + /// + /// + protected class SocketHandler : IDisposable + { + private const int MAX_CONNECTIONS = 20; + + private Socket m_serverSocket; + private ArrayList m_clients = new ArrayList(); + + /// + /// Class that represents a client connected to this handler + /// + /// + /// + /// Class that represents a client connected to this handler + /// + /// + protected class SocketClient : IDisposable + { + private Socket m_socket; + private StreamWriter m_writer; + + /// + /// Create this for the specified + /// + /// the client's socket + /// + /// + /// Opens a stream writer on the socket. + /// + /// + public SocketClient(Socket socket) + { + m_socket = socket; + + try + { + m_writer = new StreamWriter(new NetworkStream(socket)); + } + catch + { + Dispose(); + throw; + } + } + + /// + /// Write a string to the client + /// + /// string to send + /// + /// + /// Write a string to the client + /// + /// + public void Send(String message) + { + m_writer.Write(message); + m_writer.Flush(); + } + + #region IDisposable Members + + /// + /// Cleanup the clients connection + /// + /// + /// + /// Close the socket connection. + /// + /// + public void Dispose() + { + try + { + if (m_writer != null) + { + m_writer.Dispose(); + m_writer = null; + } + } + catch { } + + if (m_socket != null) + { + try + { + m_socket.Shutdown(SocketShutdown.Both); + } + catch { } + + try + { #if NET_4_0 || NETSTANDARD - m_socket.Dispose(); + m_socket.Dispose(); #else - m_socket.Close(); + m_socket.Close(); #endif - } - catch { } - - m_socket = null; - } - } - - #endregion - } - - /// - /// Opens a new server port on - /// - /// the local port to listen on for connections - /// - /// - /// Creates a socket handler on the specified local server port. - /// - /// - public SocketHandler(int port) - { - m_serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); - - m_serverSocket.Bind(new IPEndPoint(IPAddress.Any, port)); - m_serverSocket.Listen(5); - AcceptConnection(); - } - - private void AcceptConnection() - { + } + catch { } + + m_socket = null; + } + } + + #endregion + } + + /// + /// Opens a new server port on + /// + /// the local port to listen on for connections + /// + /// + /// Creates a socket handler on the specified local server port. + /// + /// + public SocketHandler(int port) + { + m_serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + + m_serverSocket.Bind(new IPEndPoint(IPAddress.Any, port)); + m_serverSocket.Listen(5); + AcceptConnection(); + } + + private void AcceptConnection() + { #if NETSTANDARD - m_serverSocket.AcceptAsync().ContinueWith(OnConnect, TaskScheduler.Default); + m_serverSocket.AcceptAsync().ContinueWith(OnConnect, TaskScheduler.Default); #else - m_serverSocket.BeginAccept(new AsyncCallback(OnConnect), null); + m_serverSocket.BeginAccept(new AsyncCallback(OnConnect), null); #endif - } - - /// - /// Sends a string message to each of the connected clients - /// - /// the text to send - /// - /// - /// Sends a string message to each of the connected clients - /// - /// - public void Send(String message) - { - ArrayList localClients = m_clients; - - foreach (SocketClient client in localClients) - { - try - { - client.Send(message); - } - catch (Exception) - { - // The client has closed the connection, remove it from our list - client.Dispose(); - RemoveClient(client); - } - } - } - - /// - /// Add a client to the internal clients list - /// - /// client to add - private void AddClient(SocketClient client) - { - lock(this) - { - ArrayList clientsCopy = (ArrayList)m_clients.Clone(); - clientsCopy.Add(client); - m_clients = clientsCopy; - } - } - - /// - /// Remove a client from the internal clients list - /// - /// client to remove - private void RemoveClient(SocketClient client) - { - lock(this) - { - ArrayList clientsCopy = (ArrayList)m_clients.Clone(); - clientsCopy.Remove(client); - m_clients = clientsCopy; - } - } - - /// - /// Test if this handler has active connections - /// - /// - /// true if this handler has active connections - /// - /// - /// - /// This property will be true while this handler has - /// active connections, that is at least one connection that - /// the handler will attempt to send a message to. - /// - /// - public bool HasConnections - { - get - { - ArrayList localClients = m_clients; - - return (localClients != null && localClients.Count > 0); - } - } - + } + + /// + /// Sends a string message to each of the connected clients + /// + /// the text to send + /// + /// + /// Sends a string message to each of the connected clients + /// + /// + public void Send(String message) + { + ArrayList localClients = m_clients; + + foreach (SocketClient client in localClients) + { + try + { + client.Send(message); + } + catch (Exception) + { + // The client has closed the connection, remove it from our list + client.Dispose(); + RemoveClient(client); + } + } + } + + /// + /// Add a client to the internal clients list + /// + /// client to add + private void AddClient(SocketClient client) + { + lock(this) + { + ArrayList clientsCopy = (ArrayList)m_clients.Clone(); + clientsCopy.Add(client); + m_clients = clientsCopy; + } + } + + /// + /// Remove a client from the internal clients list + /// + /// client to remove + private void RemoveClient(SocketClient client) + { + lock(this) + { + ArrayList clientsCopy = (ArrayList)m_clients.Clone(); + clientsCopy.Remove(client); + m_clients = clientsCopy; + } + } + + /// + /// Test if this handler has active connections + /// + /// + /// true if this handler has active connections + /// + /// + /// + /// This property will be true while this handler has + /// active connections, that is at least one connection that + /// the handler will attempt to send a message to. + /// + /// + public bool HasConnections + { + get + { + ArrayList localClients = m_clients; + + return (localClients != null && localClients.Count > 0); + } + } + #if NETSTANDARD - private void OnConnect(Task acceptTask) + private void OnConnect(Task acceptTask) #else - /// - /// Callback used to accept a connection on the server socket - /// - /// The result of the asynchronous operation - /// - /// - /// On connection adds to the list of connections - /// if there are two many open connections you will be disconnected - /// - /// - private void OnConnect(IAsyncResult asyncResult) + /// + /// Callback used to accept a connection on the server socket + /// + /// The result of the asynchronous operation + /// + /// + /// On connection adds to the list of connections + /// if there are two many open connections you will be disconnected + /// + /// + private void OnConnect(IAsyncResult asyncResult) #endif - { - try - { + { + try + { #if NETSTANDARD - Socket socket = acceptTask.GetAwaiter().GetResult(); + Socket socket = acceptTask.GetAwaiter().GetResult(); #else - // Block until a client connects - Socket socket = m_serverSocket.EndAccept(asyncResult); + // Block until a client connects + Socket socket = m_serverSocket.EndAccept(asyncResult); #endif - LogLog.Debug(declaringType, "Accepting connection from ["+socket.RemoteEndPoint.ToString()+"]"); - SocketClient client = new SocketClient(socket); - - int currentActiveConnectionsCount = m_clients.Count; - if (currentActiveConnectionsCount < MAX_CONNECTIONS) - { - try - { - client.Send("TelnetAppender v1.0 (" + (currentActiveConnectionsCount + 1) + " active connections)\r\n\r\n"); - AddClient(client); - } - catch - { - client.Dispose(); - } - } - else - { - client.Send("Sorry - Too many connections.\r\n"); - client.Dispose(); - } - } - catch - { - } - finally - { - if (m_serverSocket != null) - { - AcceptConnection(); - } - } - } - - #region IDisposable Members - - /// - /// Close all network connections - /// - /// - /// - /// Make sure we close all network connections - /// - /// - public void Dispose() - { - ArrayList localClients = m_clients; - - foreach (SocketClient client in localClients) - { - client.Dispose(); - } - m_clients.Clear(); - - Socket localSocket = m_serverSocket; - m_serverSocket = null; - try - { - localSocket.Shutdown(SocketShutdown.Both); - } - catch - { - } - - try - { + LogLog.Debug(declaringType, "Accepting connection from ["+socket.RemoteEndPoint.ToString()+"]"); + SocketClient client = new SocketClient(socket); + + int currentActiveConnectionsCount = m_clients.Count; + if (currentActiveConnectionsCount < MAX_CONNECTIONS) + { + try + { + client.Send("TelnetAppender v1.0 (" + (currentActiveConnectionsCount + 1) + " active connections)\r\n\r\n"); + AddClient(client); + } + catch + { + client.Dispose(); + } + } + else + { + client.Send("Sorry - Too many connections.\r\n"); + client.Dispose(); + } + } + catch + { + } + finally + { + if (m_serverSocket != null) + { + AcceptConnection(); + } + } + } + + #region IDisposable Members + + /// + /// Close all network connections + /// + /// + /// + /// Make sure we close all network connections + /// + /// + public void Dispose() + { + ArrayList localClients = m_clients; + + foreach (SocketClient client in localClients) + { + client.Dispose(); + } + m_clients.Clear(); + + Socket localSocket = m_serverSocket; + m_serverSocket = null; + try + { + localSocket.Shutdown(SocketShutdown.Both); + } + catch + { + } + + try + { #if NET_2_0 - localSocket.Close(); + localSocket.Close(); #else - localSocket.Dispose(); + localSocket.Dispose(); #endif - } - catch - { - } - } + } + catch + { + } + } - #endregion - } + #endregion + } - #endregion - } + #endregion + } } diff --git a/src/log4net/Appender/TextWriterAppender.cs b/src/log4net/Appender/TextWriterAppender.cs index 6eb943cc..b047be2a 100644 --- a/src/log4net/Appender/TextWriterAppender.cs +++ b/src/log4net/Appender/TextWriterAppender.cs @@ -26,417 +26,417 @@ namespace log4net.Appender { - /// - /// Sends logging events to a . - /// - /// - /// - /// An Appender that writes to a . - /// - /// - /// This appender may be used stand alone if initialized with an appropriate - /// writer, however it is typically used as a base class for an appender that - /// can open a to write to. - /// - /// - /// Nicko Cadell - /// Gert Driesen - /// Douglas de la Torre + /// + /// Sends logging events to a . + /// + /// + /// + /// An Appender that writes to a . + /// + /// + /// This appender may be used stand alone if initialized with an appropriate + /// writer, however it is typically used as a base class for an appender that + /// can open a to write to. + /// + /// + /// Nicko Cadell + /// Gert Driesen + /// Douglas de la Torre public class TextWriterAppender : AppenderSkeleton - { - #region Public Instance Constructors - - /// - /// Initializes a new instance of the class. - /// - /// - /// - /// Default constructor. - /// - /// - public TextWriterAppender() - { - } - - /// - /// Initializes a new instance of the class and - /// sets the output destination to a new initialized - /// with the specified . - /// - /// The layout to use with this appender. - /// The to output to. - /// - /// - /// Obsolete constructor. - /// - /// - [Obsolete("Instead use the default constructor and set the Layout & Writer properties")] - public TextWriterAppender(ILayout layout, Stream os) : this(layout, new StreamWriter(os)) - { - } - - /// - /// Initializes a new instance of the class and sets - /// the output destination to the specified . - /// - /// The layout to use with this appender - /// The to output to - /// - /// The must have been previously opened. - /// - /// - /// - /// Obsolete constructor. - /// - /// - [Obsolete("Instead use the default constructor and set the Layout & Writer properties")] - public TextWriterAppender(ILayout layout, TextWriter writer) - { - Layout = layout; - Writer = writer; - } - - #endregion - - #region Public Instance Properties - - /// - /// Gets or set whether the appender will flush at the end - /// of each append operation. - /// - /// - /// - /// The default behavior is to flush at the end of each - /// append operation. - /// - /// - /// If this option is set to false, then the underlying - /// stream can defer persisting the logging event to a later - /// time. - /// - /// - /// - /// Avoiding the flush operation at the end of each append results in - /// a performance gain of 10 to 20 percent. However, there is safety - /// trade-off involved in skipping flushing. Indeed, when flushing is - /// skipped, then it is likely that the last few log events will not - /// be recorded on disk when the application exits. This is a high - /// price to pay even for a 20% performance gain. - /// - public bool ImmediateFlush - { - get { return m_immediateFlush; } - set { m_immediateFlush = value; } - } - - /// - /// Sets the where the log output will go. - /// - /// - /// - /// The specified must be open and writable. - /// - /// - /// The will be closed when the appender - /// instance is closed. - /// - /// - /// Note: Logging to an unopened will fail. - /// - /// - public virtual TextWriter Writer - { - get { return m_qtw; } - set - { - lock(this) - { - Reset(); - if (value != null) - { - m_qtw = new QuietTextWriter(value, ErrorHandler); - WriteHeader(); - } - } - } - } - - #endregion Public Instance Properties - - #region Override implementation of AppenderSkeleton - - /// - /// This method determines if there is a sense in attempting to append. - /// - /// - /// - /// This method checks if an output target has been set and if a - /// layout has been set. - /// - /// - /// false if any of the preconditions fail. - protected override bool PreAppendCheck() - { - if (!base.PreAppendCheck()) - { - return false; - } - - if (m_qtw == null) - { - // Allow subclass to lazily create the writer - PrepareWriter(); - - if (m_qtw == null) - { - ErrorHandler.Error("No output stream or file set for the appender named ["+ Name +"]."); - return false; - } - } - if (m_qtw.Closed) - { - ErrorHandler.Error("Output stream for appender named ["+ Name +"] has been closed."); - return false; - } - - return true; - } - - /// - /// This method is called by the - /// method. - /// - /// The event to log. - /// - /// - /// Writes a log statement to the output stream if the output stream exists - /// and is writable. - /// - /// - /// The format of the output will depend on the appender's layout. - /// - /// - protected override void Append(LoggingEvent loggingEvent) - { - RenderLoggingEvent(m_qtw, loggingEvent); - - if (m_immediateFlush) - { - m_qtw.Flush(); - } - } - - /// - /// This method is called by the - /// method. - /// - /// The array of events to log. - /// - /// - /// This method writes all the bulk logged events to the output writer - /// before flushing the stream. - /// - /// - protected override void Append(LoggingEvent[] loggingEvents) - { - foreach(LoggingEvent loggingEvent in loggingEvents) - { - RenderLoggingEvent(m_qtw, loggingEvent); - } - - if (m_immediateFlush) - { - m_qtw.Flush(); - } - } - - /// - /// Close this appender instance. The underlying stream or writer is also closed. - /// - /// - /// Closed appenders cannot be reused. - /// - protected override void OnClose() - { - lock(this) - { - Reset(); - } - } - - /// - /// Gets or set the and the underlying - /// , if any, for this appender. - /// - /// - /// The for this appender. - /// - public override IErrorHandler ErrorHandler - { - get { return base.ErrorHandler; } - set - { - lock(this) - { - if (value == null) - { - LogLog.Warn(declaringType, "TextWriterAppender: You have tried to set a null error-handler."); - } - else - { - base.ErrorHandler = value; - if (m_qtw != null) - { - m_qtw.ErrorHandler = value; - } - } - } - } - } - - /// - /// This appender requires a to be set. - /// - /// true - /// - /// - /// This appender requires a to be set. - /// - /// - protected override bool RequiresLayout - { - get { return true; } - } - - #endregion Override implementation of AppenderSkeleton - - #region Protected Instance Methods - - /// - /// Writes the footer and closes the underlying . - /// - /// - /// - /// Writes the footer and closes the underlying . - /// - /// - protected virtual void WriteFooterAndCloseWriter() - { - WriteFooter(); - CloseWriter(); - } - - /// - /// Closes the underlying . - /// - /// - /// - /// Closes the underlying . - /// - /// - protected virtual void CloseWriter() - { - if (m_qtw != null) - { - try - { - m_qtw.Close(); - } - catch(Exception e) - { - ErrorHandler.Error("Could not close writer ["+m_qtw+"]", e); - // do need to invoke an error handler - // at this late stage - } - } - } - - /// - /// Clears internal references to the underlying - /// and other variables. - /// - /// - /// - /// Subclasses can override this method for an alternate closing behavior. - /// - /// - protected virtual void Reset() - { - WriteFooterAndCloseWriter(); - m_qtw = null; - } - - /// - /// Writes a footer as produced by the embedded layout's property. - /// - /// - /// - /// Writes a footer as produced by the embedded layout's property. - /// - /// - protected virtual void WriteFooter() - { - if (Layout != null && m_qtw != null && !m_qtw.Closed) - { - string f = Layout.Footer; - if (f != null) - { - m_qtw.Write(f); - } - } - } - - /// - /// Writes a header produced by the embedded layout's property. - /// - /// - /// - /// Writes a header produced by the embedded layout's property. - /// - /// - protected virtual void WriteHeader() - { - if (Layout != null && m_qtw != null && !m_qtw.Closed) - { - string h = Layout.Header; - if (h != null) - { - m_qtw.Write(h); - } - } - } - - /// - /// Called to allow a subclass to lazily initialize the writer - /// - /// - /// - /// This method is called when an event is logged and the or - /// have not been set. This allows a subclass to - /// attempt to initialize the writer multiple times. - /// - /// - protected virtual void PrepareWriter() - { - } - - /// - /// Gets or sets the where logging events - /// will be written to. - /// - /// - /// The where logging events are written. - /// - /// - /// - /// This is the where logging events - /// will be written to. - /// - /// - protected QuietTextWriter QuietWriter - { - get { return m_qtw; } - set { m_qtw = value; } + { + #region Public Instance Constructors + + /// + /// Initializes a new instance of the class. + /// + /// + /// + /// Default constructor. + /// + /// + public TextWriterAppender() + { + } + + /// + /// Initializes a new instance of the class and + /// sets the output destination to a new initialized + /// with the specified . + /// + /// The layout to use with this appender. + /// The to output to. + /// + /// + /// Obsolete constructor. + /// + /// + [Obsolete("Instead use the default constructor and set the Layout & Writer properties")] + public TextWriterAppender(ILayout layout, Stream os) : this(layout, new StreamWriter(os)) + { + } + + /// + /// Initializes a new instance of the class and sets + /// the output destination to the specified . + /// + /// The layout to use with this appender + /// The to output to + /// + /// The must have been previously opened. + /// + /// + /// + /// Obsolete constructor. + /// + /// + [Obsolete("Instead use the default constructor and set the Layout & Writer properties")] + public TextWriterAppender(ILayout layout, TextWriter writer) + { + Layout = layout; + Writer = writer; + } + + #endregion + + #region Public Instance Properties + + /// + /// Gets or set whether the appender will flush at the end + /// of each append operation. + /// + /// + /// + /// The default behavior is to flush at the end of each + /// append operation. + /// + /// + /// If this option is set to false, then the underlying + /// stream can defer persisting the logging event to a later + /// time. + /// + /// + /// + /// Avoiding the flush operation at the end of each append results in + /// a performance gain of 10 to 20 percent. However, there is safety + /// trade-off involved in skipping flushing. Indeed, when flushing is + /// skipped, then it is likely that the last few log events will not + /// be recorded on disk when the application exits. This is a high + /// price to pay even for a 20% performance gain. + /// + public bool ImmediateFlush + { + get { return m_immediateFlush; } + set { m_immediateFlush = value; } + } + + /// + /// Sets the where the log output will go. + /// + /// + /// + /// The specified must be open and writable. + /// + /// + /// The will be closed when the appender + /// instance is closed. + /// + /// + /// Note: Logging to an unopened will fail. + /// + /// + public virtual TextWriter Writer + { + get { return m_qtw; } + set + { + lock(this) + { + Reset(); + if (value != null) + { + m_qtw = new QuietTextWriter(value, ErrorHandler); + WriteHeader(); + } + } + } + } + + #endregion Public Instance Properties + + #region Override implementation of AppenderSkeleton + + /// + /// This method determines if there is a sense in attempting to append. + /// + /// + /// + /// This method checks if an output target has been set and if a + /// layout has been set. + /// + /// + /// false if any of the preconditions fail. + protected override bool PreAppendCheck() + { + if (!base.PreAppendCheck()) + { + return false; + } + + if (m_qtw == null) + { + // Allow subclass to lazily create the writer + PrepareWriter(); + + if (m_qtw == null) + { + ErrorHandler.Error("No output stream or file set for the appender named ["+ Name +"]."); + return false; + } + } + if (m_qtw.Closed) + { + ErrorHandler.Error("Output stream for appender named ["+ Name +"] has been closed."); + return false; + } + + return true; + } + + /// + /// This method is called by the + /// method. + /// + /// The event to log. + /// + /// + /// Writes a log statement to the output stream if the output stream exists + /// and is writable. + /// + /// + /// The format of the output will depend on the appender's layout. + /// + /// + protected override void Append(LoggingEvent loggingEvent) + { + RenderLoggingEvent(m_qtw, loggingEvent); + + if (m_immediateFlush) + { + m_qtw.Flush(); + } + } + + /// + /// This method is called by the + /// method. + /// + /// The array of events to log. + /// + /// + /// This method writes all the bulk logged events to the output writer + /// before flushing the stream. + /// + /// + protected override void Append(LoggingEvent[] loggingEvents) + { + foreach(LoggingEvent loggingEvent in loggingEvents) + { + RenderLoggingEvent(m_qtw, loggingEvent); + } + + if (m_immediateFlush) + { + m_qtw.Flush(); + } + } + + /// + /// Close this appender instance. The underlying stream or writer is also closed. + /// + /// + /// Closed appenders cannot be reused. + /// + protected override void OnClose() + { + lock(this) + { + Reset(); + } + } + + /// + /// Gets or set the and the underlying + /// , if any, for this appender. + /// + /// + /// The for this appender. + /// + public override IErrorHandler ErrorHandler + { + get { return base.ErrorHandler; } + set + { + lock(this) + { + if (value == null) + { + LogLog.Warn(declaringType, "TextWriterAppender: You have tried to set a null error-handler."); + } + else + { + base.ErrorHandler = value; + if (m_qtw != null) + { + m_qtw.ErrorHandler = value; + } + } + } + } + } + + /// + /// This appender requires a to be set. + /// + /// true + /// + /// + /// This appender requires a to be set. + /// + /// + protected override bool RequiresLayout + { + get { return true; } + } + + #endregion Override implementation of AppenderSkeleton + + #region Protected Instance Methods + + /// + /// Writes the footer and closes the underlying . + /// + /// + /// + /// Writes the footer and closes the underlying . + /// + /// + protected virtual void WriteFooterAndCloseWriter() + { + WriteFooter(); + CloseWriter(); + } + + /// + /// Closes the underlying . + /// + /// + /// + /// Closes the underlying . + /// + /// + protected virtual void CloseWriter() + { + if (m_qtw != null) + { + try + { + m_qtw.Close(); + } + catch(Exception e) + { + ErrorHandler.Error("Could not close writer ["+m_qtw+"]", e); + // do need to invoke an error handler + // at this late stage + } + } + } + + /// + /// Clears internal references to the underlying + /// and other variables. + /// + /// + /// + /// Subclasses can override this method for an alternate closing behavior. + /// + /// + protected virtual void Reset() + { + WriteFooterAndCloseWriter(); + m_qtw = null; + } + + /// + /// Writes a footer as produced by the embedded layout's property. + /// + /// + /// + /// Writes a footer as produced by the embedded layout's property. + /// + /// + protected virtual void WriteFooter() + { + if (Layout != null && m_qtw != null && !m_qtw.Closed) + { + string f = Layout.Footer; + if (f != null) + { + m_qtw.Write(f); + } + } + } + + /// + /// Writes a header produced by the embedded layout's property. + /// + /// + /// + /// Writes a header produced by the embedded layout's property. + /// + /// + protected virtual void WriteHeader() + { + if (Layout != null && m_qtw != null && !m_qtw.Closed) + { + string h = Layout.Header; + if (h != null) + { + m_qtw.Write(h); + } + } + } + + /// + /// Called to allow a subclass to lazily initialize the writer + /// + /// + /// + /// This method is called when an event is logged and the or + /// have not been set. This allows a subclass to + /// attempt to initialize the writer multiple times. + /// + /// + protected virtual void PrepareWriter() + { + } + + /// + /// Gets or sets the where logging events + /// will be written to. + /// + /// + /// The where logging events are written. + /// + /// + /// + /// This is the where logging events + /// will be written to. + /// + /// + protected QuietTextWriter QuietWriter + { + get { return m_qtw; } + set { m_qtw = value; } } #endregion Protected Instance Methods @@ -444,43 +444,43 @@ protected QuietTextWriter QuietWriter #region Private Instance Fields /// - /// This is the where logging events - /// will be written to. - /// - private QuietTextWriter m_qtw; - - /// - /// Immediate flush means that the underlying - /// or output stream will be flushed at the end of each append operation. - /// - /// - /// - /// Immediate flush is slower but ensures that each append request is - /// actually written. If is set to - /// false, then there is a good chance that the last few - /// logging events are not actually persisted if and when the application - /// crashes. - /// - /// - /// The default value is true. - /// - /// - private bool m_immediateFlush = true; - - #endregion Private Instance Fields - - #region Private Static Fields - - /// - /// The fully qualified type of the TextWriterAppender class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(TextWriterAppender); - - #endregion Private Static Fields + /// This is the where logging events + /// will be written to. + /// + private QuietTextWriter m_qtw; + + /// + /// Immediate flush means that the underlying + /// or output stream will be flushed at the end of each append operation. + /// + /// + /// + /// Immediate flush is slower but ensures that each append request is + /// actually written. If is set to + /// false, then there is a good chance that the last few + /// logging events are not actually persisted if and when the application + /// crashes. + /// + /// + /// The default value is true. + /// + /// + private bool m_immediateFlush = true; + + #endregion Private Instance Fields + + #region Private Static Fields + + /// + /// The fully qualified type of the TextWriterAppender class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(TextWriterAppender); + + #endregion Private Static Fields /// /// Flushes any buffered log data. @@ -500,5 +500,5 @@ public override bool Flush(int millisecondsTimeout) return true; } - } + } } diff --git a/src/log4net/Appender/TraceAppender.cs b/src/log4net/Appender/TraceAppender.cs index 8e6cb7f3..e266f4b8 100644 --- a/src/log4net/Appender/TraceAppender.cs +++ b/src/log4net/Appender/TraceAppender.cs @@ -24,92 +24,92 @@ namespace log4net.Appender { - /// - /// Appends log events to the system. - /// - /// - /// - /// The application configuration file can be used to control what listeners - /// are actually used. See the MSDN documentation for the - /// class for details on configuring the - /// trace system. - /// - /// - /// Events are written using the System.Diagnostics.Trace.Write(string,string) - /// method. The event's logger name is the default value for the category parameter + /// + /// Appends log events to the system. + /// + /// + /// + /// The application configuration file can be used to control what listeners + /// are actually used. See the MSDN documentation for the + /// class for details on configuring the + /// trace system. + /// + /// + /// Events are written using the System.Diagnostics.Trace.Write(string,string) + /// method. The event's logger name is the default value for the category parameter /// of the Write method. - /// - /// - /// Compact Framework
- /// The Compact Framework does not support the - /// class for any operation except Assert. When using the Compact Framework this - /// appender will write to the system rather than - /// the Trace system. This appender will therefore behave like the . - ///
- ///
- /// Douglas de la Torre - /// Nicko Cadell - /// Gert Driesen + ///
+ /// + /// Compact Framework
+ /// The Compact Framework does not support the + /// class for any operation except Assert. When using the Compact Framework this + /// appender will write to the system rather than + /// the Trace system. This appender will therefore behave like the . + ///
+ ///
+ /// Douglas de la Torre + /// Nicko Cadell + /// Gert Driesen /// Ron Grabowski - public class TraceAppender : AppenderSkeleton - { - #region Public Instance Constructors - - /// - /// Initializes a new instance of the . - /// - /// - /// - /// Default constructor. - /// - /// - public TraceAppender() - { - } - - /// - /// Initializes a new instance of the - /// with a specified layout. - /// - /// The layout to use with this appender. - /// - /// - /// Obsolete constructor. - /// - /// - [System.Obsolete("Instead use the default constructor and set the Layout property")] - public TraceAppender(ILayout layout) - { - Layout = layout; - } - - #endregion Public Instance Constructors - - #region Public Instance Properties - - /// - /// Gets or sets a value that indicates whether the appender will - /// flush at the end of each write. - /// - /// - /// The default behavior is to flush at the end of each - /// write. If the option is set tofalse, then the underlying - /// stream can defer writing to physical medium to a later time. - /// - /// - /// Avoiding the flush operation at the end of each append results - /// in a performance gain of 10 to 20 percent. However, there is safety - /// trade-off involved in skipping flushing. Indeed, when flushing is - /// skipped, then it is likely that the last few log events will not - /// be recorded on disk when the application exits. This is a high - /// price to pay even for a 20% performance gain. - /// - /// - public bool ImmediateFlush - { - get { return m_immediateFlush; } - set { m_immediateFlush = value; } - } + public class TraceAppender : AppenderSkeleton + { + #region Public Instance Constructors + + /// + /// Initializes a new instance of the . + /// + /// + /// + /// Default constructor. + /// + /// + public TraceAppender() + { + } + + /// + /// Initializes a new instance of the + /// with a specified layout. + /// + /// The layout to use with this appender. + /// + /// + /// Obsolete constructor. + /// + /// + [System.Obsolete("Instead use the default constructor and set the Layout property")] + public TraceAppender(ILayout layout) + { + Layout = layout; + } + + #endregion Public Instance Constructors + + #region Public Instance Properties + + /// + /// Gets or sets a value that indicates whether the appender will + /// flush at the end of each write. + /// + /// + /// The default behavior is to flush at the end of each + /// write. If the option is set tofalse, then the underlying + /// stream can defer writing to physical medium to a later time. + /// + /// + /// Avoiding the flush operation at the end of each append results + /// in a performance gain of 10 to 20 percent. However, there is safety + /// trade-off involved in skipping flushing. Indeed, when flushing is + /// skipped, then it is likely that the last few log events will not + /// be recorded on disk when the application exits. This is a high + /// price to pay even for a 20% performance gain. + /// + /// + public bool ImmediateFlush + { + get { return m_immediateFlush; } + set { m_immediateFlush = value; } + } /// /// The category parameter sent to the Trace method. @@ -122,90 +122,90 @@ public bool ImmediateFlush /// /// /// - public PatternLayout Category - { - get { return m_category; } - set { m_category = value; } - } - - #endregion Public Instance Properties - - #region Override implementation of AppenderSkeleton - - /// - /// Writes the logging event to the system. - /// - /// The event to log. - /// - /// - /// Writes the logging event to the system. - /// - /// - protected override void Append(LoggingEvent loggingEvent) - { - // - // Write the string to the Trace system - // + public PatternLayout Category + { + get { return m_category; } + set { m_category = value; } + } + + #endregion Public Instance Properties + + #region Override implementation of AppenderSkeleton + + /// + /// Writes the logging event to the system. + /// + /// The event to log. + /// + /// + /// Writes the logging event to the system. + /// + /// + protected override void Append(LoggingEvent loggingEvent) + { + // + // Write the string to the Trace system + // #if NETCF - System.Diagnostics.Debug.Write(RenderLoggingEvent(loggingEvent), m_category.Format(loggingEvent)); + System.Diagnostics.Debug.Write(RenderLoggingEvent(loggingEvent), m_category.Format(loggingEvent)); #else System.Diagnostics.Trace.Write(RenderLoggingEvent(loggingEvent), m_category.Format(loggingEvent)); #endif - - // - // Flush the Trace system if needed - // - if (m_immediateFlush) - { + + // + // Flush the Trace system if needed + // + if (m_immediateFlush) + { #if NETCF - System.Diagnostics.Debug.Flush(); + System.Diagnostics.Debug.Flush(); #else - System.Diagnostics.Trace.Flush(); + System.Diagnostics.Trace.Flush(); #endif - } - } - - /// - /// This appender requires a to be set. - /// - /// true - /// - /// - /// This appender requires a to be set. - /// - /// - protected override bool RequiresLayout - { - get { return true; } - } - - #endregion Override implementation of AppenderSkeleton - - #region Private Instance Fields - - /// - /// Immediate flush means that the underlying writer or output stream - /// will be flushed at the end of each append operation. - /// - /// - /// - /// Immediate flush is slower but ensures that each append request is - /// actually written. If is set to - /// false, then there is a good chance that the last few - /// logs events are not actually written to persistent media if and - /// when the application crashes. - /// - /// - /// The default value is true. - /// - private bool m_immediateFlush = true; + } + } + + /// + /// This appender requires a to be set. + /// + /// true + /// + /// + /// This appender requires a to be set. + /// + /// + protected override bool RequiresLayout + { + get { return true; } + } + + #endregion Override implementation of AppenderSkeleton + + #region Private Instance Fields + + /// + /// Immediate flush means that the underlying writer or output stream + /// will be flushed at the end of each append operation. + /// + /// + /// + /// Immediate flush is slower but ensures that each append request is + /// actually written. If is set to + /// false, then there is a good chance that the last few + /// logs events are not actually written to persistent media if and + /// when the application crashes. + /// + /// + /// The default value is true. + /// + private bool m_immediateFlush = true; /// /// Defaults to %logger /// private PatternLayout m_category = new PatternLayout("%logger"); - #endregion Private Instance Fields + #endregion Private Instance Fields /// /// Flushes any buffered log data. @@ -219,7 +219,7 @@ public override bool Flush(int millisecondsTimeout) // System.Diagnostics.Trace and System.Diagnostics.Debug are thread-safe, so no need for lock(this). #if NETCF - System.Diagnostics.Debug.Flush(); + System.Diagnostics.Debug.Flush(); #else System.Diagnostics.Trace.Flush(); #endif diff --git a/src/log4net/Appender/UdpAppender.cs b/src/log4net/Appender/UdpAppender.cs index e2cafe49..70acff03 100644 --- a/src/log4net/Appender/UdpAppender.cs +++ b/src/log4net/Appender/UdpAppender.cs @@ -27,522 +27,522 @@ namespace log4net.Appender { - /// - /// Sends logging events as connectionless UDP datagrams to a remote host or a - /// multicast group using an . - /// - /// - /// - /// UDP guarantees neither that messages arrive, nor that they arrive in the correct order. - /// - /// - /// To view the logging results, a custom application can be developed that listens for logging - /// events. - /// - /// - /// When decoding events send via this appender remember to use the same encoding - /// to decode the events as was used to send the events. See the - /// property to specify the encoding to use. - /// - /// - /// - /// This example shows how to log receive logging events that are sent - /// on IP address 244.0.0.1 and port 8080 to the console. The event is - /// encoded in the packet as a unicode string and it is decoded as such. - /// - /// IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0); - /// UdpClient udpClient; - /// byte[] buffer; - /// string loggingEvent; - /// - /// try - /// { - /// udpClient = new UdpClient(8080); - /// - /// while(true) - /// { - /// buffer = udpClient.Receive(ref remoteEndPoint); - /// loggingEvent = System.Text.Encoding.Unicode.GetString(buffer); - /// Console.WriteLine(loggingEvent); - /// } - /// } - /// catch(Exception e) - /// { - /// Console.WriteLine(e.ToString()); - /// } - /// - /// - /// Dim remoteEndPoint as IPEndPoint - /// Dim udpClient as UdpClient - /// Dim buffer as Byte() - /// Dim loggingEvent as String - /// - /// Try - /// remoteEndPoint = new IPEndPoint(IPAddress.Any, 0) - /// udpClient = new UdpClient(8080) - /// - /// While True - /// buffer = udpClient.Receive(ByRef remoteEndPoint) - /// loggingEvent = System.Text.Encoding.Unicode.GetString(buffer) - /// Console.WriteLine(loggingEvent) - /// Wend - /// Catch e As Exception - /// Console.WriteLine(e.ToString()) - /// End Try - /// - /// - /// An example configuration section to log information using this appender to the - /// IP 224.0.0.1 on port 8080: - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// Gert Driesen - /// Nicko Cadell - public class UdpAppender : AppenderSkeleton - { - #region Public Instance Constructors - - /// - /// Initializes a new instance of the class. - /// - /// - /// The default constructor initializes all fields to their default values. - /// - public UdpAppender() - { - } - - #endregion Public Instance Constructors - - #region Public Instance Properties - - /// - /// Gets or sets the IP address of the remote host or multicast group to which - /// the underlying should sent the logging event. - /// - /// - /// The IP address of the remote host or multicast group to which the logging event - /// will be sent. - /// - /// - /// - /// Multicast addresses are identified by IP class D addresses (in the range 224.0.0.0 to - /// 239.255.255.255). Multicast packets can pass across different networks through routers, so - /// it is possible to use multicasts in an Internet scenario as long as your network provider - /// supports multicasting. - /// - /// - /// Hosts that want to receive particular multicast messages must register their interest by joining - /// the multicast group. Multicast messages are not sent to networks where no host has joined - /// the multicast group. Class D IP addresses are used for multicast groups, to differentiate - /// them from normal host addresses, allowing nodes to easily detect if a message is of interest. - /// - /// - /// Static multicast addresses that are needed globally are assigned by IANA. A few examples are listed in the table below: - /// - /// - /// - /// - /// IP Address - /// Description - /// - /// - /// 224.0.0.1 - /// - /// - /// Sends a message to all system on the subnet. - /// - /// - /// - /// - /// 224.0.0.2 - /// - /// - /// Sends a message to all routers on the subnet. - /// - /// - /// - /// - /// 224.0.0.12 - /// - /// - /// The DHCP server answers messages on the IP address 224.0.0.12, but only on a subnet. - /// - /// - /// - /// - /// - /// - /// A complete list of actually reserved multicast addresses and their owners in the ranges - /// defined by RFC 3171 can be found at the IANA web site. - /// - /// - /// The address range 239.0.0.0 to 239.255.255.255 is reserved for administrative scope-relative - /// addresses. These addresses can be reused with other local groups. Routers are typically - /// configured with filters to prevent multicast traffic in this range from flowing outside - /// of the local network. - /// - /// - public IPAddress RemoteAddress - { - get { return m_remoteAddress; } - set { m_remoteAddress = value; } - } - - /// - /// Gets or sets the TCP port number of the remote host or multicast group to which - /// the underlying should sent the logging event. - /// - /// - /// An integer value in the range to - /// indicating the TCP port number of the remote host or multicast group to which the logging event - /// will be sent. - /// - /// - /// The underlying will send messages to this TCP port number - /// on the remote host or multicast group. - /// - /// The value specified is less than or greater than . - public int RemotePort - { - get { return m_remotePort; } - set - { - if (value < IPEndPoint.MinPort || value > IPEndPoint.MaxPort) - { - throw log4net.Util.SystemInfo.CreateArgumentOutOfRangeException("value", (object)value, - "The value specified is less than " + - IPEndPoint.MinPort.ToString(NumberFormatInfo.InvariantInfo) + - " or greater than " + - IPEndPoint.MaxPort.ToString(NumberFormatInfo.InvariantInfo) + "."); - } - else - { - m_remotePort = value; - } - } - } - - /// - /// Gets or sets the TCP port number from which the underlying will communicate. - /// - /// - /// An integer value in the range to - /// indicating the TCP port number from which the underlying will communicate. - /// - /// - /// - /// The underlying will bind to this port for sending messages. - /// - /// - /// Setting the value to 0 (the default) will cause the udp client not to bind to - /// a local port. - /// - /// - /// The value specified is less than or greater than . - public int LocalPort - { - get { return m_localPort; } - set - { - if (value != 0 && (value < IPEndPoint.MinPort || value > IPEndPoint.MaxPort)) - { - throw log4net.Util.SystemInfo.CreateArgumentOutOfRangeException("value", (object)value, - "The value specified is less than " + - IPEndPoint.MinPort.ToString(NumberFormatInfo.InvariantInfo) + - " or greater than " + - IPEndPoint.MaxPort.ToString(NumberFormatInfo.InvariantInfo) + "."); - } - else - { - m_localPort = value; - } - } - } - - /// - /// Gets or sets used to write the packets. - /// - /// - /// The used to write the packets. - /// - /// - /// - /// The used to write the packets. - /// - /// - public Encoding Encoding - { - get { return m_encoding; } - set { m_encoding = value; } - } - - #endregion Public Instance Properties - - #region Protected Instance Properties - - /// - /// Gets or sets the underlying . - /// - /// - /// The underlying . - /// - /// - /// creates a to send logging events - /// over a network. Classes deriving from can use this - /// property to get or set this . Use the underlying - /// returned from if you require access beyond that which - /// provides. - /// - protected UdpClient Client - { - get { return this.m_client; } - set { this.m_client = value; } - } - - /// - /// Gets or sets the cached remote endpoint to which the logging events should be sent. - /// - /// - /// The cached remote endpoint to which the logging events will be sent. - /// - /// - /// The method will initialize the remote endpoint - /// with the values of the and - /// properties. - /// - protected IPEndPoint RemoteEndPoint - { - get { return this.m_remoteEndPoint; } - set { this.m_remoteEndPoint = value; } - } - - #endregion Protected Instance Properties - - #region Implementation of IOptionHandler - - /// - /// Initialize the appender based on the options set. - /// - /// - /// - /// This is part of the delayed object - /// activation scheme. The method must - /// be called on this object after the configuration properties have - /// been set. Until is called this - /// object is in an undefined state and must not be used. - /// - /// - /// If any of the configuration properties are modified then - /// must be called again. - /// - /// - /// The appender will be ignored if no was specified or - /// an invalid remote or local TCP port number was specified. - /// - /// - /// The required property was not specified. - /// The TCP port number assigned to or is less than or greater than . - public override void ActivateOptions() - { - base.ActivateOptions(); - - if (this.RemoteAddress == null) - { - throw new ArgumentNullException("The required property 'Address' was not specified."); - } - else if (this.RemotePort < IPEndPoint.MinPort || this.RemotePort > IPEndPoint.MaxPort) - { - throw log4net.Util.SystemInfo.CreateArgumentOutOfRangeException("this.RemotePort", (object)this.RemotePort, - "The RemotePort is less than " + - IPEndPoint.MinPort.ToString(NumberFormatInfo.InvariantInfo) + - " or greater than " + - IPEndPoint.MaxPort.ToString(NumberFormatInfo.InvariantInfo) + "."); - } - else if (this.LocalPort != 0 && (this.LocalPort < IPEndPoint.MinPort || this.LocalPort > IPEndPoint.MaxPort)) - { - throw log4net.Util.SystemInfo.CreateArgumentOutOfRangeException("this.LocalPort", (object)this.LocalPort, - "The LocalPort is less than " + - IPEndPoint.MinPort.ToString(NumberFormatInfo.InvariantInfo) + - " or greater than " + - IPEndPoint.MaxPort.ToString(NumberFormatInfo.InvariantInfo) + "."); - } - else - { - this.RemoteEndPoint = new IPEndPoint(this.RemoteAddress, this.RemotePort); - this.InitializeClientConnection(); - } - } - - #endregion - - #region Override implementation of AppenderSkeleton - - /// - /// This method is called by the method. - /// - /// The event to log. - /// - /// - /// Sends the event using an UDP datagram. - /// - /// - /// Exceptions are passed to the . - /// - /// - protected override void Append(LoggingEvent loggingEvent) - { - try - { - Byte [] buffer = m_encoding.GetBytes(RenderLoggingEvent(loggingEvent).ToCharArray()); + /// + /// Sends logging events as connectionless UDP datagrams to a remote host or a + /// multicast group using an . + /// + /// + /// + /// UDP guarantees neither that messages arrive, nor that they arrive in the correct order. + /// + /// + /// To view the logging results, a custom application can be developed that listens for logging + /// events. + /// + /// + /// When decoding events send via this appender remember to use the same encoding + /// to decode the events as was used to send the events. See the + /// property to specify the encoding to use. + /// + /// + /// + /// This example shows how to log receive logging events that are sent + /// on IP address 244.0.0.1 and port 8080 to the console. The event is + /// encoded in the packet as a unicode string and it is decoded as such. + /// + /// IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0); + /// UdpClient udpClient; + /// byte[] buffer; + /// string loggingEvent; + /// + /// try + /// { + /// udpClient = new UdpClient(8080); + /// + /// while(true) + /// { + /// buffer = udpClient.Receive(ref remoteEndPoint); + /// loggingEvent = System.Text.Encoding.Unicode.GetString(buffer); + /// Console.WriteLine(loggingEvent); + /// } + /// } + /// catch(Exception e) + /// { + /// Console.WriteLine(e.ToString()); + /// } + /// + /// + /// Dim remoteEndPoint as IPEndPoint + /// Dim udpClient as UdpClient + /// Dim buffer as Byte() + /// Dim loggingEvent as String + /// + /// Try + /// remoteEndPoint = new IPEndPoint(IPAddress.Any, 0) + /// udpClient = new UdpClient(8080) + /// + /// While True + /// buffer = udpClient.Receive(ByRef remoteEndPoint) + /// loggingEvent = System.Text.Encoding.Unicode.GetString(buffer) + /// Console.WriteLine(loggingEvent) + /// Wend + /// Catch e As Exception + /// Console.WriteLine(e.ToString()) + /// End Try + /// + /// + /// An example configuration section to log information using this appender to the + /// IP 224.0.0.1 on port 8080: + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// Gert Driesen + /// Nicko Cadell + public class UdpAppender : AppenderSkeleton + { + #region Public Instance Constructors + + /// + /// Initializes a new instance of the class. + /// + /// + /// The default constructor initializes all fields to their default values. + /// + public UdpAppender() + { + } + + #endregion Public Instance Constructors + + #region Public Instance Properties + + /// + /// Gets or sets the IP address of the remote host or multicast group to which + /// the underlying should sent the logging event. + /// + /// + /// The IP address of the remote host or multicast group to which the logging event + /// will be sent. + /// + /// + /// + /// Multicast addresses are identified by IP class D addresses (in the range 224.0.0.0 to + /// 239.255.255.255). Multicast packets can pass across different networks through routers, so + /// it is possible to use multicasts in an Internet scenario as long as your network provider + /// supports multicasting. + /// + /// + /// Hosts that want to receive particular multicast messages must register their interest by joining + /// the multicast group. Multicast messages are not sent to networks where no host has joined + /// the multicast group. Class D IP addresses are used for multicast groups, to differentiate + /// them from normal host addresses, allowing nodes to easily detect if a message is of interest. + /// + /// + /// Static multicast addresses that are needed globally are assigned by IANA. A few examples are listed in the table below: + /// + /// + /// + /// + /// IP Address + /// Description + /// + /// + /// 224.0.0.1 + /// + /// + /// Sends a message to all system on the subnet. + /// + /// + /// + /// + /// 224.0.0.2 + /// + /// + /// Sends a message to all routers on the subnet. + /// + /// + /// + /// + /// 224.0.0.12 + /// + /// + /// The DHCP server answers messages on the IP address 224.0.0.12, but only on a subnet. + /// + /// + /// + /// + /// + /// + /// A complete list of actually reserved multicast addresses and their owners in the ranges + /// defined by RFC 3171 can be found at the IANA web site. + /// + /// + /// The address range 239.0.0.0 to 239.255.255.255 is reserved for administrative scope-relative + /// addresses. These addresses can be reused with other local groups. Routers are typically + /// configured with filters to prevent multicast traffic in this range from flowing outside + /// of the local network. + /// + /// + public IPAddress RemoteAddress + { + get { return m_remoteAddress; } + set { m_remoteAddress = value; } + } + + /// + /// Gets or sets the TCP port number of the remote host or multicast group to which + /// the underlying should sent the logging event. + /// + /// + /// An integer value in the range to + /// indicating the TCP port number of the remote host or multicast group to which the logging event + /// will be sent. + /// + /// + /// The underlying will send messages to this TCP port number + /// on the remote host or multicast group. + /// + /// The value specified is less than or greater than . + public int RemotePort + { + get { return m_remotePort; } + set + { + if (value < IPEndPoint.MinPort || value > IPEndPoint.MaxPort) + { + throw log4net.Util.SystemInfo.CreateArgumentOutOfRangeException("value", (object)value, + "The value specified is less than " + + IPEndPoint.MinPort.ToString(NumberFormatInfo.InvariantInfo) + + " or greater than " + + IPEndPoint.MaxPort.ToString(NumberFormatInfo.InvariantInfo) + "."); + } + else + { + m_remotePort = value; + } + } + } + + /// + /// Gets or sets the TCP port number from which the underlying will communicate. + /// + /// + /// An integer value in the range to + /// indicating the TCP port number from which the underlying will communicate. + /// + /// + /// + /// The underlying will bind to this port for sending messages. + /// + /// + /// Setting the value to 0 (the default) will cause the udp client not to bind to + /// a local port. + /// + /// + /// The value specified is less than or greater than . + public int LocalPort + { + get { return m_localPort; } + set + { + if (value != 0 && (value < IPEndPoint.MinPort || value > IPEndPoint.MaxPort)) + { + throw log4net.Util.SystemInfo.CreateArgumentOutOfRangeException("value", (object)value, + "The value specified is less than " + + IPEndPoint.MinPort.ToString(NumberFormatInfo.InvariantInfo) + + " or greater than " + + IPEndPoint.MaxPort.ToString(NumberFormatInfo.InvariantInfo) + "."); + } + else + { + m_localPort = value; + } + } + } + + /// + /// Gets or sets used to write the packets. + /// + /// + /// The used to write the packets. + /// + /// + /// + /// The used to write the packets. + /// + /// + public Encoding Encoding + { + get { return m_encoding; } + set { m_encoding = value; } + } + + #endregion Public Instance Properties + + #region Protected Instance Properties + + /// + /// Gets or sets the underlying . + /// + /// + /// The underlying . + /// + /// + /// creates a to send logging events + /// over a network. Classes deriving from can use this + /// property to get or set this . Use the underlying + /// returned from if you require access beyond that which + /// provides. + /// + protected UdpClient Client + { + get { return this.m_client; } + set { this.m_client = value; } + } + + /// + /// Gets or sets the cached remote endpoint to which the logging events should be sent. + /// + /// + /// The cached remote endpoint to which the logging events will be sent. + /// + /// + /// The method will initialize the remote endpoint + /// with the values of the and + /// properties. + /// + protected IPEndPoint RemoteEndPoint + { + get { return this.m_remoteEndPoint; } + set { this.m_remoteEndPoint = value; } + } + + #endregion Protected Instance Properties + + #region Implementation of IOptionHandler + + /// + /// Initialize the appender based on the options set. + /// + /// + /// + /// This is part of the delayed object + /// activation scheme. The method must + /// be called on this object after the configuration properties have + /// been set. Until is called this + /// object is in an undefined state and must not be used. + /// + /// + /// If any of the configuration properties are modified then + /// must be called again. + /// + /// + /// The appender will be ignored if no was specified or + /// an invalid remote or local TCP port number was specified. + /// + /// + /// The required property was not specified. + /// The TCP port number assigned to or is less than or greater than . + public override void ActivateOptions() + { + base.ActivateOptions(); + + if (this.RemoteAddress == null) + { + throw new ArgumentNullException("The required property 'Address' was not specified."); + } + else if (this.RemotePort < IPEndPoint.MinPort || this.RemotePort > IPEndPoint.MaxPort) + { + throw log4net.Util.SystemInfo.CreateArgumentOutOfRangeException("this.RemotePort", (object)this.RemotePort, + "The RemotePort is less than " + + IPEndPoint.MinPort.ToString(NumberFormatInfo.InvariantInfo) + + " or greater than " + + IPEndPoint.MaxPort.ToString(NumberFormatInfo.InvariantInfo) + "."); + } + else if (this.LocalPort != 0 && (this.LocalPort < IPEndPoint.MinPort || this.LocalPort > IPEndPoint.MaxPort)) + { + throw log4net.Util.SystemInfo.CreateArgumentOutOfRangeException("this.LocalPort", (object)this.LocalPort, + "The LocalPort is less than " + + IPEndPoint.MinPort.ToString(NumberFormatInfo.InvariantInfo) + + " or greater than " + + IPEndPoint.MaxPort.ToString(NumberFormatInfo.InvariantInfo) + "."); + } + else + { + this.RemoteEndPoint = new IPEndPoint(this.RemoteAddress, this.RemotePort); + this.InitializeClientConnection(); + } + } + + #endregion + + #region Override implementation of AppenderSkeleton + + /// + /// This method is called by the method. + /// + /// The event to log. + /// + /// + /// Sends the event using an UDP datagram. + /// + /// + /// Exceptions are passed to the . + /// + /// + protected override void Append(LoggingEvent loggingEvent) + { + try + { + Byte [] buffer = m_encoding.GetBytes(RenderLoggingEvent(loggingEvent).ToCharArray()); #if NETSTANDARD - Client.SendAsync(buffer, buffer.Length, RemoteEndPoint).Wait(); + Client.SendAsync(buffer, buffer.Length, RemoteEndPoint).Wait(); #else - this.Client.Send(buffer, buffer.Length, this.RemoteEndPoint); + this.Client.Send(buffer, buffer.Length, this.RemoteEndPoint); #endif - } - catch (Exception ex) - { - ErrorHandler.Error( - "Unable to send logging event to remote host " + - this.RemoteAddress.ToString() + - " on port " + - this.RemotePort + ".", - ex, - ErrorCode.WriteFailure); - } - } - - /// - /// This appender requires a to be set. - /// - /// true - /// - /// - /// This appender requires a to be set. - /// - /// - protected override bool RequiresLayout - { - get { return true; } - } - - /// - /// Closes the UDP connection and releases all resources associated with - /// this instance. - /// - /// - /// - /// Disables the underlying and releases all managed - /// and unmanaged resources associated with the . - /// - /// - protected override void OnClose() - { - base.OnClose(); - - if (this.Client != null) - { - this.Client.Close(); - } - } - - #endregion Override implementation of AppenderSkeleton - - #region Protected Instance Methods - - /// - /// Initializes the underlying connection. - /// - /// - /// - /// The underlying is initialized and binds to the - /// port number from which you intend to communicate. - /// - /// - /// Exceptions are passed to the . - /// - /// - protected virtual void InitializeClientConnection() - { - try - { - if (this.LocalPort == 0) - { + } + catch (Exception ex) + { + ErrorHandler.Error( + "Unable to send logging event to remote host " + + this.RemoteAddress.ToString() + + " on port " + + this.RemotePort + ".", + ex, + ErrorCode.WriteFailure); + } + } + + /// + /// This appender requires a to be set. + /// + /// true + /// + /// + /// This appender requires a to be set. + /// + /// + protected override bool RequiresLayout + { + get { return true; } + } + + /// + /// Closes the UDP connection and releases all resources associated with + /// this instance. + /// + /// + /// + /// Disables the underlying and releases all managed + /// and unmanaged resources associated with the . + /// + /// + protected override void OnClose() + { + base.OnClose(); + + if (this.Client != null) + { + this.Client.Close(); + } + } + + #endregion Override implementation of AppenderSkeleton + + #region Protected Instance Methods + + /// + /// Initializes the underlying connection. + /// + /// + /// + /// The underlying is initialized and binds to the + /// port number from which you intend to communicate. + /// + /// + /// Exceptions are passed to the . + /// + /// + protected virtual void InitializeClientConnection() + { + try + { + if (this.LocalPort == 0) + { #if NETCF || NET_1_0 || SSCLI_1_0 || CLI_1_0 - this.Client = new UdpClient(); + this.Client = new UdpClient(); #else - this.Client = new UdpClient(RemoteAddress.AddressFamily); + this.Client = new UdpClient(RemoteAddress.AddressFamily); #endif - } - else - { + } + else + { #if NETCF || NET_1_0 || SSCLI_1_0 || CLI_1_0 - this.Client = new UdpClient(this.LocalPort); + this.Client = new UdpClient(this.LocalPort); #else - this.Client = new UdpClient(this.LocalPort, RemoteAddress.AddressFamily); + this.Client = new UdpClient(this.LocalPort, RemoteAddress.AddressFamily); #endif - } - } - catch (Exception ex) - { - ErrorHandler.Error( - "Could not initialize the UdpClient connection on port " + - this.LocalPort.ToString(NumberFormatInfo.InvariantInfo) + ".", - ex, - ErrorCode.GenericFailure); - - this.Client = null; - } - } - - #endregion Protected Instance Methods - - #region Private Instance Fields - - /// - /// The IP address of the remote host or multicast group to which - /// the logging event will be sent. - /// - private IPAddress m_remoteAddress; - - /// - /// The TCP port number of the remote host or multicast group to - /// which the logging event will be sent. - /// - private int m_remotePort; - - /// - /// The cached remote endpoint to which the logging events will be sent. - /// - private IPEndPoint m_remoteEndPoint; - - /// - /// The TCP port number from which the will communicate. - /// - private int m_localPort; - - /// - /// The instance that will be used for sending the - /// logging events. - /// - private UdpClient m_client; - - /// - /// The encoding to use for the packet. - /// + } + } + catch (Exception ex) + { + ErrorHandler.Error( + "Could not initialize the UdpClient connection on port " + + this.LocalPort.ToString(NumberFormatInfo.InvariantInfo) + ".", + ex, + ErrorCode.GenericFailure); + + this.Client = null; + } + } + + #endregion Protected Instance Methods + + #region Private Instance Fields + + /// + /// The IP address of the remote host or multicast group to which + /// the logging event will be sent. + /// + private IPAddress m_remoteAddress; + + /// + /// The TCP port number of the remote host or multicast group to + /// which the logging event will be sent. + /// + private int m_remotePort; + + /// + /// The cached remote endpoint to which the logging events will be sent. + /// + private IPEndPoint m_remoteEndPoint; + + /// + /// The TCP port number from which the will communicate. + /// + private int m_localPort; + + /// + /// The instance that will be used for sending the + /// logging events. + /// + private UdpClient m_client; + + /// + /// The encoding to use for the packet. + /// #if NETSTANDARD - private Encoding m_encoding = Encoding.Unicode; + private Encoding m_encoding = Encoding.Unicode; #else - private Encoding m_encoding = Encoding.Default; + private Encoding m_encoding = Encoding.Default; #endif - #endregion Private Instance Fields - } + #endregion Private Instance Fields + } } diff --git a/src/log4net/AssemblyInfo.cs b/src/log4net/AssemblyInfo.cs index 2cae3b92..19772bc6 100644 --- a/src/log4net/AssemblyInfo.cs +++ b/src/log4net/AssemblyInfo.cs @@ -137,8 +137,8 @@ [assembly: AssemblyProduct("log4net")] [assembly: AssemblyDefaultAlias("log4net")] -[assembly: AssemblyCulture("")] - +[assembly: AssemblyCulture("")] + // // In order to sign your assembly you must specify a key to use. Refer to the // Microsoft .NET Framework documentation for more information on assembly signing. diff --git a/src/log4net/Config/AliasDomainAttribute.cs b/src/log4net/Config/AliasDomainAttribute.cs index 11906f66..dc1af1f5 100644 --- a/src/log4net/Config/AliasDomainAttribute.cs +++ b/src/log4net/Config/AliasDomainAttribute.cs @@ -24,51 +24,51 @@ namespace log4net.Config { - /// - /// Assembly level attribute that specifies a domain to alias to this assembly's repository. - /// - /// - /// - /// AliasDomainAttribute is obsolete. Use AliasRepositoryAttribute instead of AliasDomainAttribute. - /// - /// - /// An assembly's logger repository is defined by its , - /// however this can be overridden by an assembly loaded before the target assembly. - /// - /// - /// An assembly can alias another assembly's domain to its repository by - /// specifying this attribute with the name of the target domain. - /// - /// - /// This attribute can only be specified on the assembly and may be used - /// as many times as necessary to alias all the required domains. - /// - /// - /// Nicko Cadell - /// Gert Driesen - [AttributeUsage(AttributeTargets.Assembly,AllowMultiple=true)] - [Serializable] - [Obsolete("Use AliasRepositoryAttribute instead of AliasDomainAttribute")] - public sealed class AliasDomainAttribute : AliasRepositoryAttribute - { - #region Public Instance Constructors + /// + /// Assembly level attribute that specifies a domain to alias to this assembly's repository. + /// + /// + /// + /// AliasDomainAttribute is obsolete. Use AliasRepositoryAttribute instead of AliasDomainAttribute. + /// + /// + /// An assembly's logger repository is defined by its , + /// however this can be overridden by an assembly loaded before the target assembly. + /// + /// + /// An assembly can alias another assembly's domain to its repository by + /// specifying this attribute with the name of the target domain. + /// + /// + /// This attribute can only be specified on the assembly and may be used + /// as many times as necessary to alias all the required domains. + /// + /// + /// Nicko Cadell + /// Gert Driesen + [AttributeUsage(AttributeTargets.Assembly,AllowMultiple=true)] + [Serializable] + [Obsolete("Use AliasRepositoryAttribute instead of AliasDomainAttribute")] + public sealed class AliasDomainAttribute : AliasRepositoryAttribute + { + #region Public Instance Constructors - /// - /// Initializes a new instance of the class with - /// the specified domain to alias to this assembly's repository. - /// - /// The domain to alias to this assemby's repository. - /// - /// - /// Obsolete. Use instead of . - /// - /// - public AliasDomainAttribute(string name) : base(name) - { - } + /// + /// Initializes a new instance of the class with + /// the specified domain to alias to this assembly's repository. + /// + /// The domain to alias to this assemby's repository. + /// + /// + /// Obsolete. Use instead of . + /// + /// + public AliasDomainAttribute(string name) : base(name) + { + } - #endregion Public Instance Constructors - } + #endregion Public Instance Constructors + } } #endif // !NETCF \ No newline at end of file diff --git a/src/log4net/Config/AliasRepositoryAttribute.cs b/src/log4net/Config/AliasRepositoryAttribute.cs index da83b77b..1b6021fe 100644 --- a/src/log4net/Config/AliasRepositoryAttribute.cs +++ b/src/log4net/Config/AliasRepositoryAttribute.cs @@ -24,80 +24,80 @@ namespace log4net.Config { - /// - /// Assembly level attribute that specifies a repository to alias to this assembly's repository. - /// - /// - /// - /// An assembly's logger repository is defined by its , - /// however this can be overridden by an assembly loaded before the target assembly. - /// - /// - /// An assembly can alias another assembly's repository to its repository by - /// specifying this attribute with the name of the target repository. - /// - /// - /// This attribute can only be specified on the assembly and may be used - /// as many times as necessary to alias all the required repositories. - /// - /// - /// Nicko Cadell - /// Gert Driesen - [AttributeUsage(AttributeTargets.Assembly,AllowMultiple=true)] - [Serializable] - public /*sealed*/ class AliasRepositoryAttribute : Attribute - { - // - // Class is not sealed because AliasDomainAttribute extends it while it is obsoleted - // + /// + /// Assembly level attribute that specifies a repository to alias to this assembly's repository. + /// + /// + /// + /// An assembly's logger repository is defined by its , + /// however this can be overridden by an assembly loaded before the target assembly. + /// + /// + /// An assembly can alias another assembly's repository to its repository by + /// specifying this attribute with the name of the target repository. + /// + /// + /// This attribute can only be specified on the assembly and may be used + /// as many times as necessary to alias all the required repositories. + /// + /// + /// Nicko Cadell + /// Gert Driesen + [AttributeUsage(AttributeTargets.Assembly,AllowMultiple=true)] + [Serializable] + public /*sealed*/ class AliasRepositoryAttribute : Attribute + { + // + // Class is not sealed because AliasDomainAttribute extends it while it is obsoleted + // - #region Public Instance Constructors + #region Public Instance Constructors - /// - /// Initializes a new instance of the class with - /// the specified repository to alias to this assembly's repository. - /// - /// The repository to alias to this assemby's repository. - /// - /// - /// Initializes a new instance of the class with - /// the specified repository to alias to this assembly's repository. - /// - /// - public AliasRepositoryAttribute(string name) - { - Name = name; - } + /// + /// Initializes a new instance of the class with + /// the specified repository to alias to this assembly's repository. + /// + /// The repository to alias to this assemby's repository. + /// + /// + /// Initializes a new instance of the class with + /// the specified repository to alias to this assembly's repository. + /// + /// + public AliasRepositoryAttribute(string name) + { + Name = name; + } - #endregion Public Instance Constructors + #endregion Public Instance Constructors - #region Public Instance Properties + #region Public Instance Properties - /// - /// Gets or sets the repository to alias to this assemby's repository. - /// - /// - /// The repository to alias to this assemby's repository. - /// - /// - /// - /// The name of the repository to alias to this assemby's repository. - /// - /// - public string Name - { - get { return m_name; } - set { m_name = value ; } - } + /// + /// Gets or sets the repository to alias to this assemby's repository. + /// + /// + /// The repository to alias to this assemby's repository. + /// + /// + /// + /// The name of the repository to alias to this assemby's repository. + /// + /// + public string Name + { + get { return m_name; } + set { m_name = value ; } + } - #endregion Public Instance Properties + #endregion Public Instance Properties - #region Private Instance Fields + #region Private Instance Fields - private string m_name = null; + private string m_name = null; - #endregion Private Instance Fields - } + #endregion Private Instance Fields + } } #endif // !NETCF \ No newline at end of file diff --git a/src/log4net/Config/BasicConfigurator.cs b/src/log4net/Config/BasicConfigurator.cs index 374cf72b..8e5a6b23 100644 --- a/src/log4net/Config/BasicConfigurator.cs +++ b/src/log4net/Config/BasicConfigurator.cs @@ -31,74 +31,74 @@ namespace log4net.Config { - /// - /// Use this class to quickly configure a . - /// - /// - /// - /// Allows very simple programmatic configuration of log4net. - /// - /// - /// Only one appender can be configured using this configurator. - /// The appender is set at the root of the hierarchy and all logging - /// events will be delivered to that appender. - /// - /// - /// Appenders can also implement the interface. Therefore - /// they would require that the method - /// be called after the appenders properties have been configured. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public sealed class BasicConfigurator + /// + /// Use this class to quickly configure a . + /// + /// + /// + /// Allows very simple programmatic configuration of log4net. + /// + /// + /// Only one appender can be configured using this configurator. + /// The appender is set at the root of the hierarchy and all logging + /// events will be delivered to that appender. + /// + /// + /// Appenders can also implement the interface. Therefore + /// they would require that the method + /// be called after the appenders properties have been configured. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public sealed class BasicConfigurator { - #region Private Static Fields + #region Private Static Fields - /// - /// The fully qualified type of the BasicConfigurator class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(BasicConfigurator); + /// + /// The fully qualified type of the BasicConfigurator class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(BasicConfigurator); - #endregion Private Static Fields + #endregion Private Static Fields #region Private Instance Constructors /// - /// Initializes a new instance of the class. - /// - /// - /// - /// Uses a private access modifier to prevent instantiation of this class. - /// - /// - private BasicConfigurator() - { - } + /// Initializes a new instance of the class. + /// + /// + /// + /// Uses a private access modifier to prevent instantiation of this class. + /// + /// + private BasicConfigurator() + { + } - #endregion Private Instance Constructors + #endregion Private Instance Constructors - #region Public Static Methods + #region Public Static Methods #if !NETSTANDARD1_3 - /// - /// Initializes the log4net system with a default configuration. - /// - /// - /// - /// Initializes the log4net logging system using a - /// that will write to Console.Out. The log messages are - /// formatted using the layout object - /// with the - /// layout style. - /// - /// + /// + /// Initializes the log4net system with a default configuration. + /// + /// + /// + /// Initializes the log4net logging system using a + /// that will write to Console.Out. The log messages are + /// formatted using the layout object + /// with the + /// layout style. + /// + /// public static ICollection Configure() - { + { return BasicConfigurator.Configure(LogManager.GetRepository(Assembly.GetCallingAssembly())); } @@ -127,36 +127,36 @@ public static ICollection Configure(params IAppender[] appenders) return configurationMessages; } - /// - /// Initializes the log4net system using the specified appender. - /// - /// The appender to use to log all logging events. - /// - /// - /// Initializes the log4net system using the specified appender. - /// - /// - public static ICollection Configure(IAppender appender) - { + /// + /// Initializes the log4net system using the specified appender. + /// + /// The appender to use to log all logging events. + /// + /// + /// Initializes the log4net system using the specified appender. + /// + /// + public static ICollection Configure(IAppender appender) + { return Configure(new IAppender[] { appender }); - } + } #endif // !NETSTANDARD1_3 - /// - /// Initializes the with a default configuration. - /// - /// The repository to configure. - /// - /// - /// Initializes the specified repository using a - /// that will write to Console.Out. The log messages are - /// formatted using the layout object - /// with the - /// layout style. - /// - /// + /// + /// Initializes the with a default configuration. + /// + /// The repository to configure. + /// + /// + /// Initializes the specified repository using a + /// that will write to Console.Out. The log messages are + /// formatted using the layout object + /// with the + /// layout style. + /// + /// public static ICollection Configure(ILoggerRepository repository) - { + { ArrayList configurationMessages = new ArrayList(); using (new LogLog.LogReceivedAdapter(configurationMessages)) @@ -177,7 +177,7 @@ public static ICollection Configure(ILoggerRepository repository) repository.ConfigurationMessages = configurationMessages; return configurationMessages; - } + } /// /// Initializes the using the specified appender. @@ -217,9 +217,9 @@ public static ICollection Configure(ILoggerRepository repository, params IAppend return configurationMessages; } - - private static void InternalConfigure(ILoggerRepository repository, params IAppender[] appenders) - { + + private static void InternalConfigure(ILoggerRepository repository, params IAppender[] appenders) + { IBasicRepositoryConfigurator configurableRepository = repository as IBasicRepositoryConfigurator; if (configurableRepository != null) { @@ -229,8 +229,8 @@ private static void InternalConfigure(ILoggerRepository repository, params IAppe { LogLog.Warn(declaringType, "BasicConfigurator: Repository [" + repository + "] does not support the BasicConfigurator"); } - } + } - #endregion Public Static Methods - } + #endregion Public Static Methods + } } diff --git a/src/log4net/Config/ConfiguratorAttribute.cs b/src/log4net/Config/ConfiguratorAttribute.cs index e3da6745..c884736c 100644 --- a/src/log4net/Config/ConfiguratorAttribute.cs +++ b/src/log4net/Config/ConfiguratorAttribute.cs @@ -27,87 +27,87 @@ namespace log4net.Config { - /// - /// Base class for all log4net configuration attributes. - /// - /// - /// This is an abstract class that must be extended by - /// specific configurators. This attribute allows the - /// configurator to be parameterized by an assembly level - /// attribute. - /// - /// Nicko Cadell - /// Gert Driesen - [AttributeUsage(AttributeTargets.Assembly)] - public abstract class ConfiguratorAttribute : Attribute, IComparable - { - private int m_priority = 0; + /// + /// Base class for all log4net configuration attributes. + /// + /// + /// This is an abstract class that must be extended by + /// specific configurators. This attribute allows the + /// configurator to be parameterized by an assembly level + /// attribute. + /// + /// Nicko Cadell + /// Gert Driesen + [AttributeUsage(AttributeTargets.Assembly)] + public abstract class ConfiguratorAttribute : Attribute, IComparable + { + private int m_priority = 0; - /// - /// Constructor used by subclasses. - /// - /// the ordering priority for this configurator - /// - /// - /// The is used to order the configurator - /// attributes before they are invoked. Higher priority configurators are executed - /// before lower priority ones. - /// - /// - protected ConfiguratorAttribute(int priority) - { - m_priority = priority; - } + /// + /// Constructor used by subclasses. + /// + /// the ordering priority for this configurator + /// + /// + /// The is used to order the configurator + /// attributes before they are invoked. Higher priority configurators are executed + /// before lower priority ones. + /// + /// + protected ConfiguratorAttribute(int priority) + { + m_priority = priority; + } - /// - /// Configures the for the specified assembly. - /// - /// The assembly that this attribute was defined on. - /// The repository to configure. - /// - /// - /// Abstract method implemented by a subclass. When this method is called - /// the subclass should configure the . - /// - /// - public abstract void Configure(Assembly sourceAssembly, ILoggerRepository targetRepository); + /// + /// Configures the for the specified assembly. + /// + /// The assembly that this attribute was defined on. + /// The repository to configure. + /// + /// + /// Abstract method implemented by a subclass. When this method is called + /// the subclass should configure the . + /// + /// + public abstract void Configure(Assembly sourceAssembly, ILoggerRepository targetRepository); - /// - /// Compare this instance to another ConfiguratorAttribute - /// - /// the object to compare to - /// see - /// - /// - /// Compares the priorities of the two instances. - /// Sorts by priority in descending order. Objects with the same priority are - /// randomly ordered. - /// - /// - public int CompareTo(object obj) - { - // Reference equals - if ((object)this == obj) - { - return 0; - } + /// + /// Compare this instance to another ConfiguratorAttribute + /// + /// the object to compare to + /// see + /// + /// + /// Compares the priorities of the two instances. + /// Sorts by priority in descending order. Objects with the same priority are + /// randomly ordered. + /// + /// + public int CompareTo(object obj) + { + // Reference equals + if ((object)this == obj) + { + return 0; + } - int result = -1; + int result = -1; - ConfiguratorAttribute target = obj as ConfiguratorAttribute; - if (target != null) - { - // Compare the priorities - result = target.m_priority.CompareTo(m_priority); - if (result == 0) - { - // Same priority, so have to provide some ordering - result = -1; - } - } - return result; - } - } + ConfiguratorAttribute target = obj as ConfiguratorAttribute; + if (target != null) + { + // Compare the priorities + result = target.m_priority.CompareTo(m_priority); + if (result == 0) + { + // Same priority, so have to provide some ordering + result = -1; + } + } + return result; + } + } } #endif //!NETCF \ No newline at end of file diff --git a/src/log4net/Config/DOMConfigurator.cs b/src/log4net/Config/DOMConfigurator.cs index 2dd16d84..0486edfc 100644 --- a/src/log4net/Config/DOMConfigurator.cs +++ b/src/log4net/Config/DOMConfigurator.cs @@ -31,329 +31,329 @@ namespace log4net.Config { - /// - /// Use this class to initialize the log4net environment using an Xml tree. - /// - /// - /// - /// DOMConfigurator is obsolete. Use XmlConfigurator instead of DOMConfigurator. - /// - /// - /// Configures a using an Xml tree. - /// - /// - /// Nicko Cadell - /// Gert Driesen - [Obsolete("Use XmlConfigurator instead of DOMConfigurator")] - public sealed class DOMConfigurator - { - #region Private Instance Constructors + /// + /// Use this class to initialize the log4net environment using an Xml tree. + /// + /// + /// + /// DOMConfigurator is obsolete. Use XmlConfigurator instead of DOMConfigurator. + /// + /// + /// Configures a using an Xml tree. + /// + /// + /// Nicko Cadell + /// Gert Driesen + [Obsolete("Use XmlConfigurator instead of DOMConfigurator")] + public sealed class DOMConfigurator + { + #region Private Instance Constructors - /// - /// Private constructor - /// - private DOMConfigurator() - { - } + /// + /// Private constructor + /// + private DOMConfigurator() + { + } - #endregion Protected Instance Constructors + #endregion Protected Instance Constructors - #region Configure static methods + #region Configure static methods - /// - /// Automatically configures the log4net system based on the - /// application's configuration settings. - /// - /// - /// - /// DOMConfigurator is obsolete. Use XmlConfigurator instead of DOMConfigurator. - /// - /// Each application has a configuration file. This has the - /// same name as the application with '.config' appended. - /// This file is XML and calling this function prompts the - /// configurator to look in that file for a section called - /// log4net that contains the configuration data. - /// - [Obsolete("Use XmlConfigurator.Configure instead of DOMConfigurator.Configure")] - public static void Configure() - { - XmlConfigurator.Configure(LogManager.GetRepository(Assembly.GetCallingAssembly())); - } + /// + /// Automatically configures the log4net system based on the + /// application's configuration settings. + /// + /// + /// + /// DOMConfigurator is obsolete. Use XmlConfigurator instead of DOMConfigurator. + /// + /// Each application has a configuration file. This has the + /// same name as the application with '.config' appended. + /// This file is XML and calling this function prompts the + /// configurator to look in that file for a section called + /// log4net that contains the configuration data. + /// + [Obsolete("Use XmlConfigurator.Configure instead of DOMConfigurator.Configure")] + public static void Configure() + { + XmlConfigurator.Configure(LogManager.GetRepository(Assembly.GetCallingAssembly())); + } - /// - /// Automatically configures the using settings - /// stored in the application's configuration file. - /// - /// - /// - /// DOMConfigurator is obsolete. Use XmlConfigurator instead of DOMConfigurator. - /// - /// Each application has a configuration file. This has the - /// same name as the application with '.config' appended. - /// This file is XML and calling this function prompts the - /// configurator to look in that file for a section called - /// log4net that contains the configuration data. - /// - /// The repository to configure. - [Obsolete("Use XmlConfigurator.Configure instead of DOMConfigurator.Configure")] - public static void Configure(ILoggerRepository repository) - { - XmlConfigurator.Configure(repository); - } + /// + /// Automatically configures the using settings + /// stored in the application's configuration file. + /// + /// + /// + /// DOMConfigurator is obsolete. Use XmlConfigurator instead of DOMConfigurator. + /// + /// Each application has a configuration file. This has the + /// same name as the application with '.config' appended. + /// This file is XML and calling this function prompts the + /// configurator to look in that file for a section called + /// log4net that contains the configuration data. + /// + /// The repository to configure. + [Obsolete("Use XmlConfigurator.Configure instead of DOMConfigurator.Configure")] + public static void Configure(ILoggerRepository repository) + { + XmlConfigurator.Configure(repository); + } - /// - /// Configures log4net using a log4net element - /// - /// - /// - /// DOMConfigurator is obsolete. Use XmlConfigurator instead of DOMConfigurator. - /// - /// Loads the log4net configuration from the XML element - /// supplied as . - /// - /// The element to parse. - [Obsolete("Use XmlConfigurator.Configure instead of DOMConfigurator.Configure")] - public static void Configure(XmlElement element) - { - XmlConfigurator.Configure(LogManager.GetRepository(Assembly.GetCallingAssembly()), element); - } + /// + /// Configures log4net using a log4net element + /// + /// + /// + /// DOMConfigurator is obsolete. Use XmlConfigurator instead of DOMConfigurator. + /// + /// Loads the log4net configuration from the XML element + /// supplied as . + /// + /// The element to parse. + [Obsolete("Use XmlConfigurator.Configure instead of DOMConfigurator.Configure")] + public static void Configure(XmlElement element) + { + XmlConfigurator.Configure(LogManager.GetRepository(Assembly.GetCallingAssembly()), element); + } - /// - /// Configures the using the specified XML - /// element. - /// - /// - /// - /// DOMConfigurator is obsolete. Use XmlConfigurator instead of DOMConfigurator. - /// - /// Loads the log4net configuration from the XML element - /// supplied as . - /// - /// The repository to configure. - /// The element to parse. - [Obsolete("Use XmlConfigurator.Configure instead of DOMConfigurator.Configure")] - public static void Configure(ILoggerRepository repository, XmlElement element) - { - XmlConfigurator.Configure(repository, element); - } + /// + /// Configures the using the specified XML + /// element. + /// + /// + /// + /// DOMConfigurator is obsolete. Use XmlConfigurator instead of DOMConfigurator. + /// + /// Loads the log4net configuration from the XML element + /// supplied as . + /// + /// The repository to configure. + /// The element to parse. + [Obsolete("Use XmlConfigurator.Configure instead of DOMConfigurator.Configure")] + public static void Configure(ILoggerRepository repository, XmlElement element) + { + XmlConfigurator.Configure(repository, element); + } - /// - /// Configures log4net using the specified configuration file. - /// - /// The XML file to load the configuration from. - /// - /// - /// DOMConfigurator is obsolete. Use XmlConfigurator instead of DOMConfigurator. - /// - /// - /// The configuration file must be valid XML. It must contain - /// at least one element called log4net that holds - /// the log4net configuration data. - /// - /// - /// The log4net configuration file can possible be specified in the application's - /// configuration file (either MyAppName.exe.config for a - /// normal application on Web.config for an ASP.NET application). - /// - /// - /// The following example configures log4net using a configuration file, of which the - /// location is stored in the application's configuration file : - /// - /// - /// using log4net.Config; - /// using System.IO; - /// using System.Configuration; - /// - /// ... - /// - /// DOMConfigurator.Configure(new FileInfo(ConfigurationSettings.AppSettings["log4net-config-file"])); - /// - /// - /// In the .config file, the path to the log4net can be specified like this : - /// - /// - /// - /// - /// - /// - /// - /// - /// - [Obsolete("Use XmlConfigurator.Configure instead of DOMConfigurator.Configure")] - public static void Configure(FileInfo configFile) - { - XmlConfigurator.Configure(LogManager.GetRepository(Assembly.GetCallingAssembly()), configFile); - } + /// + /// Configures log4net using the specified configuration file. + /// + /// The XML file to load the configuration from. + /// + /// + /// DOMConfigurator is obsolete. Use XmlConfigurator instead of DOMConfigurator. + /// + /// + /// The configuration file must be valid XML. It must contain + /// at least one element called log4net that holds + /// the log4net configuration data. + /// + /// + /// The log4net configuration file can possible be specified in the application's + /// configuration file (either MyAppName.exe.config for a + /// normal application on Web.config for an ASP.NET application). + /// + /// + /// The following example configures log4net using a configuration file, of which the + /// location is stored in the application's configuration file : + /// + /// + /// using log4net.Config; + /// using System.IO; + /// using System.Configuration; + /// + /// ... + /// + /// DOMConfigurator.Configure(new FileInfo(ConfigurationSettings.AppSettings["log4net-config-file"])); + /// + /// + /// In the .config file, the path to the log4net can be specified like this : + /// + /// + /// + /// + /// + /// + /// + /// + /// + [Obsolete("Use XmlConfigurator.Configure instead of DOMConfigurator.Configure")] + public static void Configure(FileInfo configFile) + { + XmlConfigurator.Configure(LogManager.GetRepository(Assembly.GetCallingAssembly()), configFile); + } - /// - /// Configures log4net using the specified configuration file. - /// - /// A stream to load the XML configuration from. - /// - /// - /// DOMConfigurator is obsolete. Use XmlConfigurator instead of DOMConfigurator. - /// - /// - /// The configuration data must be valid XML. It must contain - /// at least one element called log4net that holds - /// the log4net configuration data. - /// - /// - /// Note that this method will NOT close the stream parameter. - /// - /// - [Obsolete("Use XmlConfigurator.Configure instead of DOMConfigurator.Configure")] - public static void Configure(Stream configStream) - { - XmlConfigurator.Configure(LogManager.GetRepository(Assembly.GetCallingAssembly()), configStream); - } + /// + /// Configures log4net using the specified configuration file. + /// + /// A stream to load the XML configuration from. + /// + /// + /// DOMConfigurator is obsolete. Use XmlConfigurator instead of DOMConfigurator. + /// + /// + /// The configuration data must be valid XML. It must contain + /// at least one element called log4net that holds + /// the log4net configuration data. + /// + /// + /// Note that this method will NOT close the stream parameter. + /// + /// + [Obsolete("Use XmlConfigurator.Configure instead of DOMConfigurator.Configure")] + public static void Configure(Stream configStream) + { + XmlConfigurator.Configure(LogManager.GetRepository(Assembly.GetCallingAssembly()), configStream); + } - /// - /// Configures the using the specified configuration - /// file. - /// - /// The repository to configure. - /// The XML file to load the configuration from. - /// - /// - /// DOMConfigurator is obsolete. Use XmlConfigurator instead of DOMConfigurator. - /// - /// - /// The configuration file must be valid XML. It must contain - /// at least one element called log4net that holds - /// the configuration data. - /// - /// - /// The log4net configuration file can possible be specified in the application's - /// configuration file (either MyAppName.exe.config for a - /// normal application on Web.config for an ASP.NET application). - /// - /// - /// The following example configures log4net using a configuration file, of which the - /// location is stored in the application's configuration file : - /// - /// - /// using log4net.Config; - /// using System.IO; - /// using System.Configuration; - /// - /// ... - /// - /// DOMConfigurator.Configure(new FileInfo(ConfigurationSettings.AppSettings["log4net-config-file"])); - /// - /// - /// In the .config file, the path to the log4net can be specified like this : - /// - /// - /// - /// - /// - /// - /// - /// - /// - [Obsolete("Use XmlConfigurator.Configure instead of DOMConfigurator.Configure")] - public static void Configure(ILoggerRepository repository, FileInfo configFile) - { - XmlConfigurator.Configure(repository, configFile); - } + /// + /// Configures the using the specified configuration + /// file. + /// + /// The repository to configure. + /// The XML file to load the configuration from. + /// + /// + /// DOMConfigurator is obsolete. Use XmlConfigurator instead of DOMConfigurator. + /// + /// + /// The configuration file must be valid XML. It must contain + /// at least one element called log4net that holds + /// the configuration data. + /// + /// + /// The log4net configuration file can possible be specified in the application's + /// configuration file (either MyAppName.exe.config for a + /// normal application on Web.config for an ASP.NET application). + /// + /// + /// The following example configures log4net using a configuration file, of which the + /// location is stored in the application's configuration file : + /// + /// + /// using log4net.Config; + /// using System.IO; + /// using System.Configuration; + /// + /// ... + /// + /// DOMConfigurator.Configure(new FileInfo(ConfigurationSettings.AppSettings["log4net-config-file"])); + /// + /// + /// In the .config file, the path to the log4net can be specified like this : + /// + /// + /// + /// + /// + /// + /// + /// + /// + [Obsolete("Use XmlConfigurator.Configure instead of DOMConfigurator.Configure")] + public static void Configure(ILoggerRepository repository, FileInfo configFile) + { + XmlConfigurator.Configure(repository, configFile); + } - /// - /// Configures the using the specified configuration - /// file. - /// - /// The repository to configure. - /// The stream to load the XML configuration from. - /// - /// - /// DOMConfigurator is obsolete. Use XmlConfigurator instead of DOMConfigurator. - /// - /// - /// The configuration data must be valid XML. It must contain - /// at least one element called log4net that holds - /// the configuration data. - /// - /// - /// Note that this method will NOT close the stream parameter. - /// - /// - [Obsolete("Use XmlConfigurator.Configure instead of DOMConfigurator.Configure")] - public static void Configure(ILoggerRepository repository, Stream configStream) - { - XmlConfigurator.Configure(repository, configStream); - } + /// + /// Configures the using the specified configuration + /// file. + /// + /// The repository to configure. + /// The stream to load the XML configuration from. + /// + /// + /// DOMConfigurator is obsolete. Use XmlConfigurator instead of DOMConfigurator. + /// + /// + /// The configuration data must be valid XML. It must contain + /// at least one element called log4net that holds + /// the configuration data. + /// + /// + /// Note that this method will NOT close the stream parameter. + /// + /// + [Obsolete("Use XmlConfigurator.Configure instead of DOMConfigurator.Configure")] + public static void Configure(ILoggerRepository repository, Stream configStream) + { + XmlConfigurator.Configure(repository, configStream); + } - #endregion Configure static methods + #endregion Configure static methods - #region ConfigureAndWatch static methods + #region ConfigureAndWatch static methods #if (!NETCF && !SSCLI) - /// - /// Configures log4net using the file specified, monitors the file for changes - /// and reloads the configuration if a change is detected. - /// - /// The XML file to load the configuration from. - /// - /// - /// DOMConfigurator is obsolete. Use XmlConfigurator instead of DOMConfigurator. - /// - /// - /// The configuration file must be valid XML. It must contain - /// at least one element called log4net that holds - /// the configuration data. - /// - /// - /// The configuration file will be monitored using a - /// and depends on the behavior of that class. - /// - /// - /// For more information on how to configure log4net using - /// a separate configuration file, see . - /// - /// - /// - [Obsolete("Use XmlConfigurator.ConfigureAndWatch instead of DOMConfigurator.ConfigureAndWatch")] - public static void ConfigureAndWatch(FileInfo configFile) - { - XmlConfigurator.ConfigureAndWatch(LogManager.GetRepository(Assembly.GetCallingAssembly()), configFile); - } + /// + /// Configures log4net using the file specified, monitors the file for changes + /// and reloads the configuration if a change is detected. + /// + /// The XML file to load the configuration from. + /// + /// + /// DOMConfigurator is obsolete. Use XmlConfigurator instead of DOMConfigurator. + /// + /// + /// The configuration file must be valid XML. It must contain + /// at least one element called log4net that holds + /// the configuration data. + /// + /// + /// The configuration file will be monitored using a + /// and depends on the behavior of that class. + /// + /// + /// For more information on how to configure log4net using + /// a separate configuration file, see . + /// + /// + /// + [Obsolete("Use XmlConfigurator.ConfigureAndWatch instead of DOMConfigurator.ConfigureAndWatch")] + public static void ConfigureAndWatch(FileInfo configFile) + { + XmlConfigurator.ConfigureAndWatch(LogManager.GetRepository(Assembly.GetCallingAssembly()), configFile); + } - /// - /// Configures the using the file specified, - /// monitors the file for changes and reloads the configuration if a change - /// is detected. - /// - /// The repository to configure. - /// The XML file to load the configuration from. - /// - /// - /// DOMConfigurator is obsolete. Use XmlConfigurator instead of DOMConfigurator. - /// - /// - /// The configuration file must be valid XML. It must contain - /// at least one element called log4net that holds - /// the configuration data. - /// - /// - /// The configuration file will be monitored using a - /// and depends on the behavior of that class. - /// - /// - /// For more information on how to configure log4net using - /// a separate configuration file, see . - /// - /// - /// - [Obsolete("Use XmlConfigurator.ConfigureAndWatch instead of DOMConfigurator.ConfigureAndWatch")] - public static void ConfigureAndWatch(ILoggerRepository repository, FileInfo configFile) - { - XmlConfigurator.ConfigureAndWatch(repository, configFile); - } + /// + /// Configures the using the file specified, + /// monitors the file for changes and reloads the configuration if a change + /// is detected. + /// + /// The repository to configure. + /// The XML file to load the configuration from. + /// + /// + /// DOMConfigurator is obsolete. Use XmlConfigurator instead of DOMConfigurator. + /// + /// + /// The configuration file must be valid XML. It must contain + /// at least one element called log4net that holds + /// the configuration data. + /// + /// + /// The configuration file will be monitored using a + /// and depends on the behavior of that class. + /// + /// + /// For more information on how to configure log4net using + /// a separate configuration file, see . + /// + /// + /// + [Obsolete("Use XmlConfigurator.ConfigureAndWatch instead of DOMConfigurator.ConfigureAndWatch")] + public static void ConfigureAndWatch(ILoggerRepository repository, FileInfo configFile) + { + XmlConfigurator.ConfigureAndWatch(repository, configFile); + } #endif - #endregion ConfigureAndWatch static methods - } + #endregion ConfigureAndWatch static methods + } } #endif // NET_2_0 diff --git a/src/log4net/Config/DOMConfiguratorAttribute.cs b/src/log4net/Config/DOMConfiguratorAttribute.cs index e996b0e0..4a2c2b58 100644 --- a/src/log4net/Config/DOMConfiguratorAttribute.cs +++ b/src/log4net/Config/DOMConfiguratorAttribute.cs @@ -30,31 +30,31 @@ namespace log4net.Config { - /// - /// Assembly level attribute to configure the . - /// - /// - /// - /// AliasDomainAttribute is obsolete. Use AliasRepositoryAttribute instead of AliasDomainAttribute. - /// - /// - /// This attribute may only be used at the assembly scope and can only - /// be used once per assembly. - /// - /// - /// Use this attribute to configure the - /// without calling one of the - /// methods. - /// - /// - /// Nicko Cadell - /// Gert Driesen - [AttributeUsage(AttributeTargets.Assembly)] - [Serializable] - [Obsolete("Use XmlConfiguratorAttribute instead of DOMConfiguratorAttribute")] - public sealed class DOMConfiguratorAttribute : XmlConfiguratorAttribute - { - } + /// + /// Assembly level attribute to configure the . + /// + /// + /// + /// AliasDomainAttribute is obsolete. Use AliasRepositoryAttribute instead of AliasDomainAttribute. + /// + /// + /// This attribute may only be used at the assembly scope and can only + /// be used once per assembly. + /// + /// + /// Use this attribute to configure the + /// without calling one of the + /// methods. + /// + /// + /// Nicko Cadell + /// Gert Driesen + [AttributeUsage(AttributeTargets.Assembly)] + [Serializable] + [Obsolete("Use XmlConfiguratorAttribute instead of DOMConfiguratorAttribute")] + public sealed class DOMConfiguratorAttribute : XmlConfiguratorAttribute + { + } } #endif // !NETCF \ No newline at end of file diff --git a/src/log4net/Config/DomainAttribute.cs b/src/log4net/Config/DomainAttribute.cs index 8e49ff72..1aeab430 100644 --- a/src/log4net/Config/DomainAttribute.cs +++ b/src/log4net/Config/DomainAttribute.cs @@ -24,64 +24,64 @@ namespace log4net.Config { - /// - /// Assembly level attribute that specifies the logging domain for the assembly. - /// - /// - /// - /// DomainAttribute is obsolete. Use RepositoryAttribute instead of DomainAttribute. - /// - /// - /// Assemblies are mapped to logging domains. Each domain has its own - /// logging repository. This attribute specified on the assembly controls - /// the configuration of the domain. The property specifies the name - /// of the domain that this assembly is a part of. The - /// specifies the type of the repository objects to create for the domain. If - /// this attribute is not specified and a is not specified - /// then the assembly will be part of the default shared logging domain. - /// - /// - /// This attribute can only be specified on the assembly and may only be used - /// once per assembly. - /// - /// - /// Nicko Cadell - /// Gert Driesen - [AttributeUsage(AttributeTargets.Assembly)] - [Serializable] - [Obsolete("Use RepositoryAttribute instead of DomainAttribute")] - public sealed class DomainAttribute : RepositoryAttribute - { - #region Public Instance Constructors + /// + /// Assembly level attribute that specifies the logging domain for the assembly. + /// + /// + /// + /// DomainAttribute is obsolete. Use RepositoryAttribute instead of DomainAttribute. + /// + /// + /// Assemblies are mapped to logging domains. Each domain has its own + /// logging repository. This attribute specified on the assembly controls + /// the configuration of the domain. The property specifies the name + /// of the domain that this assembly is a part of. The + /// specifies the type of the repository objects to create for the domain. If + /// this attribute is not specified and a is not specified + /// then the assembly will be part of the default shared logging domain. + /// + /// + /// This attribute can only be specified on the assembly and may only be used + /// once per assembly. + /// + /// + /// Nicko Cadell + /// Gert Driesen + [AttributeUsage(AttributeTargets.Assembly)] + [Serializable] + [Obsolete("Use RepositoryAttribute instead of DomainAttribute")] + public sealed class DomainAttribute : RepositoryAttribute + { + #region Public Instance Constructors - /// - /// Initializes a new instance of the class. - /// - /// - /// - /// Obsolete. Use RepositoryAttribute instead of DomainAttribute. - /// - /// - public DomainAttribute() : base() - { - } + /// + /// Initializes a new instance of the class. + /// + /// + /// + /// Obsolete. Use RepositoryAttribute instead of DomainAttribute. + /// + /// + public DomainAttribute() : base() + { + } - /// - /// Initialize a new instance of the class - /// with the name of the domain. - /// - /// The name of the domain. - /// - /// - /// Obsolete. Use RepositoryAttribute instead of DomainAttribute. - /// - /// - public DomainAttribute(string name) : base(name) - { - } + /// + /// Initialize a new instance of the class + /// with the name of the domain. + /// + /// The name of the domain. + /// + /// + /// Obsolete. Use RepositoryAttribute instead of DomainAttribute. + /// + /// + public DomainAttribute(string name) : base(name) + { + } - #endregion Public Instance Constructors - } + #endregion Public Instance Constructors + } } #endif // !NETCF \ No newline at end of file diff --git a/src/log4net/Config/Log4NetConfigurationSectionHandler.cs b/src/log4net/Config/Log4NetConfigurationSectionHandler.cs index d5d47230..be34c8c7 100644 --- a/src/log4net/Config/Log4NetConfigurationSectionHandler.cs +++ b/src/log4net/Config/Log4NetConfigurationSectionHandler.cs @@ -26,68 +26,68 @@ namespace log4net.Config { - /// - /// Class to register for the log4net section of the configuration file - /// - /// - /// The log4net section of the configuration file needs to have a section - /// handler registered. This is the section handler used. It simply returns - /// the XML element that is the root of the section. - /// - /// - /// Example of registering the log4net section handler : - /// - /// - /// - ///
- /// - /// - /// log4net configuration XML goes here - /// - /// - /// - /// - /// Nicko Cadell - /// Gert Driesen - public class Log4NetConfigurationSectionHandler : IConfigurationSectionHandler - { - #region Public Instance Constructors + /// + /// Class to register for the log4net section of the configuration file + /// + /// + /// The log4net section of the configuration file needs to have a section + /// handler registered. This is the section handler used. It simply returns + /// the XML element that is the root of the section. + /// + /// + /// Example of registering the log4net section handler : + /// + /// + /// + ///
+ /// + /// + /// log4net configuration XML goes here + /// + /// + /// + /// + /// Nicko Cadell + /// Gert Driesen + public class Log4NetConfigurationSectionHandler : IConfigurationSectionHandler + { + #region Public Instance Constructors - /// - /// Initializes a new instance of the class. - /// - /// - /// - /// Default constructor. - /// - /// - public Log4NetConfigurationSectionHandler() - { - } + /// + /// Initializes a new instance of the class. + /// + /// + /// + /// Default constructor. + /// + /// + public Log4NetConfigurationSectionHandler() + { + } - #endregion Public Instance Constructors + #endregion Public Instance Constructors - #region Implementation of IConfigurationSectionHandler + #region Implementation of IConfigurationSectionHandler - /// - /// Parses the configuration section. - /// - /// The configuration settings in a corresponding parent configuration section. - /// The configuration context when called from the ASP.NET configuration system. Otherwise, this parameter is reserved and is a null reference. - /// The for the log4net section. - /// The for the log4net section. - /// - /// - /// Returns the containing the configuration data, - /// - /// - public object Create(object parent, object configContext, XmlNode section) - { - return section; - } + /// + /// Parses the configuration section. + /// + /// The configuration settings in a corresponding parent configuration section. + /// The configuration context when called from the ASP.NET configuration system. Otherwise, this parameter is reserved and is a null reference. + /// The for the log4net section. + /// The for the log4net section. + /// + /// + /// Returns the containing the configuration data, + /// + /// + public object Create(object parent, object configContext, XmlNode section) + { + return section; + } - #endregion Implementation of IConfigurationSectionHandler - } + #endregion Implementation of IConfigurationSectionHandler + } } #endif // !NETCF diff --git a/src/log4net/Config/PluginAttribute.cs b/src/log4net/Config/PluginAttribute.cs index b6629725..229dad9b 100644 --- a/src/log4net/Config/PluginAttribute.cs +++ b/src/log4net/Config/PluginAttribute.cs @@ -30,169 +30,169 @@ namespace log4net.Config { - /// - /// Assembly level attribute that specifies a plugin to attach to - /// the repository. - /// - /// - /// - /// Specifies the type of a plugin to create and attach to the - /// assembly's repository. The plugin type must implement the - /// interface. - /// - /// - /// Nicko Cadell - /// Gert Driesen - [AttributeUsage(AttributeTargets.Assembly,AllowMultiple=true)] - [Serializable] - public sealed class PluginAttribute : Attribute, IPluginFactory - { - #region Public Instance Constructors + /// + /// Assembly level attribute that specifies a plugin to attach to + /// the repository. + /// + /// + /// + /// Specifies the type of a plugin to create and attach to the + /// assembly's repository. The plugin type must implement the + /// interface. + /// + /// + /// Nicko Cadell + /// Gert Driesen + [AttributeUsage(AttributeTargets.Assembly,AllowMultiple=true)] + [Serializable] + public sealed class PluginAttribute : Attribute, IPluginFactory + { + #region Public Instance Constructors #if !NETSTANDARD1_3 // Excluded because GetCallingAssembly() is not available in CoreFX (https://github.com/dotnet/corefx/issues/2221). - /// - /// Initializes a new instance of the class - /// with the specified type. - /// - /// The type name of plugin to create. - /// - /// - /// Create the attribute with the plugin type specified. - /// - /// - /// Where possible use the constructor that takes a . - /// - /// - public PluginAttribute(string typeName) - { - m_typeName = typeName; - } + /// + /// Initializes a new instance of the class + /// with the specified type. + /// + /// The type name of plugin to create. + /// + /// + /// Create the attribute with the plugin type specified. + /// + /// + /// Where possible use the constructor that takes a . + /// + /// + public PluginAttribute(string typeName) + { + m_typeName = typeName; + } #endif - /// - /// Initializes a new instance of the class - /// with the specified type. - /// - /// The type of plugin to create. - /// - /// - /// Create the attribute with the plugin type specified. - /// - /// - public PluginAttribute(Type type) - { - m_type = type; - } - - #endregion Public Instance Constructors - - #region Public Instance Properties - - /// - /// Gets or sets the type for the plugin. - /// - /// - /// The type for the plugin. - /// - /// - /// - /// The type for the plugin. - /// - /// - public Type Type - { - get { return m_type; } - set { m_type = value ; } - } - - /// - /// Gets or sets the type name for the plugin. - /// - /// - /// The type name for the plugin. - /// - /// - /// - /// The type name for the plugin. - /// - /// - /// Where possible use the property instead. - /// - /// - public string TypeName - { - get { return m_typeName; } - set { m_typeName = value ; } - } - - #endregion Public Instance Properties - - #region Implementation of IPluginFactory - - /// - /// Creates the plugin object defined by this attribute. - /// - /// - /// - /// Creates the instance of the object as - /// specified by this attribute. - /// - /// - /// The plugin object. - public IPlugin CreatePlugin() - { - Type pluginType = m_type; + /// + /// Initializes a new instance of the class + /// with the specified type. + /// + /// The type of plugin to create. + /// + /// + /// Create the attribute with the plugin type specified. + /// + /// + public PluginAttribute(Type type) + { + m_type = type; + } + + #endregion Public Instance Constructors + + #region Public Instance Properties + + /// + /// Gets or sets the type for the plugin. + /// + /// + /// The type for the plugin. + /// + /// + /// + /// The type for the plugin. + /// + /// + public Type Type + { + get { return m_type; } + set { m_type = value ; } + } + + /// + /// Gets or sets the type name for the plugin. + /// + /// + /// The type name for the plugin. + /// + /// + /// + /// The type name for the plugin. + /// + /// + /// Where possible use the property instead. + /// + /// + public string TypeName + { + get { return m_typeName; } + set { m_typeName = value ; } + } + + #endregion Public Instance Properties + + #region Implementation of IPluginFactory + + /// + /// Creates the plugin object defined by this attribute. + /// + /// + /// + /// Creates the instance of the object as + /// specified by this attribute. + /// + /// + /// The plugin object. + public IPlugin CreatePlugin() + { + Type pluginType = m_type; #if !NETSTANDARD1_3 - if (m_type == null) - { - // Get the plugin object type from the string type name - pluginType = SystemInfo.GetTypeFromString(m_typeName, true, true); - } + if (m_type == null) + { + // Get the plugin object type from the string type name + pluginType = SystemInfo.GetTypeFromString(m_typeName, true, true); + } #endif - // Check that the type is a plugin - if (!(typeof(IPlugin).IsAssignableFrom(pluginType))) - { - throw new LogException("Plugin type [" + pluginType.FullName + "] does not implement the log4net.IPlugin interface"); - } - - // Create an instance of the plugin using the default constructor - IPlugin plugin = (IPlugin)Activator.CreateInstance(pluginType); - - return plugin; - } - - #endregion Implementation of IPluginFactory - - #region Override implementation of Object - - /// - /// Returns a representation of the properties of this object. - /// - /// - /// - /// Overrides base class method to - /// return a representation of the properties of this object. - /// - /// - /// A representation of the properties of this object - public override string ToString() - { - if (m_type != null) - { - return "PluginAttribute[Type=" + m_type.FullName + "]"; - } - return "PluginAttribute[Type=" + m_typeName + "]"; - } - - #endregion Override implementation of Object - - #region Private Instance Fields - - private string m_typeName = null; - private Type m_type = null; - - #endregion Private Instance Fields - } + // Check that the type is a plugin + if (!(typeof(IPlugin).IsAssignableFrom(pluginType))) + { + throw new LogException("Plugin type [" + pluginType.FullName + "] does not implement the log4net.IPlugin interface"); + } + + // Create an instance of the plugin using the default constructor + IPlugin plugin = (IPlugin)Activator.CreateInstance(pluginType); + + return plugin; + } + + #endregion Implementation of IPluginFactory + + #region Override implementation of Object + + /// + /// Returns a representation of the properties of this object. + /// + /// + /// + /// Overrides base class method to + /// return a representation of the properties of this object. + /// + /// + /// A representation of the properties of this object + public override string ToString() + { + if (m_type != null) + { + return "PluginAttribute[Type=" + m_type.FullName + "]"; + } + return "PluginAttribute[Type=" + m_typeName + "]"; + } + + #endregion Override implementation of Object + + #region Private Instance Fields + + private string m_typeName = null; + private Type m_type = null; + + #endregion Private Instance Fields + } } #endif // !NETCF \ No newline at end of file diff --git a/src/log4net/Config/RepositoryAttribute.cs b/src/log4net/Config/RepositoryAttribute.cs index 56dd9822..2bacd532 100644 --- a/src/log4net/Config/RepositoryAttribute.cs +++ b/src/log4net/Config/RepositoryAttribute.cs @@ -24,121 +24,121 @@ namespace log4net.Config { - /// - /// Assembly level attribute that specifies the logging repository for the assembly. - /// - /// - /// - /// Assemblies are mapped to logging repository. This attribute specified - /// on the assembly controls - /// the configuration of the repository. The property specifies the name - /// of the repository that this assembly is a part of. The - /// specifies the type of the object - /// to create for the assembly. If this attribute is not specified or a - /// is not specified then the assembly will be part of the default shared logging repository. - /// - /// - /// This attribute can only be specified on the assembly and may only be used - /// once per assembly. - /// - /// - /// Nicko Cadell - /// Gert Driesen - [AttributeUsage(AttributeTargets.Assembly)] - [Serializable] - public /*sealed*/ class RepositoryAttribute : Attribute - { - // - // Class is not sealed because DomainAttribute extends it while it is obsoleted - // + /// + /// Assembly level attribute that specifies the logging repository for the assembly. + /// + /// + /// + /// Assemblies are mapped to logging repository. This attribute specified + /// on the assembly controls + /// the configuration of the repository. The property specifies the name + /// of the repository that this assembly is a part of. The + /// specifies the type of the object + /// to create for the assembly. If this attribute is not specified or a + /// is not specified then the assembly will be part of the default shared logging repository. + /// + /// + /// This attribute can only be specified on the assembly and may only be used + /// once per assembly. + /// + /// + /// Nicko Cadell + /// Gert Driesen + [AttributeUsage(AttributeTargets.Assembly)] + [Serializable] + public /*sealed*/ class RepositoryAttribute : Attribute + { + // + // Class is not sealed because DomainAttribute extends it while it is obsoleted + // - #region Public Instance Constructors + #region Public Instance Constructors - /// - /// Initializes a new instance of the class. - /// - /// - /// - /// Default constructor. - /// - /// - public RepositoryAttribute() - { - } + /// + /// Initializes a new instance of the class. + /// + /// + /// + /// Default constructor. + /// + /// + public RepositoryAttribute() + { + } - /// - /// Initialize a new instance of the class - /// with the name of the repository. - /// - /// The name of the repository. - /// - /// - /// Initialize the attribute with the name for the assembly's repository. - /// - /// - public RepositoryAttribute(string name) - { - m_name = name; - } + /// + /// Initialize a new instance of the class + /// with the name of the repository. + /// + /// The name of the repository. + /// + /// + /// Initialize the attribute with the name for the assembly's repository. + /// + /// + public RepositoryAttribute(string name) + { + m_name = name; + } - #endregion Public Instance Constructors + #endregion Public Instance Constructors - #region Public Instance Properties + #region Public Instance Properties - /// - /// Gets or sets the name of the logging repository. - /// - /// - /// The string name to use as the name of the repository associated with this - /// assembly. - /// - /// - /// - /// This value does not have to be unique. Several assemblies can share the - /// same repository. They will share the logging configuration of the repository. - /// - /// - public string Name - { - get { return m_name; } - set { m_name = value ; } - } + /// + /// Gets or sets the name of the logging repository. + /// + /// + /// The string name to use as the name of the repository associated with this + /// assembly. + /// + /// + /// + /// This value does not have to be unique. Several assemblies can share the + /// same repository. They will share the logging configuration of the repository. + /// + /// + public string Name + { + get { return m_name; } + set { m_name = value ; } + } - /// - /// Gets or sets the type of repository to create for this assembly. - /// - /// - /// The type of repository to create for this assembly. - /// - /// - /// - /// The type of the repository to create for the assembly. - /// The type must implement the - /// interface. - /// - /// - /// This will be the type of repository created when - /// the repository is created. If multiple assemblies reference the - /// same repository then the repository is only created once using the - /// of the first assembly to call into the - /// repository. - /// - /// - public Type RepositoryType - { - get { return m_repositoryType; } - set { m_repositoryType = value ; } - } + /// + /// Gets or sets the type of repository to create for this assembly. + /// + /// + /// The type of repository to create for this assembly. + /// + /// + /// + /// The type of the repository to create for the assembly. + /// The type must implement the + /// interface. + /// + /// + /// This will be the type of repository created when + /// the repository is created. If multiple assemblies reference the + /// same repository then the repository is only created once using the + /// of the first assembly to call into the + /// repository. + /// + /// + public Type RepositoryType + { + get { return m_repositoryType; } + set { m_repositoryType = value ; } + } - #endregion Public Instance Properties + #endregion Public Instance Properties - #region Private Instance Fields + #region Private Instance Fields - private string m_name = null; - private Type m_repositoryType = null; + private string m_name = null; + private Type m_repositoryType = null; - #endregion Private Instance Fields - } + #endregion Private Instance Fields + } } #endif // !NETCF \ No newline at end of file diff --git a/src/log4net/Config/SecurityContextProviderAttribute.cs b/src/log4net/Config/SecurityContextProviderAttribute.cs index 7698c1be..c85c15f8 100644 --- a/src/log4net/Config/SecurityContextProviderAttribute.cs +++ b/src/log4net/Config/SecurityContextProviderAttribute.cs @@ -29,123 +29,123 @@ namespace log4net.Config { - /// - /// Assembly level attribute to configure the . - /// - /// - /// - /// This attribute may only be used at the assembly scope and can only - /// be used once per assembly. - /// - /// - /// Use this attribute to configure the - /// without calling one of the - /// methods. - /// - /// - /// Nicko Cadell - [AttributeUsage(AttributeTargets.Assembly)] - [Serializable] - public sealed class SecurityContextProviderAttribute : ConfiguratorAttribute - { - #region Constructor - - /// - /// Construct provider attribute with type specified - /// - /// the type of the provider to use - /// - /// - /// The provider specified must subclass the - /// class. - /// - /// - public SecurityContextProviderAttribute(Type providerType) : base(100) /* configurator priority 100 to execute before the XmlConfigurator */ - { - m_providerType = providerType; - } - - #endregion - - #region Public Instance Properties - - /// - /// Gets or sets the type of the provider to use. - /// - /// - /// the type of the provider to use. - /// - /// - /// - /// The provider specified must subclass the - /// class. - /// - /// - public Type ProviderType - { - get { return m_providerType; } - set { m_providerType = value; } - } - - #endregion Public Instance Properties - - #region Override ConfiguratorAttribute - - /// - /// Configures the SecurityContextProvider - /// - /// The assembly that this attribute was defined on. - /// The repository to configure. - /// - /// - /// Creates a provider instance from the specified. - /// Sets this as the default security context provider . - /// - /// - public override void Configure(Assembly sourceAssembly, ILoggerRepository targetRepository) - { - if (m_providerType == null) - { - LogLog.Error(declaringType, "Attribute specified on assembly ["+sourceAssembly.FullName+"] with null ProviderType."); - } - else - { - LogLog.Debug(declaringType, "Creating provider of type ["+ m_providerType.FullName +"]"); - - SecurityContextProvider provider = Activator.CreateInstance(m_providerType) as SecurityContextProvider; - - if (provider == null) - { - LogLog.Error(declaringType, "Failed to create SecurityContextProvider instance of type ["+m_providerType.Name+"]."); - } - else - { - SecurityContextProvider.DefaultProvider = provider; - } - } - } - - #endregion - - #region Private Instance Fields - - private Type m_providerType = null; - - #endregion Private Instance Fields - - #region Private Static Fields - - /// - /// The fully qualified type of the SecurityContextProviderAttribute class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(SecurityContextProviderAttribute); - - #endregion Private Static Fields - } + /// + /// Assembly level attribute to configure the . + /// + /// + /// + /// This attribute may only be used at the assembly scope and can only + /// be used once per assembly. + /// + /// + /// Use this attribute to configure the + /// without calling one of the + /// methods. + /// + /// + /// Nicko Cadell + [AttributeUsage(AttributeTargets.Assembly)] + [Serializable] + public sealed class SecurityContextProviderAttribute : ConfiguratorAttribute + { + #region Constructor + + /// + /// Construct provider attribute with type specified + /// + /// the type of the provider to use + /// + /// + /// The provider specified must subclass the + /// class. + /// + /// + public SecurityContextProviderAttribute(Type providerType) : base(100) /* configurator priority 100 to execute before the XmlConfigurator */ + { + m_providerType = providerType; + } + + #endregion + + #region Public Instance Properties + + /// + /// Gets or sets the type of the provider to use. + /// + /// + /// the type of the provider to use. + /// + /// + /// + /// The provider specified must subclass the + /// class. + /// + /// + public Type ProviderType + { + get { return m_providerType; } + set { m_providerType = value; } + } + + #endregion Public Instance Properties + + #region Override ConfiguratorAttribute + + /// + /// Configures the SecurityContextProvider + /// + /// The assembly that this attribute was defined on. + /// The repository to configure. + /// + /// + /// Creates a provider instance from the specified. + /// Sets this as the default security context provider . + /// + /// + public override void Configure(Assembly sourceAssembly, ILoggerRepository targetRepository) + { + if (m_providerType == null) + { + LogLog.Error(declaringType, "Attribute specified on assembly ["+sourceAssembly.FullName+"] with null ProviderType."); + } + else + { + LogLog.Debug(declaringType, "Creating provider of type ["+ m_providerType.FullName +"]"); + + SecurityContextProvider provider = Activator.CreateInstance(m_providerType) as SecurityContextProvider; + + if (provider == null) + { + LogLog.Error(declaringType, "Failed to create SecurityContextProvider instance of type ["+m_providerType.Name+"]."); + } + else + { + SecurityContextProvider.DefaultProvider = provider; + } + } + } + + #endregion + + #region Private Instance Fields + + private Type m_providerType = null; + + #endregion Private Instance Fields + + #region Private Static Fields + + /// + /// The fully qualified type of the SecurityContextProviderAttribute class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(SecurityContextProviderAttribute); + + #endregion Private Static Fields + } } #endif // !NETCF \ No newline at end of file diff --git a/src/log4net/Config/XmlConfigurator.cs b/src/log4net/Config/XmlConfigurator.cs index ce37d2d3..e854e75f 100644 --- a/src/log4net/Config/XmlConfigurator.cs +++ b/src/log4net/Config/XmlConfigurator.cs @@ -32,1102 +32,1102 @@ namespace log4net.Config { - /// - /// Use this class to initialize the log4net environment using an Xml tree. - /// - /// - /// - /// Configures a using an Xml tree. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public sealed class XmlConfigurator - { - #region Private Instance Constructors - - /// - /// Private constructor - /// - private XmlConfigurator() - { - } - - #endregion Protected Instance Constructors - - #region Configure static methods + /// + /// Use this class to initialize the log4net environment using an Xml tree. + /// + /// + /// + /// Configures a using an Xml tree. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public sealed class XmlConfigurator + { + #region Private Instance Constructors + + /// + /// Private constructor + /// + private XmlConfigurator() + { + } + + #endregion Protected Instance Constructors + + #region Configure static methods #if !NETCF - /// - /// Automatically configures the using settings - /// stored in the application's configuration file. - /// - /// - /// - /// Each application has a configuration file. This has the - /// same name as the application with '.config' appended. - /// This file is XML and calling this function prompts the - /// configurator to look in that file for a section called - /// log4net that contains the configuration data. - /// - /// - /// To use this method to configure log4net you must specify - /// the section - /// handler for the log4net configuration section. See the - /// for an example. - /// - /// - /// The repository to configure. + /// + /// Automatically configures the using settings + /// stored in the application's configuration file. + /// + /// + /// + /// Each application has a configuration file. This has the + /// same name as the application with '.config' appended. + /// This file is XML and calling this function prompts the + /// configurator to look in that file for a section called + /// log4net that contains the configuration data. + /// + /// + /// To use this method to configure log4net you must specify + /// the section + /// handler for the log4net configuration section. See the + /// for an example. + /// + /// + /// The repository to configure. #else - /// - /// Automatically configures the using settings - /// stored in the application's configuration file. - /// - /// - /// - /// Each application has a configuration file. This has the - /// same name as the application with '.config' appended. - /// This file is XML and calling this function prompts the - /// configurator to look in that file for a section called - /// log4net that contains the configuration data. - /// - /// - /// The repository to configure. + /// + /// Automatically configures the using settings + /// stored in the application's configuration file. + /// + /// + /// + /// Each application has a configuration file. This has the + /// same name as the application with '.config' appended. + /// This file is XML and calling this function prompts the + /// configurator to look in that file for a section called + /// log4net that contains the configuration data. + /// + /// + /// The repository to configure. #endif - public static ICollection Configure(ILoggerRepository repository) - { - ArrayList configurationMessages = new ArrayList(); - - using (new LogLog.LogReceivedAdapter(configurationMessages)) - { - InternalConfigure(repository); - } - - repository.ConfigurationMessages = configurationMessages; - - return configurationMessages; - } - - private static void InternalConfigure(ILoggerRepository repository) - { - LogLog.Debug(declaringType, "configuring repository [" + repository.Name + "] using .config file section"); - - try - { - LogLog.Debug(declaringType, "Application config file is [" + SystemInfo.ConfigurationFileLocation + "]"); - } - catch - { - // ignore error - LogLog.Debug(declaringType, "Application config file location unknown"); - } + public static ICollection Configure(ILoggerRepository repository) + { + ArrayList configurationMessages = new ArrayList(); + + using (new LogLog.LogReceivedAdapter(configurationMessages)) + { + InternalConfigure(repository); + } + + repository.ConfigurationMessages = configurationMessages; + + return configurationMessages; + } + + private static void InternalConfigure(ILoggerRepository repository) + { + LogLog.Debug(declaringType, "configuring repository [" + repository.Name + "] using .config file section"); + + try + { + LogLog.Debug(declaringType, "Application config file is [" + SystemInfo.ConfigurationFileLocation + "]"); + } + catch + { + // ignore error + LogLog.Debug(declaringType, "Application config file location unknown"); + } #if NETCF || NETSTANDARD1_3 - // No config file reading stuff. Just go straight for the file - Configure(repository, new FileInfo(SystemInfo.ConfigurationFileLocation)); + // No config file reading stuff. Just go straight for the file + Configure(repository, new FileInfo(SystemInfo.ConfigurationFileLocation)); #else - try - { - XmlElement configElement = System.Configuration.ConfigurationManager.GetSection("log4net") as XmlElement; - if (configElement == null) - { - // Failed to load the xml config using configuration settings handler - LogLog.Error(declaringType, "Failed to find configuration section 'log4net' in the application's .config file. Check your .config file for the and elements. The configuration section should look like:
"); - } - else - { - // Configure using the xml loaded from the config file - InternalConfigureFromXml(repository, configElement); - } - } - catch(System.Configuration.ConfigurationException confEx) - { - if (confEx.BareMessage.IndexOf("Unrecognized element") >= 0) - { - // Looks like the XML file is not valid - LogLog.Error(declaringType, "Failed to parse config file. Check your .config file is well formed XML.", confEx); - } - else - { - // This exception is typically due to the assembly name not being correctly specified in the section type. - string configSectionStr = "
"; - LogLog.Error(declaringType, "Failed to parse config file. Is the specified as: " + configSectionStr, confEx); - } - } + try + { + XmlElement configElement = System.Configuration.ConfigurationManager.GetSection("log4net") as XmlElement; + if (configElement == null) + { + // Failed to load the xml config using configuration settings handler + LogLog.Error(declaringType, "Failed to find configuration section 'log4net' in the application's .config file. Check your .config file for the and elements. The configuration section should look like:
"); + } + else + { + // Configure using the xml loaded from the config file + InternalConfigureFromXml(repository, configElement); + } + } + catch(System.Configuration.ConfigurationException confEx) + { + if (confEx.BareMessage.IndexOf("Unrecognized element") >= 0) + { + // Looks like the XML file is not valid + LogLog.Error(declaringType, "Failed to parse config file. Check your .config file is well formed XML.", confEx); + } + else + { + // This exception is typically due to the assembly name not being correctly specified in the section type. + string configSectionStr = "
"; + LogLog.Error(declaringType, "Failed to parse config file. Is the specified as: " + configSectionStr, confEx); + } + } #endif - } + } #if !NETSTANDARD1_3 // Excluded because GetCallingAssembly() is not available in CoreFX (https://github.com/dotnet/corefx/issues/2221). #if !NETCF - /// - /// Automatically configures the log4net system based on the - /// application's configuration settings. - /// - /// - /// - /// Each application has a configuration file. This has the - /// same name as the application with '.config' appended. - /// This file is XML and calling this function prompts the - /// configurator to look in that file for a section called - /// log4net that contains the configuration data. - /// - /// - /// To use this method to configure log4net you must specify - /// the section - /// handler for the log4net configuration section. See the - /// for an example. - /// - /// - /// + /// + /// Automatically configures the log4net system based on the + /// application's configuration settings. + /// + /// + /// + /// Each application has a configuration file. This has the + /// same name as the application with '.config' appended. + /// This file is XML and calling this function prompts the + /// configurator to look in that file for a section called + /// log4net that contains the configuration data. + /// + /// + /// To use this method to configure log4net you must specify + /// the section + /// handler for the log4net configuration section. See the + /// for an example. + /// + /// + /// #else - /// - /// Automatically configures the log4net system based on the - /// application's configuration settings. - /// - /// - /// - /// Each application has a configuration file. This has the - /// same name as the application with '.config' appended. - /// This file is XML and calling this function prompts the - /// configurator to look in that file for a section called - /// log4net that contains the configuration data. - /// - /// + /// + /// Automatically configures the log4net system based on the + /// application's configuration settings. + /// + /// + /// + /// Each application has a configuration file. This has the + /// same name as the application with '.config' appended. + /// This file is XML and calling this function prompts the + /// configurator to look in that file for a section called + /// log4net that contains the configuration data. + /// + /// #endif - public static ICollection Configure() - { - return Configure(LogManager.GetRepository(Assembly.GetCallingAssembly())); - } - - /// - /// Configures log4net using a log4net element - /// - /// - /// - /// Loads the log4net configuration from the XML element - /// supplied as . - /// - /// - /// The element to parse. - public static ICollection Configure(XmlElement element) - { - ArrayList configurationMessages = new ArrayList(); - - ILoggerRepository repository = LogManager.GetRepository(Assembly.GetCallingAssembly()); - - using (new LogLog.LogReceivedAdapter(configurationMessages)) - { - InternalConfigureFromXml(repository, element); - } - - repository.ConfigurationMessages = configurationMessages; - - return configurationMessages; - } + public static ICollection Configure() + { + return Configure(LogManager.GetRepository(Assembly.GetCallingAssembly())); + } + + /// + /// Configures log4net using a log4net element + /// + /// + /// + /// Loads the log4net configuration from the XML element + /// supplied as . + /// + /// + /// The element to parse. + public static ICollection Configure(XmlElement element) + { + ArrayList configurationMessages = new ArrayList(); + + ILoggerRepository repository = LogManager.GetRepository(Assembly.GetCallingAssembly()); + + using (new LogLog.LogReceivedAdapter(configurationMessages)) + { + InternalConfigureFromXml(repository, element); + } + + repository.ConfigurationMessages = configurationMessages; + + return configurationMessages; + } #if !NETCF - /// - /// Configures log4net using the specified configuration file. - /// - /// The XML file to load the configuration from. - /// - /// - /// The configuration file must be valid XML. It must contain - /// at least one element called log4net that holds - /// the log4net configuration data. - /// - /// - /// The log4net configuration file can possible be specified in the application's - /// configuration file (either MyAppName.exe.config for a - /// normal application on Web.config for an ASP.NET application). - /// - /// - /// The first element matching <configuration> will be read as the - /// configuration. If this file is also a .NET .config file then you must specify - /// a configuration section for the log4net element otherwise .NET will - /// complain. Set the type for the section handler to , for example: - /// - /// - ///
- /// - /// - /// - /// - /// The following example configures log4net using a configuration file, of which the - /// location is stored in the application's configuration file : - /// - /// - /// using log4net.Config; - /// using System.IO; - /// using System.Configuration; - /// - /// ... - /// - /// XmlConfigurator.Configure(new FileInfo(ConfigurationSettings.AppSettings["log4net-config-file"])); - /// - /// - /// In the .config file, the path to the log4net can be specified like this : - /// - /// - /// - /// - /// - /// - /// - /// - /// + /// + /// Configures log4net using the specified configuration file. + /// + /// The XML file to load the configuration from. + /// + /// + /// The configuration file must be valid XML. It must contain + /// at least one element called log4net that holds + /// the log4net configuration data. + /// + /// + /// The log4net configuration file can possible be specified in the application's + /// configuration file (either MyAppName.exe.config for a + /// normal application on Web.config for an ASP.NET application). + /// + /// + /// The first element matching <configuration> will be read as the + /// configuration. If this file is also a .NET .config file then you must specify + /// a configuration section for the log4net element otherwise .NET will + /// complain. Set the type for the section handler to , for example: + /// + /// + ///
+ /// + /// + /// + /// + /// The following example configures log4net using a configuration file, of which the + /// location is stored in the application's configuration file : + /// + /// + /// using log4net.Config; + /// using System.IO; + /// using System.Configuration; + /// + /// ... + /// + /// XmlConfigurator.Configure(new FileInfo(ConfigurationSettings.AppSettings["log4net-config-file"])); + /// + /// + /// In the .config file, the path to the log4net can be specified like this : + /// + /// + /// + /// + /// + /// + /// + /// + /// #else - /// - /// Configures log4net using the specified configuration file. - /// - /// The XML file to load the configuration from. - /// - /// - /// The configuration file must be valid XML. It must contain - /// at least one element called log4net that holds - /// the log4net configuration data. - /// - /// - /// The following example configures log4net using a configuration file, of which the - /// location is stored in the application's configuration file : - /// - /// - /// using log4net.Config; - /// using System.IO; - /// using System.Configuration; - /// - /// ... - /// - /// XmlConfigurator.Configure(new FileInfo(ConfigurationSettings.AppSettings["log4net-config-file"])); - /// - /// - /// In the .config file, the path to the log4net can be specified like this : - /// - /// - /// - /// - /// - /// - /// - /// - /// + /// + /// Configures log4net using the specified configuration file. + /// + /// The XML file to load the configuration from. + /// + /// + /// The configuration file must be valid XML. It must contain + /// at least one element called log4net that holds + /// the log4net configuration data. + /// + /// + /// The following example configures log4net using a configuration file, of which the + /// location is stored in the application's configuration file : + /// + /// + /// using log4net.Config; + /// using System.IO; + /// using System.Configuration; + /// + /// ... + /// + /// XmlConfigurator.Configure(new FileInfo(ConfigurationSettings.AppSettings["log4net-config-file"])); + /// + /// + /// In the .config file, the path to the log4net can be specified like this : + /// + /// + /// + /// + /// + /// + /// + /// + /// #endif - public static ICollection Configure(FileInfo configFile) - { - ArrayList configurationMessages = new ArrayList(); - - using (new LogLog.LogReceivedAdapter(configurationMessages)) - { - InternalConfigure(LogManager.GetRepository(Assembly.GetCallingAssembly()), configFile); - } - - return configurationMessages; - } - - /// - /// Configures log4net using the specified configuration URI. - /// - /// A URI to load the XML configuration from. - /// - /// - /// The configuration data must be valid XML. It must contain - /// at least one element called log4net that holds - /// the log4net configuration data. - /// - /// - /// The must support the URI scheme specified. - /// - /// - public static ICollection Configure(Uri configUri) - { - ArrayList configurationMessages = new ArrayList(); - - ILoggerRepository repository = LogManager.GetRepository(Assembly.GetCallingAssembly()); - using (new LogLog.LogReceivedAdapter(configurationMessages)) - { - InternalConfigure(repository, configUri); - } - - repository.ConfigurationMessages = configurationMessages; - - return configurationMessages; - } - - /// - /// Configures log4net using the specified configuration data stream. - /// - /// A stream to load the XML configuration from. - /// - /// - /// The configuration data must be valid XML. It must contain - /// at least one element called log4net that holds - /// the log4net configuration data. - /// - /// - /// Note that this method will NOT close the stream parameter. - /// - /// - public static ICollection Configure(Stream configStream) - { - ArrayList configurationMessages = new ArrayList(); - - ILoggerRepository repository = LogManager.GetRepository(Assembly.GetCallingAssembly()); - using (new LogLog.LogReceivedAdapter(configurationMessages)) - { - InternalConfigure(repository, configStream); - } - - repository.ConfigurationMessages = configurationMessages; - - return configurationMessages; - } + public static ICollection Configure(FileInfo configFile) + { + ArrayList configurationMessages = new ArrayList(); + + using (new LogLog.LogReceivedAdapter(configurationMessages)) + { + InternalConfigure(LogManager.GetRepository(Assembly.GetCallingAssembly()), configFile); + } + + return configurationMessages; + } + + /// + /// Configures log4net using the specified configuration URI. + /// + /// A URI to load the XML configuration from. + /// + /// + /// The configuration data must be valid XML. It must contain + /// at least one element called log4net that holds + /// the log4net configuration data. + /// + /// + /// The must support the URI scheme specified. + /// + /// + public static ICollection Configure(Uri configUri) + { + ArrayList configurationMessages = new ArrayList(); + + ILoggerRepository repository = LogManager.GetRepository(Assembly.GetCallingAssembly()); + using (new LogLog.LogReceivedAdapter(configurationMessages)) + { + InternalConfigure(repository, configUri); + } + + repository.ConfigurationMessages = configurationMessages; + + return configurationMessages; + } + + /// + /// Configures log4net using the specified configuration data stream. + /// + /// A stream to load the XML configuration from. + /// + /// + /// The configuration data must be valid XML. It must contain + /// at least one element called log4net that holds + /// the log4net configuration data. + /// + /// + /// Note that this method will NOT close the stream parameter. + /// + /// + public static ICollection Configure(Stream configStream) + { + ArrayList configurationMessages = new ArrayList(); + + ILoggerRepository repository = LogManager.GetRepository(Assembly.GetCallingAssembly()); + using (new LogLog.LogReceivedAdapter(configurationMessages)) + { + InternalConfigure(repository, configStream); + } + + repository.ConfigurationMessages = configurationMessages; + + return configurationMessages; + } #endif // !NETSTANDARD1_3 - /// - /// Configures the using the specified XML - /// element. - /// - /// - /// Loads the log4net configuration from the XML element - /// supplied as . - /// - /// The repository to configure. - /// The element to parse. - public static ICollection Configure(ILoggerRepository repository, XmlElement element) - { - ArrayList configurationMessages = new ArrayList(); + /// + /// Configures the using the specified XML + /// element. + /// + /// + /// Loads the log4net configuration from the XML element + /// supplied as . + /// + /// The repository to configure. + /// The element to parse. + public static ICollection Configure(ILoggerRepository repository, XmlElement element) + { + ArrayList configurationMessages = new ArrayList(); - using (new LogLog.LogReceivedAdapter(configurationMessages)) - { - LogLog.Debug(declaringType, "configuring repository [" + repository.Name + "] using XML element"); + using (new LogLog.LogReceivedAdapter(configurationMessages)) + { + LogLog.Debug(declaringType, "configuring repository [" + repository.Name + "] using XML element"); - InternalConfigureFromXml(repository, element); - } + InternalConfigureFromXml(repository, element); + } - repository.ConfigurationMessages = configurationMessages; + repository.ConfigurationMessages = configurationMessages; - return configurationMessages; - } + return configurationMessages; + } #if !NETCF - /// - /// Configures the using the specified configuration - /// file. - /// - /// The repository to configure. - /// The XML file to load the configuration from. - /// - /// - /// The configuration file must be valid XML. It must contain - /// at least one element called log4net that holds - /// the configuration data. - /// - /// - /// The log4net configuration file can possible be specified in the application's - /// configuration file (either MyAppName.exe.config for a - /// normal application on Web.config for an ASP.NET application). - /// - /// - /// The first element matching <configuration> will be read as the - /// configuration. If this file is also a .NET .config file then you must specify - /// a configuration section for the log4net element otherwise .NET will - /// complain. Set the type for the section handler to , for example: - /// - /// - ///
- /// - /// - /// - /// - /// The following example configures log4net using a configuration file, of which the - /// location is stored in the application's configuration file : - /// - /// - /// using log4net.Config; - /// using System.IO; - /// using System.Configuration; - /// - /// ... - /// - /// XmlConfigurator.Configure(new FileInfo(ConfigurationSettings.AppSettings["log4net-config-file"])); - /// - /// - /// In the .config file, the path to the log4net can be specified like this : - /// - /// - /// - /// - /// - /// - /// - /// - /// + /// + /// Configures the using the specified configuration + /// file. + /// + /// The repository to configure. + /// The XML file to load the configuration from. + /// + /// + /// The configuration file must be valid XML. It must contain + /// at least one element called log4net that holds + /// the configuration data. + /// + /// + /// The log4net configuration file can possible be specified in the application's + /// configuration file (either MyAppName.exe.config for a + /// normal application on Web.config for an ASP.NET application). + /// + /// + /// The first element matching <configuration> will be read as the + /// configuration. If this file is also a .NET .config file then you must specify + /// a configuration section for the log4net element otherwise .NET will + /// complain. Set the type for the section handler to , for example: + /// + /// + ///
+ /// + /// + /// + /// + /// The following example configures log4net using a configuration file, of which the + /// location is stored in the application's configuration file : + /// + /// + /// using log4net.Config; + /// using System.IO; + /// using System.Configuration; + /// + /// ... + /// + /// XmlConfigurator.Configure(new FileInfo(ConfigurationSettings.AppSettings["log4net-config-file"])); + /// + /// + /// In the .config file, the path to the log4net can be specified like this : + /// + /// + /// + /// + /// + /// + /// + /// + /// #else - /// - /// Configures the using the specified configuration - /// file. - /// - /// The repository to configure. - /// The XML file to load the configuration from. - /// - /// - /// The configuration file must be valid XML. It must contain - /// at least one element called log4net that holds - /// the configuration data. - /// - /// - /// The following example configures log4net using a configuration file, of which the - /// location is stored in the application's configuration file : - /// - /// - /// using log4net.Config; - /// using System.IO; - /// using System.Configuration; - /// - /// ... - /// - /// XmlConfigurator.Configure(new FileInfo(ConfigurationSettings.AppSettings["log4net-config-file"])); - /// - /// - /// In the .config file, the path to the log4net can be specified like this : - /// - /// - /// - /// - /// - /// - /// - /// - /// + /// + /// Configures the using the specified configuration + /// file. + /// + /// The repository to configure. + /// The XML file to load the configuration from. + /// + /// + /// The configuration file must be valid XML. It must contain + /// at least one element called log4net that holds + /// the configuration data. + /// + /// + /// The following example configures log4net using a configuration file, of which the + /// location is stored in the application's configuration file : + /// + /// + /// using log4net.Config; + /// using System.IO; + /// using System.Configuration; + /// + /// ... + /// + /// XmlConfigurator.Configure(new FileInfo(ConfigurationSettings.AppSettings["log4net-config-file"])); + /// + /// + /// In the .config file, the path to the log4net can be specified like this : + /// + /// + /// + /// + /// + /// + /// + /// + /// #endif - public static ICollection Configure(ILoggerRepository repository, FileInfo configFile) - { - ArrayList configurationMessages = new ArrayList(); - - using (new LogLog.LogReceivedAdapter(configurationMessages)) - { - InternalConfigure(repository, configFile); - } - - repository.ConfigurationMessages = configurationMessages; - - return configurationMessages; - } - - private static void InternalConfigure(ILoggerRepository repository, FileInfo configFile) - { - LogLog.Debug(declaringType, "configuring repository [" + repository.Name + "] using file [" + configFile + "]"); - - if (configFile == null) - { - LogLog.Error(declaringType, "Configure called with null 'configFile' parameter"); - } - else - { - // Have to use File.Exists() rather than configFile.Exists() - // because configFile.Exists() caches the value, not what we want. - if (File.Exists(configFile.FullName)) - { - // Open the file for reading - FileStream fs = null; - - // Try hard to open the file - for(int retry = 5; --retry >= 0; ) - { - try - { - fs = configFile.Open(FileMode.Open, FileAccess.Read, FileShare.Read); - break; - } - catch(IOException ex) - { - if (retry == 0) - { - LogLog.Error(declaringType, "Failed to open XML config file [" + configFile.Name + "]", ex); - - // The stream cannot be valid - fs = null; - } - System.Threading.Thread.Sleep(250); - } - } - - if (fs != null) - { - try - { - // Load the configuration from the stream - InternalConfigure(repository, fs); - } - finally - { - // Force the file closed whatever happens - fs.Dispose(); - } - } - } - else - { - LogLog.Debug(declaringType, "config file [" + configFile.FullName + "] not found. Configuration unchanged."); - } - } - } - - /// - /// Configures the using the specified configuration - /// URI. - /// - /// The repository to configure. - /// A URI to load the XML configuration from. - /// - /// - /// The configuration data must be valid XML. It must contain - /// at least one element called log4net that holds - /// the configuration data. - /// - /// - /// The must support the URI scheme specified. - /// - /// - public static ICollection Configure(ILoggerRepository repository, Uri configUri) - { - ArrayList configurationMessages = new ArrayList(); - - using (new LogLog.LogReceivedAdapter(configurationMessages)) - { - InternalConfigure(repository, configUri); - } - - repository.ConfigurationMessages = configurationMessages; - - return configurationMessages; - } - - private static void InternalConfigure(ILoggerRepository repository, Uri configUri) - { - LogLog.Debug(declaringType, "configuring repository [" + repository.Name + "] using URI ["+configUri+"]"); - - if (configUri == null) - { - LogLog.Error(declaringType, "Configure called with null 'configUri' parameter"); - } - else - { - if (configUri.IsFile) - { - // If URI is local file then call Configure with FileInfo - InternalConfigure(repository, new FileInfo(configUri.LocalPath)); - } - else - { - // NETCF dose not support WebClient - WebRequest configRequest = null; - - try - { - configRequest = WebRequest.Create(configUri); - } - catch(Exception ex) - { - LogLog.Error(declaringType, "Failed to create WebRequest for URI ["+configUri+"]", ex); - } - - if (configRequest != null) - { + public static ICollection Configure(ILoggerRepository repository, FileInfo configFile) + { + ArrayList configurationMessages = new ArrayList(); + + using (new LogLog.LogReceivedAdapter(configurationMessages)) + { + InternalConfigure(repository, configFile); + } + + repository.ConfigurationMessages = configurationMessages; + + return configurationMessages; + } + + private static void InternalConfigure(ILoggerRepository repository, FileInfo configFile) + { + LogLog.Debug(declaringType, "configuring repository [" + repository.Name + "] using file [" + configFile + "]"); + + if (configFile == null) + { + LogLog.Error(declaringType, "Configure called with null 'configFile' parameter"); + } + else + { + // Have to use File.Exists() rather than configFile.Exists() + // because configFile.Exists() caches the value, not what we want. + if (File.Exists(configFile.FullName)) + { + // Open the file for reading + FileStream fs = null; + + // Try hard to open the file + for(int retry = 5; --retry >= 0; ) + { + try + { + fs = configFile.Open(FileMode.Open, FileAccess.Read, FileShare.Read); + break; + } + catch(IOException ex) + { + if (retry == 0) + { + LogLog.Error(declaringType, "Failed to open XML config file [" + configFile.Name + "]", ex); + + // The stream cannot be valid + fs = null; + } + System.Threading.Thread.Sleep(250); + } + } + + if (fs != null) + { + try + { + // Load the configuration from the stream + InternalConfigure(repository, fs); + } + finally + { + // Force the file closed whatever happens + fs.Dispose(); + } + } + } + else + { + LogLog.Debug(declaringType, "config file [" + configFile.FullName + "] not found. Configuration unchanged."); + } + } + } + + /// + /// Configures the using the specified configuration + /// URI. + /// + /// The repository to configure. + /// A URI to load the XML configuration from. + /// + /// + /// The configuration data must be valid XML. It must contain + /// at least one element called log4net that holds + /// the configuration data. + /// + /// + /// The must support the URI scheme specified. + /// + /// + public static ICollection Configure(ILoggerRepository repository, Uri configUri) + { + ArrayList configurationMessages = new ArrayList(); + + using (new LogLog.LogReceivedAdapter(configurationMessages)) + { + InternalConfigure(repository, configUri); + } + + repository.ConfigurationMessages = configurationMessages; + + return configurationMessages; + } + + private static void InternalConfigure(ILoggerRepository repository, Uri configUri) + { + LogLog.Debug(declaringType, "configuring repository [" + repository.Name + "] using URI ["+configUri+"]"); + + if (configUri == null) + { + LogLog.Error(declaringType, "Configure called with null 'configUri' parameter"); + } + else + { + if (configUri.IsFile) + { + // If URI is local file then call Configure with FileInfo + InternalConfigure(repository, new FileInfo(configUri.LocalPath)); + } + else + { + // NETCF dose not support WebClient + WebRequest configRequest = null; + + try + { + configRequest = WebRequest.Create(configUri); + } + catch(Exception ex) + { + LogLog.Error(declaringType, "Failed to create WebRequest for URI ["+configUri+"]", ex); + } + + if (configRequest != null) + { #if !NETCF_1_0 - // authentication may be required, set client to use default credentials - try - { - configRequest.Credentials = CredentialCache.DefaultCredentials; - } - catch - { - // ignore security exception - } + // authentication may be required, set client to use default credentials + try + { + configRequest.Credentials = CredentialCache.DefaultCredentials; + } + catch + { + // ignore security exception + } #endif - try - { + try + { #if NETSTANDARD - using WebResponse response = configRequest.GetResponseAsync().GetAwaiter().GetResult(); + using WebResponse response = configRequest.GetResponseAsync().GetAwaiter().GetResult(); #else - using WebResponse response = configRequest.GetResponse(); + using WebResponse response = configRequest.GetResponse(); #endif - if (response != null) - { - using var configStream = response.GetResponseStream(); - InternalConfigure(repository, configStream); - } - } - catch(Exception ex) - { - LogLog.Error(declaringType, "Failed to request config from URI ["+configUri+"]", ex); - } - } - } - } - } - - /// - /// Configures the using the specified configuration - /// file. - /// - /// The repository to configure. - /// The stream to load the XML configuration from. - /// - /// - /// The configuration data must be valid XML. It must contain - /// at least one element called log4net that holds - /// the configuration data. - /// - /// - /// Note that this method will NOT close the stream parameter. - /// - /// - public static ICollection Configure(ILoggerRepository repository, Stream configStream) - { - ArrayList configurationMessages = new ArrayList(); - - using (new LogLog.LogReceivedAdapter(configurationMessages)) - { - InternalConfigure(repository, configStream); - } - - repository.ConfigurationMessages = configurationMessages; - - return configurationMessages; - } - - private static void InternalConfigure(ILoggerRepository repository, Stream configStream) - { - LogLog.Debug(declaringType, "configuring repository [" + repository.Name + "] using stream"); - - if (configStream == null) - { - LogLog.Error(declaringType, "Configure called with null 'configStream' parameter"); - } - else - { - // Load the config file into a document + if (response != null) + { + using var configStream = response.GetResponseStream(); + InternalConfigure(repository, configStream); + } + } + catch(Exception ex) + { + LogLog.Error(declaringType, "Failed to request config from URI ["+configUri+"]", ex); + } + } + } + } + } + + /// + /// Configures the using the specified configuration + /// file. + /// + /// The repository to configure. + /// The stream to load the XML configuration from. + /// + /// + /// The configuration data must be valid XML. It must contain + /// at least one element called log4net that holds + /// the configuration data. + /// + /// + /// Note that this method will NOT close the stream parameter. + /// + /// + public static ICollection Configure(ILoggerRepository repository, Stream configStream) + { + ArrayList configurationMessages = new ArrayList(); + + using (new LogLog.LogReceivedAdapter(configurationMessages)) + { + InternalConfigure(repository, configStream); + } + + repository.ConfigurationMessages = configurationMessages; + + return configurationMessages; + } + + private static void InternalConfigure(ILoggerRepository repository, Stream configStream) + { + LogLog.Debug(declaringType, "configuring repository [" + repository.Name + "] using stream"); + + if (configStream == null) + { + LogLog.Error(declaringType, "Configure called with null 'configStream' parameter"); + } + else + { + // Load the config file into a document #if NETSTANDARD1_3 - XmlDocument doc = new XmlDocument(); + XmlDocument doc = new XmlDocument(); #else - XmlDocument doc = new XmlDocument { XmlResolver = null }; + XmlDocument doc = new XmlDocument { XmlResolver = null }; #endif - try - { + try + { #if (NETCF) - // Create a text reader for the file stream - XmlTextReader xmlReader = new XmlTextReader(configStream); + // Create a text reader for the file stream + XmlTextReader xmlReader = new XmlTextReader(configStream); #elif NET_2_0 || NETSTANDARD - // Allow the DTD to specify entity includes - XmlReaderSettings settings = new XmlReaderSettings(); - // .NET 4.0 warning CS0618: 'System.Xml.XmlReaderSettings.ProhibitDtd' - // is obsolete: 'Use XmlReaderSettings.DtdProcessing property instead.' + // Allow the DTD to specify entity includes + XmlReaderSettings settings = new XmlReaderSettings(); + // .NET 4.0 warning CS0618: 'System.Xml.XmlReaderSettings.ProhibitDtd' + // is obsolete: 'Use XmlReaderSettings.DtdProcessing property instead.' #if NETSTANDARD1_3 // TODO DtdProcessing.Parse not yet available (https://github.com/dotnet/corefx/issues/4376) - settings.DtdProcessing = DtdProcessing.Ignore; + settings.DtdProcessing = DtdProcessing.Ignore; #elif !NET_4_0 && !MONO_4_0 && !NETSTANDARD2_0 - settings.ProhibitDtd = true; + settings.ProhibitDtd = true; #else - settings.DtdProcessing = DtdProcessing.Ignore; + settings.DtdProcessing = DtdProcessing.Ignore; #endif - // Create a reader over the input stream - using XmlReader xmlReader = XmlReader.Create(configStream, settings); + // Create a reader over the input stream + using XmlReader xmlReader = XmlReader.Create(configStream, settings); #else - // Create a validating reader around a text reader for the file stream - using XmlValidatingReader xmlReader = new XmlValidatingReader(new XmlTextReader(configStream)); + // Create a validating reader around a text reader for the file stream + using XmlValidatingReader xmlReader = new XmlValidatingReader(new XmlTextReader(configStream)); - // Specify that the reader should not perform validation, but that it should - // expand entity refs. - xmlReader.ValidationType = ValidationType.None; - xmlReader.EntityHandling = EntityHandling.ExpandEntities; + // Specify that the reader should not perform validation, but that it should + // expand entity refs. + xmlReader.ValidationType = ValidationType.None; + xmlReader.EntityHandling = EntityHandling.ExpandEntities; #endif - // load the data into the document - doc.Load(xmlReader); - } - catch(Exception ex) - { - LogLog.Error(declaringType, "Error while loading XML configuration", ex); - - // The document is invalid - doc = null; - } - - if (doc != null) - { - LogLog.Debug(declaringType, "loading XML configuration"); - - // Configure using the 'log4net' element - XmlNodeList configNodeList = doc.GetElementsByTagName("log4net"); - if (configNodeList.Count == 0) - { - LogLog.Debug(declaringType, "XML configuration does not contain a element. Configuration Aborted."); - } - else if (configNodeList.Count > 1) - { - LogLog.Error(declaringType, "XML configuration contains [" + configNodeList.Count + "] elements. Only one is allowed. Configuration Aborted."); - } - else - { - InternalConfigureFromXml(repository, configNodeList[0] as XmlElement); - } - } - } - } - - #endregion Configure static methods - - #region ConfigureAndWatch static methods + // load the data into the document + doc.Load(xmlReader); + } + catch(Exception ex) + { + LogLog.Error(declaringType, "Error while loading XML configuration", ex); + + // The document is invalid + doc = null; + } + + if (doc != null) + { + LogLog.Debug(declaringType, "loading XML configuration"); + + // Configure using the 'log4net' element + XmlNodeList configNodeList = doc.GetElementsByTagName("log4net"); + if (configNodeList.Count == 0) + { + LogLog.Debug(declaringType, "XML configuration does not contain a element. Configuration Aborted."); + } + else if (configNodeList.Count > 1) + { + LogLog.Error(declaringType, "XML configuration contains [" + configNodeList.Count + "] elements. Only one is allowed. Configuration Aborted."); + } + else + { + InternalConfigureFromXml(repository, configNodeList[0] as XmlElement); + } + } + } + } + + #endregion Configure static methods + + #region ConfigureAndWatch static methods #if (!NETCF && !SSCLI) #if !NETSTANDARD1_3 // Excluded because GetCallingAssembly() is not available in CoreFX (https://github.com/dotnet/corefx/issues/2221). - /// - /// Configures log4net using the file specified, monitors the file for changes - /// and reloads the configuration if a change is detected. - /// - /// The XML file to load the configuration from. - /// - /// - /// The configuration file must be valid XML. It must contain - /// at least one element called log4net that holds - /// the configuration data. - /// - /// - /// The configuration file will be monitored using a - /// and depends on the behavior of that class. - /// - /// - /// For more information on how to configure log4net using - /// a separate configuration file, see . - /// - /// - /// - public static ICollection ConfigureAndWatch(FileInfo configFile) - { - ArrayList configurationMessages = new ArrayList(); - - ILoggerRepository repository = LogManager.GetRepository(Assembly.GetCallingAssembly()); - - using (new LogLog.LogReceivedAdapter(configurationMessages)) - { - InternalConfigureAndWatch(repository, configFile); - } - - repository.ConfigurationMessages = configurationMessages; - - return configurationMessages; - } + /// + /// Configures log4net using the file specified, monitors the file for changes + /// and reloads the configuration if a change is detected. + /// + /// The XML file to load the configuration from. + /// + /// + /// The configuration file must be valid XML. It must contain + /// at least one element called log4net that holds + /// the configuration data. + /// + /// + /// The configuration file will be monitored using a + /// and depends on the behavior of that class. + /// + /// + /// For more information on how to configure log4net using + /// a separate configuration file, see . + /// + /// + /// + public static ICollection ConfigureAndWatch(FileInfo configFile) + { + ArrayList configurationMessages = new ArrayList(); + + ILoggerRepository repository = LogManager.GetRepository(Assembly.GetCallingAssembly()); + + using (new LogLog.LogReceivedAdapter(configurationMessages)) + { + InternalConfigureAndWatch(repository, configFile); + } + + repository.ConfigurationMessages = configurationMessages; + + return configurationMessages; + } #endif // !NETSTANDARD1_3 - /// - /// Configures the using the file specified, - /// monitors the file for changes and reloads the configuration if a change - /// is detected. - /// - /// The repository to configure. - /// The XML file to load the configuration from. - /// - /// - /// The configuration file must be valid XML. It must contain - /// at least one element called log4net that holds - /// the configuration data. - /// - /// - /// The configuration file will be monitored using a - /// and depends on the behavior of that class. - /// - /// - /// For more information on how to configure log4net using - /// a separate configuration file, see . - /// - /// - /// - public static ICollection ConfigureAndWatch(ILoggerRepository repository, FileInfo configFile) - { - ArrayList configurationMessages = new ArrayList(); - - using (new LogLog.LogReceivedAdapter(configurationMessages)) - { - InternalConfigureAndWatch(repository, configFile); - } - - repository.ConfigurationMessages = configurationMessages; - - return configurationMessages; - } - - private static void InternalConfigureAndWatch(ILoggerRepository repository, FileInfo configFile) - { - LogLog.Debug(declaringType, "configuring repository [" + repository.Name + "] using file [" + configFile + "] watching for file updates"); - - if (configFile == null) - { - LogLog.Error(declaringType, "ConfigureAndWatch called with null 'configFile' parameter"); - } - else - { - // Configure log4net now - InternalConfigure(repository, configFile); - - try - { - lock (m_repositoryName2ConfigAndWatchHandler) - { - // support multiple repositories each having their own watcher - ConfigureAndWatchHandler handler = - (ConfigureAndWatchHandler)m_repositoryName2ConfigAndWatchHandler[configFile.FullName]; - - if (handler != null) - { - m_repositoryName2ConfigAndWatchHandler.Remove(configFile.FullName); - handler.Dispose(); - } - - // Create and start a watch handler that will reload the - // configuration whenever the config file is modified. - handler = new ConfigureAndWatchHandler(repository, configFile); - m_repositoryName2ConfigAndWatchHandler[configFile.FullName] = handler; - } - } - catch(Exception ex) - { - LogLog.Error(declaringType, "Failed to initialize configuration file watcher for file ["+configFile.FullName+"]", ex); - } - } - } + /// + /// Configures the using the file specified, + /// monitors the file for changes and reloads the configuration if a change + /// is detected. + /// + /// The repository to configure. + /// The XML file to load the configuration from. + /// + /// + /// The configuration file must be valid XML. It must contain + /// at least one element called log4net that holds + /// the configuration data. + /// + /// + /// The configuration file will be monitored using a + /// and depends on the behavior of that class. + /// + /// + /// For more information on how to configure log4net using + /// a separate configuration file, see . + /// + /// + /// + public static ICollection ConfigureAndWatch(ILoggerRepository repository, FileInfo configFile) + { + ArrayList configurationMessages = new ArrayList(); + + using (new LogLog.LogReceivedAdapter(configurationMessages)) + { + InternalConfigureAndWatch(repository, configFile); + } + + repository.ConfigurationMessages = configurationMessages; + + return configurationMessages; + } + + private static void InternalConfigureAndWatch(ILoggerRepository repository, FileInfo configFile) + { + LogLog.Debug(declaringType, "configuring repository [" + repository.Name + "] using file [" + configFile + "] watching for file updates"); + + if (configFile == null) + { + LogLog.Error(declaringType, "ConfigureAndWatch called with null 'configFile' parameter"); + } + else + { + // Configure log4net now + InternalConfigure(repository, configFile); + + try + { + lock (m_repositoryName2ConfigAndWatchHandler) + { + // support multiple repositories each having their own watcher + ConfigureAndWatchHandler handler = + (ConfigureAndWatchHandler)m_repositoryName2ConfigAndWatchHandler[configFile.FullName]; + + if (handler != null) + { + m_repositoryName2ConfigAndWatchHandler.Remove(configFile.FullName); + handler.Dispose(); + } + + // Create and start a watch handler that will reload the + // configuration whenever the config file is modified. + handler = new ConfigureAndWatchHandler(repository, configFile); + m_repositoryName2ConfigAndWatchHandler[configFile.FullName] = handler; + } + } + catch(Exception ex) + { + LogLog.Error(declaringType, "Failed to initialize configuration file watcher for file ["+configFile.FullName+"]", ex); + } + } + } #endif - #endregion ConfigureAndWatch static methods + #endregion ConfigureAndWatch static methods - #region ConfigureAndWatchHandler + #region ConfigureAndWatchHandler #if (!NETCF && !SSCLI) - /// - /// Class used to watch config files. - /// - /// - /// - /// Uses the to monitor - /// changes to a specified file. Because multiple change notifications - /// may be raised when the file is modified, a timer is used to - /// compress the notifications into a single event. The timer - /// waits for time before delivering - /// the event notification. If any further - /// change notifications arrive while the timer is waiting it - /// is reset and waits again for to - /// elapse. - /// - /// - private sealed class ConfigureAndWatchHandler : IDisposable - { - /// - /// Holds the FileInfo used to configure the XmlConfigurator - /// - private FileInfo m_configFile; - - /// - /// Holds the repository being configured. - /// - private ILoggerRepository m_repository; - - /// - /// The timer used to compress the notification events. - /// - private Timer m_timer; - - /// - /// The default amount of time to wait after receiving notification - /// before reloading the config file. - /// - private const int TimeoutMillis = 500; - - /// - /// Watches file for changes. This object should be disposed when no longer - /// needed to free system handles on the watched resources. - /// - private FileSystemWatcher m_watcher; - - /// - /// Initializes a new instance of the class to - /// watch a specified config file used to configure a repository. - /// - /// The repository to configure. - /// The configuration file to watch. - /// - /// - /// Initializes a new instance of the class. - /// - /// + /// + /// Class used to watch config files. + /// + /// + /// + /// Uses the to monitor + /// changes to a specified file. Because multiple change notifications + /// may be raised when the file is modified, a timer is used to + /// compress the notifications into a single event. The timer + /// waits for time before delivering + /// the event notification. If any further + /// change notifications arrive while the timer is waiting it + /// is reset and waits again for to + /// elapse. + /// + /// + private sealed class ConfigureAndWatchHandler : IDisposable + { + /// + /// Holds the FileInfo used to configure the XmlConfigurator + /// + private FileInfo m_configFile; + + /// + /// Holds the repository being configured. + /// + private ILoggerRepository m_repository; + + /// + /// The timer used to compress the notification events. + /// + private Timer m_timer; + + /// + /// The default amount of time to wait after receiving notification + /// before reloading the config file. + /// + private const int TimeoutMillis = 500; + + /// + /// Watches file for changes. This object should be disposed when no longer + /// needed to free system handles on the watched resources. + /// + private FileSystemWatcher m_watcher; + + /// + /// Initializes a new instance of the class to + /// watch a specified config file used to configure a repository. + /// + /// The repository to configure. + /// The configuration file to watch. + /// + /// + /// Initializes a new instance of the class. + /// + /// #if NET_4_0 || MONO_4_0 || NETSTANDARD - [System.Security.SecuritySafeCritical] + [System.Security.SecuritySafeCritical] #endif - public ConfigureAndWatchHandler(ILoggerRepository repository, FileInfo configFile) - { - m_repository = repository; - m_configFile = configFile; - - // Create a new FileSystemWatcher and set its properties. - m_watcher = new FileSystemWatcher(); - - m_watcher.Path = m_configFile.DirectoryName; - m_watcher.Filter = m_configFile.Name; - - // Set the notification filters - m_watcher.NotifyFilter = NotifyFilters.CreationTime | NotifyFilters.LastWrite | NotifyFilters.FileName; - - // Add event handlers. OnChanged will do for all event handlers that fire a FileSystemEventArgs - m_watcher.Changed += new FileSystemEventHandler(ConfigureAndWatchHandler_OnChanged); - m_watcher.Created += new FileSystemEventHandler(ConfigureAndWatchHandler_OnChanged); - m_watcher.Deleted += new FileSystemEventHandler(ConfigureAndWatchHandler_OnChanged); - m_watcher.Renamed += new RenamedEventHandler(ConfigureAndWatchHandler_OnRenamed); - - // Begin watching. - m_watcher.EnableRaisingEvents = true; - - // Create the timer that will be used to deliver events. Set as disabled - m_timer = new Timer(new TimerCallback(OnWatchedFileChange), null, Timeout.Infinite, Timeout.Infinite); - } - - /// - /// Event handler used by . - /// - /// The firing the event. - /// The argument indicates the file that caused the event to be fired. - /// - /// - /// This handler reloads the configuration from the file when the event is fired. - /// - /// - private void ConfigureAndWatchHandler_OnChanged(object source, FileSystemEventArgs e) - { - LogLog.Debug(declaringType, "ConfigureAndWatchHandler: "+e.ChangeType+" [" + m_configFile.FullName + "]"); - - // Deliver the event in TimeoutMillis time - // timer will fire only once - m_timer.Change(TimeoutMillis, Timeout.Infinite); - } - - /// - /// Event handler used by . - /// - /// The firing the event. - /// The argument indicates the file that caused the event to be fired. - /// - /// - /// This handler reloads the configuration from the file when the event is fired. - /// - /// - private void ConfigureAndWatchHandler_OnRenamed(object source, RenamedEventArgs e) - { - LogLog.Debug(declaringType, "ConfigureAndWatchHandler: " + e.ChangeType + " [" + m_configFile.FullName + "]"); - - // Deliver the event in TimeoutMillis time - // timer will fire only once - m_timer.Change(TimeoutMillis, Timeout.Infinite); - } - - /// - /// Called by the timer when the configuration has been updated. - /// - /// null - private void OnWatchedFileChange(object state) - { - XmlConfigurator.InternalConfigure(m_repository, m_configFile); - } - - /// - /// Release the handles held by the watcher and timer. - /// + public ConfigureAndWatchHandler(ILoggerRepository repository, FileInfo configFile) + { + m_repository = repository; + m_configFile = configFile; + + // Create a new FileSystemWatcher and set its properties. + m_watcher = new FileSystemWatcher(); + + m_watcher.Path = m_configFile.DirectoryName; + m_watcher.Filter = m_configFile.Name; + + // Set the notification filters + m_watcher.NotifyFilter = NotifyFilters.CreationTime | NotifyFilters.LastWrite | NotifyFilters.FileName; + + // Add event handlers. OnChanged will do for all event handlers that fire a FileSystemEventArgs + m_watcher.Changed += new FileSystemEventHandler(ConfigureAndWatchHandler_OnChanged); + m_watcher.Created += new FileSystemEventHandler(ConfigureAndWatchHandler_OnChanged); + m_watcher.Deleted += new FileSystemEventHandler(ConfigureAndWatchHandler_OnChanged); + m_watcher.Renamed += new RenamedEventHandler(ConfigureAndWatchHandler_OnRenamed); + + // Begin watching. + m_watcher.EnableRaisingEvents = true; + + // Create the timer that will be used to deliver events. Set as disabled + m_timer = new Timer(new TimerCallback(OnWatchedFileChange), null, Timeout.Infinite, Timeout.Infinite); + } + + /// + /// Event handler used by . + /// + /// The firing the event. + /// The argument indicates the file that caused the event to be fired. + /// + /// + /// This handler reloads the configuration from the file when the event is fired. + /// + /// + private void ConfigureAndWatchHandler_OnChanged(object source, FileSystemEventArgs e) + { + LogLog.Debug(declaringType, "ConfigureAndWatchHandler: "+e.ChangeType+" [" + m_configFile.FullName + "]"); + + // Deliver the event in TimeoutMillis time + // timer will fire only once + m_timer.Change(TimeoutMillis, Timeout.Infinite); + } + + /// + /// Event handler used by . + /// + /// The firing the event. + /// The argument indicates the file that caused the event to be fired. + /// + /// + /// This handler reloads the configuration from the file when the event is fired. + /// + /// + private void ConfigureAndWatchHandler_OnRenamed(object source, RenamedEventArgs e) + { + LogLog.Debug(declaringType, "ConfigureAndWatchHandler: " + e.ChangeType + " [" + m_configFile.FullName + "]"); + + // Deliver the event in TimeoutMillis time + // timer will fire only once + m_timer.Change(TimeoutMillis, Timeout.Infinite); + } + + /// + /// Called by the timer when the configuration has been updated. + /// + /// null + private void OnWatchedFileChange(object state) + { + XmlConfigurator.InternalConfigure(m_repository, m_configFile); + } + + /// + /// Release the handles held by the watcher and timer. + /// #if NET_4_0 || MONO_4_0 || NETSTANDARD - [System.Security.SecuritySafeCritical] + [System.Security.SecuritySafeCritical] #endif - public void Dispose() - { - m_watcher.EnableRaisingEvents = false; - m_watcher.Dispose(); - m_timer.Dispose(); - } - } + public void Dispose() + { + m_watcher.EnableRaisingEvents = false; + m_watcher.Dispose(); + m_timer.Dispose(); + } + } #endif - #endregion ConfigureAndWatchHandler - - #region Private Static Methods - - /// - /// Configures the specified repository using a log4net element. - /// - /// The hierarchy to configure. - /// The element to parse. - /// - /// - /// Loads the log4net configuration from the XML element - /// supplied as . - /// - /// - /// This method is ultimately called by one of the Configure methods - /// to load the configuration from an . - /// - /// - private static void InternalConfigureFromXml(ILoggerRepository repository, XmlElement element) - { - if (element == null) - { - LogLog.Error(declaringType, "ConfigureFromXml called with null 'element' parameter"); - } - else if (repository == null) - { - LogLog.Error(declaringType, "ConfigureFromXml called with null 'repository' parameter"); - } - else - { - LogLog.Debug(declaringType, "Configuring Repository [" + repository.Name + "]"); - - IXmlRepositoryConfigurator configurableRepository = repository as IXmlRepositoryConfigurator; - if (configurableRepository == null) - { - LogLog.Warn(declaringType, "Repository [" + repository + "] does not support the XmlConfigurator"); - } - else - { - // Copy the xml data into the root of a new document - // this isolates the xml config data from the rest of - // the document + #endregion ConfigureAndWatchHandler + + #region Private Static Methods + + /// + /// Configures the specified repository using a log4net element. + /// + /// The hierarchy to configure. + /// The element to parse. + /// + /// + /// Loads the log4net configuration from the XML element + /// supplied as . + /// + /// + /// This method is ultimately called by one of the Configure methods + /// to load the configuration from an . + /// + /// + private static void InternalConfigureFromXml(ILoggerRepository repository, XmlElement element) + { + if (element == null) + { + LogLog.Error(declaringType, "ConfigureFromXml called with null 'element' parameter"); + } + else if (repository == null) + { + LogLog.Error(declaringType, "ConfigureFromXml called with null 'repository' parameter"); + } + else + { + LogLog.Debug(declaringType, "Configuring Repository [" + repository.Name + "]"); + + IXmlRepositoryConfigurator configurableRepository = repository as IXmlRepositoryConfigurator; + if (configurableRepository == null) + { + LogLog.Warn(declaringType, "Repository [" + repository + "] does not support the XmlConfigurator"); + } + else + { + // Copy the xml data into the root of a new document + // this isolates the xml config data from the rest of + // the document #if NETSTANDARD1_3 - XmlDocument newDoc = new XmlDocument(); + XmlDocument newDoc = new XmlDocument(); #else - XmlDocument newDoc = new XmlDocument { XmlResolver = null }; + XmlDocument newDoc = new XmlDocument { XmlResolver = null }; #endif - XmlElement newElement = (XmlElement)newDoc.AppendChild(newDoc.ImportNode(element, true)); - - // Pass the configurator the config element - configurableRepository.Configure(newElement); - } - } - } - - #endregion Private Static Methods - - #region Private Static Fields - - /// - /// Maps repository names to ConfigAndWatchHandler instances to allow a particular - /// ConfigAndWatchHandler to dispose of its FileSystemWatcher when a repository is - /// reconfigured. - /// - private static readonly Hashtable m_repositoryName2ConfigAndWatchHandler = new Hashtable(); - - /// - /// The fully qualified type of the XmlConfigurator class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(XmlConfigurator); - - #endregion Private Static Fields - } + XmlElement newElement = (XmlElement)newDoc.AppendChild(newDoc.ImportNode(element, true)); + + // Pass the configurator the config element + configurableRepository.Configure(newElement); + } + } + } + + #endregion Private Static Methods + + #region Private Static Fields + + /// + /// Maps repository names to ConfigAndWatchHandler instances to allow a particular + /// ConfigAndWatchHandler to dispose of its FileSystemWatcher when a repository is + /// reconfigured. + /// + private static readonly Hashtable m_repositoryName2ConfigAndWatchHandler = new Hashtable(); + + /// + /// The fully qualified type of the XmlConfigurator class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(XmlConfigurator); + + #endregion Private Static Fields + } } diff --git a/src/log4net/Config/XmlConfiguratorAttribute.cs b/src/log4net/Config/XmlConfiguratorAttribute.cs index b5cc702f..4fa93fa6 100644 --- a/src/log4net/Config/XmlConfiguratorAttribute.cs +++ b/src/log4net/Config/XmlConfiguratorAttribute.cs @@ -31,173 +31,173 @@ namespace log4net.Config { - /// - /// Assembly level attribute to configure the . - /// - /// - /// - /// This attribute may only be used at the assembly scope and can only - /// be used once per assembly. - /// - /// - /// Use this attribute to configure the - /// without calling one of the - /// methods. - /// - /// - /// If neither of the or - /// properties are set the configuration is loaded from the application's .config file. - /// If set the property takes priority over the - /// property. The property - /// specifies a path to a file to load the config from. The path is relative to the - /// application's base directory; . - /// The property is used as a postfix to the assembly file name. - /// The config file must be located in the application's base directory; . - /// For example in a console application setting the to - /// config has the same effect as not specifying the or - /// properties. - /// - /// - /// The property can be set to cause the - /// to watch the configuration file for changes. - /// - /// - /// - /// Log4net will only look for assembly level configuration attributes once. - /// When using the log4net assembly level attributes to control the configuration - /// of log4net you must ensure that the first call to any of the - /// methods is made from the assembly with the configuration - /// attributes. - /// - /// - /// If you cannot guarantee the order in which log4net calls will be made from - /// different assemblies you must use programmatic configuration instead, i.e. - /// call the method directly. - /// - /// - /// - /// Nicko Cadell - /// Gert Driesen - [AttributeUsage(AttributeTargets.Assembly)] - [Serializable] - public /*sealed*/ class XmlConfiguratorAttribute : ConfiguratorAttribute - { - // - // Class is not sealed because DOMConfiguratorAttribute extends it while it is obsoleted - // - - /// - /// Default constructor - /// - /// - /// - /// Default constructor - /// - /// - public XmlConfiguratorAttribute() : base(0) /* configurator priority 0 */ - { - } - - #region Public Instance Properties - - /// - /// Gets or sets the filename of the configuration file. - /// - /// - /// The filename of the configuration file. - /// - /// - /// - /// If specified, this is the name of the configuration file to use with - /// the . This file path is relative to the - /// application base directory (). - /// - /// - /// The takes priority over the . - /// - /// - public string ConfigFile - { - get { return m_configFile; } - set { m_configFile = value; } - } - - /// - /// Gets or sets the extension of the configuration file. - /// - /// - /// The extension of the configuration file. - /// - /// - /// - /// If specified this is the extension for the configuration file. - /// The path to the config file is built by using the application - /// base directory (), - /// the assembly file name and the config file extension. - /// - /// - /// If the is set to MyExt then - /// possible config file names would be: MyConsoleApp.exe.MyExt or - /// MyClassLibrary.dll.MyExt. - /// - /// - /// The takes priority over the . - /// - /// - public string ConfigFileExtension - { - get { return m_configFileExtension; } - set { m_configFileExtension = value; } - } - - /// - /// Gets or sets a value indicating whether to watch the configuration file. - /// - /// - /// true if the configuration should be watched, false otherwise. - /// - /// - /// - /// If this flag is specified and set to true then the framework - /// will watch the configuration file and will reload the config each time - /// the file is modified. - /// - /// - /// The config file can only be watched if it is loaded from local disk. - /// In a No-Touch (Smart Client) deployment where the application is downloaded - /// from a web server the config file may not reside on the local disk - /// and therefore it may not be able to watch it. - /// - /// - /// Watching configuration is not supported on the SSCLI. - /// - /// - public bool Watch - { - get { return m_configureAndWatch; } - set { m_configureAndWatch = value; } - } - - #endregion Public Instance Properties - - #region Override ConfiguratorAttribute - - /// - /// Configures the for the specified assembly. - /// - /// The assembly that this attribute was defined on. - /// The repository to configure. - /// - /// - /// Configure the repository using the . - /// The specified must extend the - /// class otherwise the will not be able to - /// configure it. - /// - /// + /// + /// Assembly level attribute to configure the . + /// + /// + /// + /// This attribute may only be used at the assembly scope and can only + /// be used once per assembly. + /// + /// + /// Use this attribute to configure the + /// without calling one of the + /// methods. + /// + /// + /// If neither of the or + /// properties are set the configuration is loaded from the application's .config file. + /// If set the property takes priority over the + /// property. The property + /// specifies a path to a file to load the config from. The path is relative to the + /// application's base directory; . + /// The property is used as a postfix to the assembly file name. + /// The config file must be located in the application's base directory; . + /// For example in a console application setting the to + /// config has the same effect as not specifying the or + /// properties. + /// + /// + /// The property can be set to cause the + /// to watch the configuration file for changes. + /// + /// + /// + /// Log4net will only look for assembly level configuration attributes once. + /// When using the log4net assembly level attributes to control the configuration + /// of log4net you must ensure that the first call to any of the + /// methods is made from the assembly with the configuration + /// attributes. + /// + /// + /// If you cannot guarantee the order in which log4net calls will be made from + /// different assemblies you must use programmatic configuration instead, i.e. + /// call the method directly. + /// + /// + /// + /// Nicko Cadell + /// Gert Driesen + [AttributeUsage(AttributeTargets.Assembly)] + [Serializable] + public /*sealed*/ class XmlConfiguratorAttribute : ConfiguratorAttribute + { + // + // Class is not sealed because DOMConfiguratorAttribute extends it while it is obsoleted + // + + /// + /// Default constructor + /// + /// + /// + /// Default constructor + /// + /// + public XmlConfiguratorAttribute() : base(0) /* configurator priority 0 */ + { + } + + #region Public Instance Properties + + /// + /// Gets or sets the filename of the configuration file. + /// + /// + /// The filename of the configuration file. + /// + /// + /// + /// If specified, this is the name of the configuration file to use with + /// the . This file path is relative to the + /// application base directory (). + /// + /// + /// The takes priority over the . + /// + /// + public string ConfigFile + { + get { return m_configFile; } + set { m_configFile = value; } + } + + /// + /// Gets or sets the extension of the configuration file. + /// + /// + /// The extension of the configuration file. + /// + /// + /// + /// If specified this is the extension for the configuration file. + /// The path to the config file is built by using the application + /// base directory (), + /// the assembly file name and the config file extension. + /// + /// + /// If the is set to MyExt then + /// possible config file names would be: MyConsoleApp.exe.MyExt or + /// MyClassLibrary.dll.MyExt. + /// + /// + /// The takes priority over the . + /// + /// + public string ConfigFileExtension + { + get { return m_configFileExtension; } + set { m_configFileExtension = value; } + } + + /// + /// Gets or sets a value indicating whether to watch the configuration file. + /// + /// + /// true if the configuration should be watched, false otherwise. + /// + /// + /// + /// If this flag is specified and set to true then the framework + /// will watch the configuration file and will reload the config each time + /// the file is modified. + /// + /// + /// The config file can only be watched if it is loaded from local disk. + /// In a No-Touch (Smart Client) deployment where the application is downloaded + /// from a web server the config file may not reside on the local disk + /// and therefore it may not be able to watch it. + /// + /// + /// Watching configuration is not supported on the SSCLI. + /// + /// + public bool Watch + { + get { return m_configureAndWatch; } + set { m_configureAndWatch = value; } + } + + #endregion Public Instance Properties + + #region Override ConfiguratorAttribute + + /// + /// Configures the for the specified assembly. + /// + /// The assembly that this attribute was defined on. + /// The repository to configure. + /// + /// + /// Configure the repository using the . + /// The specified must extend the + /// class otherwise the will not be able to + /// configure it. + /// + /// /// The does not extend . - public override void Configure(Assembly sourceAssembly, ILoggerRepository targetRepository) - { + public override void Configure(Assembly sourceAssembly, ILoggerRepository targetRepository) + { IList configurationMessages = new ArrayList(); using (new LogLog.LogReceivedAdapter(configurationMessages)) @@ -224,246 +224,246 @@ public override void Configure(Assembly sourceAssembly, ILoggerRepository target } targetRepository.ConfigurationMessages = configurationMessages; - } - - #endregion - - /// - /// Attempt to load configuration from the local file system - /// - /// The assembly that this attribute was defined on. - /// The repository to configure. - private void ConfigureFromFile(Assembly sourceAssembly, ILoggerRepository targetRepository) - { - // Work out the full path to the config file - string fullPath2ConfigFile = null; - - // Select the config file - if (m_configFile == null || m_configFile.Length == 0) - { - if (m_configFileExtension == null || m_configFileExtension.Length == 0) - { - // Use the default .config file for the AppDomain - try - { - fullPath2ConfigFile = SystemInfo.ConfigurationFileLocation; - } - catch(Exception ex) - { - LogLog.Error(declaringType, "XmlConfiguratorAttribute: Exception getting ConfigurationFileLocation. Must be able to resolve ConfigurationFileLocation when ConfigFile and ConfigFileExtension properties are not set.", ex); - } - } - else - { - // Force the extension to start with a '.' - if (m_configFileExtension[0] != '.') - { - m_configFileExtension = "." + m_configFileExtension; - } - - string applicationBaseDirectory = null; - try - { - applicationBaseDirectory = SystemInfo.ApplicationBaseDirectory; - } - catch(Exception ex) - { - LogLog.Error(declaringType, "Exception getting ApplicationBaseDirectory. Must be able to resolve ApplicationBaseDirectory and AssemblyFileName when ConfigFileExtension property is set.", ex); - } - - if (applicationBaseDirectory != null) - { - fullPath2ConfigFile = Path.Combine(applicationBaseDirectory, SystemInfo.AssemblyFileName(sourceAssembly) + m_configFileExtension); - } - } - } - else - { - string applicationBaseDirectory = null; - try - { - applicationBaseDirectory = SystemInfo.ApplicationBaseDirectory; - } - catch(Exception ex) - { - LogLog.Warn(declaringType, "Exception getting ApplicationBaseDirectory. ConfigFile property path ["+m_configFile+"] will be treated as an absolute path.", ex); - } - - if (applicationBaseDirectory != null) - { - // Just the base dir + the config file - fullPath2ConfigFile = Path.Combine(applicationBaseDirectory, m_configFile); - } - else - { - fullPath2ConfigFile = m_configFile; - } - } - - if (fullPath2ConfigFile != null) - { - ConfigureFromFile(targetRepository, new FileInfo(fullPath2ConfigFile)); - } - } - - /// - /// Configure the specified repository using a - /// - /// The repository to configure. - /// the FileInfo pointing to the config file - private void ConfigureFromFile(ILoggerRepository targetRepository, FileInfo configFile) - { + } + + #endregion + + /// + /// Attempt to load configuration from the local file system + /// + /// The assembly that this attribute was defined on. + /// The repository to configure. + private void ConfigureFromFile(Assembly sourceAssembly, ILoggerRepository targetRepository) + { + // Work out the full path to the config file + string fullPath2ConfigFile = null; + + // Select the config file + if (m_configFile == null || m_configFile.Length == 0) + { + if (m_configFileExtension == null || m_configFileExtension.Length == 0) + { + // Use the default .config file for the AppDomain + try + { + fullPath2ConfigFile = SystemInfo.ConfigurationFileLocation; + } + catch(Exception ex) + { + LogLog.Error(declaringType, "XmlConfiguratorAttribute: Exception getting ConfigurationFileLocation. Must be able to resolve ConfigurationFileLocation when ConfigFile and ConfigFileExtension properties are not set.", ex); + } + } + else + { + // Force the extension to start with a '.' + if (m_configFileExtension[0] != '.') + { + m_configFileExtension = "." + m_configFileExtension; + } + + string applicationBaseDirectory = null; + try + { + applicationBaseDirectory = SystemInfo.ApplicationBaseDirectory; + } + catch(Exception ex) + { + LogLog.Error(declaringType, "Exception getting ApplicationBaseDirectory. Must be able to resolve ApplicationBaseDirectory and AssemblyFileName when ConfigFileExtension property is set.", ex); + } + + if (applicationBaseDirectory != null) + { + fullPath2ConfigFile = Path.Combine(applicationBaseDirectory, SystemInfo.AssemblyFileName(sourceAssembly) + m_configFileExtension); + } + } + } + else + { + string applicationBaseDirectory = null; + try + { + applicationBaseDirectory = SystemInfo.ApplicationBaseDirectory; + } + catch(Exception ex) + { + LogLog.Warn(declaringType, "Exception getting ApplicationBaseDirectory. ConfigFile property path ["+m_configFile+"] will be treated as an absolute path.", ex); + } + + if (applicationBaseDirectory != null) + { + // Just the base dir + the config file + fullPath2ConfigFile = Path.Combine(applicationBaseDirectory, m_configFile); + } + else + { + fullPath2ConfigFile = m_configFile; + } + } + + if (fullPath2ConfigFile != null) + { + ConfigureFromFile(targetRepository, new FileInfo(fullPath2ConfigFile)); + } + } + + /// + /// Configure the specified repository using a + /// + /// The repository to configure. + /// the FileInfo pointing to the config file + private void ConfigureFromFile(ILoggerRepository targetRepository, FileInfo configFile) + { #if (SSCLI) - if (m_configureAndWatch) - { - LogLog.Warn(declaringType, "XmlConfiguratorAttribute: Unable to watch config file not supported on SSCLI"); - } - XmlConfigurator.Configure(targetRepository, configFile); + if (m_configureAndWatch) + { + LogLog.Warn(declaringType, "XmlConfiguratorAttribute: Unable to watch config file not supported on SSCLI"); + } + XmlConfigurator.Configure(targetRepository, configFile); #else - // Do we configure just once or do we configure and then watch? - if (m_configureAndWatch) - { - XmlConfigurator.ConfigureAndWatch(targetRepository, configFile); - } - else - { - XmlConfigurator.Configure(targetRepository, configFile); - } + // Do we configure just once or do we configure and then watch? + if (m_configureAndWatch) + { + XmlConfigurator.ConfigureAndWatch(targetRepository, configFile); + } + else + { + XmlConfigurator.Configure(targetRepository, configFile); + } #endif - } - - /// - /// Attempt to load configuration from a URI - /// - /// The assembly that this attribute was defined on. - /// The repository to configure. - private void ConfigureFromUri(Assembly sourceAssembly, ILoggerRepository targetRepository) - { - // Work out the full path to the config file - Uri fullPath2ConfigFile = null; - - // Select the config file - if (m_configFile == null || m_configFile.Length == 0) - { - if (m_configFileExtension == null || m_configFileExtension.Length == 0) - { - string systemConfigFilePath = null; - try - { - systemConfigFilePath = SystemInfo.ConfigurationFileLocation; - } - catch(Exception ex) - { - LogLog.Error(declaringType, "XmlConfiguratorAttribute: Exception getting ConfigurationFileLocation. Must be able to resolve ConfigurationFileLocation when ConfigFile and ConfigFileExtension properties are not set.", ex); - } - - if (systemConfigFilePath != null) - { - Uri systemConfigFileUri = new Uri(systemConfigFilePath); - - // Use the default .config file for the AppDomain - fullPath2ConfigFile = systemConfigFileUri; - } - } - else - { - // Force the extension to start with a '.' - if (m_configFileExtension[0] != '.') - { - m_configFileExtension = "." + m_configFileExtension; - } - - string systemConfigFilePath = null; - try - { - systemConfigFilePath = SystemInfo.ConfigurationFileLocation; - } - catch(Exception ex) - { - LogLog.Error(declaringType, "XmlConfiguratorAttribute: Exception getting ConfigurationFileLocation. Must be able to resolve ConfigurationFileLocation when the ConfigFile property are not set.", ex); - } - - if (systemConfigFilePath != null) - { - UriBuilder builder = new UriBuilder(new Uri(systemConfigFilePath)); - - // Remove the current extension from the systemConfigFileUri path - string path = builder.Path; - int startOfExtension = path.LastIndexOf("."); - if (startOfExtension >= 0) - { - path = path.Substring(0, startOfExtension); - } - path += m_configFileExtension; - - builder.Path = path; - fullPath2ConfigFile = builder.Uri; - } - } - } - else - { - string applicationBaseDirectory = null; - try - { - applicationBaseDirectory = SystemInfo.ApplicationBaseDirectory; - } - catch(Exception ex) - { - LogLog.Warn(declaringType, "Exception getting ApplicationBaseDirectory. ConfigFile property path ["+m_configFile+"] will be treated as an absolute URI.", ex); - } - - if (applicationBaseDirectory != null) - { - // Just the base dir + the config file - fullPath2ConfigFile = new Uri(new Uri(applicationBaseDirectory), m_configFile); - } - else - { - fullPath2ConfigFile = new Uri(m_configFile); - } - } - - if (fullPath2ConfigFile != null) - { - if (fullPath2ConfigFile.IsFile) - { - // The m_configFile could be an absolute local path, therefore we have to be - // prepared to switch back to using FileInfos here - ConfigureFromFile(targetRepository, new FileInfo(fullPath2ConfigFile.LocalPath)); - } - else - { - if (m_configureAndWatch) - { - LogLog.Warn(declaringType, "XmlConfiguratorAttribute: Unable to watch config file loaded from a URI"); - } - XmlConfigurator.Configure(targetRepository, fullPath2ConfigFile); - } - } - } - - #region Private Instance Fields - - private string m_configFile = null; - private string m_configFileExtension = null; - private bool m_configureAndWatch = false; - - #endregion Private Instance Fields - - #region Private Static Fields - - /// - /// The fully qualified type of the XmlConfiguratorAttribute class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(XmlConfiguratorAttribute); - - #endregion Private Static Fields - } + } + + /// + /// Attempt to load configuration from a URI + /// + /// The assembly that this attribute was defined on. + /// The repository to configure. + private void ConfigureFromUri(Assembly sourceAssembly, ILoggerRepository targetRepository) + { + // Work out the full path to the config file + Uri fullPath2ConfigFile = null; + + // Select the config file + if (m_configFile == null || m_configFile.Length == 0) + { + if (m_configFileExtension == null || m_configFileExtension.Length == 0) + { + string systemConfigFilePath = null; + try + { + systemConfigFilePath = SystemInfo.ConfigurationFileLocation; + } + catch(Exception ex) + { + LogLog.Error(declaringType, "XmlConfiguratorAttribute: Exception getting ConfigurationFileLocation. Must be able to resolve ConfigurationFileLocation when ConfigFile and ConfigFileExtension properties are not set.", ex); + } + + if (systemConfigFilePath != null) + { + Uri systemConfigFileUri = new Uri(systemConfigFilePath); + + // Use the default .config file for the AppDomain + fullPath2ConfigFile = systemConfigFileUri; + } + } + else + { + // Force the extension to start with a '.' + if (m_configFileExtension[0] != '.') + { + m_configFileExtension = "." + m_configFileExtension; + } + + string systemConfigFilePath = null; + try + { + systemConfigFilePath = SystemInfo.ConfigurationFileLocation; + } + catch(Exception ex) + { + LogLog.Error(declaringType, "XmlConfiguratorAttribute: Exception getting ConfigurationFileLocation. Must be able to resolve ConfigurationFileLocation when the ConfigFile property are not set.", ex); + } + + if (systemConfigFilePath != null) + { + UriBuilder builder = new UriBuilder(new Uri(systemConfigFilePath)); + + // Remove the current extension from the systemConfigFileUri path + string path = builder.Path; + int startOfExtension = path.LastIndexOf("."); + if (startOfExtension >= 0) + { + path = path.Substring(0, startOfExtension); + } + path += m_configFileExtension; + + builder.Path = path; + fullPath2ConfigFile = builder.Uri; + } + } + } + else + { + string applicationBaseDirectory = null; + try + { + applicationBaseDirectory = SystemInfo.ApplicationBaseDirectory; + } + catch(Exception ex) + { + LogLog.Warn(declaringType, "Exception getting ApplicationBaseDirectory. ConfigFile property path ["+m_configFile+"] will be treated as an absolute URI.", ex); + } + + if (applicationBaseDirectory != null) + { + // Just the base dir + the config file + fullPath2ConfigFile = new Uri(new Uri(applicationBaseDirectory), m_configFile); + } + else + { + fullPath2ConfigFile = new Uri(m_configFile); + } + } + + if (fullPath2ConfigFile != null) + { + if (fullPath2ConfigFile.IsFile) + { + // The m_configFile could be an absolute local path, therefore we have to be + // prepared to switch back to using FileInfos here + ConfigureFromFile(targetRepository, new FileInfo(fullPath2ConfigFile.LocalPath)); + } + else + { + if (m_configureAndWatch) + { + LogLog.Warn(declaringType, "XmlConfiguratorAttribute: Unable to watch config file loaded from a URI"); + } + XmlConfigurator.Configure(targetRepository, fullPath2ConfigFile); + } + } + } + + #region Private Instance Fields + + private string m_configFile = null; + private string m_configFileExtension = null; + private bool m_configureAndWatch = false; + + #endregion Private Instance Fields + + #region Private Static Fields + + /// + /// The fully qualified type of the XmlConfiguratorAttribute class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(XmlConfiguratorAttribute); + + #endregion Private Static Fields + } } #endif // !NETCF diff --git a/src/log4net/Core/CompactRepositorySelector.cs b/src/log4net/Core/CompactRepositorySelector.cs index b1b2805d..f97f1071 100644 --- a/src/log4net/Core/CompactRepositorySelector.cs +++ b/src/log4net/Core/CompactRepositorySelector.cs @@ -28,330 +28,330 @@ namespace log4net.Core { - /// - /// The implementation of the interface suitable - /// for use with the compact framework - /// - /// - /// - /// This implementation is a simple - /// mapping between repository name and - /// object. - /// - /// - /// The .NET Compact Framework 1.0 does not support retrieving assembly - /// level attributes therefore unlike the DefaultRepositorySelector - /// this selector does not examine the calling assembly for attributes. - /// - /// - /// Nicko Cadell - public class CompactRepositorySelector : IRepositorySelector - { - #region Member Variables - - private const string DefaultRepositoryName = "log4net-default-repository"; - - private readonly Hashtable m_name2repositoryMap = new Hashtable(); - private readonly Type m_defaultRepositoryType; - - private event LoggerRepositoryCreationEventHandler m_loggerRepositoryCreatedEvent; - - #endregion - - #region Constructors - - /// - /// Create a new repository selector - /// - /// the type of the repositories to create, must implement - /// - /// - /// Create an new compact repository selector. - /// The default type for repositories must be specified, - /// an appropriate value would be . - /// - /// - /// throw if is null - /// throw if does not implement - public CompactRepositorySelector(Type defaultRepositoryType) - { - if (defaultRepositoryType == null) - { - throw new ArgumentNullException("defaultRepositoryType"); - } - - // Check that the type is a repository - if (! (typeof(ILoggerRepository).IsAssignableFrom(defaultRepositoryType)) ) - { - throw log4net.Util.SystemInfo.CreateArgumentOutOfRangeException("defaultRepositoryType", (object)defaultRepositoryType, "Parameter: defaultRepositoryType, Value: ["+defaultRepositoryType+"] out of range. Argument must implement the ILoggerRepository interface"); - } - - m_defaultRepositoryType = defaultRepositoryType; - - LogLog.Debug(declaringType, "defaultRepositoryType ["+m_defaultRepositoryType+"]"); - } - - #endregion - - #region Implementation of IRepositorySelector - - /// - /// Get the for the specified assembly - /// - /// not used - /// The default - /// - /// - /// The argument is not used. This selector does not create a - /// separate repository for each assembly. - /// - /// - /// As a named repository is not specified the default repository is - /// returned. The default repository is named log4net-default-repository. - /// - /// - public ILoggerRepository GetRepository(Assembly assembly) - { - return CreateRepository(assembly, m_defaultRepositoryType); - } - - /// - /// Get the named - /// - /// the name of the repository to lookup - /// The named - /// - /// - /// Get the named . The default - /// repository is log4net-default-repository. Other repositories - /// must be created using the . - /// If the named repository does not exist an exception is thrown. - /// - /// - /// throw if is null - /// throw if the does not exist - public ILoggerRepository GetRepository(string repositoryName) - { - if (repositoryName == null) - { - throw new ArgumentNullException("repositoryName"); - } - - lock(this) - { - // Lookup in map - ILoggerRepository rep = m_name2repositoryMap[repositoryName] as ILoggerRepository; - if (rep == null) - { - throw new LogException("Repository ["+repositoryName+"] is NOT defined."); - } - return rep; - } - } - - /// - /// Create a new repository for the assembly specified - /// - /// not used - /// the type of repository to create, must implement - /// the repository created - /// - /// - /// The argument is not used. This selector does not create a - /// separate repository for each assembly. - /// - /// - /// If the is null then the - /// default repository type specified to the constructor is used. - /// - /// - /// As a named repository is not specified the default repository is - /// returned. The default repository is named log4net-default-repository. - /// - /// - public ILoggerRepository CreateRepository(Assembly assembly, Type repositoryType) - { - // If the type is not set then use the default type - if (repositoryType == null) - { - repositoryType = m_defaultRepositoryType; - } - - lock(this) - { - // This method should not throw if the default repository already exists. - - // First check that the repository does not exist - ILoggerRepository rep = m_name2repositoryMap[DefaultRepositoryName] as ILoggerRepository; - if (rep == null) - { - // Must create the repository - rep = CreateRepository(DefaultRepositoryName, repositoryType); - } - - return rep; - } - } - - /// - /// Create a new repository for the repository specified - /// - /// the repository to associate with the - /// the type of repository to create, must implement . - /// If this param is null then the default repository type is used. - /// the repository created - /// - /// - /// The created will be associated with the repository - /// specified such that a call to with the - /// same repository specified will return the same repository instance. - /// - /// - /// If the named repository already exists an exception will be thrown. - /// - /// - /// If is null then the default - /// repository type specified to the constructor is used. - /// - /// - /// throw if is null - /// throw if the already exists - public ILoggerRepository CreateRepository(string repositoryName, Type repositoryType) - { - if (repositoryName == null) - { - throw new ArgumentNullException("repositoryName"); - } - - // If the type is not set then use the default type - if (repositoryType == null) - { - repositoryType = m_defaultRepositoryType; - } - - lock(this) - { - ILoggerRepository rep = null; - - // First check that the repository does not exist - rep = m_name2repositoryMap[repositoryName] as ILoggerRepository; - if (rep != null) - { - throw new LogException("Repository ["+repositoryName+"] is already defined. Repositories cannot be redefined."); - } - else - { - LogLog.Debug(declaringType, "Creating repository ["+repositoryName+"] using type ["+repositoryType+"]"); - - // Call the no arg constructor for the repositoryType - rep = (ILoggerRepository)Activator.CreateInstance(repositoryType); - - // Set the name of the repository - rep.Name = repositoryName; - - // Store in map - m_name2repositoryMap[repositoryName] = rep; - - // Notify listeners that the repository has been created - OnLoggerRepositoryCreatedEvent(rep); - } - - return rep; - } - } - - /// - /// Test if a named repository exists - /// - /// the named repository to check - /// true if the repository exists - /// - /// - /// Test if a named repository exists. Use - /// to create a new repository and to retrieve - /// a repository. - /// - /// - public bool ExistsRepository(string repositoryName) - { - lock(this) - { - return m_name2repositoryMap.ContainsKey(repositoryName); - } - } - - /// - /// Gets a list of objects - /// - /// an array of all known objects - /// - /// - /// Gets an array of all of the repositories created by this selector. - /// - /// - public ILoggerRepository[] GetAllRepositories() - { - lock(this) - { - ICollection reps = m_name2repositoryMap.Values; - ILoggerRepository[] all = new ILoggerRepository[reps.Count]; - reps.CopyTo(all, 0); - return all; - } - } - - #endregion - - #region Private Static Fields - - /// - /// The fully qualified type of the CompactRepositorySelector class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(CompactRepositorySelector); - - #endregion Private Static Fields - - /// - /// Event to notify that a logger repository has been created. - /// - /// - /// Event to notify that a logger repository has been created. - /// - /// - /// - /// Event raised when a new repository is created. - /// The event source will be this selector. The event args will - /// be a which - /// holds the newly created . - /// - /// - public event LoggerRepositoryCreationEventHandler LoggerRepositoryCreatedEvent - { - add { m_loggerRepositoryCreatedEvent += value; } - remove { m_loggerRepositoryCreatedEvent -= value; } - } - - /// - /// Notify the registered listeners that the repository has been created - /// - /// The repository that has been created - /// - /// - /// Raises the LoggerRepositoryCreatedEvent - /// event. - /// - /// - protected virtual void OnLoggerRepositoryCreatedEvent(ILoggerRepository repository) - { - LoggerRepositoryCreationEventHandler handler = m_loggerRepositoryCreatedEvent; - if (handler != null) - { - handler(this, new LoggerRepositoryCreationEventArgs(repository)); - } - } - } + /// + /// The implementation of the interface suitable + /// for use with the compact framework + /// + /// + /// + /// This implementation is a simple + /// mapping between repository name and + /// object. + /// + /// + /// The .NET Compact Framework 1.0 does not support retrieving assembly + /// level attributes therefore unlike the DefaultRepositorySelector + /// this selector does not examine the calling assembly for attributes. + /// + /// + /// Nicko Cadell + public class CompactRepositorySelector : IRepositorySelector + { + #region Member Variables + + private const string DefaultRepositoryName = "log4net-default-repository"; + + private readonly Hashtable m_name2repositoryMap = new Hashtable(); + private readonly Type m_defaultRepositoryType; + + private event LoggerRepositoryCreationEventHandler m_loggerRepositoryCreatedEvent; + + #endregion + + #region Constructors + + /// + /// Create a new repository selector + /// + /// the type of the repositories to create, must implement + /// + /// + /// Create an new compact repository selector. + /// The default type for repositories must be specified, + /// an appropriate value would be . + /// + /// + /// throw if is null + /// throw if does not implement + public CompactRepositorySelector(Type defaultRepositoryType) + { + if (defaultRepositoryType == null) + { + throw new ArgumentNullException("defaultRepositoryType"); + } + + // Check that the type is a repository + if (! (typeof(ILoggerRepository).IsAssignableFrom(defaultRepositoryType)) ) + { + throw log4net.Util.SystemInfo.CreateArgumentOutOfRangeException("defaultRepositoryType", (object)defaultRepositoryType, "Parameter: defaultRepositoryType, Value: ["+defaultRepositoryType+"] out of range. Argument must implement the ILoggerRepository interface"); + } + + m_defaultRepositoryType = defaultRepositoryType; + + LogLog.Debug(declaringType, "defaultRepositoryType ["+m_defaultRepositoryType+"]"); + } + + #endregion + + #region Implementation of IRepositorySelector + + /// + /// Get the for the specified assembly + /// + /// not used + /// The default + /// + /// + /// The argument is not used. This selector does not create a + /// separate repository for each assembly. + /// + /// + /// As a named repository is not specified the default repository is + /// returned. The default repository is named log4net-default-repository. + /// + /// + public ILoggerRepository GetRepository(Assembly assembly) + { + return CreateRepository(assembly, m_defaultRepositoryType); + } + + /// + /// Get the named + /// + /// the name of the repository to lookup + /// The named + /// + /// + /// Get the named . The default + /// repository is log4net-default-repository. Other repositories + /// must be created using the . + /// If the named repository does not exist an exception is thrown. + /// + /// + /// throw if is null + /// throw if the does not exist + public ILoggerRepository GetRepository(string repositoryName) + { + if (repositoryName == null) + { + throw new ArgumentNullException("repositoryName"); + } + + lock(this) + { + // Lookup in map + ILoggerRepository rep = m_name2repositoryMap[repositoryName] as ILoggerRepository; + if (rep == null) + { + throw new LogException("Repository ["+repositoryName+"] is NOT defined."); + } + return rep; + } + } + + /// + /// Create a new repository for the assembly specified + /// + /// not used + /// the type of repository to create, must implement + /// the repository created + /// + /// + /// The argument is not used. This selector does not create a + /// separate repository for each assembly. + /// + /// + /// If the is null then the + /// default repository type specified to the constructor is used. + /// + /// + /// As a named repository is not specified the default repository is + /// returned. The default repository is named log4net-default-repository. + /// + /// + public ILoggerRepository CreateRepository(Assembly assembly, Type repositoryType) + { + // If the type is not set then use the default type + if (repositoryType == null) + { + repositoryType = m_defaultRepositoryType; + } + + lock(this) + { + // This method should not throw if the default repository already exists. + + // First check that the repository does not exist + ILoggerRepository rep = m_name2repositoryMap[DefaultRepositoryName] as ILoggerRepository; + if (rep == null) + { + // Must create the repository + rep = CreateRepository(DefaultRepositoryName, repositoryType); + } + + return rep; + } + } + + /// + /// Create a new repository for the repository specified + /// + /// the repository to associate with the + /// the type of repository to create, must implement . + /// If this param is null then the default repository type is used. + /// the repository created + /// + /// + /// The created will be associated with the repository + /// specified such that a call to with the + /// same repository specified will return the same repository instance. + /// + /// + /// If the named repository already exists an exception will be thrown. + /// + /// + /// If is null then the default + /// repository type specified to the constructor is used. + /// + /// + /// throw if is null + /// throw if the already exists + public ILoggerRepository CreateRepository(string repositoryName, Type repositoryType) + { + if (repositoryName == null) + { + throw new ArgumentNullException("repositoryName"); + } + + // If the type is not set then use the default type + if (repositoryType == null) + { + repositoryType = m_defaultRepositoryType; + } + + lock(this) + { + ILoggerRepository rep = null; + + // First check that the repository does not exist + rep = m_name2repositoryMap[repositoryName] as ILoggerRepository; + if (rep != null) + { + throw new LogException("Repository ["+repositoryName+"] is already defined. Repositories cannot be redefined."); + } + else + { + LogLog.Debug(declaringType, "Creating repository ["+repositoryName+"] using type ["+repositoryType+"]"); + + // Call the no arg constructor for the repositoryType + rep = (ILoggerRepository)Activator.CreateInstance(repositoryType); + + // Set the name of the repository + rep.Name = repositoryName; + + // Store in map + m_name2repositoryMap[repositoryName] = rep; + + // Notify listeners that the repository has been created + OnLoggerRepositoryCreatedEvent(rep); + } + + return rep; + } + } + + /// + /// Test if a named repository exists + /// + /// the named repository to check + /// true if the repository exists + /// + /// + /// Test if a named repository exists. Use + /// to create a new repository and to retrieve + /// a repository. + /// + /// + public bool ExistsRepository(string repositoryName) + { + lock(this) + { + return m_name2repositoryMap.ContainsKey(repositoryName); + } + } + + /// + /// Gets a list of objects + /// + /// an array of all known objects + /// + /// + /// Gets an array of all of the repositories created by this selector. + /// + /// + public ILoggerRepository[] GetAllRepositories() + { + lock(this) + { + ICollection reps = m_name2repositoryMap.Values; + ILoggerRepository[] all = new ILoggerRepository[reps.Count]; + reps.CopyTo(all, 0); + return all; + } + } + + #endregion + + #region Private Static Fields + + /// + /// The fully qualified type of the CompactRepositorySelector class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(CompactRepositorySelector); + + #endregion Private Static Fields + + /// + /// Event to notify that a logger repository has been created. + /// + /// + /// Event to notify that a logger repository has been created. + /// + /// + /// + /// Event raised when a new repository is created. + /// The event source will be this selector. The event args will + /// be a which + /// holds the newly created . + /// + /// + public event LoggerRepositoryCreationEventHandler LoggerRepositoryCreatedEvent + { + add { m_loggerRepositoryCreatedEvent += value; } + remove { m_loggerRepositoryCreatedEvent -= value; } + } + + /// + /// Notify the registered listeners that the repository has been created + /// + /// The repository that has been created + /// + /// + /// Raises the LoggerRepositoryCreatedEvent + /// event. + /// + /// + protected virtual void OnLoggerRepositoryCreatedEvent(ILoggerRepository repository) + { + LoggerRepositoryCreationEventHandler handler = m_loggerRepositoryCreatedEvent; + if (handler != null) + { + handler(this, new LoggerRepositoryCreationEventArgs(repository)); + } + } + } } diff --git a/src/log4net/Core/DefaultRepositorySelector.cs b/src/log4net/Core/DefaultRepositorySelector.cs index 2cc84d26..32408134 100644 --- a/src/log4net/Core/DefaultRepositorySelector.cs +++ b/src/log4net/Core/DefaultRepositorySelector.cs @@ -37,677 +37,677 @@ namespace log4net.Core { - /// - /// The default implementation of the interface. - /// - /// - /// - /// Uses attributes defined on the calling assembly to determine how to - /// configure the hierarchy for the repository. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public class DefaultRepositorySelector : IRepositorySelector - { - #region Public Events - - /// - /// Event to notify that a logger repository has been created. - /// - /// - /// Event to notify that a logger repository has been created. - /// - /// - /// - /// Event raised when a new repository is created. - /// The event source will be this selector. The event args will - /// be a which - /// holds the newly created . - /// - /// - public event LoggerRepositoryCreationEventHandler LoggerRepositoryCreatedEvent - { - add { m_loggerRepositoryCreatedEvent += value; } - remove { m_loggerRepositoryCreatedEvent -= value; } - } - - #endregion Public Events - - #region Public Instance Constructors - - /// - /// Creates a new repository selector. - /// - /// The type of the repositories to create, must implement - /// - /// - /// Create an new repository selector. - /// The default type for repositories must be specified, - /// an appropriate value would be . - /// - /// - /// is . - /// does not implement . - public DefaultRepositorySelector(Type defaultRepositoryType) - { - if (defaultRepositoryType == null) - { - throw new ArgumentNullException("defaultRepositoryType"); - } - - // Check that the type is a repository - if (! (typeof(ILoggerRepository).IsAssignableFrom(defaultRepositoryType)) ) - { - throw log4net.Util.SystemInfo.CreateArgumentOutOfRangeException("defaultRepositoryType", defaultRepositoryType, "Parameter: defaultRepositoryType, Value: [" + defaultRepositoryType + "] out of range. Argument must implement the ILoggerRepository interface"); - } - - m_defaultRepositoryType = defaultRepositoryType; - - LogLog.Debug(declaringType, "defaultRepositoryType [" + m_defaultRepositoryType + "]"); - } - - #endregion Public Instance Constructors - - #region Implementation of IRepositorySelector - - /// - /// Gets the for the specified assembly. - /// - /// The assembly use to lookup the . - /// - /// - /// The type of the created and the repository - /// to create can be overridden by specifying the - /// attribute on the . - /// - /// - /// The default values are to use the - /// implementation of the interface and to use the - /// as the name of the repository. - /// - /// - /// The created will be automatically configured using - /// any attributes defined on - /// the . - /// - /// - /// The for the assembly - /// is . - public ILoggerRepository GetRepository(Assembly repositoryAssembly) - { - if (repositoryAssembly == null) - { - throw new ArgumentNullException("repositoryAssembly"); - } - return CreateRepository(repositoryAssembly, m_defaultRepositoryType); - } - - /// - /// Gets the for the specified repository. - /// - /// The repository to use to lookup the . - /// The for the specified repository. - /// - /// - /// Returns the named repository. If is null - /// a is thrown. If the repository - /// does not exist a is thrown. - /// - /// - /// Use to create a repository. - /// - /// - /// is . - /// does not exist. - public ILoggerRepository GetRepository(string repositoryName) - { - if (repositoryName == null) - { - throw new ArgumentNullException("repositoryName"); - } - - lock(this) - { - // Lookup in map - ILoggerRepository rep = m_name2repositoryMap[repositoryName] as ILoggerRepository; - if (rep == null) - { - throw new LogException("Repository [" + repositoryName + "] is NOT defined."); - } - return rep; - } - } - - /// - /// Create a new repository for the assembly specified - /// - /// the assembly to use to create the repository to associate with the . - /// The type of repository to create, must implement . - /// The repository created. - /// - /// - /// The created will be associated with the repository - /// specified such that a call to with the - /// same assembly specified will return the same repository instance. - /// - /// - /// The type of the created and - /// the repository to create can be overridden by specifying the - /// attribute on the - /// . The default values are to use the - /// implementation of the - /// interface and to use the - /// as the name of the repository. - /// - /// - /// The created will be automatically - /// configured using any - /// attributes defined on the . - /// - /// - /// If a repository for the already exists - /// that repository will be returned. An error will not be raised and that - /// repository may be of a different type to that specified in . - /// Also the attribute on the - /// assembly may be used to override the repository type specified in - /// . - /// - /// - /// is . - public ILoggerRepository CreateRepository(Assembly repositoryAssembly, Type repositoryType) - { - return CreateRepository(repositoryAssembly, repositoryType, DefaultRepositoryName, true); - } - - /// - /// Creates a new repository for the assembly specified. - /// - /// the assembly to use to create the repository to associate with the . - /// The type of repository to create, must implement . - /// The name to assign to the created repository - /// Set to true to read and apply the assembly attributes - /// The repository created. - /// - /// - /// The created will be associated with the repository - /// specified such that a call to with the - /// same assembly specified will return the same repository instance. - /// - /// - /// The type of the created and - /// the repository to create can be overridden by specifying the - /// attribute on the - /// . The default values are to use the - /// implementation of the - /// interface and to use the - /// as the name of the repository. - /// - /// - /// The created will be automatically - /// configured using any - /// attributes defined on the . - /// - /// - /// If a repository for the already exists - /// that repository will be returned. An error will not be raised and that - /// repository may be of a different type to that specified in . - /// Also the attribute on the - /// assembly may be used to override the repository type specified in - /// . - /// - /// - /// is . - public ILoggerRepository CreateRepository(Assembly repositoryAssembly, Type repositoryType, string repositoryName, bool readAssemblyAttributes) - { - if (repositoryAssembly == null) - { - throw new ArgumentNullException("repositoryAssembly"); - } - - // If the type is not set then use the default type - if (repositoryType == null) - { - repositoryType = m_defaultRepositoryType; - } - - lock(this) - { - // Lookup in map - ILoggerRepository rep = m_assembly2repositoryMap[repositoryAssembly] as ILoggerRepository; - if (rep == null) - { - // Not found, therefore create - LogLog.Debug(declaringType, "Creating repository for assembly [" + repositoryAssembly + "]"); - - // Must specify defaults - string actualRepositoryName = repositoryName; - Type actualRepositoryType = repositoryType; - - if (readAssemblyAttributes) - { - // Get the repository and type from the assembly attributes - GetInfoForAssembly(repositoryAssembly, ref actualRepositoryName, ref actualRepositoryType); - } - - LogLog.Debug(declaringType, "Assembly [" + repositoryAssembly + "] using repository [" + actualRepositoryName + "] and repository type [" + actualRepositoryType + "]"); - - // Lookup the repository in the map (as this may already be defined) - rep = m_name2repositoryMap[actualRepositoryName] as ILoggerRepository; - if (rep == null) - { - // Create the repository - rep = CreateRepository(actualRepositoryName, actualRepositoryType); - - if (readAssemblyAttributes) - { - try - { - // Look for aliasing attributes - LoadAliases(repositoryAssembly, rep); - - // Look for plugins defined on the assembly - LoadPlugins(repositoryAssembly, rep); - - // Configure the repository using the assembly attributes - ConfigureRepository(repositoryAssembly, rep); - } - catch (Exception ex) - { - LogLog.Error(declaringType, "Failed to configure repository [" + actualRepositoryName + "] from assembly attributes.", ex); - } - } - } - else - { - LogLog.Debug(declaringType, "repository [" + actualRepositoryName + "] already exists, using repository type [" + rep.GetType().FullName + "]"); - - if (readAssemblyAttributes) - { - try - { - // Look for plugins defined on the assembly - LoadPlugins(repositoryAssembly, rep); - } - catch (Exception ex) - { - LogLog.Error(declaringType, "Failed to configure repository [" + actualRepositoryName + "] from assembly attributes.", ex); - } - } - } - m_assembly2repositoryMap[repositoryAssembly] = rep; - } - return rep; - } - } - - /// - /// Creates a new repository for the specified repository. - /// - /// The repository to associate with the . - /// The type of repository to create, must implement . - /// If this param is then the default repository type is used. - /// The new repository. - /// - /// - /// The created will be associated with the repository - /// specified such that a call to with the - /// same repository specified will return the same repository instance. - /// - /// - /// is . - /// already exists. - public ILoggerRepository CreateRepository(string repositoryName, Type repositoryType) - { - if (repositoryName == null) - { - throw new ArgumentNullException("repositoryName"); - } - - // If the type is not set then use the default type - if (repositoryType == null) - { - repositoryType = m_defaultRepositoryType; - } - - lock(this) - { - ILoggerRepository rep = null; - - // First check that the repository does not exist - rep = m_name2repositoryMap[repositoryName] as ILoggerRepository; - if (rep != null) - { - throw new LogException("Repository [" + repositoryName + "] is already defined. Repositories cannot be redefined."); - } - else - { - // Lookup an alias before trying to create the new repository - ILoggerRepository aliasedRepository = m_alias2repositoryMap[repositoryName] as ILoggerRepository; - if (aliasedRepository != null) - { - // Found an alias - - // Check repository type - if (aliasedRepository.GetType() == repositoryType) - { - // Repository type is compatible - LogLog.Debug(declaringType, "Aliasing repository [" + repositoryName + "] to existing repository [" + aliasedRepository.Name + "]"); - rep = aliasedRepository; - - // Store in map - m_name2repositoryMap[repositoryName] = rep; - } - else - { - // Invalid repository type for alias - LogLog.Error(declaringType, "Failed to alias repository [" + repositoryName + "] to existing repository ["+aliasedRepository.Name+"]. Requested repository type ["+repositoryType.FullName+"] is not compatible with existing type [" + aliasedRepository.GetType().FullName + "]"); - - // We now drop through to create the repository without aliasing - } - } - - // If we could not find an alias - if (rep == null) - { - LogLog.Debug(declaringType, "Creating repository [" + repositoryName + "] using type [" + repositoryType + "]"); - - // Call the no arg constructor for the repositoryType - rep = (ILoggerRepository)Activator.CreateInstance(repositoryType); - - // Set the name of the repository - rep.Name = repositoryName; - - // Store in map - m_name2repositoryMap[repositoryName] = rep; - - // Notify listeners that the repository has been created - OnLoggerRepositoryCreatedEvent(rep); - } - } - - return rep; - } - } - - /// - /// Test if a named repository exists - /// - /// the named repository to check - /// true if the repository exists - /// - /// - /// Test if a named repository exists. Use - /// to create a new repository and to retrieve - /// a repository. - /// - /// - public bool ExistsRepository(string repositoryName) - { - lock(this) - { - return m_name2repositoryMap.ContainsKey(repositoryName); - } - } - - /// - /// Gets a list of objects - /// - /// an array of all known objects - /// - /// - /// Gets an array of all of the repositories created by this selector. - /// - /// - public ILoggerRepository[] GetAllRepositories() - { - lock(this) - { - ICollection reps = m_name2repositoryMap.Values; - ILoggerRepository[] all = new ILoggerRepository[reps.Count]; - reps.CopyTo(all, 0); - return all; - } - } - - #endregion Implementation of IRepositorySelector - - #region Public Instance Methods - - /// - /// Aliases a repository to an existing repository. - /// - /// The repository to alias. - /// The repository that the repository is aliased to. - /// - /// - /// The repository specified will be aliased to the repository when created. - /// The repository must not already exist. - /// - /// - /// When the repository is created it must utilize the same repository type as - /// the repository it is aliased to, otherwise the aliasing will fail. - /// - /// - /// - /// is . - /// -or- - /// is . - /// - public void AliasRepository(string repositoryAlias, ILoggerRepository repositoryTarget) - { - if (repositoryAlias == null) - { - throw new ArgumentNullException("repositoryAlias"); - } - if (repositoryTarget == null) - { - throw new ArgumentNullException("repositoryTarget"); - } - - lock(this) - { - // Check if the alias is already set - if (m_alias2repositoryMap.Contains(repositoryAlias)) - { - // Check if this is a duplicate of the current alias - if (repositoryTarget != ((ILoggerRepository)m_alias2repositoryMap[repositoryAlias])) - { - // Cannot redefine existing alias - throw new InvalidOperationException("Repository [" + repositoryAlias + "] is already aliased to repository [" + ((ILoggerRepository)m_alias2repositoryMap[repositoryAlias]).Name + "]. Aliases cannot be redefined."); - } - } - // Check if the alias is already mapped to a repository - else if (m_name2repositoryMap.Contains(repositoryAlias)) - { - // Check if this is a duplicate of the current mapping - if ( repositoryTarget != ((ILoggerRepository)m_name2repositoryMap[repositoryAlias]) ) - { - // Cannot define alias for already mapped repository - throw new InvalidOperationException("Repository [" + repositoryAlias + "] already exists and cannot be aliased to repository [" + repositoryTarget.Name + "]."); - } - } - else - { - // Set the alias - m_alias2repositoryMap[repositoryAlias] = repositoryTarget; - } - } - } - - #endregion Public Instance Methods - - #region Protected Instance Methods - - /// - /// Notifies the registered listeners that the repository has been created. - /// - /// The repository that has been created. - /// - /// - /// Raises the event. - /// - /// - protected virtual void OnLoggerRepositoryCreatedEvent(ILoggerRepository repository) - { - LoggerRepositoryCreationEventHandler handler = m_loggerRepositoryCreatedEvent; - if (handler != null) - { - handler(this, new LoggerRepositoryCreationEventArgs(repository)); - } - } - - #endregion Protected Instance Methods - - #region Private Instance Methods - - /// - /// Gets the repository name and repository type for the specified assembly. - /// - /// The assembly that has a . - /// in/out param to hold the repository name to use for the assembly, caller should set this to the default value before calling. - /// in/out param to hold the type of the repository to create for the assembly, caller should set this to the default value before calling. - /// is . - private void GetInfoForAssembly(Assembly assembly, ref string repositoryName, ref Type repositoryType) - { - if (assembly == null) - { - throw new ArgumentNullException("assembly"); - } - - try - { - LogLog.Debug(declaringType, "Assembly [" + assembly.FullName + "] Loaded From [" + SystemInfo.AssemblyLocationInfo(assembly) + "]"); - } - catch - { - // Ignore exception from debug call - } - - try - { - // Look for the RepositoryAttribute on the assembly + /// + /// The default implementation of the interface. + /// + /// + /// + /// Uses attributes defined on the calling assembly to determine how to + /// configure the hierarchy for the repository. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public class DefaultRepositorySelector : IRepositorySelector + { + #region Public Events + + /// + /// Event to notify that a logger repository has been created. + /// + /// + /// Event to notify that a logger repository has been created. + /// + /// + /// + /// Event raised when a new repository is created. + /// The event source will be this selector. The event args will + /// be a which + /// holds the newly created . + /// + /// + public event LoggerRepositoryCreationEventHandler LoggerRepositoryCreatedEvent + { + add { m_loggerRepositoryCreatedEvent += value; } + remove { m_loggerRepositoryCreatedEvent -= value; } + } + + #endregion Public Events + + #region Public Instance Constructors + + /// + /// Creates a new repository selector. + /// + /// The type of the repositories to create, must implement + /// + /// + /// Create an new repository selector. + /// The default type for repositories must be specified, + /// an appropriate value would be . + /// + /// + /// is . + /// does not implement . + public DefaultRepositorySelector(Type defaultRepositoryType) + { + if (defaultRepositoryType == null) + { + throw new ArgumentNullException("defaultRepositoryType"); + } + + // Check that the type is a repository + if (! (typeof(ILoggerRepository).IsAssignableFrom(defaultRepositoryType)) ) + { + throw log4net.Util.SystemInfo.CreateArgumentOutOfRangeException("defaultRepositoryType", defaultRepositoryType, "Parameter: defaultRepositoryType, Value: [" + defaultRepositoryType + "] out of range. Argument must implement the ILoggerRepository interface"); + } + + m_defaultRepositoryType = defaultRepositoryType; + + LogLog.Debug(declaringType, "defaultRepositoryType [" + m_defaultRepositoryType + "]"); + } + + #endregion Public Instance Constructors + + #region Implementation of IRepositorySelector + + /// + /// Gets the for the specified assembly. + /// + /// The assembly use to lookup the . + /// + /// + /// The type of the created and the repository + /// to create can be overridden by specifying the + /// attribute on the . + /// + /// + /// The default values are to use the + /// implementation of the interface and to use the + /// as the name of the repository. + /// + /// + /// The created will be automatically configured using + /// any attributes defined on + /// the . + /// + /// + /// The for the assembly + /// is . + public ILoggerRepository GetRepository(Assembly repositoryAssembly) + { + if (repositoryAssembly == null) + { + throw new ArgumentNullException("repositoryAssembly"); + } + return CreateRepository(repositoryAssembly, m_defaultRepositoryType); + } + + /// + /// Gets the for the specified repository. + /// + /// The repository to use to lookup the . + /// The for the specified repository. + /// + /// + /// Returns the named repository. If is null + /// a is thrown. If the repository + /// does not exist a is thrown. + /// + /// + /// Use to create a repository. + /// + /// + /// is . + /// does not exist. + public ILoggerRepository GetRepository(string repositoryName) + { + if (repositoryName == null) + { + throw new ArgumentNullException("repositoryName"); + } + + lock(this) + { + // Lookup in map + ILoggerRepository rep = m_name2repositoryMap[repositoryName] as ILoggerRepository; + if (rep == null) + { + throw new LogException("Repository [" + repositoryName + "] is NOT defined."); + } + return rep; + } + } + + /// + /// Create a new repository for the assembly specified + /// + /// the assembly to use to create the repository to associate with the . + /// The type of repository to create, must implement . + /// The repository created. + /// + /// + /// The created will be associated with the repository + /// specified such that a call to with the + /// same assembly specified will return the same repository instance. + /// + /// + /// The type of the created and + /// the repository to create can be overridden by specifying the + /// attribute on the + /// . The default values are to use the + /// implementation of the + /// interface and to use the + /// as the name of the repository. + /// + /// + /// The created will be automatically + /// configured using any + /// attributes defined on the . + /// + /// + /// If a repository for the already exists + /// that repository will be returned. An error will not be raised and that + /// repository may be of a different type to that specified in . + /// Also the attribute on the + /// assembly may be used to override the repository type specified in + /// . + /// + /// + /// is . + public ILoggerRepository CreateRepository(Assembly repositoryAssembly, Type repositoryType) + { + return CreateRepository(repositoryAssembly, repositoryType, DefaultRepositoryName, true); + } + + /// + /// Creates a new repository for the assembly specified. + /// + /// the assembly to use to create the repository to associate with the . + /// The type of repository to create, must implement . + /// The name to assign to the created repository + /// Set to true to read and apply the assembly attributes + /// The repository created. + /// + /// + /// The created will be associated with the repository + /// specified such that a call to with the + /// same assembly specified will return the same repository instance. + /// + /// + /// The type of the created and + /// the repository to create can be overridden by specifying the + /// attribute on the + /// . The default values are to use the + /// implementation of the + /// interface and to use the + /// as the name of the repository. + /// + /// + /// The created will be automatically + /// configured using any + /// attributes defined on the . + /// + /// + /// If a repository for the already exists + /// that repository will be returned. An error will not be raised and that + /// repository may be of a different type to that specified in . + /// Also the attribute on the + /// assembly may be used to override the repository type specified in + /// . + /// + /// + /// is . + public ILoggerRepository CreateRepository(Assembly repositoryAssembly, Type repositoryType, string repositoryName, bool readAssemblyAttributes) + { + if (repositoryAssembly == null) + { + throw new ArgumentNullException("repositoryAssembly"); + } + + // If the type is not set then use the default type + if (repositoryType == null) + { + repositoryType = m_defaultRepositoryType; + } + + lock(this) + { + // Lookup in map + ILoggerRepository rep = m_assembly2repositoryMap[repositoryAssembly] as ILoggerRepository; + if (rep == null) + { + // Not found, therefore create + LogLog.Debug(declaringType, "Creating repository for assembly [" + repositoryAssembly + "]"); + + // Must specify defaults + string actualRepositoryName = repositoryName; + Type actualRepositoryType = repositoryType; + + if (readAssemblyAttributes) + { + // Get the repository and type from the assembly attributes + GetInfoForAssembly(repositoryAssembly, ref actualRepositoryName, ref actualRepositoryType); + } + + LogLog.Debug(declaringType, "Assembly [" + repositoryAssembly + "] using repository [" + actualRepositoryName + "] and repository type [" + actualRepositoryType + "]"); + + // Lookup the repository in the map (as this may already be defined) + rep = m_name2repositoryMap[actualRepositoryName] as ILoggerRepository; + if (rep == null) + { + // Create the repository + rep = CreateRepository(actualRepositoryName, actualRepositoryType); + + if (readAssemblyAttributes) + { + try + { + // Look for aliasing attributes + LoadAliases(repositoryAssembly, rep); + + // Look for plugins defined on the assembly + LoadPlugins(repositoryAssembly, rep); + + // Configure the repository using the assembly attributes + ConfigureRepository(repositoryAssembly, rep); + } + catch (Exception ex) + { + LogLog.Error(declaringType, "Failed to configure repository [" + actualRepositoryName + "] from assembly attributes.", ex); + } + } + } + else + { + LogLog.Debug(declaringType, "repository [" + actualRepositoryName + "] already exists, using repository type [" + rep.GetType().FullName + "]"); + + if (readAssemblyAttributes) + { + try + { + // Look for plugins defined on the assembly + LoadPlugins(repositoryAssembly, rep); + } + catch (Exception ex) + { + LogLog.Error(declaringType, "Failed to configure repository [" + actualRepositoryName + "] from assembly attributes.", ex); + } + } + } + m_assembly2repositoryMap[repositoryAssembly] = rep; + } + return rep; + } + } + + /// + /// Creates a new repository for the specified repository. + /// + /// The repository to associate with the . + /// The type of repository to create, must implement . + /// If this param is then the default repository type is used. + /// The new repository. + /// + /// + /// The created will be associated with the repository + /// specified such that a call to with the + /// same repository specified will return the same repository instance. + /// + /// + /// is . + /// already exists. + public ILoggerRepository CreateRepository(string repositoryName, Type repositoryType) + { + if (repositoryName == null) + { + throw new ArgumentNullException("repositoryName"); + } + + // If the type is not set then use the default type + if (repositoryType == null) + { + repositoryType = m_defaultRepositoryType; + } + + lock(this) + { + ILoggerRepository rep = null; + + // First check that the repository does not exist + rep = m_name2repositoryMap[repositoryName] as ILoggerRepository; + if (rep != null) + { + throw new LogException("Repository [" + repositoryName + "] is already defined. Repositories cannot be redefined."); + } + else + { + // Lookup an alias before trying to create the new repository + ILoggerRepository aliasedRepository = m_alias2repositoryMap[repositoryName] as ILoggerRepository; + if (aliasedRepository != null) + { + // Found an alias + + // Check repository type + if (aliasedRepository.GetType() == repositoryType) + { + // Repository type is compatible + LogLog.Debug(declaringType, "Aliasing repository [" + repositoryName + "] to existing repository [" + aliasedRepository.Name + "]"); + rep = aliasedRepository; + + // Store in map + m_name2repositoryMap[repositoryName] = rep; + } + else + { + // Invalid repository type for alias + LogLog.Error(declaringType, "Failed to alias repository [" + repositoryName + "] to existing repository ["+aliasedRepository.Name+"]. Requested repository type ["+repositoryType.FullName+"] is not compatible with existing type [" + aliasedRepository.GetType().FullName + "]"); + + // We now drop through to create the repository without aliasing + } + } + + // If we could not find an alias + if (rep == null) + { + LogLog.Debug(declaringType, "Creating repository [" + repositoryName + "] using type [" + repositoryType + "]"); + + // Call the no arg constructor for the repositoryType + rep = (ILoggerRepository)Activator.CreateInstance(repositoryType); + + // Set the name of the repository + rep.Name = repositoryName; + + // Store in map + m_name2repositoryMap[repositoryName] = rep; + + // Notify listeners that the repository has been created + OnLoggerRepositoryCreatedEvent(rep); + } + } + + return rep; + } + } + + /// + /// Test if a named repository exists + /// + /// the named repository to check + /// true if the repository exists + /// + /// + /// Test if a named repository exists. Use + /// to create a new repository and to retrieve + /// a repository. + /// + /// + public bool ExistsRepository(string repositoryName) + { + lock(this) + { + return m_name2repositoryMap.ContainsKey(repositoryName); + } + } + + /// + /// Gets a list of objects + /// + /// an array of all known objects + /// + /// + /// Gets an array of all of the repositories created by this selector. + /// + /// + public ILoggerRepository[] GetAllRepositories() + { + lock(this) + { + ICollection reps = m_name2repositoryMap.Values; + ILoggerRepository[] all = new ILoggerRepository[reps.Count]; + reps.CopyTo(all, 0); + return all; + } + } + + #endregion Implementation of IRepositorySelector + + #region Public Instance Methods + + /// + /// Aliases a repository to an existing repository. + /// + /// The repository to alias. + /// The repository that the repository is aliased to. + /// + /// + /// The repository specified will be aliased to the repository when created. + /// The repository must not already exist. + /// + /// + /// When the repository is created it must utilize the same repository type as + /// the repository it is aliased to, otherwise the aliasing will fail. + /// + /// + /// + /// is . + /// -or- + /// is . + /// + public void AliasRepository(string repositoryAlias, ILoggerRepository repositoryTarget) + { + if (repositoryAlias == null) + { + throw new ArgumentNullException("repositoryAlias"); + } + if (repositoryTarget == null) + { + throw new ArgumentNullException("repositoryTarget"); + } + + lock(this) + { + // Check if the alias is already set + if (m_alias2repositoryMap.Contains(repositoryAlias)) + { + // Check if this is a duplicate of the current alias + if (repositoryTarget != ((ILoggerRepository)m_alias2repositoryMap[repositoryAlias])) + { + // Cannot redefine existing alias + throw new InvalidOperationException("Repository [" + repositoryAlias + "] is already aliased to repository [" + ((ILoggerRepository)m_alias2repositoryMap[repositoryAlias]).Name + "]. Aliases cannot be redefined."); + } + } + // Check if the alias is already mapped to a repository + else if (m_name2repositoryMap.Contains(repositoryAlias)) + { + // Check if this is a duplicate of the current mapping + if ( repositoryTarget != ((ILoggerRepository)m_name2repositoryMap[repositoryAlias]) ) + { + // Cannot define alias for already mapped repository + throw new InvalidOperationException("Repository [" + repositoryAlias + "] already exists and cannot be aliased to repository [" + repositoryTarget.Name + "]."); + } + } + else + { + // Set the alias + m_alias2repositoryMap[repositoryAlias] = repositoryTarget; + } + } + } + + #endregion Public Instance Methods + + #region Protected Instance Methods + + /// + /// Notifies the registered listeners that the repository has been created. + /// + /// The repository that has been created. + /// + /// + /// Raises the event. + /// + /// + protected virtual void OnLoggerRepositoryCreatedEvent(ILoggerRepository repository) + { + LoggerRepositoryCreationEventHandler handler = m_loggerRepositoryCreatedEvent; + if (handler != null) + { + handler(this, new LoggerRepositoryCreationEventArgs(repository)); + } + } + + #endregion Protected Instance Methods + + #region Private Instance Methods + + /// + /// Gets the repository name and repository type for the specified assembly. + /// + /// The assembly that has a . + /// in/out param to hold the repository name to use for the assembly, caller should set this to the default value before calling. + /// in/out param to hold the type of the repository to create for the assembly, caller should set this to the default value before calling. + /// is . + private void GetInfoForAssembly(Assembly assembly, ref string repositoryName, ref Type repositoryType) + { + if (assembly == null) + { + throw new ArgumentNullException("assembly"); + } + + try + { + LogLog.Debug(declaringType, "Assembly [" + assembly.FullName + "] Loaded From [" + SystemInfo.AssemblyLocationInfo(assembly) + "]"); + } + catch + { + // Ignore exception from debug call + } + + try + { + // Look for the RepositoryAttribute on the assembly #if NETSTANDARD - object[] repositoryAttributes = assembly.GetCustomAttributes(typeof(log4net.Config.RepositoryAttribute)).ToArray(); + object[] repositoryAttributes = assembly.GetCustomAttributes(typeof(log4net.Config.RepositoryAttribute)).ToArray(); #else - object[] repositoryAttributes = Attribute.GetCustomAttributes(assembly, typeof(log4net.Config.RepositoryAttribute), false); + object[] repositoryAttributes = Attribute.GetCustomAttributes(assembly, typeof(log4net.Config.RepositoryAttribute), false); #endif - if (repositoryAttributes == null || repositoryAttributes.Length == 0) - { - // This is not a problem, but its nice to know what is going on. - LogLog.Debug(declaringType, "Assembly [" + assembly + "] does not have a RepositoryAttribute specified."); - } - else - { - if (repositoryAttributes.Length > 1) - { - LogLog.Error(declaringType, "Assembly [" + assembly + "] has multiple log4net.Config.RepositoryAttribute assembly attributes. Only using first occurrence."); - } - - log4net.Config.RepositoryAttribute domAttr = repositoryAttributes[0] as log4net.Config.RepositoryAttribute; - - if (domAttr == null) - { - LogLog.Error(declaringType, "Assembly [" + assembly + "] has a RepositoryAttribute but it does not!."); - } - else - { - // If the Name property is set then override the default - if (domAttr.Name != null) - { - repositoryName = domAttr.Name; - } - - // If the RepositoryType property is set then override the default - if (domAttr.RepositoryType != null) - { - // Check that the type is a repository - if (typeof(ILoggerRepository).IsAssignableFrom(domAttr.RepositoryType)) - { - repositoryType = domAttr.RepositoryType; - } - else - { - LogLog.Error(declaringType, "DefaultRepositorySelector: Repository Type [" + domAttr.RepositoryType + "] must implement the ILoggerRepository interface."); - } - } - } - } - } - catch (Exception ex) - { - LogLog.Error(declaringType, "Unhandled exception in GetInfoForAssembly", ex); - } - } - - /// - /// Configures the repository using information from the assembly. - /// - /// The assembly containing - /// attributes which define the configuration for the repository. - /// The repository to configure. - /// - /// is . - /// -or- - /// is . - /// - private void ConfigureRepository(Assembly assembly, ILoggerRepository repository) - { - if (assembly == null) - { - throw new ArgumentNullException("assembly"); - } - if (repository == null) - { - throw new ArgumentNullException("repository"); - } - - // Look for the Configurator attributes (e.g. XmlConfiguratorAttribute) on the assembly + if (repositoryAttributes == null || repositoryAttributes.Length == 0) + { + // This is not a problem, but its nice to know what is going on. + LogLog.Debug(declaringType, "Assembly [" + assembly + "] does not have a RepositoryAttribute specified."); + } + else + { + if (repositoryAttributes.Length > 1) + { + LogLog.Error(declaringType, "Assembly [" + assembly + "] has multiple log4net.Config.RepositoryAttribute assembly attributes. Only using first occurrence."); + } + + log4net.Config.RepositoryAttribute domAttr = repositoryAttributes[0] as log4net.Config.RepositoryAttribute; + + if (domAttr == null) + { + LogLog.Error(declaringType, "Assembly [" + assembly + "] has a RepositoryAttribute but it does not!."); + } + else + { + // If the Name property is set then override the default + if (domAttr.Name != null) + { + repositoryName = domAttr.Name; + } + + // If the RepositoryType property is set then override the default + if (domAttr.RepositoryType != null) + { + // Check that the type is a repository + if (typeof(ILoggerRepository).IsAssignableFrom(domAttr.RepositoryType)) + { + repositoryType = domAttr.RepositoryType; + } + else + { + LogLog.Error(declaringType, "DefaultRepositorySelector: Repository Type [" + domAttr.RepositoryType + "] must implement the ILoggerRepository interface."); + } + } + } + } + } + catch (Exception ex) + { + LogLog.Error(declaringType, "Unhandled exception in GetInfoForAssembly", ex); + } + } + + /// + /// Configures the repository using information from the assembly. + /// + /// The assembly containing + /// attributes which define the configuration for the repository. + /// The repository to configure. + /// + /// is . + /// -or- + /// is . + /// + private void ConfigureRepository(Assembly assembly, ILoggerRepository repository) + { + if (assembly == null) + { + throw new ArgumentNullException("assembly"); + } + if (repository == null) + { + throw new ArgumentNullException("repository"); + } + + // Look for the Configurator attributes (e.g. XmlConfiguratorAttribute) on the assembly #if NETSTANDARD - object[] configAttributes = assembly.GetCustomAttributes(typeof(log4net.Config.ConfiguratorAttribute)).ToArray(); + object[] configAttributes = assembly.GetCustomAttributes(typeof(log4net.Config.ConfiguratorAttribute)).ToArray(); #else - object[] configAttributes = Attribute.GetCustomAttributes(assembly, typeof(log4net.Config.ConfiguratorAttribute), false); + object[] configAttributes = Attribute.GetCustomAttributes(assembly, typeof(log4net.Config.ConfiguratorAttribute), false); #endif - if (configAttributes != null && configAttributes.Length > 0) - { - // Sort the ConfiguratorAttributes in priority order - Array.Sort(configAttributes); - - // Delegate to the attribute the job of configuring the repository - foreach(log4net.Config.ConfiguratorAttribute configAttr in configAttributes) - { - if (configAttr != null) - { - try - { - configAttr.Configure(assembly, repository); - } - catch (Exception ex) - { - LogLog.Error(declaringType, "Exception calling ["+configAttr.GetType().FullName+"] .Configure method.", ex); - } - } - } - } - - if (repository.Name == DefaultRepositoryName) - { - // Try to configure the default repository using an AppSettings specified config file - // Do this even if the repository has been configured (or claims to be), this allows overriding - // of the default config files etc, if that is required. - - string repositoryConfigFile = SystemInfo.GetAppSetting("log4net.Config"); - if (repositoryConfigFile != null && repositoryConfigFile.Length > 0) - { - string applicationBaseDirectory = null; - try - { - applicationBaseDirectory = SystemInfo.ApplicationBaseDirectory; - } - catch(Exception ex) - { - LogLog.Warn(declaringType, "Exception getting ApplicationBaseDirectory. appSettings log4net.Config path ["+repositoryConfigFile+"] will be treated as an absolute URI", ex); - } + if (configAttributes != null && configAttributes.Length > 0) + { + // Sort the ConfiguratorAttributes in priority order + Array.Sort(configAttributes); + + // Delegate to the attribute the job of configuring the repository + foreach(log4net.Config.ConfiguratorAttribute configAttr in configAttributes) + { + if (configAttr != null) + { + try + { + configAttr.Configure(assembly, repository); + } + catch (Exception ex) + { + LogLog.Error(declaringType, "Exception calling ["+configAttr.GetType().FullName+"] .Configure method.", ex); + } + } + } + } + + if (repository.Name == DefaultRepositoryName) + { + // Try to configure the default repository using an AppSettings specified config file + // Do this even if the repository has been configured (or claims to be), this allows overriding + // of the default config files etc, if that is required. + + string repositoryConfigFile = SystemInfo.GetAppSetting("log4net.Config"); + if (repositoryConfigFile != null && repositoryConfigFile.Length > 0) + { + string applicationBaseDirectory = null; + try + { + applicationBaseDirectory = SystemInfo.ApplicationBaseDirectory; + } + catch(Exception ex) + { + LogLog.Warn(declaringType, "Exception getting ApplicationBaseDirectory. appSettings log4net.Config path ["+repositoryConfigFile+"] will be treated as an absolute URI", ex); + } string repositoryConfigFilePath = repositoryConfigFile; if (applicationBaseDirectory != null) @@ -716,9 +716,9 @@ private void ConfigureRepository(Assembly assembly, ILoggerRepository repository } // Determine whether to watch the file or not based on an app setting value: - bool watchRepositoryConfigFile = false; + bool watchRepositoryConfigFile = false; #if NET_2_0 || MONO_2_0 || MONO_3_5 || MONO_4_0 || NETSTANDARD - Boolean.TryParse(SystemInfo.GetAppSetting("log4net.Config.Watch"), out watchRepositoryConfigFile); + Boolean.TryParse(SystemInfo.GetAppSetting("log4net.Config.Watch"), out watchRepositoryConfigFile); #else { string watch = SystemInfo.GetAppSetting("log4net.Config.Watch"); @@ -736,153 +736,153 @@ private void ConfigureRepository(Assembly assembly, ILoggerRepository repository } #endif - if (watchRepositoryConfigFile) - { - // As we are going to watch the config file it is required to resolve it as a - // physical file system path pass that in a FileInfo object to the Configurator - FileInfo repositoryConfigFileInfo = null; - try - { - repositoryConfigFileInfo = new FileInfo(repositoryConfigFilePath); - } - catch (Exception ex) - { + if (watchRepositoryConfigFile) + { + // As we are going to watch the config file it is required to resolve it as a + // physical file system path pass that in a FileInfo object to the Configurator + FileInfo repositoryConfigFileInfo = null; + try + { + repositoryConfigFileInfo = new FileInfo(repositoryConfigFilePath); + } + catch (Exception ex) + { LogLog.Error(declaringType, "DefaultRepositorySelector: Exception while parsing log4net.Config file physical path [" + repositoryConfigFilePath + "]", ex); - } - try - { + } + try + { LogLog.Debug(declaringType, "Loading and watching configuration for default repository from AppSettings specified Config path [" + repositoryConfigFilePath + "]"); XmlConfigurator.ConfigureAndWatch(repository, repositoryConfigFileInfo); - } - catch (Exception ex) - { + } + catch (Exception ex) + { LogLog.Error(declaringType, "DefaultRepositorySelector: Exception calling XmlConfigurator.ConfigureAndWatch method with ConfigFilePath [" + repositoryConfigFilePath + "]", ex); - } - } - else - { + } + } + else + { // As we are not going to watch the config file it is easiest to just resolve it as a - // URI and pass that to the Configurator - Uri repositoryConfigUri = null; - try - { - repositoryConfigUri = new Uri(repositoryConfigFilePath); - } - catch(Exception ex) - { - LogLog.Error(declaringType, "Exception while parsing log4net.Config file path ["+repositoryConfigFile+"]", ex); - } - - if (repositoryConfigUri != null) - { - LogLog.Debug(declaringType, "Loading configuration for default repository from AppSettings specified Config URI ["+repositoryConfigUri.ToString()+"]"); - - try - { - // TODO: Support other types of configurator - XmlConfigurator.Configure(repository, repositoryConfigUri); - } - catch (Exception ex) - { - LogLog.Error(declaringType, "Exception calling XmlConfigurator.Configure method with ConfigUri ["+repositoryConfigUri+"]", ex); - } - } + // URI and pass that to the Configurator + Uri repositoryConfigUri = null; + try + { + repositoryConfigUri = new Uri(repositoryConfigFilePath); + } + catch(Exception ex) + { + LogLog.Error(declaringType, "Exception while parsing log4net.Config file path ["+repositoryConfigFile+"]", ex); + } + + if (repositoryConfigUri != null) + { + LogLog.Debug(declaringType, "Loading configuration for default repository from AppSettings specified Config URI ["+repositoryConfigUri.ToString()+"]"); + + try + { + // TODO: Support other types of configurator + XmlConfigurator.Configure(repository, repositoryConfigUri); + } + catch (Exception ex) + { + LogLog.Error(declaringType, "Exception calling XmlConfigurator.Configure method with ConfigUri ["+repositoryConfigUri+"]", ex); + } + } } - } - } - } - - /// - /// Loads the attribute defined plugins on the assembly. - /// - /// The assembly that contains the attributes. - /// The repository to add the plugins to. - /// - /// is . - /// -or- - /// is . - /// - private void LoadPlugins(Assembly assembly, ILoggerRepository repository) - { - if (assembly == null) - { - throw new ArgumentNullException("assembly"); - } - if (repository == null) - { - throw new ArgumentNullException("repository"); - } - - // Look for the PluginAttribute on the assembly + } + } + } + + /// + /// Loads the attribute defined plugins on the assembly. + /// + /// The assembly that contains the attributes. + /// The repository to add the plugins to. + /// + /// is . + /// -or- + /// is . + /// + private void LoadPlugins(Assembly assembly, ILoggerRepository repository) + { + if (assembly == null) + { + throw new ArgumentNullException("assembly"); + } + if (repository == null) + { + throw new ArgumentNullException("repository"); + } + + // Look for the PluginAttribute on the assembly #if NETSTANDARD - object[] configAttributes = assembly.GetCustomAttributes(typeof(log4net.Config.PluginAttribute)).ToArray(); + object[] configAttributes = assembly.GetCustomAttributes(typeof(log4net.Config.PluginAttribute)).ToArray(); #else - object[] configAttributes = Attribute.GetCustomAttributes(assembly, typeof(log4net.Config.PluginAttribute), false); + object[] configAttributes = Attribute.GetCustomAttributes(assembly, typeof(log4net.Config.PluginAttribute), false); #endif - if (configAttributes != null && configAttributes.Length > 0) - { - foreach(log4net.Plugin.IPluginFactory configAttr in configAttributes) - { - try - { - // Create the plugin and add it to the repository - repository.PluginMap.Add(configAttr.CreatePlugin()); - } - catch(Exception ex) - { - LogLog.Error(declaringType, "Failed to create plugin. Attribute [" + configAttr.ToString() + "]", ex); - } - } - } - } - - /// - /// Loads the attribute defined aliases on the assembly. - /// - /// The assembly that contains the attributes. - /// The repository to alias to. - /// - /// is . - /// -or- - /// is . - /// - private void LoadAliases(Assembly assembly, ILoggerRepository repository) - { - if (assembly == null) - { - throw new ArgumentNullException("assembly"); - } - if (repository == null) - { - throw new ArgumentNullException("repository"); - } - - // Look for the AliasRepositoryAttribute on the assembly + if (configAttributes != null && configAttributes.Length > 0) + { + foreach(log4net.Plugin.IPluginFactory configAttr in configAttributes) + { + try + { + // Create the plugin and add it to the repository + repository.PluginMap.Add(configAttr.CreatePlugin()); + } + catch(Exception ex) + { + LogLog.Error(declaringType, "Failed to create plugin. Attribute [" + configAttr.ToString() + "]", ex); + } + } + } + } + + /// + /// Loads the attribute defined aliases on the assembly. + /// + /// The assembly that contains the attributes. + /// The repository to alias to. + /// + /// is . + /// -or- + /// is . + /// + private void LoadAliases(Assembly assembly, ILoggerRepository repository) + { + if (assembly == null) + { + throw new ArgumentNullException("assembly"); + } + if (repository == null) + { + throw new ArgumentNullException("repository"); + } + + // Look for the AliasRepositoryAttribute on the assembly #if NETSTANDARD - object[] configAttributes = assembly.GetCustomAttributes(typeof(log4net.Config.AliasRepositoryAttribute)).ToArray(); + object[] configAttributes = assembly.GetCustomAttributes(typeof(log4net.Config.AliasRepositoryAttribute)).ToArray(); #else - object[] configAttributes = Attribute.GetCustomAttributes(assembly, typeof(log4net.Config.AliasRepositoryAttribute), false); + object[] configAttributes = Attribute.GetCustomAttributes(assembly, typeof(log4net.Config.AliasRepositoryAttribute), false); #endif - if (configAttributes != null && configAttributes.Length > 0) - { - foreach(log4net.Config.AliasRepositoryAttribute configAttr in configAttributes) - { - try - { - AliasRepository(configAttr.Name, repository); - } - catch(Exception ex) - { - LogLog.Error(declaringType, "Failed to alias repository [" + configAttr.Name + "]", ex); - } - } - } - } - - #endregion Private Instance Methods - - #region Private Static Fields + if (configAttributes != null && configAttributes.Length > 0) + { + foreach(log4net.Config.AliasRepositoryAttribute configAttr in configAttributes) + { + try + { + AliasRepository(configAttr.Name, repository); + } + catch(Exception ex) + { + LogLog.Error(declaringType, "Failed to alias repository [" + configAttr.Name + "]", ex); + } + } + } + } + + #endregion Private Instance Methods + + #region Private Static Fields /// /// The fully qualified type of the DefaultRepositorySelector class. @@ -893,21 +893,21 @@ private void LoadAliases(Assembly assembly, ILoggerRepository repository) /// private static readonly Type declaringType = typeof(DefaultRepositorySelector); - private const string DefaultRepositoryName = "log4net-default-repository"; + private const string DefaultRepositoryName = "log4net-default-repository"; - #endregion Private Static Fields + #endregion Private Static Fields - #region Private Instance Fields + #region Private Instance Fields - private readonly Hashtable m_name2repositoryMap = new Hashtable(); - private readonly Hashtable m_assembly2repositoryMap = new Hashtable(); - private readonly Hashtable m_alias2repositoryMap = new Hashtable(); - private readonly Type m_defaultRepositoryType; + private readonly Hashtable m_name2repositoryMap = new Hashtable(); + private readonly Hashtable m_assembly2repositoryMap = new Hashtable(); + private readonly Hashtable m_alias2repositoryMap = new Hashtable(); + private readonly Type m_defaultRepositoryType; - private event LoggerRepositoryCreationEventHandler m_loggerRepositoryCreatedEvent; + private event LoggerRepositoryCreationEventHandler m_loggerRepositoryCreatedEvent; - #endregion Private Instance Fields - } + #endregion Private Instance Fields + } } #endif // !NETCF diff --git a/src/log4net/Core/ErrorCode.cs b/src/log4net/Core/ErrorCode.cs index 9107a249..3df25819 100644 --- a/src/log4net/Core/ErrorCode.cs +++ b/src/log4net/Core/ErrorCode.cs @@ -21,50 +21,50 @@ namespace log4net.Core { - /// - /// Defined error codes that can be passed to the method. - /// - /// - /// - /// Values passed to the method. - /// - /// - /// Nicko Cadell - public enum ErrorCode : int - { - /// - /// A general error - /// - GenericFailure = 0, + /// + /// Defined error codes that can be passed to the method. + /// + /// + /// + /// Values passed to the method. + /// + /// + /// Nicko Cadell + public enum ErrorCode : int + { + /// + /// A general error + /// + GenericFailure = 0, - /// - /// Error while writing output - /// - WriteFailure, + /// + /// Error while writing output + /// + WriteFailure, - /// - /// Failed to flush file - /// - FlushFailure, + /// + /// Failed to flush file + /// + FlushFailure, - /// - /// Failed to close file - /// - CloseFailure, + /// + /// Failed to close file + /// + CloseFailure, - /// - /// Unable to open output file - /// - FileOpenFailure, + /// + /// Unable to open output file + /// + FileOpenFailure, - /// - /// No layout specified - /// - MissingLayout, + /// + /// No layout specified + /// + MissingLayout, - /// - /// Failed to parse address - /// - AddressParseFailure - } + /// + /// Failed to parse address + /// + AddressParseFailure + } } diff --git a/src/log4net/Core/ExceptionEvaluator.cs b/src/log4net/Core/ExceptionEvaluator.cs index 60bac575..adaeb498 100644 --- a/src/log4net/Core/ExceptionEvaluator.cs +++ b/src/log4net/Core/ExceptionEvaluator.cs @@ -21,110 +21,110 @@ namespace log4net.Core { - /// - /// An evaluator that triggers on an Exception type - /// - /// - /// - /// This evaluator will trigger if the type of the Exception - /// passed to - /// is equal to a Type in . /// - /// - /// - /// Drew Schaeffer - public class ExceptionEvaluator : ITriggeringEventEvaluator - { - /// - /// The type that causes the trigger to fire. - /// - private Type m_type; + /// + /// An evaluator that triggers on an Exception type + /// + /// + /// + /// This evaluator will trigger if the type of the Exception + /// passed to + /// is equal to a Type in . /// + /// + /// + /// Drew Schaeffer + public class ExceptionEvaluator : ITriggeringEventEvaluator + { + /// + /// The type that causes the trigger to fire. + /// + private Type m_type; - /// - /// Causes subclasses of to cause the trigger to fire. - /// - private bool m_triggerOnSubclass; + /// + /// Causes subclasses of to cause the trigger to fire. + /// + private bool m_triggerOnSubclass; - /// - /// Default ctor to allow dynamic creation through a configurator. - /// - public ExceptionEvaluator() - { - // empty - } + /// + /// Default ctor to allow dynamic creation through a configurator. + /// + public ExceptionEvaluator() + { + // empty + } - /// - /// Constructs an evaluator and initializes to trigger on - /// - /// the type that triggers this evaluator. - /// If true, this evaluator will trigger on subclasses of . - public ExceptionEvaluator(Type exType, bool triggerOnSubClass) - { - if (exType == null) - { - throw new ArgumentNullException("exType"); - } + /// + /// Constructs an evaluator and initializes to trigger on + /// + /// the type that triggers this evaluator. + /// If true, this evaluator will trigger on subclasses of . + public ExceptionEvaluator(Type exType, bool triggerOnSubClass) + { + if (exType == null) + { + throw new ArgumentNullException("exType"); + } - m_type = exType; - m_triggerOnSubclass = triggerOnSubClass; - } + m_type = exType; + m_triggerOnSubclass = triggerOnSubClass; + } - /// - /// The type that triggers this evaluator. - /// - public Type ExceptionType - { - get { return m_type; } - set { m_type = value; } - } + /// + /// The type that triggers this evaluator. + /// + public Type ExceptionType + { + get { return m_type; } + set { m_type = value; } + } - /// - /// If true, this evaluator will trigger on subclasses of . - /// - public bool TriggerOnSubclass - { - get { return m_triggerOnSubclass; } - set { m_triggerOnSubclass = value; } - } + /// + /// If true, this evaluator will trigger on subclasses of . + /// + public bool TriggerOnSubclass + { + get { return m_triggerOnSubclass; } + set { m_triggerOnSubclass = value; } + } - #region ITriggeringEventEvaluator Members + #region ITriggeringEventEvaluator Members - /// - /// Is this the triggering event? - /// - /// The event to check - /// This method returns true, if the logging event Exception - /// Type is . - /// Otherwise it returns false - /// - /// - /// This evaluator will trigger if the Exception Type of the event - /// passed to - /// is . - /// - /// - public bool IsTriggeringEvent(LoggingEvent loggingEvent) - { - if (loggingEvent == null) - { - throw new ArgumentNullException("loggingEvent"); - } + /// + /// Is this the triggering event? + /// + /// The event to check + /// This method returns true, if the logging event Exception + /// Type is . + /// Otherwise it returns false + /// + /// + /// This evaluator will trigger if the Exception Type of the event + /// passed to + /// is . + /// + /// + public bool IsTriggeringEvent(LoggingEvent loggingEvent) + { + if (loggingEvent == null) + { + throw new ArgumentNullException("loggingEvent"); + } - if (m_triggerOnSubclass && loggingEvent.ExceptionObject != null) - { - // check if loggingEvent.ExceptionObject is of type ExceptionType or subclass of ExceptionType - Type exceptionObjectType = loggingEvent.ExceptionObject.GetType(); - return exceptionObjectType == m_type || m_type.IsAssignableFrom(exceptionObjectType); - } - else if (!m_triggerOnSubclass && loggingEvent.ExceptionObject != null) - { // check if loggingEvent.ExceptionObject is of type ExceptionType - return loggingEvent.ExceptionObject.GetType() == m_type; - } - else - { // loggingEvent.ExceptionObject is null - return false; - } - } + if (m_triggerOnSubclass && loggingEvent.ExceptionObject != null) + { + // check if loggingEvent.ExceptionObject is of type ExceptionType or subclass of ExceptionType + Type exceptionObjectType = loggingEvent.ExceptionObject.GetType(); + return exceptionObjectType == m_type || m_type.IsAssignableFrom(exceptionObjectType); + } + else if (!m_triggerOnSubclass && loggingEvent.ExceptionObject != null) + { // check if loggingEvent.ExceptionObject is of type ExceptionType + return loggingEvent.ExceptionObject.GetType() == m_type; + } + else + { // loggingEvent.ExceptionObject is null + return false; + } + } - #endregion - } + #endregion + } } diff --git a/src/log4net/Core/IAppenderAttachable.cs b/src/log4net/Core/IAppenderAttachable.cs index 9c350c1f..43b50c11 100644 --- a/src/log4net/Core/IAppenderAttachable.cs +++ b/src/log4net/Core/IAppenderAttachable.cs @@ -23,99 +23,99 @@ namespace log4net.Core { - /// - /// Interface for attaching appenders to objects. - /// - /// - /// - /// Interface for attaching, removing and retrieving appenders. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public interface IAppenderAttachable - { - /// - /// Attaches an appender. - /// - /// The appender to add. - /// - /// - /// Add the specified appender. The implementation may - /// choose to allow or deny duplicate appenders. - /// - /// - void AddAppender(IAppender appender); + /// + /// Interface for attaching appenders to objects. + /// + /// + /// + /// Interface for attaching, removing and retrieving appenders. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public interface IAppenderAttachable + { + /// + /// Attaches an appender. + /// + /// The appender to add. + /// + /// + /// Add the specified appender. The implementation may + /// choose to allow or deny duplicate appenders. + /// + /// + void AddAppender(IAppender appender); - /// - /// Gets all attached appenders. - /// - /// - /// A collection of attached appenders. - /// - /// - /// - /// Gets a collection of attached appenders. - /// If there are no attached appenders the - /// implementation should return an empty - /// collection rather than null. - /// - /// - AppenderCollection Appenders {get;} + /// + /// Gets all attached appenders. + /// + /// + /// A collection of attached appenders. + /// + /// + /// + /// Gets a collection of attached appenders. + /// If there are no attached appenders the + /// implementation should return an empty + /// collection rather than null. + /// + /// + AppenderCollection Appenders {get;} - /// - /// Gets an attached appender with the specified name. - /// - /// The name of the appender to get. - /// - /// The appender with the name specified, or null if no appender with the - /// specified name is found. - /// - /// - /// - /// Returns an attached appender with the specified. - /// If no appender with the specified name is found null will be - /// returned. - /// - /// - IAppender GetAppender(string name); + /// + /// Gets an attached appender with the specified name. + /// + /// The name of the appender to get. + /// + /// The appender with the name specified, or null if no appender with the + /// specified name is found. + /// + /// + /// + /// Returns an attached appender with the specified. + /// If no appender with the specified name is found null will be + /// returned. + /// + /// + IAppender GetAppender(string name); - /// - /// Removes all attached appenders. - /// - /// - /// - /// Removes and closes all attached appenders - /// - /// - void RemoveAllAppenders(); + /// + /// Removes all attached appenders. + /// + /// + /// + /// Removes and closes all attached appenders + /// + /// + void RemoveAllAppenders(); - /// - /// Removes the specified appender from the list of attached appenders. - /// - /// The appender to remove. - /// The appender removed from the list - /// - /// - /// The appender removed is not closed. - /// If you are discarding the appender you must call - /// on the appender removed. - /// - /// - IAppender RemoveAppender(IAppender appender); + /// + /// Removes the specified appender from the list of attached appenders. + /// + /// The appender to remove. + /// The appender removed from the list + /// + /// + /// The appender removed is not closed. + /// If you are discarding the appender you must call + /// on the appender removed. + /// + /// + IAppender RemoveAppender(IAppender appender); - /// - /// Removes the appender with the specified name from the list of appenders. - /// - /// The name of the appender to remove. - /// The appender removed from the list - /// - /// - /// The appender removed is not closed. - /// If you are discarding the appender you must call - /// on the appender removed. - /// - /// - IAppender RemoveAppender(string name); - } + /// + /// Removes the appender with the specified name from the list of appenders. + /// + /// The name of the appender to remove. + /// The appender removed from the list + /// + /// + /// The appender removed is not closed. + /// If you are discarding the appender you must call + /// on the appender removed. + /// + /// + IAppender RemoveAppender(string name); + } } diff --git a/src/log4net/Core/IErrorHandler.cs b/src/log4net/Core/IErrorHandler.cs index 763e5186..06197dee 100644 --- a/src/log4net/Core/IErrorHandler.cs +++ b/src/log4net/Core/IErrorHandler.cs @@ -21,55 +21,55 @@ namespace log4net.Core { - /// - /// Appenders may delegate their error handling to an . - /// - /// - /// - /// Error handling is a particularly tedious to get right because by - /// definition errors are hard to predict and to reproduce. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public interface IErrorHandler - { - /// - /// Handles the error and information about the error condition is passed as - /// a parameter. - /// - /// The message associated with the error. - /// The that was thrown when the error occurred. - /// The error code associated with the error. - /// - /// - /// Handles the error and information about the error condition is passed as - /// a parameter. - /// - /// - void Error(string message, Exception e, ErrorCode errorCode); + /// + /// Appenders may delegate their error handling to an . + /// + /// + /// + /// Error handling is a particularly tedious to get right because by + /// definition errors are hard to predict and to reproduce. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public interface IErrorHandler + { + /// + /// Handles the error and information about the error condition is passed as + /// a parameter. + /// + /// The message associated with the error. + /// The that was thrown when the error occurred. + /// The error code associated with the error. + /// + /// + /// Handles the error and information about the error condition is passed as + /// a parameter. + /// + /// + void Error(string message, Exception e, ErrorCode errorCode); - /// - /// Prints the error message passed as a parameter. - /// - /// The message associated with the error. - /// The that was thrown when the error occurred. - /// - /// - /// See . - /// - /// - void Error(string message, Exception e); + /// + /// Prints the error message passed as a parameter. + /// + /// The message associated with the error. + /// The that was thrown when the error occurred. + /// + /// + /// See . + /// + /// + void Error(string message, Exception e); - /// - /// Prints the error message passed as a parameter. - /// - /// The message associated with the error. - /// - /// - /// See . - /// - /// - void Error(string message); - } + /// + /// Prints the error message passed as a parameter. + /// + /// The message associated with the error. + /// + /// + /// See . + /// + /// + void Error(string message); + } } diff --git a/src/log4net/Core/IFixingRequired.cs b/src/log4net/Core/IFixingRequired.cs index 9f05b145..58e84cf3 100644 --- a/src/log4net/Core/IFixingRequired.cs +++ b/src/log4net/Core/IFixingRequired.cs @@ -21,38 +21,38 @@ namespace log4net.Core { - /// - /// Interface for objects that require fixing. - /// - /// - /// - /// Interface that indicates that the object requires fixing before it - /// can be taken outside the context of the appender's - /// method. - /// - /// - /// When objects that implement this interface are stored - /// in the context properties maps - /// and - /// are fixed - /// (see ) the - /// method will be called. - /// - /// - /// Nicko Cadell - public interface IFixingRequired - { - /// - /// Get a portable version of this object - /// - /// the portable instance of this object - /// - /// - /// Get a portable instance object that represents the current - /// state of this object. The portable object can be stored - /// and logged from any thread with identical results. - /// - /// - object GetFixedObject(); - } + /// + /// Interface for objects that require fixing. + /// + /// + /// + /// Interface that indicates that the object requires fixing before it + /// can be taken outside the context of the appender's + /// method. + /// + /// + /// When objects that implement this interface are stored + /// in the context properties maps + /// and + /// are fixed + /// (see ) the + /// method will be called. + /// + /// + /// Nicko Cadell + public interface IFixingRequired + { + /// + /// Get a portable version of this object + /// + /// the portable instance of this object + /// + /// + /// Get a portable instance object that represents the current + /// state of this object. The portable object can be stored + /// and logged from any thread with identical results. + /// + /// + object GetFixedObject(); + } } diff --git a/src/log4net/Core/ILogger.cs b/src/log4net/Core/ILogger.cs index bbb152c2..b7e45142 100644 --- a/src/log4net/Core/ILogger.cs +++ b/src/log4net/Core/ILogger.cs @@ -24,92 +24,92 @@ namespace log4net.Core { - /// - /// Interface that all loggers implement - /// - /// - /// - /// This interface supports logging events and testing if a level - /// is enabled for logging. - /// - /// - /// These methods will not throw exceptions. Note to implementor, ensure - /// that the implementation of these methods cannot allow an exception - /// to be thrown to the caller. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public interface ILogger - { - /// - /// Gets the name of the logger. - /// - /// - /// The name of the logger. - /// - /// - /// - /// The name of this logger - /// - /// - string Name { get; } + /// + /// Interface that all loggers implement + /// + /// + /// + /// This interface supports logging events and testing if a level + /// is enabled for logging. + /// + /// + /// These methods will not throw exceptions. Note to implementor, ensure + /// that the implementation of these methods cannot allow an exception + /// to be thrown to the caller. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public interface ILogger + { + /// + /// Gets the name of the logger. + /// + /// + /// The name of the logger. + /// + /// + /// + /// The name of this logger + /// + /// + string Name { get; } - /// - /// This generic form is intended to be used by wrappers. - /// - /// The declaring type of the method that is - /// the stack boundary into the logging system for this call. - /// The level of the message to be logged. - /// The message object to log. - /// the exception to log, including its stack trace. Pass null to not log an exception. - /// - /// - /// Generates a logging event for the specified using - /// the and . - /// - /// - void Log(Type callerStackBoundaryDeclaringType, Level level, object message, Exception exception); + /// + /// This generic form is intended to be used by wrappers. + /// + /// The declaring type of the method that is + /// the stack boundary into the logging system for this call. + /// The level of the message to be logged. + /// The message object to log. + /// the exception to log, including its stack trace. Pass null to not log an exception. + /// + /// + /// Generates a logging event for the specified using + /// the and . + /// + /// + void Log(Type callerStackBoundaryDeclaringType, Level level, object message, Exception exception); - /// - /// This is the most generic printing method that is intended to be used - /// by wrappers. - /// - /// The event being logged. - /// - /// - /// Logs the specified logging event through this logger. - /// - /// - void Log(LoggingEvent logEvent); + /// + /// This is the most generic printing method that is intended to be used + /// by wrappers. + /// + /// The event being logged. + /// + /// + /// Logs the specified logging event through this logger. + /// + /// + void Log(LoggingEvent logEvent); - /// - /// Checks if this logger is enabled for a given passed as parameter. - /// - /// The level to check. - /// - /// true if this logger is enabled for level, otherwise false. - /// - /// - /// - /// Test if this logger is going to log events of the specified . - /// - /// - bool IsEnabledFor(Level level); + /// + /// Checks if this logger is enabled for a given passed as parameter. + /// + /// The level to check. + /// + /// true if this logger is enabled for level, otherwise false. + /// + /// + /// + /// Test if this logger is going to log events of the specified . + /// + /// + bool IsEnabledFor(Level level); - /// - /// Gets the where this - /// Logger instance is attached to. - /// - /// - /// The that this logger belongs to. - /// - /// - /// - /// Gets the where this - /// Logger instance is attached to. - /// - /// - ILoggerRepository Repository { get; } - } + /// + /// Gets the where this + /// Logger instance is attached to. + /// + /// + /// The that this logger belongs to. + /// + /// + /// + /// Gets the where this + /// Logger instance is attached to. + /// + /// + ILoggerRepository Repository { get; } + } } diff --git a/src/log4net/Core/ILoggerWrapper.cs b/src/log4net/Core/ILoggerWrapper.cs index 735e3686..fefbd205 100644 --- a/src/log4net/Core/ILoggerWrapper.cs +++ b/src/log4net/Core/ILoggerWrapper.cs @@ -25,35 +25,35 @@ namespace log4net.Core { - /// - /// Base interface for all wrappers - /// - /// - /// - /// Base interface for all wrappers. - /// - /// - /// All wrappers must implement this interface. - /// - /// - /// Nicko Cadell - public interface ILoggerWrapper - { - /// - /// Get the implementation behind this wrapper object. - /// - /// - /// The object that in implementing this object. - /// - /// - /// - /// The object that in implementing this - /// object. The Logger object may not - /// be the same object as this object because of logger decorators. - /// This gets the actual underlying objects that is used to process - /// the log events. - /// - /// - ILogger Logger { get; } - } + /// + /// Base interface for all wrappers + /// + /// + /// + /// Base interface for all wrappers. + /// + /// + /// All wrappers must implement this interface. + /// + /// + /// Nicko Cadell + public interface ILoggerWrapper + { + /// + /// Get the implementation behind this wrapper object. + /// + /// + /// The object that in implementing this object. + /// + /// + /// + /// The object that in implementing this + /// object. The Logger object may not + /// be the same object as this object because of logger decorators. + /// This gets the actual underlying objects that is used to process + /// the log events. + /// + /// + ILogger Logger { get; } + } } diff --git a/src/log4net/Core/IOptionHandler.cs b/src/log4net/Core/IOptionHandler.cs index cdc46820..6d73ee18 100644 --- a/src/log4net/Core/IOptionHandler.cs +++ b/src/log4net/Core/IOptionHandler.cs @@ -21,38 +21,38 @@ namespace log4net.Core { - /// - /// Interface used to delay activate a configured object. - /// - /// - /// - /// This allows an object to defer activation of its options until all - /// options have been set. This is required for components which have - /// related options that remain ambiguous until all are set. - /// - /// - /// If a component implements this interface then the method - /// must be called by the container after its all the configured properties have been set - /// and before the component can be used. - /// - /// - /// Nicko Cadell - public interface IOptionHandler - { - /// - /// Activate the options that were previously set with calls to properties. - /// - /// - /// - /// This allows an object to defer activation of its options until all - /// options have been set. This is required for components which have - /// related options that remain ambiguous until all are set. - /// - /// - /// If a component implements this interface then this method must be called - /// after its properties have been set before the component can be used. - /// - /// - void ActivateOptions(); - } + /// + /// Interface used to delay activate a configured object. + /// + /// + /// + /// This allows an object to defer activation of its options until all + /// options have been set. This is required for components which have + /// related options that remain ambiguous until all are set. + /// + /// + /// If a component implements this interface then the method + /// must be called by the container after its all the configured properties have been set + /// and before the component can be used. + /// + /// + /// Nicko Cadell + public interface IOptionHandler + { + /// + /// Activate the options that were previously set with calls to properties. + /// + /// + /// + /// This allows an object to defer activation of its options until all + /// options have been set. This is required for components which have + /// related options that remain ambiguous until all are set. + /// + /// + /// If a component implements this interface then this method must be called + /// after its properties have been set before the component can be used. + /// + /// + void ActivateOptions(); + } } diff --git a/src/log4net/Core/IRepositorySelector.cs b/src/log4net/Core/IRepositorySelector.cs index 55e393a3..4e34839d 100644 --- a/src/log4net/Core/IRepositorySelector.cs +++ b/src/log4net/Core/IRepositorySelector.cs @@ -24,190 +24,190 @@ namespace log4net.Core { - #region LoggerRepositoryCreationEvent + #region LoggerRepositoryCreationEvent - /// - /// Delegate used to handle logger repository creation event notifications - /// - /// The which created the repository. - /// The event args - /// that holds the instance that has been created. - /// - /// - /// Delegate used to handle logger repository creation event notifications. - /// - /// - public delegate void LoggerRepositoryCreationEventHandler(object sender, LoggerRepositoryCreationEventArgs e); + /// + /// Delegate used to handle logger repository creation event notifications + /// + /// The which created the repository. + /// The event args + /// that holds the instance that has been created. + /// + /// + /// Delegate used to handle logger repository creation event notifications. + /// + /// + public delegate void LoggerRepositoryCreationEventHandler(object sender, LoggerRepositoryCreationEventArgs e); - /// - /// Provides data for the event. - /// - /// - /// - /// A - /// event is raised every time a is created. - /// - /// - public class LoggerRepositoryCreationEventArgs : EventArgs - { - /// - /// The created - /// - private ILoggerRepository m_repository; + /// + /// Provides data for the event. + /// + /// + /// + /// A + /// event is raised every time a is created. + /// + /// + public class LoggerRepositoryCreationEventArgs : EventArgs + { + /// + /// The created + /// + private ILoggerRepository m_repository; - /// - /// Construct instance using specified - /// - /// the that has been created - /// - /// - /// Construct instance using specified - /// - /// - public LoggerRepositoryCreationEventArgs(ILoggerRepository repository) - { - m_repository = repository; - } + /// + /// Construct instance using specified + /// + /// the that has been created + /// + /// + /// Construct instance using specified + /// + /// + public LoggerRepositoryCreationEventArgs(ILoggerRepository repository) + { + m_repository = repository; + } - /// - /// The that has been created - /// - /// - /// The that has been created - /// - /// - /// - /// The that has been created - /// - /// - public ILoggerRepository LoggerRepository - { - get { return m_repository; } - } - } + /// + /// The that has been created + /// + /// + /// The that has been created + /// + /// + /// + /// The that has been created + /// + /// + public ILoggerRepository LoggerRepository + { + get { return m_repository; } + } + } - #endregion + #endregion - /// - /// Interface used by the to select the . - /// - /// - /// - /// The uses a - /// to specify the policy for selecting the correct - /// to return to the caller. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public interface IRepositorySelector - { - /// - /// Gets the for the specified assembly. - /// - /// The assembly to use to lookup to the - /// The for the assembly. - /// - /// - /// Gets the for the specified assembly. - /// - /// - /// How the association between and - /// is made is not defined. The implementation may choose any method for - /// this association. The results of this method must be repeatable, i.e. - /// when called again with the same arguments the result must be the - /// save value. - /// - /// - ILoggerRepository GetRepository(Assembly assembly); + /// + /// Interface used by the to select the . + /// + /// + /// + /// The uses a + /// to specify the policy for selecting the correct + /// to return to the caller. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public interface IRepositorySelector + { + /// + /// Gets the for the specified assembly. + /// + /// The assembly to use to lookup to the + /// The for the assembly. + /// + /// + /// Gets the for the specified assembly. + /// + /// + /// How the association between and + /// is made is not defined. The implementation may choose any method for + /// this association. The results of this method must be repeatable, i.e. + /// when called again with the same arguments the result must be the + /// save value. + /// + /// + ILoggerRepository GetRepository(Assembly assembly); - /// - /// Gets the named . - /// - /// The name to use to lookup to the . - /// The named - /// - /// Lookup a named . This is the repository created by - /// calling . - /// - ILoggerRepository GetRepository(string repositoryName); + /// + /// Gets the named . + /// + /// The name to use to lookup to the . + /// The named + /// + /// Lookup a named . This is the repository created by + /// calling . + /// + ILoggerRepository GetRepository(string repositoryName); - /// - /// Creates a new repository for the assembly specified. - /// - /// The assembly to use to create the domain to associate with the . - /// The type of repository to create, must implement . - /// The repository created. - /// - /// - /// The created will be associated with the domain - /// specified such that a call to with the - /// same assembly specified will return the same repository instance. - /// - /// - /// How the association between and - /// is made is not defined. The implementation may choose any method for - /// this association. - /// - /// - ILoggerRepository CreateRepository(Assembly assembly, Type repositoryType); + /// + /// Creates a new repository for the assembly specified. + /// + /// The assembly to use to create the domain to associate with the . + /// The type of repository to create, must implement . + /// The repository created. + /// + /// + /// The created will be associated with the domain + /// specified such that a call to with the + /// same assembly specified will return the same repository instance. + /// + /// + /// How the association between and + /// is made is not defined. The implementation may choose any method for + /// this association. + /// + /// + ILoggerRepository CreateRepository(Assembly assembly, Type repositoryType); - /// - /// Creates a new repository with the name specified. - /// - /// The name to associate with the . - /// The type of repository to create, must implement . - /// The repository created. - /// - /// - /// The created will be associated with the name - /// specified such that a call to with the - /// same name will return the same repository instance. - /// - /// - ILoggerRepository CreateRepository(string repositoryName, Type repositoryType); + /// + /// Creates a new repository with the name specified. + /// + /// The name to associate with the . + /// The type of repository to create, must implement . + /// The repository created. + /// + /// + /// The created will be associated with the name + /// specified such that a call to with the + /// same name will return the same repository instance. + /// + /// + ILoggerRepository CreateRepository(string repositoryName, Type repositoryType); - /// - /// Test if a named repository exists - /// - /// the named repository to check - /// true if the repository exists - /// - /// - /// Test if a named repository exists. Use - /// to create a new repository and to retrieve - /// a repository. - /// - /// - bool ExistsRepository(string repositoryName); + /// + /// Test if a named repository exists + /// + /// the named repository to check + /// true if the repository exists + /// + /// + /// Test if a named repository exists. Use + /// to create a new repository and to retrieve + /// a repository. + /// + /// + bool ExistsRepository(string repositoryName); - /// - /// Gets an array of all currently defined repositories. - /// - /// - /// An array of the instances created by - /// this . - /// - /// - /// Gets an array of all of the repositories created by this selector. - /// - /// - ILoggerRepository[] GetAllRepositories(); + /// + /// Gets an array of all currently defined repositories. + /// + /// + /// An array of the instances created by + /// this . + /// + /// + /// Gets an array of all of the repositories created by this selector. + /// + /// + ILoggerRepository[] GetAllRepositories(); - /// - /// Event to notify that a logger repository has been created. - /// - /// - /// Event to notify that a logger repository has been created. - /// - /// - /// - /// Event raised when a new repository is created. - /// The event source will be this selector. The event args will - /// be a which - /// holds the newly created . - /// - /// - event LoggerRepositoryCreationEventHandler LoggerRepositoryCreatedEvent; - } + /// + /// Event to notify that a logger repository has been created. + /// + /// + /// Event to notify that a logger repository has been created. + /// + /// + /// + /// Event raised when a new repository is created. + /// The event source will be this selector. The event args will + /// be a which + /// holds the newly created . + /// + /// + event LoggerRepositoryCreationEventHandler LoggerRepositoryCreatedEvent; + } } diff --git a/src/log4net/Core/ITriggeringEventEvaluator.cs b/src/log4net/Core/ITriggeringEventEvaluator.cs index baa7536a..2063c342 100644 --- a/src/log4net/Core/ITriggeringEventEvaluator.cs +++ b/src/log4net/Core/ITriggeringEventEvaluator.cs @@ -21,31 +21,31 @@ namespace log4net.Core { - /// - /// Test if an triggers an action - /// - /// - /// - /// Implementations of this interface allow certain appenders to decide - /// when to perform an appender specific action. - /// - /// - /// The action or behavior triggered is defined by the implementation. - /// - /// - /// Nicko Cadell - public interface ITriggeringEventEvaluator - { - /// - /// Test if this event triggers the action - /// - /// The event to check - /// true if this event triggers the action, otherwise false - /// - /// - /// Return true if this event triggers the action - /// - /// - bool IsTriggeringEvent(LoggingEvent loggingEvent); - } + /// + /// Test if an triggers an action + /// + /// + /// + /// Implementations of this interface allow certain appenders to decide + /// when to perform an appender specific action. + /// + /// + /// The action or behavior triggered is defined by the implementation. + /// + /// + /// Nicko Cadell + public interface ITriggeringEventEvaluator + { + /// + /// Test if this event triggers the action + /// + /// The event to check + /// true if this event triggers the action, otherwise false + /// + /// + /// Return true if this event triggers the action + /// + /// + bool IsTriggeringEvent(LoggingEvent loggingEvent); + } } diff --git a/src/log4net/Core/Level.cs b/src/log4net/Core/Level.cs index 767d03ee..ced11f8d 100644 --- a/src/log4net/Core/Level.cs +++ b/src/log4net/Core/Level.cs @@ -22,485 +22,485 @@ namespace log4net.Core { - /// - /// Defines the default set of levels recognized by the system. - /// - /// - /// - /// Each has an associated . - /// - /// - /// Levels have a numeric that defines the relative - /// ordering between levels. Two Levels with the same - /// are deemed to be equivalent. - /// - /// - /// The levels that are recognized by log4net are set for each - /// and each repository can have different levels defined. The levels are stored - /// in the on the repository. Levels are - /// looked up by name from the . - /// - /// - /// When logging at level INFO the actual level used is not but - /// the value of LoggerRepository.LevelMap["INFO"]. The default value for this is - /// , but this can be changed by reconfiguring the level map. - /// - /// - /// Each level has a in addition to its . The - /// is the string that is written into the output log. By default - /// the display name is the same as the level name, but this can be used to alias levels - /// or to localize the log output. - /// - /// - /// Some of the predefined levels recognized by the system are: - /// - /// - /// - /// . - /// - /// - /// . - /// - /// - /// . - /// - /// - /// . - /// - /// - /// . - /// - /// - /// . - /// - /// - /// . - /// - /// - /// - /// Nicko Cadell - /// Gert Driesen + /// + /// Defines the default set of levels recognized by the system. + /// + /// + /// + /// Each has an associated . + /// + /// + /// Levels have a numeric that defines the relative + /// ordering between levels. Two Levels with the same + /// are deemed to be equivalent. + /// + /// + /// The levels that are recognized by log4net are set for each + /// and each repository can have different levels defined. The levels are stored + /// in the on the repository. Levels are + /// looked up by name from the . + /// + /// + /// When logging at level INFO the actual level used is not but + /// the value of LoggerRepository.LevelMap["INFO"]. The default value for this is + /// , but this can be changed by reconfiguring the level map. + /// + /// + /// Each level has a in addition to its . The + /// is the string that is written into the output log. By default + /// the display name is the same as the level name, but this can be used to alias levels + /// or to localize the log output. + /// + /// + /// Some of the predefined levels recognized by the system are: + /// + /// + /// + /// . + /// + /// + /// . + /// + /// + /// . + /// + /// + /// . + /// + /// + /// . + /// + /// + /// . + /// + /// + /// . + /// + /// + /// + /// Nicko Cadell + /// Gert Driesen #if !NETCF - [Serializable] + [Serializable] #endif - public sealed class Level : IComparable - { - #region Public Instance Constructors - - /// - /// Constructor - /// - /// Integer value for this level, higher values represent more severe levels. - /// The string name of this level. - /// The display name for this level. This may be localized or otherwise different from the name - /// - /// - /// Initializes a new instance of the class with - /// the specified level name and value. - /// - /// - public Level(int level, string levelName, string displayName) - { - if (levelName == null) - { - throw new ArgumentNullException("levelName"); - } - if (displayName == null) - { - throw new ArgumentNullException("displayName"); - } - - m_levelValue = level; + public sealed class Level : IComparable + { + #region Public Instance Constructors + + /// + /// Constructor + /// + /// Integer value for this level, higher values represent more severe levels. + /// The string name of this level. + /// The display name for this level. This may be localized or otherwise different from the name + /// + /// + /// Initializes a new instance of the class with + /// the specified level name and value. + /// + /// + public Level(int level, string levelName, string displayName) + { + if (levelName == null) + { + throw new ArgumentNullException("levelName"); + } + if (displayName == null) + { + throw new ArgumentNullException("displayName"); + } + + m_levelValue = level; #if NETSTANDARD1_3 - m_levelName = levelName; + m_levelName = levelName; #else - m_levelName = string.Intern(levelName); + m_levelName = string.Intern(levelName); #endif - m_levelDisplayName = displayName; - } - - /// - /// Constructor - /// - /// Integer value for this level, higher values represent more severe levels. - /// The string name of this level. - /// - /// - /// Initializes a new instance of the class with - /// the specified level name and value. - /// - /// - public Level(int level, string levelName) : this(level, levelName, levelName) - { - } - - #endregion Public Instance Constructors - - #region Public Instance Properties - - /// - /// Gets the name of this level. - /// - /// - /// The name of this level. - /// - /// - /// - /// Gets the name of this level. - /// - /// - public string Name - { - get { return m_levelName; } - } - - /// - /// Gets the value of this level. - /// - /// - /// The value of this level. - /// - /// - /// - /// Gets the value of this level. - /// - /// - public int Value - { - get { return m_levelValue; } - } - - /// - /// Gets the display name of this level. - /// - /// - /// The display name of this level. - /// - /// - /// - /// Gets the display name of this level. - /// - /// - public string DisplayName - { - get { return m_levelDisplayName; } - } - - #endregion Public Instance Properties - - #region Override implementation of Object - - /// - /// Returns the representation of the current - /// . - /// - /// - /// A representation of the current . - /// - /// - /// - /// Returns the level . - /// - /// - public override string ToString() - { - return m_levelName; - } - - /// - /// Compares levels. - /// - /// The object to compare against. - /// true if the objects are equal. - /// - /// - /// Compares the levels of instances, and - /// defers to base class if the target object is not a - /// instance. - /// - /// - public override bool Equals(object o) - { - Level otherLevel = o as Level; - if (otherLevel != null) - { - return m_levelValue == otherLevel.m_levelValue; - } - else - { - return base.Equals(o); - } - } - - /// - /// Returns a hash code - /// - /// A hash code for the current . - /// - /// - /// Returns a hash code suitable for use in hashing algorithms and data - /// structures like a hash table. - /// - /// - /// Returns the hash code of the level . - /// - /// - public override int GetHashCode() - { - return m_levelValue; - } - - #endregion Override implementation of Object - - #region Implementation of IComparable - - /// - /// Compares this instance to a specified object and returns an - /// indication of their relative values. - /// - /// A instance or to compare with this instance. - /// - /// A 32-bit signed integer that indicates the relative order of the - /// values compared. The return value has these meanings: - /// - /// - /// Value - /// Meaning - /// - /// - /// Less than zero - /// This instance is less than . - /// - /// - /// Zero - /// This instance is equal to . - /// - /// - /// Greater than zero - /// - /// This instance is greater than . - /// -or- - /// is . - /// - /// - /// - /// - /// - /// - /// must be an instance of - /// or ; otherwise, an exception is thrown. - /// - /// - /// is not a . - public int CompareTo(object r) - { - Level target = r as Level; - if (target != null) - { - return Compare(this, target); - } - throw new ArgumentException("Parameter: r, Value: [" + r + "] is not an instance of Level"); - } - - #endregion Implementation of IComparable - - #region Operators - - /// - /// Returns a value indicating whether a specified - /// is greater than another specified . - /// - /// A - /// A - /// - /// true if is greater than - /// ; otherwise, false. - /// - /// - /// - /// Compares two levels. - /// - /// - public static bool operator > (Level l, Level r) - { - return l.m_levelValue > r.m_levelValue; - } - - /// - /// Returns a value indicating whether a specified - /// is less than another specified . - /// - /// A - /// A - /// - /// true if is less than - /// ; otherwise, false. - /// - /// - /// - /// Compares two levels. - /// - /// - public static bool operator < (Level l, Level r) - { - return l.m_levelValue < r.m_levelValue; - } - - /// - /// Returns a value indicating whether a specified - /// is greater than or equal to another specified . - /// - /// A - /// A - /// - /// true if is greater than or equal to - /// ; otherwise, false. - /// - /// - /// - /// Compares two levels. - /// - /// - public static bool operator >= (Level l, Level r) - { - return l.m_levelValue >= r.m_levelValue; - } - - /// - /// Returns a value indicating whether a specified - /// is less than or equal to another specified . - /// - /// A - /// A - /// - /// true if is less than or equal to - /// ; otherwise, false. - /// - /// - /// - /// Compares two levels. - /// - /// - public static bool operator <= (Level l, Level r) - { - return l.m_levelValue <= r.m_levelValue; - } - - /// - /// Returns a value indicating whether two specified - /// objects have the same value. - /// - /// A or . - /// A or . - /// - /// true if the value of is the same as the - /// value of ; otherwise, false. - /// - /// - /// - /// Compares two levels. - /// - /// - public static bool operator == (Level l, Level r) - { - if (((object)l) != null && ((object)r) != null) - { - return l.m_levelValue == r.m_levelValue; - } - else - { - return ((object) l) == ((object) r); - } - } - - /// - /// Returns a value indicating whether two specified - /// objects have different values. - /// - /// A or . - /// A or . - /// - /// true if the value of is different from - /// the value of ; otherwise, false. - /// - /// - /// - /// Compares two levels. - /// - /// - public static bool operator != (Level l, Level r) - { - return !(l==r); - } - - #endregion Operators - - #region Public Static Methods - - /// - /// Compares two specified instances. - /// - /// The first to compare. - /// The second to compare. - /// - /// A 32-bit signed integer that indicates the relative order of the - /// two values compared. The return value has these meanings: - /// - /// - /// Value - /// Meaning - /// - /// - /// Less than zero - /// is less than . - /// - /// - /// Zero - /// is equal to . - /// - /// - /// Greater than zero - /// is greater than . - /// - /// - /// - /// - /// - /// Compares two levels. - /// - /// - public static int Compare(Level l, Level r) - { - // Reference equals - if ((object)l == (object)r) - { - return 0; - } - - if (l == null && r == null) - { - return 0; - } - if (l == null) - { - return -1; - } - if (r == null) - { - return 1; - } - - return l.m_levelValue.CompareTo(r.m_levelValue); - } - - #endregion Public Static Methods - - #region Public Static Fields - - /// - /// The level designates a higher level than all the rest. - /// - public static readonly Level Off = new Level(int.MaxValue, "OFF"); + m_levelDisplayName = displayName; + } + + /// + /// Constructor + /// + /// Integer value for this level, higher values represent more severe levels. + /// The string name of this level. + /// + /// + /// Initializes a new instance of the class with + /// the specified level name and value. + /// + /// + public Level(int level, string levelName) : this(level, levelName, levelName) + { + } + + #endregion Public Instance Constructors + + #region Public Instance Properties + + /// + /// Gets the name of this level. + /// + /// + /// The name of this level. + /// + /// + /// + /// Gets the name of this level. + /// + /// + public string Name + { + get { return m_levelName; } + } + + /// + /// Gets the value of this level. + /// + /// + /// The value of this level. + /// + /// + /// + /// Gets the value of this level. + /// + /// + public int Value + { + get { return m_levelValue; } + } + + /// + /// Gets the display name of this level. + /// + /// + /// The display name of this level. + /// + /// + /// + /// Gets the display name of this level. + /// + /// + public string DisplayName + { + get { return m_levelDisplayName; } + } + + #endregion Public Instance Properties + + #region Override implementation of Object + + /// + /// Returns the representation of the current + /// . + /// + /// + /// A representation of the current . + /// + /// + /// + /// Returns the level . + /// + /// + public override string ToString() + { + return m_levelName; + } + + /// + /// Compares levels. + /// + /// The object to compare against. + /// true if the objects are equal. + /// + /// + /// Compares the levels of instances, and + /// defers to base class if the target object is not a + /// instance. + /// + /// + public override bool Equals(object o) + { + Level otherLevel = o as Level; + if (otherLevel != null) + { + return m_levelValue == otherLevel.m_levelValue; + } + else + { + return base.Equals(o); + } + } + + /// + /// Returns a hash code + /// + /// A hash code for the current . + /// + /// + /// Returns a hash code suitable for use in hashing algorithms and data + /// structures like a hash table. + /// + /// + /// Returns the hash code of the level . + /// + /// + public override int GetHashCode() + { + return m_levelValue; + } + + #endregion Override implementation of Object + + #region Implementation of IComparable + + /// + /// Compares this instance to a specified object and returns an + /// indication of their relative values. + /// + /// A instance or to compare with this instance. + /// + /// A 32-bit signed integer that indicates the relative order of the + /// values compared. The return value has these meanings: + /// + /// + /// Value + /// Meaning + /// + /// + /// Less than zero + /// This instance is less than . + /// + /// + /// Zero + /// This instance is equal to . + /// + /// + /// Greater than zero + /// + /// This instance is greater than . + /// -or- + /// is . + /// + /// + /// + /// + /// + /// + /// must be an instance of + /// or ; otherwise, an exception is thrown. + /// + /// + /// is not a . + public int CompareTo(object r) + { + Level target = r as Level; + if (target != null) + { + return Compare(this, target); + } + throw new ArgumentException("Parameter: r, Value: [" + r + "] is not an instance of Level"); + } + + #endregion Implementation of IComparable + + #region Operators + + /// + /// Returns a value indicating whether a specified + /// is greater than another specified . + /// + /// A + /// A + /// + /// true if is greater than + /// ; otherwise, false. + /// + /// + /// + /// Compares two levels. + /// + /// + public static bool operator > (Level l, Level r) + { + return l.m_levelValue > r.m_levelValue; + } + + /// + /// Returns a value indicating whether a specified + /// is less than another specified . + /// + /// A + /// A + /// + /// true if is less than + /// ; otherwise, false. + /// + /// + /// + /// Compares two levels. + /// + /// + public static bool operator < (Level l, Level r) + { + return l.m_levelValue < r.m_levelValue; + } + + /// + /// Returns a value indicating whether a specified + /// is greater than or equal to another specified . + /// + /// A + /// A + /// + /// true if is greater than or equal to + /// ; otherwise, false. + /// + /// + /// + /// Compares two levels. + /// + /// + public static bool operator >= (Level l, Level r) + { + return l.m_levelValue >= r.m_levelValue; + } + + /// + /// Returns a value indicating whether a specified + /// is less than or equal to another specified . + /// + /// A + /// A + /// + /// true if is less than or equal to + /// ; otherwise, false. + /// + /// + /// + /// Compares two levels. + /// + /// + public static bool operator <= (Level l, Level r) + { + return l.m_levelValue <= r.m_levelValue; + } + + /// + /// Returns a value indicating whether two specified + /// objects have the same value. + /// + /// A or . + /// A or . + /// + /// true if the value of is the same as the + /// value of ; otherwise, false. + /// + /// + /// + /// Compares two levels. + /// + /// + public static bool operator == (Level l, Level r) + { + if (((object)l) != null && ((object)r) != null) + { + return l.m_levelValue == r.m_levelValue; + } + else + { + return ((object) l) == ((object) r); + } + } + + /// + /// Returns a value indicating whether two specified + /// objects have different values. + /// + /// A or . + /// A or . + /// + /// true if the value of is different from + /// the value of ; otherwise, false. + /// + /// + /// + /// Compares two levels. + /// + /// + public static bool operator != (Level l, Level r) + { + return !(l==r); + } + + #endregion Operators + + #region Public Static Methods + + /// + /// Compares two specified instances. + /// + /// The first to compare. + /// The second to compare. + /// + /// A 32-bit signed integer that indicates the relative order of the + /// two values compared. The return value has these meanings: + /// + /// + /// Value + /// Meaning + /// + /// + /// Less than zero + /// is less than . + /// + /// + /// Zero + /// is equal to . + /// + /// + /// Greater than zero + /// is greater than . + /// + /// + /// + /// + /// + /// Compares two levels. + /// + /// + public static int Compare(Level l, Level r) + { + // Reference equals + if ((object)l == (object)r) + { + return 0; + } + + if (l == null && r == null) + { + return 0; + } + if (l == null) + { + return -1; + } + if (r == null) + { + return 1; + } + + return l.m_levelValue.CompareTo(r.m_levelValue); + } + + #endregion Public Static Methods + + #region Public Static Fields + + /// + /// The level designates a higher level than all the rest. + /// + public static readonly Level Off = new Level(int.MaxValue, "OFF"); /// /// The level designates very severe error events. @@ -508,108 +508,108 @@ public static int Compare(Level l, Level r) /// public static readonly Level Log4Net_Debug = new Level(120000, "log4net:DEBUG"); - /// - /// The level designates very severe error events. - /// System unusable, emergencies. - /// - public static readonly Level Emergency = new Level(120000, "EMERGENCY"); - - /// - /// The level designates very severe error events - /// that will presumably lead the application to abort. - /// - public static readonly Level Fatal = new Level(110000, "FATAL"); - - /// - /// The level designates very severe error events. - /// Take immediate action, alerts. - /// - public static readonly Level Alert = new Level(100000, "ALERT"); - - /// - /// The level designates very severe error events. - /// Critical condition, critical. - /// - public static readonly Level Critical = new Level(90000, "CRITICAL"); - - /// - /// The level designates very severe error events. - /// - public static readonly Level Severe = new Level(80000, "SEVERE"); - - /// - /// The level designates error events that might - /// still allow the application to continue running. - /// - public static readonly Level Error = new Level(70000, "ERROR"); - - /// - /// The level designates potentially harmful - /// situations. - /// - public static readonly Level Warn = new Level(60000, "WARN"); - - /// - /// The level designates informational messages - /// that highlight the progress of the application at the highest level. - /// - public static readonly Level Notice = new Level(50000, "NOTICE"); - - /// - /// The level designates informational messages that - /// highlight the progress of the application at coarse-grained level. - /// - public static readonly Level Info = new Level(40000, "INFO"); - - /// - /// The level designates fine-grained informational - /// events that are most useful to debug an application. - /// - public static readonly Level Debug = new Level(30000, "DEBUG"); - - /// - /// The level designates fine-grained informational - /// events that are most useful to debug an application. - /// - public static readonly Level Fine = new Level(30000, "FINE"); - - /// - /// The level designates fine-grained informational - /// events that are most useful to debug an application. - /// - public static readonly Level Trace = new Level(20000, "TRACE"); - - /// - /// The level designates fine-grained informational - /// events that are most useful to debug an application. - /// - public static readonly Level Finer = new Level(20000, "FINER"); - - /// - /// The level designates fine-grained informational - /// events that are most useful to debug an application. - /// - public static readonly Level Verbose = new Level(10000, "VERBOSE"); - - /// - /// The level designates fine-grained informational - /// events that are most useful to debug an application. - /// - public static readonly Level Finest = new Level(10000, "FINEST"); - - /// - /// The level designates the lowest level possible. - /// - public static readonly Level All = new Level(int.MinValue, "ALL"); - - #endregion Public Static Fields - - #region Private Instance Fields - - private readonly int m_levelValue; - private readonly string m_levelName; - private readonly string m_levelDisplayName; - - #endregion Private Instance Fields - } + /// + /// The level designates very severe error events. + /// System unusable, emergencies. + /// + public static readonly Level Emergency = new Level(120000, "EMERGENCY"); + + /// + /// The level designates very severe error events + /// that will presumably lead the application to abort. + /// + public static readonly Level Fatal = new Level(110000, "FATAL"); + + /// + /// The level designates very severe error events. + /// Take immediate action, alerts. + /// + public static readonly Level Alert = new Level(100000, "ALERT"); + + /// + /// The level designates very severe error events. + /// Critical condition, critical. + /// + public static readonly Level Critical = new Level(90000, "CRITICAL"); + + /// + /// The level designates very severe error events. + /// + public static readonly Level Severe = new Level(80000, "SEVERE"); + + /// + /// The level designates error events that might + /// still allow the application to continue running. + /// + public static readonly Level Error = new Level(70000, "ERROR"); + + /// + /// The level designates potentially harmful + /// situations. + /// + public static readonly Level Warn = new Level(60000, "WARN"); + + /// + /// The level designates informational messages + /// that highlight the progress of the application at the highest level. + /// + public static readonly Level Notice = new Level(50000, "NOTICE"); + + /// + /// The level designates informational messages that + /// highlight the progress of the application at coarse-grained level. + /// + public static readonly Level Info = new Level(40000, "INFO"); + + /// + /// The level designates fine-grained informational + /// events that are most useful to debug an application. + /// + public static readonly Level Debug = new Level(30000, "DEBUG"); + + /// + /// The level designates fine-grained informational + /// events that are most useful to debug an application. + /// + public static readonly Level Fine = new Level(30000, "FINE"); + + /// + /// The level designates fine-grained informational + /// events that are most useful to debug an application. + /// + public static readonly Level Trace = new Level(20000, "TRACE"); + + /// + /// The level designates fine-grained informational + /// events that are most useful to debug an application. + /// + public static readonly Level Finer = new Level(20000, "FINER"); + + /// + /// The level designates fine-grained informational + /// events that are most useful to debug an application. + /// + public static readonly Level Verbose = new Level(10000, "VERBOSE"); + + /// + /// The level designates fine-grained informational + /// events that are most useful to debug an application. + /// + public static readonly Level Finest = new Level(10000, "FINEST"); + + /// + /// The level designates the lowest level possible. + /// + public static readonly Level All = new Level(int.MinValue, "ALL"); + + #endregion Public Static Fields + + #region Private Instance Fields + + private readonly int m_levelValue; + private readonly string m_levelName; + private readonly string m_levelDisplayName; + + #endregion Private Instance Fields + } } diff --git a/src/log4net/Core/LevelCollection.cs b/src/log4net/Core/LevelCollection.cs index d51bd0d9..649eeca7 100644 --- a/src/log4net/Core/LevelCollection.cs +++ b/src/log4net/Core/LevelCollection.cs @@ -22,839 +22,839 @@ namespace log4net.Core { - /// - /// A strongly-typed collection of objects. - /// - /// Nicko Cadell - public class LevelCollection : ICollection, IList, IEnumerable + /// + /// A strongly-typed collection of objects. + /// + /// Nicko Cadell + public class LevelCollection : ICollection, IList, IEnumerable #if !NETSTANDARD1_3 - , ICloneable + , ICloneable #endif - { - #region Interfaces - - /// - /// Supports type-safe iteration over a . - /// - public interface ILevelCollectionEnumerator - { - /// - /// Gets the current element in the collection. - /// - Level Current { get; } - - /// - /// Advances the enumerator to the next element in the collection. - /// - /// - /// true if the enumerator was successfully advanced to the next element; - /// false if the enumerator has passed the end of the collection. - /// - /// - /// The collection was modified after the enumerator was created. - /// - bool MoveNext(); - - /// - /// Sets the enumerator to its initial position, before the first element in the collection. - /// - void Reset(); - } - - #endregion - - private const int DEFAULT_CAPACITY = 16; - - #region Implementation (data) - - private Level[] m_array; - private int m_count = 0; - private int m_version = 0; - - #endregion - - #region Static Wrappers - - /// - /// Creates a read-only wrapper for a LevelCollection instance. - /// - /// list to create a readonly wrapper arround - /// - /// A LevelCollection wrapper that is read-only. - /// - public static LevelCollection ReadOnly(LevelCollection list) - { - if(list==null) throw new ArgumentNullException("list"); - - return new ReadOnlyLevelCollection(list); - } - - #endregion - - #region Constructors - - /// - /// Initializes a new instance of the LevelCollection class - /// that is empty and has the default initial capacity. - /// - public LevelCollection() - { - m_array = new Level[DEFAULT_CAPACITY]; - } - - /// - /// Initializes a new instance of the LevelCollection class - /// that has the specified initial capacity. - /// - /// - /// The number of elements that the new LevelCollection is initially capable of storing. - /// - public LevelCollection(int capacity) - { - m_array = new Level[capacity]; - } - - /// - /// Initializes a new instance of the LevelCollection class - /// that contains elements copied from the specified LevelCollection. - /// - /// The LevelCollection whose elements are copied to the new collection. - public LevelCollection(LevelCollection c) - { - m_array = new Level[c.Count]; - AddRange(c); - } - - /// - /// Initializes a new instance of the LevelCollection class - /// that contains elements copied from the specified array. - /// - /// The array whose elements are copied to the new list. - public LevelCollection(Level[] a) - { - m_array = new Level[a.Length]; - AddRange(a); - } - - /// - /// Initializes a new instance of the LevelCollection class - /// that contains elements copied from the specified collection. - /// - /// The collection whose elements are copied to the new list. - public LevelCollection(ICollection col) - { - m_array = new Level[col.Count]; - AddRange(col); - } - - /// - /// Type visible only to our subclasses - /// Used to access protected constructor - /// - protected internal enum Tag - { - /// - /// A value - /// - Default - } - - /// - /// Allow subclasses to avoid our default constructors - /// - /// - protected internal LevelCollection(Tag tag) - { - m_array = null; - } - #endregion - - #region Operations (type-safe ICollection) - - /// - /// Gets the number of elements actually contained in the LevelCollection. - /// - public virtual int Count - { - get { return m_count; } - } - - /// - /// Copies the entire LevelCollection to a one-dimensional - /// array. - /// - /// The one-dimensional array to copy to. - public virtual void CopyTo(Level[] array) - { - this.CopyTo(array, 0); - } - - /// - /// Copies the entire LevelCollection to a one-dimensional - /// array, starting at the specified index of the target array. - /// - /// The one-dimensional array to copy to. - /// The zero-based index in at which copying begins. - public virtual void CopyTo(Level[] array, int start) - { - if (m_count > array.GetUpperBound(0) + 1 - start) - { - throw new System.ArgumentException("Destination array was not long enough."); - } - - Array.Copy(m_array, 0, array, start, m_count); - } - - /// - /// Gets a value indicating whether access to the collection is synchronized (thread-safe). - /// - /// false, because the backing type is an array, which is never thread-safe. - public virtual bool IsSynchronized - { - get { return false; } - } - - /// - /// Gets an object that can be used to synchronize access to the collection. - /// - public virtual object SyncRoot - { - get { return m_array; } - } - - #endregion - - #region Operations (type-safe IList) - - /// - /// Gets or sets the at the specified index. - /// - /// The zero-based index of the element to get or set. - /// - /// is less than zero - /// -or- - /// is equal to or greater than . - /// - public virtual Level this[int index] - { - get - { - ValidateIndex(index); // throws - return m_array[index]; - } - set - { - ValidateIndex(index); // throws - ++m_version; - m_array[index] = value; - } - } - - /// - /// Adds a to the end of the LevelCollection. - /// - /// The to be added to the end of the LevelCollection. - /// The index at which the value has been added. - public virtual int Add(Level item) - { - if (m_count == m_array.Length) - { - EnsureCapacity(m_count + 1); - } - - m_array[m_count] = item; - m_version++; - - return m_count++; - } - - /// - /// Removes all elements from the LevelCollection. - /// - public virtual void Clear() - { - ++m_version; - m_array = new Level[DEFAULT_CAPACITY]; - m_count = 0; - } - - /// - /// Creates a shallow copy of the . - /// - /// A new with a shallow copy of the collection data. - public virtual object Clone() - { - LevelCollection newCol = new LevelCollection(m_count); - Array.Copy(m_array, 0, newCol.m_array, 0, m_count); - newCol.m_count = m_count; - newCol.m_version = m_version; - - return newCol; - } - - /// - /// Determines whether a given is in the LevelCollection. - /// - /// The to check for. - /// true if is found in the LevelCollection; otherwise, false. - public virtual bool Contains(Level item) - { - for (int i=0; i != m_count; ++i) - { - if (m_array[i].Equals(item)) - { - return true; - } - } - return false; - } - - /// - /// Returns the zero-based index of the first occurrence of a - /// in the LevelCollection. - /// - /// The to locate in the LevelCollection. - /// - /// The zero-based index of the first occurrence of - /// in the entire LevelCollection, if found; otherwise, -1. - /// - public virtual int IndexOf(Level item) - { - for (int i=0; i != m_count; ++i) - { - if (m_array[i].Equals(item)) - { - return i; - } - } - return -1; - } - - /// - /// Inserts an element into the LevelCollection at the specified index. - /// - /// The zero-based index at which should be inserted. - /// The to insert. - /// - /// is less than zero - /// -or- - /// is equal to or greater than . - /// - public virtual void Insert(int index, Level item) - { - ValidateIndex(index, true); // throws - - if (m_count == m_array.Length) - { - EnsureCapacity(m_count + 1); - } - - if (index < m_count) - { - Array.Copy(m_array, index, m_array, index + 1, m_count - index); - } - - m_array[index] = item; - m_count++; - m_version++; - } - - /// - /// Removes the first occurrence of a specific from the LevelCollection. - /// - /// The to remove from the LevelCollection. - /// - /// The specified was not found in the LevelCollection. - /// - public virtual void Remove(Level item) - { - int i = IndexOf(item); - if (i < 0) - { - throw new System.ArgumentException("Cannot remove the specified item because it was not found in the specified Collection."); - } - - ++m_version; - RemoveAt(i); - } - - /// - /// Removes the element at the specified index of the LevelCollection. - /// - /// The zero-based index of the element to remove. - /// - /// is less than zero - /// -or- - /// is equal to or greater than . - /// - public virtual void RemoveAt(int index) - { - ValidateIndex(index); // throws - - m_count--; - - if (index < m_count) - { - Array.Copy(m_array, index + 1, m_array, index, m_count - index); - } - - // We can't set the deleted entry equal to null, because it might be a value type. - // Instead, we'll create an empty single-element array of the right type and copy it - // over the entry we want to erase. - Level[] temp = new Level[1]; - Array.Copy(temp, 0, m_array, m_count, 1); - m_version++; - } - - /// - /// Gets a value indicating whether the collection has a fixed size. - /// - /// true if the collection has a fixed size; otherwise, false. The default is false - public virtual bool IsFixedSize - { - get { return false; } - } - - /// - /// Gets a value indicating whether the IList is read-only. - /// - /// true if the collection is read-only; otherwise, false. The default is false - public virtual bool IsReadOnly - { - get { return false; } - } - - #endregion - - #region Operations (type-safe IEnumerable) - - /// - /// Returns an enumerator that can iterate through the LevelCollection. - /// - /// An for the entire LevelCollection. - public virtual ILevelCollectionEnumerator GetEnumerator() - { - return new Enumerator(this); - } - - #endregion - - #region Public helpers (just to mimic some nice features of ArrayList) - - /// - /// Gets or sets the number of elements the LevelCollection can contain. - /// - public virtual int Capacity - { - get - { - return m_array.Length; - } - set - { - if (value < m_count) - { - value = m_count; - } - - if (value != m_array.Length) - { - if (value > 0) - { - Level[] temp = new Level[value]; - Array.Copy(m_array, 0, temp, 0, m_count); - m_array = temp; - } - else - { - m_array = new Level[DEFAULT_CAPACITY]; - } - } - } - } - - /// - /// Adds the elements of another LevelCollection to the current LevelCollection. - /// - /// The LevelCollection whose elements should be added to the end of the current LevelCollection. - /// The new of the LevelCollection. - public virtual int AddRange(LevelCollection x) - { - if (m_count + x.Count >= m_array.Length) - { - EnsureCapacity(m_count + x.Count); - } - - Array.Copy(x.m_array, 0, m_array, m_count, x.Count); - m_count += x.Count; - m_version++; - - return m_count; - } - - /// - /// Adds the elements of a array to the current LevelCollection. - /// - /// The array whose elements should be added to the end of the LevelCollection. - /// The new of the LevelCollection. - public virtual int AddRange(Level[] x) - { - if (m_count + x.Length >= m_array.Length) - { - EnsureCapacity(m_count + x.Length); - } - - Array.Copy(x, 0, m_array, m_count, x.Length); - m_count += x.Length; - m_version++; - - return m_count; - } - - /// - /// Adds the elements of a collection to the current LevelCollection. - /// - /// The collection whose elements should be added to the end of the LevelCollection. - /// The new of the LevelCollection. - public virtual int AddRange(ICollection col) - { - if (m_count + col.Count >= m_array.Length) - { - EnsureCapacity(m_count + col.Count); - } - - foreach(object item in col) - { - Add((Level)item); - } - - return m_count; - } - - /// - /// Sets the capacity to the actual number of elements. - /// - public virtual void TrimToSize() - { - this.Capacity = m_count; - } - - #endregion - - #region Implementation (helpers) - - /// - /// is less than zero - /// -or- - /// is equal to or greater than . - /// - private void ValidateIndex(int i) - { - ValidateIndex(i, false); - } - - /// - /// is less than zero - /// -or- - /// is equal to or greater than . - /// - private void ValidateIndex(int i, bool allowEqualEnd) - { - int max = (allowEqualEnd) ? (m_count) : (m_count-1); - if (i < 0 || i > max) - { - throw log4net.Util.SystemInfo.CreateArgumentOutOfRangeException("i", (object)i, "Index was out of range. Must be non-negative and less than the size of the collection. [" + (object)i + "] Specified argument was out of the range of valid values."); - } - } - - private void EnsureCapacity(int min) - { - int newCapacity = ((m_array.Length == 0) ? DEFAULT_CAPACITY : m_array.Length * 2); - if (newCapacity < min) - { - newCapacity = min; - } - - this.Capacity = newCapacity; - } - - #endregion - - #region Implementation (ICollection) - - void ICollection.CopyTo(Array array, int start) - { - Array.Copy(m_array, 0, array, start, m_count); - } - - #endregion - - #region Implementation (IList) - - object IList.this[int i] - { - get { return (object)this[i]; } - set { this[i] = (Level)value; } - } - - int IList.Add(object x) - { - return this.Add((Level)x); - } - - bool IList.Contains(object x) - { - return this.Contains((Level)x); - } - - int IList.IndexOf(object x) - { - return this.IndexOf((Level)x); - } - - void IList.Insert(int pos, object x) - { - this.Insert(pos, (Level)x); - } - - void IList.Remove(object x) - { - this.Remove((Level)x); - } - - void IList.RemoveAt(int pos) - { - this.RemoveAt(pos); - } - - #endregion - - #region Implementation (IEnumerable) - - IEnumerator IEnumerable.GetEnumerator() - { - return (IEnumerator)(this.GetEnumerator()); - } - - #endregion - - #region Nested enumerator class - - /// - /// Supports simple iteration over a . - /// - private sealed class Enumerator : IEnumerator, ILevelCollectionEnumerator - { - #region Implementation (data) - - private readonly LevelCollection m_collection; - private int m_index; - private int m_version; - - #endregion - - #region Construction - - /// - /// Initializes a new instance of the Enumerator class. - /// - /// - internal Enumerator(LevelCollection tc) - { - m_collection = tc; - m_index = -1; - m_version = tc.m_version; - } - - #endregion - - #region Operations (type-safe IEnumerator) - - /// - /// Gets the current element in the collection. - /// - public Level Current - { - get { return m_collection[m_index]; } - } - - /// - /// Advances the enumerator to the next element in the collection. - /// - /// - /// true if the enumerator was successfully advanced to the next element; - /// false if the enumerator has passed the end of the collection. - /// - /// - /// The collection was modified after the enumerator was created. - /// - public bool MoveNext() - { - if (m_version != m_collection.m_version) - { - throw new System.InvalidOperationException("Collection was modified; enumeration operation may not execute."); - } - - ++m_index; - return (m_index < m_collection.Count); - } - - /// - /// Sets the enumerator to its initial position, before the first element in the collection. - /// - public void Reset() - { - m_index = -1; - } - - #endregion - - #region Implementation (IEnumerator) - - object IEnumerator.Current - { - get { return this.Current; } - } - - #endregion - } - - #endregion - - #region Nested Read Only Wrapper class - - private sealed class ReadOnlyLevelCollection : LevelCollection - { - #region Implementation (data) - - private readonly LevelCollection m_collection; - - #endregion - - #region Construction - - internal ReadOnlyLevelCollection(LevelCollection list) : base(Tag.Default) - { - m_collection = list; - } - - #endregion - - #region Type-safe ICollection - - public override void CopyTo(Level[] array) - { - m_collection.CopyTo(array); - } - - public override void CopyTo(Level[] array, int start) - { - m_collection.CopyTo(array,start); - } - public override int Count - { - get { return m_collection.Count; } - } - - public override bool IsSynchronized - { - get { return m_collection.IsSynchronized; } - } - - public override object SyncRoot - { - get { return this.m_collection.SyncRoot; } - } - - #endregion - - #region Type-safe IList - - public override Level this[int i] - { - get { return m_collection[i]; } - set { throw new NotSupportedException("This is a Read Only Collection and can not be modified"); } - } - - public override int Add(Level x) - { - throw new NotSupportedException("This is a Read Only Collection and can not be modified"); - } - - public override void Clear() - { - throw new NotSupportedException("This is a Read Only Collection and can not be modified"); - } - - public override bool Contains(Level x) - { - return m_collection.Contains(x); - } - - public override int IndexOf(Level x) - { - return m_collection.IndexOf(x); - } - - public override void Insert(int pos, Level x) - { - throw new NotSupportedException("This is a Read Only Collection and can not be modified"); - } - - public override void Remove(Level x) - { - throw new NotSupportedException("This is a Read Only Collection and can not be modified"); - } - - public override void RemoveAt(int pos) - { - throw new NotSupportedException("This is a Read Only Collection and can not be modified"); - } - - public override bool IsFixedSize - { - get { return true; } - } + { + #region Interfaces + + /// + /// Supports type-safe iteration over a . + /// + public interface ILevelCollectionEnumerator + { + /// + /// Gets the current element in the collection. + /// + Level Current { get; } + + /// + /// Advances the enumerator to the next element in the collection. + /// + /// + /// true if the enumerator was successfully advanced to the next element; + /// false if the enumerator has passed the end of the collection. + /// + /// + /// The collection was modified after the enumerator was created. + /// + bool MoveNext(); + + /// + /// Sets the enumerator to its initial position, before the first element in the collection. + /// + void Reset(); + } + + #endregion + + private const int DEFAULT_CAPACITY = 16; + + #region Implementation (data) + + private Level[] m_array; + private int m_count = 0; + private int m_version = 0; + + #endregion + + #region Static Wrappers + + /// + /// Creates a read-only wrapper for a LevelCollection instance. + /// + /// list to create a readonly wrapper arround + /// + /// A LevelCollection wrapper that is read-only. + /// + public static LevelCollection ReadOnly(LevelCollection list) + { + if(list==null) throw new ArgumentNullException("list"); + + return new ReadOnlyLevelCollection(list); + } + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the LevelCollection class + /// that is empty and has the default initial capacity. + /// + public LevelCollection() + { + m_array = new Level[DEFAULT_CAPACITY]; + } + + /// + /// Initializes a new instance of the LevelCollection class + /// that has the specified initial capacity. + /// + /// + /// The number of elements that the new LevelCollection is initially capable of storing. + /// + public LevelCollection(int capacity) + { + m_array = new Level[capacity]; + } + + /// + /// Initializes a new instance of the LevelCollection class + /// that contains elements copied from the specified LevelCollection. + /// + /// The LevelCollection whose elements are copied to the new collection. + public LevelCollection(LevelCollection c) + { + m_array = new Level[c.Count]; + AddRange(c); + } + + /// + /// Initializes a new instance of the LevelCollection class + /// that contains elements copied from the specified array. + /// + /// The array whose elements are copied to the new list. + public LevelCollection(Level[] a) + { + m_array = new Level[a.Length]; + AddRange(a); + } + + /// + /// Initializes a new instance of the LevelCollection class + /// that contains elements copied from the specified collection. + /// + /// The collection whose elements are copied to the new list. + public LevelCollection(ICollection col) + { + m_array = new Level[col.Count]; + AddRange(col); + } + + /// + /// Type visible only to our subclasses + /// Used to access protected constructor + /// + protected internal enum Tag + { + /// + /// A value + /// + Default + } + + /// + /// Allow subclasses to avoid our default constructors + /// + /// + protected internal LevelCollection(Tag tag) + { + m_array = null; + } + #endregion + + #region Operations (type-safe ICollection) + + /// + /// Gets the number of elements actually contained in the LevelCollection. + /// + public virtual int Count + { + get { return m_count; } + } + + /// + /// Copies the entire LevelCollection to a one-dimensional + /// array. + /// + /// The one-dimensional array to copy to. + public virtual void CopyTo(Level[] array) + { + this.CopyTo(array, 0); + } + + /// + /// Copies the entire LevelCollection to a one-dimensional + /// array, starting at the specified index of the target array. + /// + /// The one-dimensional array to copy to. + /// The zero-based index in at which copying begins. + public virtual void CopyTo(Level[] array, int start) + { + if (m_count > array.GetUpperBound(0) + 1 - start) + { + throw new System.ArgumentException("Destination array was not long enough."); + } + + Array.Copy(m_array, 0, array, start, m_count); + } + + /// + /// Gets a value indicating whether access to the collection is synchronized (thread-safe). + /// + /// false, because the backing type is an array, which is never thread-safe. + public virtual bool IsSynchronized + { + get { return false; } + } + + /// + /// Gets an object that can be used to synchronize access to the collection. + /// + public virtual object SyncRoot + { + get { return m_array; } + } + + #endregion + + #region Operations (type-safe IList) + + /// + /// Gets or sets the at the specified index. + /// + /// The zero-based index of the element to get or set. + /// + /// is less than zero + /// -or- + /// is equal to or greater than . + /// + public virtual Level this[int index] + { + get + { + ValidateIndex(index); // throws + return m_array[index]; + } + set + { + ValidateIndex(index); // throws + ++m_version; + m_array[index] = value; + } + } + + /// + /// Adds a to the end of the LevelCollection. + /// + /// The to be added to the end of the LevelCollection. + /// The index at which the value has been added. + public virtual int Add(Level item) + { + if (m_count == m_array.Length) + { + EnsureCapacity(m_count + 1); + } + + m_array[m_count] = item; + m_version++; + + return m_count++; + } + + /// + /// Removes all elements from the LevelCollection. + /// + public virtual void Clear() + { + ++m_version; + m_array = new Level[DEFAULT_CAPACITY]; + m_count = 0; + } + + /// + /// Creates a shallow copy of the . + /// + /// A new with a shallow copy of the collection data. + public virtual object Clone() + { + LevelCollection newCol = new LevelCollection(m_count); + Array.Copy(m_array, 0, newCol.m_array, 0, m_count); + newCol.m_count = m_count; + newCol.m_version = m_version; + + return newCol; + } + + /// + /// Determines whether a given is in the LevelCollection. + /// + /// The to check for. + /// true if is found in the LevelCollection; otherwise, false. + public virtual bool Contains(Level item) + { + for (int i=0; i != m_count; ++i) + { + if (m_array[i].Equals(item)) + { + return true; + } + } + return false; + } + + /// + /// Returns the zero-based index of the first occurrence of a + /// in the LevelCollection. + /// + /// The to locate in the LevelCollection. + /// + /// The zero-based index of the first occurrence of + /// in the entire LevelCollection, if found; otherwise, -1. + /// + public virtual int IndexOf(Level item) + { + for (int i=0; i != m_count; ++i) + { + if (m_array[i].Equals(item)) + { + return i; + } + } + return -1; + } + + /// + /// Inserts an element into the LevelCollection at the specified index. + /// + /// The zero-based index at which should be inserted. + /// The to insert. + /// + /// is less than zero + /// -or- + /// is equal to or greater than . + /// + public virtual void Insert(int index, Level item) + { + ValidateIndex(index, true); // throws + + if (m_count == m_array.Length) + { + EnsureCapacity(m_count + 1); + } + + if (index < m_count) + { + Array.Copy(m_array, index, m_array, index + 1, m_count - index); + } + + m_array[index] = item; + m_count++; + m_version++; + } + + /// + /// Removes the first occurrence of a specific from the LevelCollection. + /// + /// The to remove from the LevelCollection. + /// + /// The specified was not found in the LevelCollection. + /// + public virtual void Remove(Level item) + { + int i = IndexOf(item); + if (i < 0) + { + throw new System.ArgumentException("Cannot remove the specified item because it was not found in the specified Collection."); + } + + ++m_version; + RemoveAt(i); + } + + /// + /// Removes the element at the specified index of the LevelCollection. + /// + /// The zero-based index of the element to remove. + /// + /// is less than zero + /// -or- + /// is equal to or greater than . + /// + public virtual void RemoveAt(int index) + { + ValidateIndex(index); // throws + + m_count--; + + if (index < m_count) + { + Array.Copy(m_array, index + 1, m_array, index, m_count - index); + } + + // We can't set the deleted entry equal to null, because it might be a value type. + // Instead, we'll create an empty single-element array of the right type and copy it + // over the entry we want to erase. + Level[] temp = new Level[1]; + Array.Copy(temp, 0, m_array, m_count, 1); + m_version++; + } + + /// + /// Gets a value indicating whether the collection has a fixed size. + /// + /// true if the collection has a fixed size; otherwise, false. The default is false + public virtual bool IsFixedSize + { + get { return false; } + } + + /// + /// Gets a value indicating whether the IList is read-only. + /// + /// true if the collection is read-only; otherwise, false. The default is false + public virtual bool IsReadOnly + { + get { return false; } + } + + #endregion + + #region Operations (type-safe IEnumerable) + + /// + /// Returns an enumerator that can iterate through the LevelCollection. + /// + /// An for the entire LevelCollection. + public virtual ILevelCollectionEnumerator GetEnumerator() + { + return new Enumerator(this); + } + + #endregion + + #region Public helpers (just to mimic some nice features of ArrayList) + + /// + /// Gets or sets the number of elements the LevelCollection can contain. + /// + public virtual int Capacity + { + get + { + return m_array.Length; + } + set + { + if (value < m_count) + { + value = m_count; + } + + if (value != m_array.Length) + { + if (value > 0) + { + Level[] temp = new Level[value]; + Array.Copy(m_array, 0, temp, 0, m_count); + m_array = temp; + } + else + { + m_array = new Level[DEFAULT_CAPACITY]; + } + } + } + } + + /// + /// Adds the elements of another LevelCollection to the current LevelCollection. + /// + /// The LevelCollection whose elements should be added to the end of the current LevelCollection. + /// The new of the LevelCollection. + public virtual int AddRange(LevelCollection x) + { + if (m_count + x.Count >= m_array.Length) + { + EnsureCapacity(m_count + x.Count); + } + + Array.Copy(x.m_array, 0, m_array, m_count, x.Count); + m_count += x.Count; + m_version++; + + return m_count; + } + + /// + /// Adds the elements of a array to the current LevelCollection. + /// + /// The array whose elements should be added to the end of the LevelCollection. + /// The new of the LevelCollection. + public virtual int AddRange(Level[] x) + { + if (m_count + x.Length >= m_array.Length) + { + EnsureCapacity(m_count + x.Length); + } + + Array.Copy(x, 0, m_array, m_count, x.Length); + m_count += x.Length; + m_version++; + + return m_count; + } + + /// + /// Adds the elements of a collection to the current LevelCollection. + /// + /// The collection whose elements should be added to the end of the LevelCollection. + /// The new of the LevelCollection. + public virtual int AddRange(ICollection col) + { + if (m_count + col.Count >= m_array.Length) + { + EnsureCapacity(m_count + col.Count); + } + + foreach(object item in col) + { + Add((Level)item); + } + + return m_count; + } + + /// + /// Sets the capacity to the actual number of elements. + /// + public virtual void TrimToSize() + { + this.Capacity = m_count; + } + + #endregion + + #region Implementation (helpers) + + /// + /// is less than zero + /// -or- + /// is equal to or greater than . + /// + private void ValidateIndex(int i) + { + ValidateIndex(i, false); + } + + /// + /// is less than zero + /// -or- + /// is equal to or greater than . + /// + private void ValidateIndex(int i, bool allowEqualEnd) + { + int max = (allowEqualEnd) ? (m_count) : (m_count-1); + if (i < 0 || i > max) + { + throw log4net.Util.SystemInfo.CreateArgumentOutOfRangeException("i", (object)i, "Index was out of range. Must be non-negative and less than the size of the collection. [" + (object)i + "] Specified argument was out of the range of valid values."); + } + } + + private void EnsureCapacity(int min) + { + int newCapacity = ((m_array.Length == 0) ? DEFAULT_CAPACITY : m_array.Length * 2); + if (newCapacity < min) + { + newCapacity = min; + } + + this.Capacity = newCapacity; + } + + #endregion + + #region Implementation (ICollection) + + void ICollection.CopyTo(Array array, int start) + { + Array.Copy(m_array, 0, array, start, m_count); + } + + #endregion + + #region Implementation (IList) + + object IList.this[int i] + { + get { return (object)this[i]; } + set { this[i] = (Level)value; } + } + + int IList.Add(object x) + { + return this.Add((Level)x); + } + + bool IList.Contains(object x) + { + return this.Contains((Level)x); + } + + int IList.IndexOf(object x) + { + return this.IndexOf((Level)x); + } + + void IList.Insert(int pos, object x) + { + this.Insert(pos, (Level)x); + } + + void IList.Remove(object x) + { + this.Remove((Level)x); + } + + void IList.RemoveAt(int pos) + { + this.RemoveAt(pos); + } + + #endregion + + #region Implementation (IEnumerable) + + IEnumerator IEnumerable.GetEnumerator() + { + return (IEnumerator)(this.GetEnumerator()); + } + + #endregion + + #region Nested enumerator class + + /// + /// Supports simple iteration over a . + /// + private sealed class Enumerator : IEnumerator, ILevelCollectionEnumerator + { + #region Implementation (data) + + private readonly LevelCollection m_collection; + private int m_index; + private int m_version; + + #endregion + + #region Construction + + /// + /// Initializes a new instance of the Enumerator class. + /// + /// + internal Enumerator(LevelCollection tc) + { + m_collection = tc; + m_index = -1; + m_version = tc.m_version; + } + + #endregion + + #region Operations (type-safe IEnumerator) + + /// + /// Gets the current element in the collection. + /// + public Level Current + { + get { return m_collection[m_index]; } + } + + /// + /// Advances the enumerator to the next element in the collection. + /// + /// + /// true if the enumerator was successfully advanced to the next element; + /// false if the enumerator has passed the end of the collection. + /// + /// + /// The collection was modified after the enumerator was created. + /// + public bool MoveNext() + { + if (m_version != m_collection.m_version) + { + throw new System.InvalidOperationException("Collection was modified; enumeration operation may not execute."); + } + + ++m_index; + return (m_index < m_collection.Count); + } + + /// + /// Sets the enumerator to its initial position, before the first element in the collection. + /// + public void Reset() + { + m_index = -1; + } + + #endregion + + #region Implementation (IEnumerator) + + object IEnumerator.Current + { + get { return this.Current; } + } + + #endregion + } + + #endregion + + #region Nested Read Only Wrapper class + + private sealed class ReadOnlyLevelCollection : LevelCollection + { + #region Implementation (data) + + private readonly LevelCollection m_collection; + + #endregion + + #region Construction + + internal ReadOnlyLevelCollection(LevelCollection list) : base(Tag.Default) + { + m_collection = list; + } + + #endregion + + #region Type-safe ICollection + + public override void CopyTo(Level[] array) + { + m_collection.CopyTo(array); + } + + public override void CopyTo(Level[] array, int start) + { + m_collection.CopyTo(array,start); + } + public override int Count + { + get { return m_collection.Count; } + } + + public override bool IsSynchronized + { + get { return m_collection.IsSynchronized; } + } + + public override object SyncRoot + { + get { return this.m_collection.SyncRoot; } + } + + #endregion + + #region Type-safe IList + + public override Level this[int i] + { + get { return m_collection[i]; } + set { throw new NotSupportedException("This is a Read Only Collection and can not be modified"); } + } + + public override int Add(Level x) + { + throw new NotSupportedException("This is a Read Only Collection and can not be modified"); + } + + public override void Clear() + { + throw new NotSupportedException("This is a Read Only Collection and can not be modified"); + } + + public override bool Contains(Level x) + { + return m_collection.Contains(x); + } + + public override int IndexOf(Level x) + { + return m_collection.IndexOf(x); + } + + public override void Insert(int pos, Level x) + { + throw new NotSupportedException("This is a Read Only Collection and can not be modified"); + } + + public override void Remove(Level x) + { + throw new NotSupportedException("This is a Read Only Collection and can not be modified"); + } + + public override void RemoveAt(int pos) + { + throw new NotSupportedException("This is a Read Only Collection and can not be modified"); + } + + public override bool IsFixedSize + { + get { return true; } + } - public override bool IsReadOnly - { - get { return true; } - } + public override bool IsReadOnly + { + get { return true; } + } - #endregion + #endregion - #region Type-safe IEnumerable - - public override ILevelCollectionEnumerator GetEnumerator() - { - return m_collection.GetEnumerator(); - } - - #endregion - - #region Public Helpers - - // (just to mimic some nice features of ArrayList) - public override int Capacity - { - get { return m_collection.Capacity; } - set { throw new NotSupportedException("This is a Read Only Collection and can not be modified"); } - } - - public override int AddRange(LevelCollection x) - { - throw new NotSupportedException("This is a Read Only Collection and can not be modified"); - } - - public override int AddRange(Level[] x) - { - throw new NotSupportedException("This is a Read Only Collection and can not be modified"); - } - - #endregion - } - - #endregion - } + #region Type-safe IEnumerable + + public override ILevelCollectionEnumerator GetEnumerator() + { + return m_collection.GetEnumerator(); + } + + #endregion + + #region Public Helpers + + // (just to mimic some nice features of ArrayList) + public override int Capacity + { + get { return m_collection.Capacity; } + set { throw new NotSupportedException("This is a Read Only Collection and can not be modified"); } + } + + public override int AddRange(LevelCollection x) + { + throw new NotSupportedException("This is a Read Only Collection and can not be modified"); + } + + public override int AddRange(Level[] x) + { + throw new NotSupportedException("This is a Read Only Collection and can not be modified"); + } + + #endregion + } + + #endregion + } } diff --git a/src/log4net/Core/LevelEvaluator.cs b/src/log4net/Core/LevelEvaluator.cs index 35706df8..d058cee9 100644 --- a/src/log4net/Core/LevelEvaluator.cs +++ b/src/log4net/Core/LevelEvaluator.cs @@ -23,111 +23,111 @@ namespace log4net.Core { - /// - /// An evaluator that triggers at a threshold level - /// - /// - /// - /// This evaluator will trigger if the level of the event - /// passed to - /// is equal to or greater than the - /// level. - /// - /// - /// Nicko Cadell - public class LevelEvaluator : ITriggeringEventEvaluator - { - /// - /// The threshold for triggering - /// - private Level m_threshold; + /// + /// An evaluator that triggers at a threshold level + /// + /// + /// + /// This evaluator will trigger if the level of the event + /// passed to + /// is equal to or greater than the + /// level. + /// + /// + /// Nicko Cadell + public class LevelEvaluator : ITriggeringEventEvaluator + { + /// + /// The threshold for triggering + /// + private Level m_threshold; - /// - /// Create a new evaluator using the threshold. - /// - /// - /// - /// Create a new evaluator using the threshold. - /// - /// - /// This evaluator will trigger if the level of the event - /// passed to - /// is equal to or greater than the - /// level. - /// - /// - public LevelEvaluator() : this(Level.Off) - { - } + /// + /// Create a new evaluator using the threshold. + /// + /// + /// + /// Create a new evaluator using the threshold. + /// + /// + /// This evaluator will trigger if the level of the event + /// passed to + /// is equal to or greater than the + /// level. + /// + /// + public LevelEvaluator() : this(Level.Off) + { + } - /// - /// Create a new evaluator using the specified threshold. - /// - /// the threshold to trigger at - /// - /// - /// Create a new evaluator using the specified threshold. - /// - /// - /// This evaluator will trigger if the level of the event - /// passed to - /// is equal to or greater than the - /// level. - /// - /// - public LevelEvaluator(Level threshold) - { - if (threshold == null) - { - throw new ArgumentNullException("threshold"); - } + /// + /// Create a new evaluator using the specified threshold. + /// + /// the threshold to trigger at + /// + /// + /// Create a new evaluator using the specified threshold. + /// + /// + /// This evaluator will trigger if the level of the event + /// passed to + /// is equal to or greater than the + /// level. + /// + /// + public LevelEvaluator(Level threshold) + { + if (threshold == null) + { + throw new ArgumentNullException("threshold"); + } - m_threshold = threshold; - } + m_threshold = threshold; + } - /// - /// the threshold to trigger at - /// - /// - /// The that will cause this evaluator to trigger - /// - /// - /// - /// This evaluator will trigger if the level of the event - /// passed to - /// is equal to or greater than the - /// level. - /// - /// - public Level Threshold - { - get { return m_threshold; } - set { m_threshold = value; } - } + /// + /// the threshold to trigger at + /// + /// + /// The that will cause this evaluator to trigger + /// + /// + /// + /// This evaluator will trigger if the level of the event + /// passed to + /// is equal to or greater than the + /// level. + /// + /// + public Level Threshold + { + get { return m_threshold; } + set { m_threshold = value; } + } - /// - /// Is this the triggering event? - /// - /// The event to check - /// This method returns true, if the event level - /// is equal or higher than the . - /// Otherwise it returns false - /// - /// - /// This evaluator will trigger if the level of the event - /// passed to - /// is equal to or greater than the - /// level. - /// - /// - public bool IsTriggeringEvent(LoggingEvent loggingEvent) - { - if (loggingEvent == null) - { - throw new ArgumentNullException("loggingEvent"); - } + /// + /// Is this the triggering event? + /// + /// The event to check + /// This method returns true, if the event level + /// is equal or higher than the . + /// Otherwise it returns false + /// + /// + /// This evaluator will trigger if the level of the event + /// passed to + /// is equal to or greater than the + /// level. + /// + /// + public bool IsTriggeringEvent(LoggingEvent loggingEvent) + { + if (loggingEvent == null) + { + throw new ArgumentNullException("loggingEvent"); + } - return (loggingEvent.Level >= m_threshold); - } - } + return (loggingEvent.Level >= m_threshold); + } + } } diff --git a/src/log4net/Core/LevelMap.cs b/src/log4net/Core/LevelMap.cs index d458533a..7558d1ac 100644 --- a/src/log4net/Core/LevelMap.cs +++ b/src/log4net/Core/LevelMap.cs @@ -25,205 +25,205 @@ namespace log4net.Core { - /// - /// Mapping between string name and Level object - /// - /// - /// - /// Mapping between string name and object. - /// This mapping is held separately for each . - /// The level name is case insensitive. - /// - /// - /// Nicko Cadell - public sealed class LevelMap - { - #region Member Variables - - /// - /// Mapping from level name to Level object. The - /// level name is case insensitive - /// - private Hashtable m_mapName2Level = SystemInfo.CreateCaseInsensitiveHashtable(); - - #endregion - - /// - /// Construct the level map - /// - /// - /// - /// Construct the level map. - /// - /// - public LevelMap() - { - } - - /// - /// Clear the internal maps of all levels - /// - /// - /// - /// Clear the internal maps of all levels - /// - /// - public void Clear() - { - // Clear all current levels - m_mapName2Level.Clear(); - } - - /// - /// Lookup a by name - /// - /// The name of the Level to lookup - /// a Level from the map with the name specified - /// - /// - /// Returns the from the - /// map with the name specified. If the no level is - /// found then null is returned. - /// - /// - public Level this[string name] - { - get - { - if (name == null) - { - throw new ArgumentNullException("name"); - } - - lock(this) - { - return (Level)m_mapName2Level[name]; - } - } - } - - /// - /// Create a new Level and add it to the map - /// - /// the string to display for the Level - /// the level value to give to the Level - /// - /// - /// Create a new Level and add it to the map - /// - /// - /// - public void Add(string name, int value) - { - Add(name, value, null); - } - - /// - /// Create a new Level and add it to the map - /// - /// the string to display for the Level - /// the level value to give to the Level - /// the display name to give to the Level - /// - /// - /// Create a new Level and add it to the map - /// - /// - public void Add(string name, int value, string displayName) - { - if (name == null) - { - throw new ArgumentNullException("name"); - } - if (name.Length == 0) - { - throw log4net.Util.SystemInfo.CreateArgumentOutOfRangeException("name", name, "Parameter: name, Value: ["+name+"] out of range. Level name must not be empty"); - } - - if (displayName == null || displayName.Length == 0) - { - displayName = name; - } - - Add(new Level(value, name, displayName)); - } - - /// - /// Add a Level to the map - /// - /// the Level to add - /// - /// - /// Add a Level to the map - /// - /// - public void Add(Level level) - { - if (level == null) - { - throw new ArgumentNullException("level"); - } - lock(this) - { - m_mapName2Level[level.Name] = level; - } - } - - /// - /// Return all possible levels as a list of Level objects. - /// - /// all possible levels as a list of Level objects - /// - /// - /// Return all possible levels as a list of Level objects. - /// - /// - public LevelCollection AllLevels - { - get - { - lock(this) - { - return new LevelCollection(m_mapName2Level.Values); - } - } - } - - /// - /// Lookup a named level from the map - /// - /// the name of the level to lookup is taken from this level. - /// If the level is not set on the map then this level is added - /// the level in the map with the name specified - /// - /// - /// Lookup a named level from the map. The name of the level to lookup is taken - /// from the property of the - /// argument. - /// - /// - /// If no level with the specified name is found then the - /// argument is added to the level map - /// and returned. - /// - /// - public Level LookupWithDefault(Level defaultLevel) - { - if (defaultLevel == null) - { - throw new ArgumentNullException("defaultLevel"); - } - - lock(this) - { - Level level = (Level)m_mapName2Level[defaultLevel.Name]; - if (level == null) - { - m_mapName2Level[defaultLevel.Name] = defaultLevel; - return defaultLevel; - } - return level; - } - } - } + /// + /// Mapping between string name and Level object + /// + /// + /// + /// Mapping between string name and object. + /// This mapping is held separately for each . + /// The level name is case insensitive. + /// + /// + /// Nicko Cadell + public sealed class LevelMap + { + #region Member Variables + + /// + /// Mapping from level name to Level object. The + /// level name is case insensitive + /// + private Hashtable m_mapName2Level = SystemInfo.CreateCaseInsensitiveHashtable(); + + #endregion + + /// + /// Construct the level map + /// + /// + /// + /// Construct the level map. + /// + /// + public LevelMap() + { + } + + /// + /// Clear the internal maps of all levels + /// + /// + /// + /// Clear the internal maps of all levels + /// + /// + public void Clear() + { + // Clear all current levels + m_mapName2Level.Clear(); + } + + /// + /// Lookup a by name + /// + /// The name of the Level to lookup + /// a Level from the map with the name specified + /// + /// + /// Returns the from the + /// map with the name specified. If the no level is + /// found then null is returned. + /// + /// + public Level this[string name] + { + get + { + if (name == null) + { + throw new ArgumentNullException("name"); + } + + lock(this) + { + return (Level)m_mapName2Level[name]; + } + } + } + + /// + /// Create a new Level and add it to the map + /// + /// the string to display for the Level + /// the level value to give to the Level + /// + /// + /// Create a new Level and add it to the map + /// + /// + /// + public void Add(string name, int value) + { + Add(name, value, null); + } + + /// + /// Create a new Level and add it to the map + /// + /// the string to display for the Level + /// the level value to give to the Level + /// the display name to give to the Level + /// + /// + /// Create a new Level and add it to the map + /// + /// + public void Add(string name, int value, string displayName) + { + if (name == null) + { + throw new ArgumentNullException("name"); + } + if (name.Length == 0) + { + throw log4net.Util.SystemInfo.CreateArgumentOutOfRangeException("name", name, "Parameter: name, Value: ["+name+"] out of range. Level name must not be empty"); + } + + if (displayName == null || displayName.Length == 0) + { + displayName = name; + } + + Add(new Level(value, name, displayName)); + } + + /// + /// Add a Level to the map + /// + /// the Level to add + /// + /// + /// Add a Level to the map + /// + /// + public void Add(Level level) + { + if (level == null) + { + throw new ArgumentNullException("level"); + } + lock(this) + { + m_mapName2Level[level.Name] = level; + } + } + + /// + /// Return all possible levels as a list of Level objects. + /// + /// all possible levels as a list of Level objects + /// + /// + /// Return all possible levels as a list of Level objects. + /// + /// + public LevelCollection AllLevels + { + get + { + lock(this) + { + return new LevelCollection(m_mapName2Level.Values); + } + } + } + + /// + /// Lookup a named level from the map + /// + /// the name of the level to lookup is taken from this level. + /// If the level is not set on the map then this level is added + /// the level in the map with the name specified + /// + /// + /// Lookup a named level from the map. The name of the level to lookup is taken + /// from the property of the + /// argument. + /// + /// + /// If no level with the specified name is found then the + /// argument is added to the level map + /// and returned. + /// + /// + public Level LookupWithDefault(Level defaultLevel) + { + if (defaultLevel == null) + { + throw new ArgumentNullException("defaultLevel"); + } + + lock(this) + { + Level level = (Level)m_mapName2Level[defaultLevel.Name]; + if (level == null) + { + m_mapName2Level[defaultLevel.Name] = defaultLevel; + return defaultLevel; + } + return level; + } + } + } } diff --git a/src/log4net/Core/LocationInfo.cs b/src/log4net/Core/LocationInfo.cs index d364f9dc..b2403385 100644 --- a/src/log4net/Core/LocationInfo.cs +++ b/src/log4net/Core/LocationInfo.cs @@ -27,295 +27,295 @@ namespace log4net.Core { - /// - /// The internal representation of caller location information. - /// - /// - /// - /// This class uses the System.Diagnostics.StackTrace class to generate - /// a call stack. The caller's information is then extracted from this stack. - /// - /// - /// The System.Diagnostics.StackTrace class is not supported on the - /// .NET Compact Framework 1.0 therefore caller location information is not - /// available on that framework. - /// - /// - /// The System.Diagnostics.StackTrace class has this to say about Release builds: - /// - /// - /// "StackTrace information will be most informative with Debug build configurations. - /// By default, Debug builds include debug symbols, while Release builds do not. The - /// debug symbols contain most of the file, method name, line number, and column - /// information used in constructing StackFrame and StackTrace objects. StackTrace - /// might not report as many method calls as expected, due to code transformations - /// that occur during optimization." - /// - /// - /// This means that in a Release build the caller information may be incomplete or may - /// not exist at all! Therefore caller location information cannot be relied upon in a Release build. - /// - /// - /// Nicko Cadell - /// Gert Driesen + /// + /// The internal representation of caller location information. + /// + /// + /// + /// This class uses the System.Diagnostics.StackTrace class to generate + /// a call stack. The caller's information is then extracted from this stack. + /// + /// + /// The System.Diagnostics.StackTrace class is not supported on the + /// .NET Compact Framework 1.0 therefore caller location information is not + /// available on that framework. + /// + /// + /// The System.Diagnostics.StackTrace class has this to say about Release builds: + /// + /// + /// "StackTrace information will be most informative with Debug build configurations. + /// By default, Debug builds include debug symbols, while Release builds do not. The + /// debug symbols contain most of the file, method name, line number, and column + /// information used in constructing StackFrame and StackTrace objects. StackTrace + /// might not report as many method calls as expected, due to code transformations + /// that occur during optimization." + /// + /// + /// This means that in a Release build the caller information may be incomplete or may + /// not exist at all! Therefore caller location information cannot be relied upon in a Release build. + /// + /// + /// Nicko Cadell + /// Gert Driesen #if !NETCF - [Serializable] + [Serializable] #endif - public class LocationInfo - { - #region Public Instance Constructors + public class LocationInfo + { + #region Public Instance Constructors - /// - /// Constructor - /// - /// The declaring type of the method that is - /// the stack boundary into the logging system for this call. - /// - /// - /// Initializes a new instance of the - /// class based on the current thread. - /// - /// - public LocationInfo(Type callerStackBoundaryDeclaringType) - { - // Initialize all fields - m_className = NA; - m_fileName = NA; - m_lineNumber = NA; - m_methodName = NA; - m_fullInfo = NA; + /// + /// Constructor + /// + /// The declaring type of the method that is + /// the stack boundary into the logging system for this call. + /// + /// + /// Initializes a new instance of the + /// class based on the current thread. + /// + /// + public LocationInfo(Type callerStackBoundaryDeclaringType) + { + // Initialize all fields + m_className = NA; + m_fileName = NA; + m_lineNumber = NA; + m_methodName = NA; + m_fullInfo = NA; #if !NETCF && !NETSTANDARD1_3 // StackTrace isn't fully implemented for NETSTANDARD1_3 https://github.com/dotnet/corefx/issues/1797 - if (callerStackBoundaryDeclaringType != null) - { - try - { - StackTrace st = new StackTrace(true); - int frameIndex = 0; - - // skip frames not from fqnOfCallingClass - while (frameIndex < st.FrameCount) - { - StackFrame frame = st.GetFrame(frameIndex); - if (frame != null && frame.GetMethod().DeclaringType == callerStackBoundaryDeclaringType) - { - break; - } - frameIndex++; - } + if (callerStackBoundaryDeclaringType != null) + { + try + { + StackTrace st = new StackTrace(true); + int frameIndex = 0; + + // skip frames not from fqnOfCallingClass + while (frameIndex < st.FrameCount) + { + StackFrame frame = st.GetFrame(frameIndex); + if (frame != null && frame.GetMethod().DeclaringType == callerStackBoundaryDeclaringType) + { + break; + } + frameIndex++; + } - // skip frames from fqnOfCallingClass - while (frameIndex < st.FrameCount) - { - StackFrame frame = st.GetFrame(frameIndex); - if (frame != null && frame.GetMethod().DeclaringType != callerStackBoundaryDeclaringType) - { - break; - } - frameIndex++; - } + // skip frames from fqnOfCallingClass + while (frameIndex < st.FrameCount) + { + StackFrame frame = st.GetFrame(frameIndex); + if (frame != null && frame.GetMethod().DeclaringType != callerStackBoundaryDeclaringType) + { + break; + } + frameIndex++; + } - if (frameIndex < st.FrameCount) - { - // take into account the frames we skip above - int adjustedFrameCount = st.FrameCount - frameIndex; + if (frameIndex < st.FrameCount) + { + // take into account the frames we skip above + int adjustedFrameCount = st.FrameCount - frameIndex; ArrayList stackFramesList = new ArrayList(adjustedFrameCount); - m_stackFrames = new StackFrameItem[adjustedFrameCount]; - for (int i=frameIndex; i < st.FrameCount; i++) - { - stackFramesList.Add(new StackFrameItem(st.GetFrame(i))); - } - - stackFramesList.CopyTo(m_stackFrames, 0); - - // now frameIndex is the first 'user' caller frame - StackFrame locationFrame = st.GetFrame(frameIndex); + m_stackFrames = new StackFrameItem[adjustedFrameCount]; + for (int i=frameIndex; i < st.FrameCount; i++) + { + stackFramesList.Add(new StackFrameItem(st.GetFrame(i))); + } + + stackFramesList.CopyTo(m_stackFrames, 0); + + // now frameIndex is the first 'user' caller frame + StackFrame locationFrame = st.GetFrame(frameIndex); - if (locationFrame != null) - { - System.Reflection.MethodBase method = locationFrame.GetMethod(); + if (locationFrame != null) + { + System.Reflection.MethodBase method = locationFrame.GetMethod(); - if (method != null) - { - m_methodName = method.Name; - if (method.DeclaringType != null) - { - m_className = method.DeclaringType.FullName; - } - } - m_fileName = locationFrame.GetFileName(); - m_lineNumber = locationFrame.GetFileLineNumber().ToString(System.Globalization.NumberFormatInfo.InvariantInfo); + if (method != null) + { + m_methodName = method.Name; + if (method.DeclaringType != null) + { + m_className = method.DeclaringType.FullName; + } + } + m_fileName = locationFrame.GetFileName(); + m_lineNumber = locationFrame.GetFileLineNumber().ToString(System.Globalization.NumberFormatInfo.InvariantInfo); - // Combine all location info - m_fullInfo = m_className + '.' + m_methodName + '(' + m_fileName + ':' + m_lineNumber + ')'; - } - } - } - catch(System.Security.SecurityException) - { - // This security exception will occur if the caller does not have - // some undefined set of SecurityPermission flags. - LogLog.Debug(declaringType, "Security exception while trying to get caller stack frame. Error Ignored. Location Information Not Available."); - } - } + // Combine all location info + m_fullInfo = m_className + '.' + m_methodName + '(' + m_fileName + ':' + m_lineNumber + ')'; + } + } + } + catch(System.Security.SecurityException) + { + // This security exception will occur if the caller does not have + // some undefined set of SecurityPermission flags. + LogLog.Debug(declaringType, "Security exception while trying to get caller stack frame. Error Ignored. Location Information Not Available."); + } + } #endif - } + } - /// - /// Constructor - /// - /// The fully qualified class name. - /// The method name. - /// The file name. - /// The line number of the method within the file. - /// - /// - /// Initializes a new instance of the - /// class with the specified data. - /// - /// - public LocationInfo(string className, string methodName, string fileName, string lineNumber) - { - m_className = className; - m_fileName = fileName; - m_lineNumber = lineNumber; - m_methodName = methodName; - m_fullInfo = m_className + '.' + m_methodName + '(' + m_fileName + - ':' + m_lineNumber + ')'; - } + /// + /// Constructor + /// + /// The fully qualified class name. + /// The method name. + /// The file name. + /// The line number of the method within the file. + /// + /// + /// Initializes a new instance of the + /// class with the specified data. + /// + /// + public LocationInfo(string className, string methodName, string fileName, string lineNumber) + { + m_className = className; + m_fileName = fileName; + m_lineNumber = lineNumber; + m_methodName = methodName; + m_fullInfo = m_className + '.' + m_methodName + '(' + m_fileName + + ':' + m_lineNumber + ')'; + } - #endregion Public Instance Constructors + #endregion Public Instance Constructors - #region Public Instance Properties + #region Public Instance Properties - /// - /// Gets the fully qualified class name of the caller making the logging - /// request. - /// - /// - /// The fully qualified class name of the caller making the logging - /// request. - /// - /// - /// - /// Gets the fully qualified class name of the caller making the logging - /// request. - /// - /// - public string ClassName - { - get { return m_className; } - } + /// + /// Gets the fully qualified class name of the caller making the logging + /// request. + /// + /// + /// The fully qualified class name of the caller making the logging + /// request. + /// + /// + /// + /// Gets the fully qualified class name of the caller making the logging + /// request. + /// + /// + public string ClassName + { + get { return m_className; } + } - /// - /// Gets the file name of the caller. - /// - /// - /// The file name of the caller. - /// - /// - /// - /// Gets the file name of the caller. - /// - /// - public string FileName - { - get { return m_fileName; } - } + /// + /// Gets the file name of the caller. + /// + /// + /// The file name of the caller. + /// + /// + /// + /// Gets the file name of the caller. + /// + /// + public string FileName + { + get { return m_fileName; } + } - /// - /// Gets the line number of the caller. - /// - /// - /// The line number of the caller. - /// - /// - /// - /// Gets the line number of the caller. - /// - /// - public string LineNumber - { - get { return m_lineNumber; } - } + /// + /// Gets the line number of the caller. + /// + /// + /// The line number of the caller. + /// + /// + /// + /// Gets the line number of the caller. + /// + /// + public string LineNumber + { + get { return m_lineNumber; } + } - /// - /// Gets the method name of the caller. - /// - /// - /// The method name of the caller. - /// - /// - /// - /// Gets the method name of the caller. - /// - /// - public string MethodName - { - get { return m_methodName; } - } + /// + /// Gets the method name of the caller. + /// + /// + /// The method name of the caller. + /// + /// + /// + /// Gets the method name of the caller. + /// + /// + public string MethodName + { + get { return m_methodName; } + } - /// - /// Gets all available caller information - /// - /// - /// All available caller information, in the format - /// fully.qualified.classname.of.caller.methodName(Filename:line) - /// - /// - /// - /// Gets all available caller information, in the format - /// fully.qualified.classname.of.caller.methodName(Filename:line) - /// - /// - public string FullInfo - { - get { return m_fullInfo; } - } - + /// + /// Gets all available caller information + /// + /// + /// All available caller information, in the format + /// fully.qualified.classname.of.caller.methodName(Filename:line) + /// + /// + /// + /// Gets all available caller information, in the format + /// fully.qualified.classname.of.caller.methodName(Filename:line) + /// + /// + public string FullInfo + { + get { return m_fullInfo; } + } + #if !NETCF && !NETSTANDARD1_3 - /// - /// Gets the stack frames from the stack trace of the caller making the log request - /// - public StackFrameItem[] StackFrames - { - get { return m_stackFrames; } - } + /// + /// Gets the stack frames from the stack trace of the caller making the log request + /// + public StackFrameItem[] StackFrames + { + get { return m_stackFrames; } + } #endif - #endregion Public Instance Properties + #endregion Public Instance Properties - #region Private Instance Fields + #region Private Instance Fields - private readonly string m_className; - private readonly string m_fileName; - private readonly string m_lineNumber; - private readonly string m_methodName; - private readonly string m_fullInfo; + private readonly string m_className; + private readonly string m_fileName; + private readonly string m_lineNumber; + private readonly string m_methodName; + private readonly string m_fullInfo; #if !NETCF && !NETSTANDARD1_3 - private readonly StackFrameItem[] m_stackFrames; + private readonly StackFrameItem[] m_stackFrames; #endif - #endregion Private Instance Fields + #endregion Private Instance Fields - #region Private Static Fields + #region Private Static Fields - /// - /// The fully qualified type of the LocationInfo class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(LocationInfo); + /// + /// The fully qualified type of the LocationInfo class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(LocationInfo); - /// - /// When location information is not available the constant - /// NA is returned. Current value of this string - /// constant is ?. - /// - private const string NA = "?"; + /// + /// When location information is not available the constant + /// NA is returned. Current value of this string + /// constant is ?. + /// + private const string NA = "?"; - #endregion Private Static Fields - } + #endregion Private Static Fields + } } diff --git a/src/log4net/Core/LogException.cs b/src/log4net/Core/LogException.cs index 32a64ff7..88243895 100644 --- a/src/log4net/Core/LogException.cs +++ b/src/log4net/Core/LogException.cs @@ -24,91 +24,91 @@ namespace log4net.Core { - /// - /// Exception base type for log4net. - /// - /// - /// - /// This type extends . It - /// does not add any new functionality but does differentiate the - /// type of exception being thrown. - /// - /// - /// Nicko Cadell - /// Gert Driesen + /// + /// Exception base type for log4net. + /// + /// + /// + /// This type extends . It + /// does not add any new functionality but does differentiate the + /// type of exception being thrown. + /// + /// + /// Nicko Cadell + /// Gert Driesen #if !NETCF - [Serializable] + [Serializable] #endif #if NETSTANDARD1_3 - public class LogException : Exception + public class LogException : Exception #else - public class LogException : ApplicationException + public class LogException : ApplicationException #endif - { - #region Public Instance Constructors + { + #region Public Instance Constructors - /// - /// Constructor - /// - /// - /// - /// Initializes a new instance of the class. - /// - /// - public LogException() - { - } + /// + /// Constructor + /// + /// + /// + /// Initializes a new instance of the class. + /// + /// + public LogException() + { + } - /// - /// Constructor - /// - /// A message to include with the exception. - /// - /// - /// Initializes a new instance of the class with - /// the specified message. - /// - /// - public LogException(String message) : base(message) - { - } - - /// - /// Constructor - /// - /// A message to include with the exception. - /// A nested exception to include. - /// - /// - /// Initializes a new instance of the class - /// with the specified message and inner exception. - /// - /// - public LogException(String message, Exception innerException) : base(message, innerException) - { - } + /// + /// Constructor + /// + /// A message to include with the exception. + /// + /// + /// Initializes a new instance of the class with + /// the specified message. + /// + /// + public LogException(String message) : base(message) + { + } + + /// + /// Constructor + /// + /// A message to include with the exception. + /// A nested exception to include. + /// + /// + /// Initializes a new instance of the class + /// with the specified message and inner exception. + /// + /// + public LogException(String message, Exception innerException) : base(message, innerException) + { + } - #endregion Public Instance Constructors + #endregion Public Instance Constructors - #region Protected Instance Constructors + #region Protected Instance Constructors #if !NETCF && !NETSTANDARD1_3 - /// - /// Serialization constructor - /// - /// The that holds the serialized object data about the exception being thrown. - /// The that contains contextual information about the source or destination. - /// - /// - /// Initializes a new instance of the class - /// with serialized data. - /// - /// - protected LogException(SerializationInfo info, StreamingContext context) : base(info, context) - { - } + /// + /// Serialization constructor + /// + /// The that holds the serialized object data about the exception being thrown. + /// The that contains contextual information about the source or destination. + /// + /// + /// Initializes a new instance of the class + /// with serialized data. + /// + /// + protected LogException(SerializationInfo info, StreamingContext context) : base(info, context) + { + } #endif - #endregion Protected Instance Constructors - } + #endregion Protected Instance Constructors + } } diff --git a/src/log4net/Core/LogImpl.cs b/src/log4net/Core/LogImpl.cs index f997ac36..965b5aaf 100644 --- a/src/log4net/Core/LogImpl.cs +++ b/src/log4net/Core/LogImpl.cs @@ -25,1272 +25,1272 @@ namespace log4net.Core { - /// - /// Implementation of wrapper interface. - /// - /// - /// - /// This implementation of the interface - /// forwards to the held by the base class. - /// - /// - /// This logger has methods to allow the caller to log at the following - /// levels: - /// - /// - /// - /// DEBUG - /// - /// The and methods log messages - /// at the DEBUG level. That is the level with that name defined in the - /// repositories . The default value - /// for this level is . The - /// property tests if this level is enabled for logging. - /// - /// - /// - /// INFO - /// - /// The and methods log messages - /// at the INFO level. That is the level with that name defined in the - /// repositories . The default value - /// for this level is . The - /// property tests if this level is enabled for logging. - /// - /// - /// - /// WARN - /// - /// The and methods log messages - /// at the WARN level. That is the level with that name defined in the - /// repositories . The default value - /// for this level is . The - /// property tests if this level is enabled for logging. - /// - /// - /// - /// ERROR - /// - /// The and methods log messages - /// at the ERROR level. That is the level with that name defined in the - /// repositories . The default value - /// for this level is . The - /// property tests if this level is enabled for logging. - /// - /// - /// - /// FATAL - /// - /// The and methods log messages - /// at the FATAL level. That is the level with that name defined in the - /// repositories . The default value - /// for this level is . The - /// property tests if this level is enabled for logging. - /// - /// - /// - /// - /// The values for these levels and their semantic meanings can be changed by - /// configuring the for the repository. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public class LogImpl : LoggerWrapperImpl, ILog - { - #region Public Instance Constructors + /// + /// Implementation of wrapper interface. + /// + /// + /// + /// This implementation of the interface + /// forwards to the held by the base class. + /// + /// + /// This logger has methods to allow the caller to log at the following + /// levels: + /// + /// + /// + /// DEBUG + /// + /// The and methods log messages + /// at the DEBUG level. That is the level with that name defined in the + /// repositories . The default value + /// for this level is . The + /// property tests if this level is enabled for logging. + /// + /// + /// + /// INFO + /// + /// The and methods log messages + /// at the INFO level. That is the level with that name defined in the + /// repositories . The default value + /// for this level is . The + /// property tests if this level is enabled for logging. + /// + /// + /// + /// WARN + /// + /// The and methods log messages + /// at the WARN level. That is the level with that name defined in the + /// repositories . The default value + /// for this level is . The + /// property tests if this level is enabled for logging. + /// + /// + /// + /// ERROR + /// + /// The and methods log messages + /// at the ERROR level. That is the level with that name defined in the + /// repositories . The default value + /// for this level is . The + /// property tests if this level is enabled for logging. + /// + /// + /// + /// FATAL + /// + /// The and methods log messages + /// at the FATAL level. That is the level with that name defined in the + /// repositories . The default value + /// for this level is . The + /// property tests if this level is enabled for logging. + /// + /// + /// + /// + /// The values for these levels and their semantic meanings can be changed by + /// configuring the for the repository. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public class LogImpl : LoggerWrapperImpl, ILog + { + #region Public Instance Constructors - /// - /// Construct a new wrapper for the specified logger. - /// - /// The logger to wrap. - /// - /// - /// Construct a new wrapper for the specified logger. - /// - /// - public LogImpl(ILogger logger) : base(logger) - { - // Listen for changes to the repository - logger.Repository.ConfigurationChanged += new LoggerRepositoryConfigurationChangedEventHandler(LoggerRepositoryConfigurationChanged); + /// + /// Construct a new wrapper for the specified logger. + /// + /// The logger to wrap. + /// + /// + /// Construct a new wrapper for the specified logger. + /// + /// + public LogImpl(ILogger logger) : base(logger) + { + // Listen for changes to the repository + logger.Repository.ConfigurationChanged += new LoggerRepositoryConfigurationChangedEventHandler(LoggerRepositoryConfigurationChanged); - // load the current levels - ReloadLevels(logger.Repository); - } + // load the current levels + ReloadLevels(logger.Repository); + } - #endregion Public Instance Constructors + #endregion Public Instance Constructors - /// - /// Virtual method called when the configuration of the repository changes - /// - /// the repository holding the levels - /// - /// - /// Virtual method called when the configuration of the repository changes - /// - /// - protected virtual void ReloadLevels(ILoggerRepository repository) - { - LevelMap levelMap = repository.LevelMap; + /// + /// Virtual method called when the configuration of the repository changes + /// + /// the repository holding the levels + /// + /// + /// Virtual method called when the configuration of the repository changes + /// + /// + protected virtual void ReloadLevels(ILoggerRepository repository) + { + LevelMap levelMap = repository.LevelMap; - m_levelDebug = levelMap.LookupWithDefault(Level.Debug); - m_levelInfo = levelMap.LookupWithDefault(Level.Info); - m_levelWarn = levelMap.LookupWithDefault(Level.Warn); - m_levelError = levelMap.LookupWithDefault(Level.Error); - m_levelFatal = levelMap.LookupWithDefault(Level.Fatal); - } + m_levelDebug = levelMap.LookupWithDefault(Level.Debug); + m_levelInfo = levelMap.LookupWithDefault(Level.Info); + m_levelWarn = levelMap.LookupWithDefault(Level.Warn); + m_levelError = levelMap.LookupWithDefault(Level.Error); + m_levelFatal = levelMap.LookupWithDefault(Level.Fatal); + } - #region Implementation of ILog + #region Implementation of ILog - /// - /// Logs a message object with the DEBUG level. - /// - /// The message object to log. - /// - /// - /// This method first checks if this logger is DEBUG - /// enabled by comparing the level of this logger with the - /// DEBUG level. If this logger is - /// DEBUG enabled, then it converts the message object - /// (passed as parameter) to a string by invoking the appropriate - /// . It then - /// proceeds to call all the registered appenders in this logger - /// and also higher in the hierarchy depending on the value of the - /// additivity flag. - /// - /// - /// WARNING Note that passing an - /// to this method will print the name of the - /// but no stack trace. To print a stack trace use the - /// form instead. - /// - /// - public virtual void Debug(object message) - { - Logger.Log(ThisDeclaringType, m_levelDebug, message, null); - } + /// + /// Logs a message object with the DEBUG level. + /// + /// The message object to log. + /// + /// + /// This method first checks if this logger is DEBUG + /// enabled by comparing the level of this logger with the + /// DEBUG level. If this logger is + /// DEBUG enabled, then it converts the message object + /// (passed as parameter) to a string by invoking the appropriate + /// . It then + /// proceeds to call all the registered appenders in this logger + /// and also higher in the hierarchy depending on the value of the + /// additivity flag. + /// + /// + /// WARNING Note that passing an + /// to this method will print the name of the + /// but no stack trace. To print a stack trace use the + /// form instead. + /// + /// + public virtual void Debug(object message) + { + Logger.Log(ThisDeclaringType, m_levelDebug, message, null); + } - /// - /// Logs a message object with the DEBUG level - /// - /// The message object to log. - /// The exception to log, including its stack trace. - /// - /// - /// Logs a message object with the DEBUG level including - /// the stack trace of the passed - /// as a parameter. - /// - /// - /// See the form for more detailed information. - /// - /// - /// - public virtual void Debug(object message, Exception exception) - { - Logger.Log(ThisDeclaringType, m_levelDebug, message, exception); - } + /// + /// Logs a message object with the DEBUG level + /// + /// The message object to log. + /// The exception to log, including its stack trace. + /// + /// + /// Logs a message object with the DEBUG level including + /// the stack trace of the passed + /// as a parameter. + /// + /// + /// See the form for more detailed information. + /// + /// + /// + public virtual void Debug(object message, Exception exception) + { + Logger.Log(ThisDeclaringType, m_levelDebug, message, exception); + } - /// - /// Logs a formatted message string with the DEBUG level. - /// - /// A String containing zero or more format items - /// An Object array containing zero or more objects to format - /// - /// - /// The message is formatted using the method. See - /// String.Format for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// The string is formatted using the - /// format provider. To specify a localized provider use the - /// method. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - public virtual void DebugFormat(string format, params object[] args) - { - if (IsDebugEnabled) - { - Logger.Log(ThisDeclaringType, m_levelDebug, new SystemStringFormat(CultureInfo.InvariantCulture, format, args), null); - } - } + /// + /// Logs a formatted message string with the DEBUG level. + /// + /// A String containing zero or more format items + /// An Object array containing zero or more objects to format + /// + /// + /// The message is formatted using the method. See + /// String.Format for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// The string is formatted using the + /// format provider. To specify a localized provider use the + /// method. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + public virtual void DebugFormat(string format, params object[] args) + { + if (IsDebugEnabled) + { + Logger.Log(ThisDeclaringType, m_levelDebug, new SystemStringFormat(CultureInfo.InvariantCulture, format, args), null); + } + } - /// - /// Logs a formatted message string with the DEBUG level. - /// - /// A String containing zero or more format items - /// An Object to format - /// - /// - /// The message is formatted using the method. See - /// String.Format for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// The string is formatted using the - /// format provider. To specify a localized provider use the - /// method. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - public virtual void DebugFormat(string format, object arg0) - { - if (IsDebugEnabled) - { - Logger.Log(ThisDeclaringType, m_levelDebug, new SystemStringFormat(CultureInfo.InvariantCulture, format, new object[] { arg0 }), null); - } - } + /// + /// Logs a formatted message string with the DEBUG level. + /// + /// A String containing zero or more format items + /// An Object to format + /// + /// + /// The message is formatted using the method. See + /// String.Format for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// The string is formatted using the + /// format provider. To specify a localized provider use the + /// method. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + public virtual void DebugFormat(string format, object arg0) + { + if (IsDebugEnabled) + { + Logger.Log(ThisDeclaringType, m_levelDebug, new SystemStringFormat(CultureInfo.InvariantCulture, format, new object[] { arg0 }), null); + } + } - /// - /// Logs a formatted message string with the DEBUG level. - /// - /// A String containing zero or more format items - /// An Object to format - /// An Object to format - /// - /// - /// The message is formatted using the method. See - /// String.Format for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// The string is formatted using the - /// format provider. To specify a localized provider use the - /// method. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - public virtual void DebugFormat(string format, object arg0, object arg1) - { - if (IsDebugEnabled) - { - Logger.Log(ThisDeclaringType, m_levelDebug, new SystemStringFormat(CultureInfo.InvariantCulture, format, new object[] { arg0, arg1 }), null); - } - } + /// + /// Logs a formatted message string with the DEBUG level. + /// + /// A String containing zero or more format items + /// An Object to format + /// An Object to format + /// + /// + /// The message is formatted using the method. See + /// String.Format for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// The string is formatted using the + /// format provider. To specify a localized provider use the + /// method. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + public virtual void DebugFormat(string format, object arg0, object arg1) + { + if (IsDebugEnabled) + { + Logger.Log(ThisDeclaringType, m_levelDebug, new SystemStringFormat(CultureInfo.InvariantCulture, format, new object[] { arg0, arg1 }), null); + } + } - /// - /// Logs a formatted message string with the DEBUG level. - /// - /// A String containing zero or more format items - /// An Object to format - /// An Object to format - /// An Object to format - /// - /// - /// The message is formatted using the method. See - /// String.Format for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// The string is formatted using the - /// format provider. To specify a localized provider use the - /// method. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - public virtual void DebugFormat(string format, object arg0, object arg1, object arg2) - { - if (IsDebugEnabled) - { - Logger.Log(ThisDeclaringType, m_levelDebug, new SystemStringFormat(CultureInfo.InvariantCulture, format, new object[] { arg0, arg1, arg2 }), null); - } - } + /// + /// Logs a formatted message string with the DEBUG level. + /// + /// A String containing zero or more format items + /// An Object to format + /// An Object to format + /// An Object to format + /// + /// + /// The message is formatted using the method. See + /// String.Format for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// The string is formatted using the + /// format provider. To specify a localized provider use the + /// method. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + public virtual void DebugFormat(string format, object arg0, object arg1, object arg2) + { + if (IsDebugEnabled) + { + Logger.Log(ThisDeclaringType, m_levelDebug, new SystemStringFormat(CultureInfo.InvariantCulture, format, new object[] { arg0, arg1, arg2 }), null); + } + } - /// - /// Logs a formatted message string with the DEBUG level. - /// - /// An that supplies culture-specific formatting information - /// A String containing zero or more format items - /// An Object array containing zero or more objects to format - /// - /// - /// The message is formatted using the method. See - /// String.Format for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - public virtual void DebugFormat(IFormatProvider provider, string format, params object[] args) - { - if (IsDebugEnabled) - { - Logger.Log(ThisDeclaringType, m_levelDebug, new SystemStringFormat(provider, format, args), null); - } - } + /// + /// Logs a formatted message string with the DEBUG level. + /// + /// An that supplies culture-specific formatting information + /// A String containing zero or more format items + /// An Object array containing zero or more objects to format + /// + /// + /// The message is formatted using the method. See + /// String.Format for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + public virtual void DebugFormat(IFormatProvider provider, string format, params object[] args) + { + if (IsDebugEnabled) + { + Logger.Log(ThisDeclaringType, m_levelDebug, new SystemStringFormat(provider, format, args), null); + } + } - /// - /// Logs a message object with the INFO level. - /// - /// The message object to log. - /// - /// - /// This method first checks if this logger is INFO - /// enabled by comparing the level of this logger with the - /// INFO level. If this logger is - /// INFO enabled, then it converts the message object - /// (passed as parameter) to a string by invoking the appropriate - /// . It then - /// proceeds to call all the registered appenders in this logger - /// and also higher in the hierarchy depending on the value of - /// the additivity flag. - /// - /// - /// WARNING Note that passing an - /// to this method will print the name of the - /// but no stack trace. To print a stack trace use the - /// form instead. - /// - /// - public virtual void Info(object message) - { - Logger.Log(ThisDeclaringType, m_levelInfo, message, null); - } + /// + /// Logs a message object with the INFO level. + /// + /// The message object to log. + /// + /// + /// This method first checks if this logger is INFO + /// enabled by comparing the level of this logger with the + /// INFO level. If this logger is + /// INFO enabled, then it converts the message object + /// (passed as parameter) to a string by invoking the appropriate + /// . It then + /// proceeds to call all the registered appenders in this logger + /// and also higher in the hierarchy depending on the value of + /// the additivity flag. + /// + /// + /// WARNING Note that passing an + /// to this method will print the name of the + /// but no stack trace. To print a stack trace use the + /// form instead. + /// + /// + public virtual void Info(object message) + { + Logger.Log(ThisDeclaringType, m_levelInfo, message, null); + } - /// - /// Logs a message object with the INFO level. - /// - /// The message object to log. - /// The exception to log, including its stack trace. - /// - /// - /// Logs a message object with the INFO level including - /// the stack trace of the - /// passed as a parameter. - /// - /// - /// See the form for more detailed information. - /// - /// - /// - public virtual void Info(object message, Exception exception) - { - Logger.Log(ThisDeclaringType, m_levelInfo, message, exception); - } + /// + /// Logs a message object with the INFO level. + /// + /// The message object to log. + /// The exception to log, including its stack trace. + /// + /// + /// Logs a message object with the INFO level including + /// the stack trace of the + /// passed as a parameter. + /// + /// + /// See the form for more detailed information. + /// + /// + /// + public virtual void Info(object message, Exception exception) + { + Logger.Log(ThisDeclaringType, m_levelInfo, message, exception); + } - /// - /// Logs a formatted message string with the INFO level. - /// - /// A String containing zero or more format items - /// An Object array containing zero or more objects to format - /// - /// - /// The message is formatted using the method. See - /// String.Format for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// The string is formatted using the - /// format provider. To specify a localized provider use the - /// method. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - public virtual void InfoFormat(string format, params object[] args) - { - if (IsInfoEnabled) - { - Logger.Log(ThisDeclaringType, m_levelInfo, new SystemStringFormat(CultureInfo.InvariantCulture, format, args), null); - } - } + /// + /// Logs a formatted message string with the INFO level. + /// + /// A String containing zero or more format items + /// An Object array containing zero or more objects to format + /// + /// + /// The message is formatted using the method. See + /// String.Format for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// The string is formatted using the + /// format provider. To specify a localized provider use the + /// method. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + public virtual void InfoFormat(string format, params object[] args) + { + if (IsInfoEnabled) + { + Logger.Log(ThisDeclaringType, m_levelInfo, new SystemStringFormat(CultureInfo.InvariantCulture, format, args), null); + } + } - /// - /// Logs a formatted message string with the INFO level. - /// - /// A String containing zero or more format items - /// An Object to format - /// - /// - /// The message is formatted using the method. See - /// String.Format for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// The string is formatted using the - /// format provider. To specify a localized provider use the - /// method. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - public virtual void InfoFormat(string format, object arg0) - { - if (IsInfoEnabled) - { - Logger.Log(ThisDeclaringType, m_levelInfo, new SystemStringFormat(CultureInfo.InvariantCulture, format, new object[] { arg0 }), null); - } - } + /// + /// Logs a formatted message string with the INFO level. + /// + /// A String containing zero or more format items + /// An Object to format + /// + /// + /// The message is formatted using the method. See + /// String.Format for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// The string is formatted using the + /// format provider. To specify a localized provider use the + /// method. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + public virtual void InfoFormat(string format, object arg0) + { + if (IsInfoEnabled) + { + Logger.Log(ThisDeclaringType, m_levelInfo, new SystemStringFormat(CultureInfo.InvariantCulture, format, new object[] { arg0 }), null); + } + } - /// - /// Logs a formatted message string with the INFO level. - /// - /// A String containing zero or more format items - /// An Object to format - /// An Object to format - /// - /// - /// The message is formatted using the method. See - /// String.Format for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// The string is formatted using the - /// format provider. To specify a localized provider use the - /// method. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - public virtual void InfoFormat(string format, object arg0, object arg1) - { - if (IsInfoEnabled) - { - Logger.Log(ThisDeclaringType, m_levelInfo, new SystemStringFormat(CultureInfo.InvariantCulture, format, new object[] { arg0, arg1 }), null); - } - } + /// + /// Logs a formatted message string with the INFO level. + /// + /// A String containing zero or more format items + /// An Object to format + /// An Object to format + /// + /// + /// The message is formatted using the method. See + /// String.Format for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// The string is formatted using the + /// format provider. To specify a localized provider use the + /// method. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + public virtual void InfoFormat(string format, object arg0, object arg1) + { + if (IsInfoEnabled) + { + Logger.Log(ThisDeclaringType, m_levelInfo, new SystemStringFormat(CultureInfo.InvariantCulture, format, new object[] { arg0, arg1 }), null); + } + } - /// - /// Logs a formatted message string with the INFO level. - /// - /// A String containing zero or more format items - /// An Object to format - /// An Object to format - /// An Object to format - /// - /// - /// The message is formatted using the method. See - /// String.Format for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// The string is formatted using the - /// format provider. To specify a localized provider use the - /// method. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - public virtual void InfoFormat(string format, object arg0, object arg1, object arg2) - { - if (IsInfoEnabled) - { - Logger.Log(ThisDeclaringType, m_levelInfo, new SystemStringFormat(CultureInfo.InvariantCulture, format, new object[] { arg0, arg1, arg2 }), null); - } - } + /// + /// Logs a formatted message string with the INFO level. + /// + /// A String containing zero or more format items + /// An Object to format + /// An Object to format + /// An Object to format + /// + /// + /// The message is formatted using the method. See + /// String.Format for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// The string is formatted using the + /// format provider. To specify a localized provider use the + /// method. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + public virtual void InfoFormat(string format, object arg0, object arg1, object arg2) + { + if (IsInfoEnabled) + { + Logger.Log(ThisDeclaringType, m_levelInfo, new SystemStringFormat(CultureInfo.InvariantCulture, format, new object[] { arg0, arg1, arg2 }), null); + } + } - /// - /// Logs a formatted message string with the INFO level. - /// - /// An that supplies culture-specific formatting information - /// A String containing zero or more format items - /// An Object array containing zero or more objects to format - /// - /// - /// The message is formatted using the method. See - /// String.Format for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - public virtual void InfoFormat(IFormatProvider provider, string format, params object[] args) - { - if (IsInfoEnabled) - { - Logger.Log(ThisDeclaringType, m_levelInfo, new SystemStringFormat(provider, format, args), null); - } - } + /// + /// Logs a formatted message string with the INFO level. + /// + /// An that supplies culture-specific formatting information + /// A String containing zero or more format items + /// An Object array containing zero or more objects to format + /// + /// + /// The message is formatted using the method. See + /// String.Format for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + public virtual void InfoFormat(IFormatProvider provider, string format, params object[] args) + { + if (IsInfoEnabled) + { + Logger.Log(ThisDeclaringType, m_levelInfo, new SystemStringFormat(provider, format, args), null); + } + } - /// - /// Logs a message object with the WARN level. - /// - /// the message object to log - /// - /// - /// This method first checks if this logger is WARN - /// enabled by comparing the level of this logger with the - /// WARN level. If this logger is - /// WARN enabled, then it converts the message object - /// (passed as parameter) to a string by invoking the appropriate - /// . It then - /// proceeds to call all the registered appenders in this logger and - /// also higher in the hierarchy depending on the value of the - /// additivity flag. - /// - /// - /// WARNING Note that passing an to this - /// method will print the name of the but no - /// stack trace. To print a stack trace use the - /// form instead. - /// - /// - public virtual void Warn(object message) - { - Logger.Log(ThisDeclaringType, m_levelWarn, message, null); - } + /// + /// Logs a message object with the WARN level. + /// + /// the message object to log + /// + /// + /// This method first checks if this logger is WARN + /// enabled by comparing the level of this logger with the + /// WARN level. If this logger is + /// WARN enabled, then it converts the message object + /// (passed as parameter) to a string by invoking the appropriate + /// . It then + /// proceeds to call all the registered appenders in this logger and + /// also higher in the hierarchy depending on the value of the + /// additivity flag. + /// + /// + /// WARNING Note that passing an to this + /// method will print the name of the but no + /// stack trace. To print a stack trace use the + /// form instead. + /// + /// + public virtual void Warn(object message) + { + Logger.Log(ThisDeclaringType, m_levelWarn, message, null); + } - /// - /// Logs a message object with the WARN level - /// - /// The message object to log. - /// The exception to log, including its stack trace. - /// - /// - /// Logs a message object with the WARN level including - /// the stack trace of the - /// passed as a parameter. - /// - /// - /// See the form for more detailed information. - /// - /// - /// - public virtual void Warn(object message, Exception exception) - { - Logger.Log(ThisDeclaringType, m_levelWarn, message, exception); - } + /// + /// Logs a message object with the WARN level + /// + /// The message object to log. + /// The exception to log, including its stack trace. + /// + /// + /// Logs a message object with the WARN level including + /// the stack trace of the + /// passed as a parameter. + /// + /// + /// See the form for more detailed information. + /// + /// + /// + public virtual void Warn(object message, Exception exception) + { + Logger.Log(ThisDeclaringType, m_levelWarn, message, exception); + } - /// - /// Logs a formatted message string with the WARN level. - /// - /// A String containing zero or more format items - /// An Object array containing zero or more objects to format - /// - /// - /// The message is formatted using the method. See - /// String.Format for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// The string is formatted using the - /// format provider. To specify a localized provider use the - /// method. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - public virtual void WarnFormat(string format, params object[] args) - { - if (IsWarnEnabled) - { - Logger.Log(ThisDeclaringType, m_levelWarn, new SystemStringFormat(CultureInfo.InvariantCulture, format, args), null); - } - } + /// + /// Logs a formatted message string with the WARN level. + /// + /// A String containing zero or more format items + /// An Object array containing zero or more objects to format + /// + /// + /// The message is formatted using the method. See + /// String.Format for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// The string is formatted using the + /// format provider. To specify a localized provider use the + /// method. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + public virtual void WarnFormat(string format, params object[] args) + { + if (IsWarnEnabled) + { + Logger.Log(ThisDeclaringType, m_levelWarn, new SystemStringFormat(CultureInfo.InvariantCulture, format, args), null); + } + } - /// - /// Logs a formatted message string with the WARN level. - /// - /// A String containing zero or more format items - /// An Object to format - /// - /// - /// The message is formatted using the method. See - /// String.Format for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// The string is formatted using the - /// format provider. To specify a localized provider use the - /// method. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - public virtual void WarnFormat(string format, object arg0) - { - if (IsWarnEnabled) - { - Logger.Log(ThisDeclaringType, m_levelWarn, new SystemStringFormat(CultureInfo.InvariantCulture, format, new object[] { arg0 }), null); - } - } + /// + /// Logs a formatted message string with the WARN level. + /// + /// A String containing zero or more format items + /// An Object to format + /// + /// + /// The message is formatted using the method. See + /// String.Format for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// The string is formatted using the + /// format provider. To specify a localized provider use the + /// method. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + public virtual void WarnFormat(string format, object arg0) + { + if (IsWarnEnabled) + { + Logger.Log(ThisDeclaringType, m_levelWarn, new SystemStringFormat(CultureInfo.InvariantCulture, format, new object[] { arg0 }), null); + } + } - /// - /// Logs a formatted message string with the WARN level. - /// - /// A String containing zero or more format items - /// An Object to format - /// An Object to format - /// - /// - /// The message is formatted using the method. See - /// String.Format for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// The string is formatted using the - /// format provider. To specify a localized provider use the - /// method. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - public virtual void WarnFormat(string format, object arg0, object arg1) - { - if (IsWarnEnabled) - { - Logger.Log(ThisDeclaringType, m_levelWarn, new SystemStringFormat(CultureInfo.InvariantCulture, format, new object[] { arg0, arg1 }), null); - } - } + /// + /// Logs a formatted message string with the WARN level. + /// + /// A String containing zero or more format items + /// An Object to format + /// An Object to format + /// + /// + /// The message is formatted using the method. See + /// String.Format for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// The string is formatted using the + /// format provider. To specify a localized provider use the + /// method. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + public virtual void WarnFormat(string format, object arg0, object arg1) + { + if (IsWarnEnabled) + { + Logger.Log(ThisDeclaringType, m_levelWarn, new SystemStringFormat(CultureInfo.InvariantCulture, format, new object[] { arg0, arg1 }), null); + } + } - /// - /// Logs a formatted message string with the WARN level. - /// - /// A String containing zero or more format items - /// An Object to format - /// An Object to format - /// An Object to format - /// - /// - /// The message is formatted using the method. See - /// String.Format for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// The string is formatted using the - /// format provider. To specify a localized provider use the - /// method. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - public virtual void WarnFormat(string format, object arg0, object arg1, object arg2) - { - if (IsWarnEnabled) - { - Logger.Log(ThisDeclaringType, m_levelWarn, new SystemStringFormat(CultureInfo.InvariantCulture, format, new object[] { arg0, arg1, arg2 }), null); - } - } + /// + /// Logs a formatted message string with the WARN level. + /// + /// A String containing zero or more format items + /// An Object to format + /// An Object to format + /// An Object to format + /// + /// + /// The message is formatted using the method. See + /// String.Format for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// The string is formatted using the + /// format provider. To specify a localized provider use the + /// method. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + public virtual void WarnFormat(string format, object arg0, object arg1, object arg2) + { + if (IsWarnEnabled) + { + Logger.Log(ThisDeclaringType, m_levelWarn, new SystemStringFormat(CultureInfo.InvariantCulture, format, new object[] { arg0, arg1, arg2 }), null); + } + } - /// - /// Logs a formatted message string with the WARN level. - /// - /// An that supplies culture-specific formatting information - /// A String containing zero or more format items - /// An Object array containing zero or more objects to format - /// - /// - /// The message is formatted using the method. See - /// String.Format for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - public virtual void WarnFormat(IFormatProvider provider, string format, params object[] args) - { - if (IsWarnEnabled) - { - Logger.Log(ThisDeclaringType, m_levelWarn, new SystemStringFormat(provider, format, args), null); - } - } + /// + /// Logs a formatted message string with the WARN level. + /// + /// An that supplies culture-specific formatting information + /// A String containing zero or more format items + /// An Object array containing zero or more objects to format + /// + /// + /// The message is formatted using the method. See + /// String.Format for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + public virtual void WarnFormat(IFormatProvider provider, string format, params object[] args) + { + if (IsWarnEnabled) + { + Logger.Log(ThisDeclaringType, m_levelWarn, new SystemStringFormat(provider, format, args), null); + } + } - /// - /// Logs a message object with the ERROR level. - /// - /// The message object to log. - /// - /// - /// This method first checks if this logger is ERROR - /// enabled by comparing the level of this logger with the - /// ERROR level. If this logger is - /// ERROR enabled, then it converts the message object - /// (passed as parameter) to a string by invoking the appropriate - /// . It then - /// proceeds to call all the registered appenders in this logger and - /// also higher in the hierarchy depending on the value of the - /// additivity flag. - /// - /// - /// WARNING Note that passing an to this - /// method will print the name of the but no - /// stack trace. To print a stack trace use the - /// form instead. - /// - /// - public virtual void Error(object message) - { - Logger.Log(ThisDeclaringType, m_levelError, message, null); - } + /// + /// Logs a message object with the ERROR level. + /// + /// The message object to log. + /// + /// + /// This method first checks if this logger is ERROR + /// enabled by comparing the level of this logger with the + /// ERROR level. If this logger is + /// ERROR enabled, then it converts the message object + /// (passed as parameter) to a string by invoking the appropriate + /// . It then + /// proceeds to call all the registered appenders in this logger and + /// also higher in the hierarchy depending on the value of the + /// additivity flag. + /// + /// + /// WARNING Note that passing an to this + /// method will print the name of the but no + /// stack trace. To print a stack trace use the + /// form instead. + /// + /// + public virtual void Error(object message) + { + Logger.Log(ThisDeclaringType, m_levelError, message, null); + } - /// - /// Logs a message object with the ERROR level - /// - /// The message object to log. - /// The exception to log, including its stack trace. - /// - /// - /// Logs a message object with the ERROR level including - /// the stack trace of the - /// passed as a parameter. - /// - /// - /// See the form for more detailed information. - /// - /// - /// - public virtual void Error(object message, Exception exception) - { - Logger.Log(ThisDeclaringType, m_levelError, message, exception); - } + /// + /// Logs a message object with the ERROR level + /// + /// The message object to log. + /// The exception to log, including its stack trace. + /// + /// + /// Logs a message object with the ERROR level including + /// the stack trace of the + /// passed as a parameter. + /// + /// + /// See the form for more detailed information. + /// + /// + /// + public virtual void Error(object message, Exception exception) + { + Logger.Log(ThisDeclaringType, m_levelError, message, exception); + } - /// - /// Logs a formatted message string with the ERROR level. - /// - /// A String containing zero or more format items - /// An Object array containing zero or more objects to format - /// - /// - /// The message is formatted using the method. See - /// String.Format for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// The string is formatted using the - /// format provider. To specify a localized provider use the - /// method. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - public virtual void ErrorFormat(string format, params object[] args) - { - if (IsErrorEnabled) - { - Logger.Log(ThisDeclaringType, m_levelError, new SystemStringFormat(CultureInfo.InvariantCulture, format, args), null); - } - } + /// + /// Logs a formatted message string with the ERROR level. + /// + /// A String containing zero or more format items + /// An Object array containing zero or more objects to format + /// + /// + /// The message is formatted using the method. See + /// String.Format for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// The string is formatted using the + /// format provider. To specify a localized provider use the + /// method. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + public virtual void ErrorFormat(string format, params object[] args) + { + if (IsErrorEnabled) + { + Logger.Log(ThisDeclaringType, m_levelError, new SystemStringFormat(CultureInfo.InvariantCulture, format, args), null); + } + } - /// - /// Logs a formatted message string with the ERROR level. - /// - /// A String containing zero or more format items - /// An Object to format - /// - /// - /// The message is formatted using the method. See - /// String.Format for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// The string is formatted using the - /// format provider. To specify a localized provider use the - /// method. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - public virtual void ErrorFormat(string format, object arg0) - { - if (IsErrorEnabled) - { - Logger.Log(ThisDeclaringType, m_levelError, new SystemStringFormat(CultureInfo.InvariantCulture, format, new object[] { arg0 }), null); - } - } + /// + /// Logs a formatted message string with the ERROR level. + /// + /// A String containing zero or more format items + /// An Object to format + /// + /// + /// The message is formatted using the method. See + /// String.Format for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// The string is formatted using the + /// format provider. To specify a localized provider use the + /// method. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + public virtual void ErrorFormat(string format, object arg0) + { + if (IsErrorEnabled) + { + Logger.Log(ThisDeclaringType, m_levelError, new SystemStringFormat(CultureInfo.InvariantCulture, format, new object[] { arg0 }), null); + } + } - /// - /// Logs a formatted message string with the ERROR level. - /// - /// A String containing zero or more format items - /// An Object to format - /// An Object to format - /// - /// - /// The message is formatted using the method. See - /// String.Format for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// The string is formatted using the - /// format provider. To specify a localized provider use the - /// method. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - public virtual void ErrorFormat(string format, object arg0, object arg1) - { - if (IsErrorEnabled) - { - Logger.Log(ThisDeclaringType, m_levelError, new SystemStringFormat(CultureInfo.InvariantCulture, format, new object[] { arg0, arg1 }), null); - } - } + /// + /// Logs a formatted message string with the ERROR level. + /// + /// A String containing zero or more format items + /// An Object to format + /// An Object to format + /// + /// + /// The message is formatted using the method. See + /// String.Format for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// The string is formatted using the + /// format provider. To specify a localized provider use the + /// method. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + public virtual void ErrorFormat(string format, object arg0, object arg1) + { + if (IsErrorEnabled) + { + Logger.Log(ThisDeclaringType, m_levelError, new SystemStringFormat(CultureInfo.InvariantCulture, format, new object[] { arg0, arg1 }), null); + } + } - /// - /// Logs a formatted message string with the ERROR level. - /// - /// A String containing zero or more format items - /// An Object to format - /// An Object to format - /// An Object to format - /// - /// - /// The message is formatted using the method. See - /// String.Format for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// The string is formatted using the - /// format provider. To specify a localized provider use the - /// method. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - public virtual void ErrorFormat(string format, object arg0, object arg1, object arg2) - { - if (IsErrorEnabled) - { - Logger.Log(ThisDeclaringType, m_levelError, new SystemStringFormat(CultureInfo.InvariantCulture, format, new object[] { arg0, arg1, arg2 }), null); - } - } + /// + /// Logs a formatted message string with the ERROR level. + /// + /// A String containing zero or more format items + /// An Object to format + /// An Object to format + /// An Object to format + /// + /// + /// The message is formatted using the method. See + /// String.Format for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// The string is formatted using the + /// format provider. To specify a localized provider use the + /// method. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + public virtual void ErrorFormat(string format, object arg0, object arg1, object arg2) + { + if (IsErrorEnabled) + { + Logger.Log(ThisDeclaringType, m_levelError, new SystemStringFormat(CultureInfo.InvariantCulture, format, new object[] { arg0, arg1, arg2 }), null); + } + } - /// - /// Logs a formatted message string with the ERROR level. - /// - /// An that supplies culture-specific formatting information - /// A String containing zero or more format items - /// An Object array containing zero or more objects to format - /// - /// - /// The message is formatted using the method. See - /// String.Format for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - public virtual void ErrorFormat(IFormatProvider provider, string format, params object[] args) - { - if (IsErrorEnabled) - { - Logger.Log(ThisDeclaringType, m_levelError, new SystemStringFormat(provider, format, args), null); - } - } + /// + /// Logs a formatted message string with the ERROR level. + /// + /// An that supplies culture-specific formatting information + /// A String containing zero or more format items + /// An Object array containing zero or more objects to format + /// + /// + /// The message is formatted using the method. See + /// String.Format for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + public virtual void ErrorFormat(IFormatProvider provider, string format, params object[] args) + { + if (IsErrorEnabled) + { + Logger.Log(ThisDeclaringType, m_levelError, new SystemStringFormat(provider, format, args), null); + } + } - /// - /// Logs a message object with the FATAL level. - /// - /// The message object to log. - /// - /// - /// This method first checks if this logger is FATAL - /// enabled by comparing the level of this logger with the - /// FATAL level. If this logger is - /// FATAL enabled, then it converts the message object - /// (passed as parameter) to a string by invoking the appropriate - /// . It then - /// proceeds to call all the registered appenders in this logger and - /// also higher in the hierarchy depending on the value of the - /// additivity flag. - /// - /// - /// WARNING Note that passing an to this - /// method will print the name of the but no - /// stack trace. To print a stack trace use the - /// form instead. - /// - /// - public virtual void Fatal(object message) - { - Logger.Log(ThisDeclaringType, m_levelFatal, message, null); - } + /// + /// Logs a message object with the FATAL level. + /// + /// The message object to log. + /// + /// + /// This method first checks if this logger is FATAL + /// enabled by comparing the level of this logger with the + /// FATAL level. If this logger is + /// FATAL enabled, then it converts the message object + /// (passed as parameter) to a string by invoking the appropriate + /// . It then + /// proceeds to call all the registered appenders in this logger and + /// also higher in the hierarchy depending on the value of the + /// additivity flag. + /// + /// + /// WARNING Note that passing an to this + /// method will print the name of the but no + /// stack trace. To print a stack trace use the + /// form instead. + /// + /// + public virtual void Fatal(object message) + { + Logger.Log(ThisDeclaringType, m_levelFatal, message, null); + } - /// - /// Logs a message object with the FATAL level - /// - /// The message object to log. - /// The exception to log, including its stack trace. - /// - /// - /// Logs a message object with the FATAL level including - /// the stack trace of the - /// passed as a parameter. - /// - /// - /// See the form for more detailed information. - /// - /// - /// - public virtual void Fatal(object message, Exception exception) - { - Logger.Log(ThisDeclaringType, m_levelFatal, message, exception); - } + /// + /// Logs a message object with the FATAL level + /// + /// The message object to log. + /// The exception to log, including its stack trace. + /// + /// + /// Logs a message object with the FATAL level including + /// the stack trace of the + /// passed as a parameter. + /// + /// + /// See the form for more detailed information. + /// + /// + /// + public virtual void Fatal(object message, Exception exception) + { + Logger.Log(ThisDeclaringType, m_levelFatal, message, exception); + } - /// - /// Logs a formatted message string with the FATAL level. - /// - /// A String containing zero or more format items - /// An Object array containing zero or more objects to format - /// - /// - /// The message is formatted using the method. See - /// String.Format for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// The string is formatted using the - /// format provider. To specify a localized provider use the - /// method. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - public virtual void FatalFormat(string format, params object[] args) - { - if (IsFatalEnabled) - { - Logger.Log(ThisDeclaringType, m_levelFatal, new SystemStringFormat(CultureInfo.InvariantCulture, format, args), null); - } - } + /// + /// Logs a formatted message string with the FATAL level. + /// + /// A String containing zero or more format items + /// An Object array containing zero or more objects to format + /// + /// + /// The message is formatted using the method. See + /// String.Format for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// The string is formatted using the + /// format provider. To specify a localized provider use the + /// method. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + public virtual void FatalFormat(string format, params object[] args) + { + if (IsFatalEnabled) + { + Logger.Log(ThisDeclaringType, m_levelFatal, new SystemStringFormat(CultureInfo.InvariantCulture, format, args), null); + } + } - /// - /// Logs a formatted message string with the FATAL level. - /// - /// A String containing zero or more format items - /// An Object to format - /// - /// - /// The message is formatted using the method. See - /// String.Format for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// The string is formatted using the - /// format provider. To specify a localized provider use the - /// method. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - public virtual void FatalFormat(string format, object arg0) - { - if (IsFatalEnabled) - { - Logger.Log(ThisDeclaringType, m_levelFatal, new SystemStringFormat(CultureInfo.InvariantCulture, format, new object[] { arg0 }), null); - } - } + /// + /// Logs a formatted message string with the FATAL level. + /// + /// A String containing zero or more format items + /// An Object to format + /// + /// + /// The message is formatted using the method. See + /// String.Format for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// The string is formatted using the + /// format provider. To specify a localized provider use the + /// method. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + public virtual void FatalFormat(string format, object arg0) + { + if (IsFatalEnabled) + { + Logger.Log(ThisDeclaringType, m_levelFatal, new SystemStringFormat(CultureInfo.InvariantCulture, format, new object[] { arg0 }), null); + } + } - /// - /// Logs a formatted message string with the FATAL level. - /// - /// A String containing zero or more format items - /// An Object to format - /// An Object to format - /// - /// - /// The message is formatted using the method. See - /// String.Format for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// The string is formatted using the - /// format provider. To specify a localized provider use the - /// method. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - public virtual void FatalFormat(string format, object arg0, object arg1) - { - if (IsFatalEnabled) - { - Logger.Log(ThisDeclaringType, m_levelFatal, new SystemStringFormat(CultureInfo.InvariantCulture, format, new object[] { arg0, arg1 }), null); - } - } + /// + /// Logs a formatted message string with the FATAL level. + /// + /// A String containing zero or more format items + /// An Object to format + /// An Object to format + /// + /// + /// The message is formatted using the method. See + /// String.Format for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// The string is formatted using the + /// format provider. To specify a localized provider use the + /// method. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + public virtual void FatalFormat(string format, object arg0, object arg1) + { + if (IsFatalEnabled) + { + Logger.Log(ThisDeclaringType, m_levelFatal, new SystemStringFormat(CultureInfo.InvariantCulture, format, new object[] { arg0, arg1 }), null); + } + } - /// - /// Logs a formatted message string with the FATAL level. - /// - /// A String containing zero or more format items - /// An Object to format - /// An Object to format - /// An Object to format - /// - /// - /// The message is formatted using the method. See - /// String.Format for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// The string is formatted using the - /// format provider. To specify a localized provider use the - /// method. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - public virtual void FatalFormat(string format, object arg0, object arg1, object arg2) - { - if (IsFatalEnabled) - { - Logger.Log(ThisDeclaringType, m_levelFatal, new SystemStringFormat(CultureInfo.InvariantCulture, format, new object[] { arg0, arg1, arg2 }), null); - } - } + /// + /// Logs a formatted message string with the FATAL level. + /// + /// A String containing zero or more format items + /// An Object to format + /// An Object to format + /// An Object to format + /// + /// + /// The message is formatted using the method. See + /// String.Format for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// The string is formatted using the + /// format provider. To specify a localized provider use the + /// method. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + public virtual void FatalFormat(string format, object arg0, object arg1, object arg2) + { + if (IsFatalEnabled) + { + Logger.Log(ThisDeclaringType, m_levelFatal, new SystemStringFormat(CultureInfo.InvariantCulture, format, new object[] { arg0, arg1, arg2 }), null); + } + } - /// - /// Logs a formatted message string with the FATAL level. - /// - /// An that supplies culture-specific formatting information - /// A String containing zero or more format items - /// An Object array containing zero or more objects to format - /// - /// - /// The message is formatted using the method. See - /// String.Format for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - public virtual void FatalFormat(IFormatProvider provider, string format, params object[] args) - { - if (IsFatalEnabled) - { - Logger.Log(ThisDeclaringType, m_levelFatal, new SystemStringFormat(provider, format, args), null); - } - } + /// + /// Logs a formatted message string with the FATAL level. + /// + /// An that supplies culture-specific formatting information + /// A String containing zero or more format items + /// An Object array containing zero or more objects to format + /// + /// + /// The message is formatted using the method. See + /// String.Format for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + public virtual void FatalFormat(IFormatProvider provider, string format, params object[] args) + { + if (IsFatalEnabled) + { + Logger.Log(ThisDeclaringType, m_levelFatal, new SystemStringFormat(provider, format, args), null); + } + } - /// - /// Checks if this logger is enabled for the DEBUG - /// level. - /// - /// - /// true if this logger is enabled for DEBUG events, - /// false otherwise. - /// - /// - /// - /// This function is intended to lessen the computational cost of - /// disabled log debug statements. - /// - /// - /// For some log Logger object, when you write: - /// - /// - /// log.Debug("This is entry number: " + i ); - /// - /// - /// You incur the cost constructing the message, concatenation in - /// this case, regardless of whether the message is logged or not. - /// - /// - /// If you are worried about speed, then you should write: - /// - /// - /// if (log.IsDebugEnabled()) - /// { - /// log.Debug("This is entry number: " + i ); - /// } - /// - /// - /// This way you will not incur the cost of parameter - /// construction if debugging is disabled for log. On - /// the other hand, if the log is debug enabled, you - /// will incur the cost of evaluating whether the logger is debug - /// enabled twice. Once in IsDebugEnabled and once in - /// the Debug. This is an insignificant overhead - /// since evaluating a logger takes about 1% of the time it - /// takes to actually log. - /// - /// - public virtual bool IsDebugEnabled - { - get { return Logger.IsEnabledFor(m_levelDebug); } - } + /// + /// Checks if this logger is enabled for the DEBUG + /// level. + /// + /// + /// true if this logger is enabled for DEBUG events, + /// false otherwise. + /// + /// + /// + /// This function is intended to lessen the computational cost of + /// disabled log debug statements. + /// + /// + /// For some log Logger object, when you write: + /// + /// + /// log.Debug("This is entry number: " + i ); + /// + /// + /// You incur the cost constructing the message, concatenation in + /// this case, regardless of whether the message is logged or not. + /// + /// + /// If you are worried about speed, then you should write: + /// + /// + /// if (log.IsDebugEnabled()) + /// { + /// log.Debug("This is entry number: " + i ); + /// } + /// + /// + /// This way you will not incur the cost of parameter + /// construction if debugging is disabled for log. On + /// the other hand, if the log is debug enabled, you + /// will incur the cost of evaluating whether the logger is debug + /// enabled twice. Once in IsDebugEnabled and once in + /// the Debug. This is an insignificant overhead + /// since evaluating a logger takes about 1% of the time it + /// takes to actually log. + /// + /// + public virtual bool IsDebugEnabled + { + get { return Logger.IsEnabledFor(m_levelDebug); } + } - /// - /// Checks if this logger is enabled for the INFO level. - /// - /// - /// true if this logger is enabled for INFO events, - /// false otherwise. - /// - /// - /// - /// See for more information and examples - /// of using this method. - /// - /// - /// - public virtual bool IsInfoEnabled - { - get { return Logger.IsEnabledFor(m_levelInfo); } - } + /// + /// Checks if this logger is enabled for the INFO level. + /// + /// + /// true if this logger is enabled for INFO events, + /// false otherwise. + /// + /// + /// + /// See for more information and examples + /// of using this method. + /// + /// + /// + public virtual bool IsInfoEnabled + { + get { return Logger.IsEnabledFor(m_levelInfo); } + } - /// - /// Checks if this logger is enabled for the WARN level. - /// - /// - /// true if this logger is enabled for WARN events, - /// false otherwise. - /// - /// - /// - /// See for more information and examples - /// of using this method. - /// - /// - /// - public virtual bool IsWarnEnabled - { - get { return Logger.IsEnabledFor(m_levelWarn); } - } + /// + /// Checks if this logger is enabled for the WARN level. + /// + /// + /// true if this logger is enabled for WARN events, + /// false otherwise. + /// + /// + /// + /// See for more information and examples + /// of using this method. + /// + /// + /// + public virtual bool IsWarnEnabled + { + get { return Logger.IsEnabledFor(m_levelWarn); } + } - /// - /// Checks if this logger is enabled for the ERROR level. - /// - /// - /// true if this logger is enabled for ERROR events, - /// false otherwise. - /// - /// - /// - /// See for more information and examples of using this method. - /// - /// - /// - public virtual bool IsErrorEnabled - { - get { return Logger.IsEnabledFor(m_levelError); } - } + /// + /// Checks if this logger is enabled for the ERROR level. + /// + /// + /// true if this logger is enabled for ERROR events, + /// false otherwise. + /// + /// + /// + /// See for more information and examples of using this method. + /// + /// + /// + public virtual bool IsErrorEnabled + { + get { return Logger.IsEnabledFor(m_levelError); } + } - /// - /// Checks if this logger is enabled for the FATAL level. - /// - /// - /// true if this logger is enabled for FATAL events, - /// false otherwise. - /// - /// - /// - /// See for more information and examples of using this method. - /// - /// - /// - public virtual bool IsFatalEnabled - { - get { return Logger.IsEnabledFor(m_levelFatal); } - } + /// + /// Checks if this logger is enabled for the FATAL level. + /// + /// + /// true if this logger is enabled for FATAL events, + /// false otherwise. + /// + /// + /// + /// See for more information and examples of using this method. + /// + /// + /// + public virtual bool IsFatalEnabled + { + get { return Logger.IsEnabledFor(m_levelFatal); } + } - #endregion Implementation of ILog + #endregion Implementation of ILog - #region Private Methods + #region Private Methods - /// - /// Event handler for the event - /// - /// the repository - /// Empty - private void LoggerRepositoryConfigurationChanged(object sender, EventArgs e) - { - ILoggerRepository repository = sender as ILoggerRepository; - if (repository != null) - { - ReloadLevels(repository); - } - } + /// + /// Event handler for the event + /// + /// the repository + /// Empty + private void LoggerRepositoryConfigurationChanged(object sender, EventArgs e) + { + ILoggerRepository repository = sender as ILoggerRepository; + if (repository != null) + { + ReloadLevels(repository); + } + } - #endregion + #endregion - #region Private Static Instance Fields + #region Private Static Instance Fields - /// - /// The fully qualified name of this declaring type not the type of any subclass. - /// - private static readonly Type ThisDeclaringType = typeof(LogImpl); + /// + /// The fully qualified name of this declaring type not the type of any subclass. + /// + private static readonly Type ThisDeclaringType = typeof(LogImpl); - #endregion Private Static Instance Fields + #endregion Private Static Instance Fields - #region Private Fields + #region Private Fields - private Level m_levelDebug; - private Level m_levelInfo; - private Level m_levelWarn; - private Level m_levelError; - private Level m_levelFatal; + private Level m_levelDebug; + private Level m_levelInfo; + private Level m_levelWarn; + private Level m_levelError; + private Level m_levelFatal; - #endregion - } + #endregion + } } diff --git a/src/log4net/Core/LoggerManager.cs b/src/log4net/Core/LoggerManager.cs index 98a2fe8e..8fb38c8c 100644 --- a/src/log4net/Core/LoggerManager.cs +++ b/src/log4net/Core/LoggerManager.cs @@ -28,851 +28,851 @@ namespace log4net.Core { - /// - /// Static manager that controls the creation of repositories - /// - /// - /// - /// Static manager that controls the creation of repositories - /// - /// - /// This class is used by the wrapper managers (e.g. ) - /// to provide access to the objects. - /// - /// - /// This manager also holds the that is used to - /// lookup and create repositories. The selector can be set either programmatically using - /// the property, or by setting the log4net.RepositorySelector - /// AppSetting in the applications config file to the fully qualified type name of the - /// selector to use. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public sealed class LoggerManager - { - #region Private Instance Constructors - - /// - /// Private constructor to prevent instances. Only static methods should be used. - /// - /// - /// - /// Private constructor to prevent instances. Only static methods should be used. - /// - /// - private LoggerManager() - { - } - - #endregion Private Instance Constructors - - #region Static Constructor - - /// - /// Hook the shutdown event - /// - /// - /// - /// On the full .NET runtime, the static constructor hooks up the - /// AppDomain.ProcessExit and AppDomain.DomainUnload> events. - /// These are used to shutdown the log4net system as the application exits. - /// - /// - static LoggerManager() - { - try - { - // Register the AppDomain events, note we have to do this with a - // method call rather than directly here because the AppDomain - // makes a LinkDemand which throws the exception during the JIT phase. - RegisterAppDomainEvents(); - } - catch(System.Security.SecurityException) - { - LogLog.Debug(declaringType, "Security Exception (ControlAppDomain LinkDemand) while trying "+ - "to register Shutdown handler with the AppDomain. LoggerManager.Shutdown() "+ - "will not be called automatically when the AppDomain exits. It must be called "+ - "programmatically."); - } - - // Dump out our assembly version into the log if debug is enabled + /// + /// Static manager that controls the creation of repositories + /// + /// + /// + /// Static manager that controls the creation of repositories + /// + /// + /// This class is used by the wrapper managers (e.g. ) + /// to provide access to the objects. + /// + /// + /// This manager also holds the that is used to + /// lookup and create repositories. The selector can be set either programmatically using + /// the property, or by setting the log4net.RepositorySelector + /// AppSetting in the applications config file to the fully qualified type name of the + /// selector to use. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public sealed class LoggerManager + { + #region Private Instance Constructors + + /// + /// Private constructor to prevent instances. Only static methods should be used. + /// + /// + /// + /// Private constructor to prevent instances. Only static methods should be used. + /// + /// + private LoggerManager() + { + } + + #endregion Private Instance Constructors + + #region Static Constructor + + /// + /// Hook the shutdown event + /// + /// + /// + /// On the full .NET runtime, the static constructor hooks up the + /// AppDomain.ProcessExit and AppDomain.DomainUnload> events. + /// These are used to shutdown the log4net system as the application exits. + /// + /// + static LoggerManager() + { + try + { + // Register the AppDomain events, note we have to do this with a + // method call rather than directly here because the AppDomain + // makes a LinkDemand which throws the exception during the JIT phase. + RegisterAppDomainEvents(); + } + catch(System.Security.SecurityException) + { + LogLog.Debug(declaringType, "Security Exception (ControlAppDomain LinkDemand) while trying "+ + "to register Shutdown handler with the AppDomain. LoggerManager.Shutdown() "+ + "will not be called automatically when the AppDomain exits. It must be called "+ + "programmatically."); + } + + // Dump out our assembly version into the log if debug is enabled LogLog.Debug(declaringType, GetVersionInfo()); - // Set the default repository selector + // Set the default repository selector #if NETCF - s_repositorySelector = new CompactRepositorySelector(typeof(log4net.Repository.Hierarchy.Hierarchy)); - return; + s_repositorySelector = new CompactRepositorySelector(typeof(log4net.Repository.Hierarchy.Hierarchy)); + return; #elif !NETSTANDARD1_3 - // Look for the RepositorySelector type specified in the AppSettings 'log4net.RepositorySelector' - string appRepositorySelectorTypeName = SystemInfo.GetAppSetting("log4net.RepositorySelector"); - if (appRepositorySelectorTypeName != null && appRepositorySelectorTypeName.Length > 0) - { - // Resolve the config string into a Type - Type appRepositorySelectorType = null; - try - { - appRepositorySelectorType = SystemInfo.GetTypeFromString(appRepositorySelectorTypeName, false, true); - } - catch(Exception ex) - { - LogLog.Error(declaringType, "Exception while resolving RepositorySelector Type ["+appRepositorySelectorTypeName+"]", ex); - } - - if (appRepositorySelectorType != null) - { - // Create an instance of the RepositorySelectorType - object appRepositorySelectorObj = null; - try - { - appRepositorySelectorObj = Activator.CreateInstance(appRepositorySelectorType); - } - catch(Exception ex) - { - LogLog.Error(declaringType, "Exception while creating RepositorySelector ["+appRepositorySelectorType.FullName+"]", ex); - } - - if (appRepositorySelectorObj != null && appRepositorySelectorObj is IRepositorySelector) - { - s_repositorySelector = (IRepositorySelector)appRepositorySelectorObj; - } - else - { - LogLog.Error(declaringType, "RepositorySelector Type ["+appRepositorySelectorType.FullName+"] is not an IRepositorySelector"); - } - } - } + // Look for the RepositorySelector type specified in the AppSettings 'log4net.RepositorySelector' + string appRepositorySelectorTypeName = SystemInfo.GetAppSetting("log4net.RepositorySelector"); + if (appRepositorySelectorTypeName != null && appRepositorySelectorTypeName.Length > 0) + { + // Resolve the config string into a Type + Type appRepositorySelectorType = null; + try + { + appRepositorySelectorType = SystemInfo.GetTypeFromString(appRepositorySelectorTypeName, false, true); + } + catch(Exception ex) + { + LogLog.Error(declaringType, "Exception while resolving RepositorySelector Type ["+appRepositorySelectorTypeName+"]", ex); + } + + if (appRepositorySelectorType != null) + { + // Create an instance of the RepositorySelectorType + object appRepositorySelectorObj = null; + try + { + appRepositorySelectorObj = Activator.CreateInstance(appRepositorySelectorType); + } + catch(Exception ex) + { + LogLog.Error(declaringType, "Exception while creating RepositorySelector ["+appRepositorySelectorType.FullName+"]", ex); + } + + if (appRepositorySelectorObj != null && appRepositorySelectorObj is IRepositorySelector) + { + s_repositorySelector = (IRepositorySelector)appRepositorySelectorObj; + } + else + { + LogLog.Error(declaringType, "RepositorySelector Type ["+appRepositorySelectorType.FullName+"] is not an IRepositorySelector"); + } + } + } #endif - // Create the DefaultRepositorySelector if not configured above - if (s_repositorySelector == null) - { - s_repositorySelector = new DefaultRepositorySelector(typeof(log4net.Repository.Hierarchy.Hierarchy)); - } - } - - /// - /// Register for ProcessExit and DomainUnload events on the AppDomain - /// - /// - /// - /// This needs to be in a separate method because the events make - /// a LinkDemand for the ControlAppDomain SecurityPermission. Because - /// this is a LinkDemand it is demanded at JIT time. Therefore we cannot - /// catch the exception in the method itself, we have to catch it in the - /// caller. - /// - /// - private static void RegisterAppDomainEvents() - { + // Create the DefaultRepositorySelector if not configured above + if (s_repositorySelector == null) + { + s_repositorySelector = new DefaultRepositorySelector(typeof(log4net.Repository.Hierarchy.Hierarchy)); + } + } + + /// + /// Register for ProcessExit and DomainUnload events on the AppDomain + /// + /// + /// + /// This needs to be in a separate method because the events make + /// a LinkDemand for the ControlAppDomain SecurityPermission. Because + /// this is a LinkDemand it is demanded at JIT time. Therefore we cannot + /// catch the exception in the method itself, we have to catch it in the + /// caller. + /// + /// + private static void RegisterAppDomainEvents() + { #if !NETCF && !NETSTANDARD1_3 - // ProcessExit seems to be fired if we are part of the default domain - AppDomain.CurrentDomain.ProcessExit += new EventHandler(OnProcessExit); + // ProcessExit seems to be fired if we are part of the default domain + AppDomain.CurrentDomain.ProcessExit += new EventHandler(OnProcessExit); - // Otherwise DomainUnload is fired - AppDomain.CurrentDomain.DomainUnload += new EventHandler(OnDomainUnload); + // Otherwise DomainUnload is fired + AppDomain.CurrentDomain.DomainUnload += new EventHandler(OnDomainUnload); #endif - } - - #endregion Static Constructor - - #region Public Static Methods - - /// - /// Return the default instance. - /// - /// the repository to lookup in - /// Return the default instance - /// - /// - /// Gets the for the repository specified - /// by the argument. - /// - /// - [Obsolete("Use GetRepository instead of GetLoggerRepository")] - public static ILoggerRepository GetLoggerRepository(string repository) - { - return GetRepository(repository); - } - - /// - /// Returns the default instance. - /// - /// The assembly to use to lookup the repository. - /// The default instance. - [Obsolete("Use GetRepository instead of GetLoggerRepository")] - public static ILoggerRepository GetLoggerRepository(Assembly repositoryAssembly) - { - return GetRepository(repositoryAssembly); - } - - /// - /// Return the default instance. - /// - /// the repository to lookup in - /// Return the default instance - /// - /// - /// Gets the for the repository specified - /// by the argument. - /// - /// - public static ILoggerRepository GetRepository(string repository) - { - if (repository == null) - { - throw new ArgumentNullException("repository"); - } - return RepositorySelector.GetRepository(repository); - } - - /// - /// Returns the default instance. - /// - /// The assembly to use to lookup the repository. - /// The default instance. - /// - /// - /// Returns the default instance. - /// - /// - public static ILoggerRepository GetRepository(Assembly repositoryAssembly) - { - if (repositoryAssembly == null) - { - throw new ArgumentNullException("repositoryAssembly"); - } - return RepositorySelector.GetRepository(repositoryAssembly); - } - - /// - /// Returns the named logger if it exists. - /// - /// The repository to lookup in. - /// The fully qualified logger name to look for. - /// - /// The logger found, or null if the named logger does not exist in the - /// specified repository. - /// - /// - /// - /// If the named logger exists (in the specified repository) then it - /// returns a reference to the logger, otherwise it returns - /// null. - /// - /// - public static ILogger Exists(string repository, string name) - { - if (repository == null) - { - throw new ArgumentNullException("repository"); - } - if (name == null) - { - throw new ArgumentNullException("name"); - } - return RepositorySelector.GetRepository(repository).Exists(name); - } - - /// - /// Returns the named logger if it exists. - /// - /// The assembly to use to lookup the repository. - /// The fully qualified logger name to look for. - /// - /// The logger found, or null if the named logger does not exist in the - /// specified assembly's repository. - /// - /// - /// - /// If the named logger exists (in the specified assembly's repository) then it - /// returns a reference to the logger, otherwise it returns - /// null. - /// - /// - public static ILogger Exists(Assembly repositoryAssembly, string name) - { - if (repositoryAssembly == null) - { - throw new ArgumentNullException("repositoryAssembly"); - } - if (name == null) - { - throw new ArgumentNullException("name"); - } - return RepositorySelector.GetRepository(repositoryAssembly).Exists(name); - } - - /// - /// Returns all the currently defined loggers in the specified repository. - /// - /// The repository to lookup in. - /// All the defined loggers. - /// - /// - /// The root logger is not included in the returned array. - /// - /// - public static ILogger[] GetCurrentLoggers(string repository) - { - if (repository == null) - { - throw new ArgumentNullException("repository"); - } - return RepositorySelector.GetRepository(repository).GetCurrentLoggers(); - } - - /// - /// Returns all the currently defined loggers in the specified assembly's repository. - /// - /// The assembly to use to lookup the repository. - /// All the defined loggers. - /// - /// - /// The root logger is not included in the returned array. - /// - /// - public static ILogger[] GetCurrentLoggers(Assembly repositoryAssembly) - { - if (repositoryAssembly == null) - { - throw new ArgumentNullException("repositoryAssembly"); - } - return RepositorySelector.GetRepository(repositoryAssembly).GetCurrentLoggers(); - } - - /// - /// Retrieves or creates a named logger. - /// - /// The repository to lookup in. - /// The name of the logger to retrieve. - /// The logger with the name specified. - /// - /// - /// Retrieves a logger named as the - /// parameter. If the named logger already exists, then the - /// existing instance will be returned. Otherwise, a new instance is - /// created. - /// - /// - /// By default, loggers do not have a set level but inherit - /// it from the hierarchy. This is one of the central features of - /// log4net. - /// - /// - public static ILogger GetLogger(string repository, string name) - { - if (repository == null) - { - throw new ArgumentNullException("repository"); - } - if (name == null) - { - throw new ArgumentNullException("name"); - } - return RepositorySelector.GetRepository(repository).GetLogger(name); - } - - /// - /// Retrieves or creates a named logger. - /// - /// The assembly to use to lookup the repository. - /// The name of the logger to retrieve. - /// The logger with the name specified. - /// - /// - /// Retrieves a logger named as the - /// parameter. If the named logger already exists, then the - /// existing instance will be returned. Otherwise, a new instance is - /// created. - /// - /// - /// By default, loggers do not have a set level but inherit - /// it from the hierarchy. This is one of the central features of - /// log4net. - /// - /// - public static ILogger GetLogger(Assembly repositoryAssembly, string name) - { - if (repositoryAssembly == null) - { - throw new ArgumentNullException("repositoryAssembly"); - } - if (name == null) - { - throw new ArgumentNullException("name"); - } - return RepositorySelector.GetRepository(repositoryAssembly).GetLogger(name); - } - - /// - /// Shorthand for . - /// - /// The repository to lookup in. - /// The of which the fullname will be used as the name of the logger to retrieve. - /// The logger with the name specified. - /// - /// - /// Gets the logger for the fully qualified name of the type specified. - /// - /// - public static ILogger GetLogger(string repository, Type type) - { - if (repository == null) - { - throw new ArgumentNullException("repository"); - } - if (type == null) - { - throw new ArgumentNullException("type"); - } - return RepositorySelector.GetRepository(repository).GetLogger(type.FullName); - } - - /// - /// Shorthand for . - /// - /// the assembly to use to lookup the repository - /// The of which the fullname will be used as the name of the logger to retrieve. - /// The logger with the name specified. - /// - /// - /// Gets the logger for the fully qualified name of the type specified. - /// - /// - public static ILogger GetLogger(Assembly repositoryAssembly, Type type) - { - if (repositoryAssembly == null) - { - throw new ArgumentNullException("repositoryAssembly"); - } - if (type == null) - { - throw new ArgumentNullException("type"); - } - return RepositorySelector.GetRepository(repositoryAssembly).GetLogger(type.FullName); - } - - /// - /// Shuts down the log4net system. - /// - /// - /// - /// Calling this method will safely close and remove all - /// appenders in all the loggers including root contained in all the - /// default repositories. - /// - /// - /// Some appenders need to be closed before the application exists. - /// Otherwise, pending logging events might be lost. - /// - /// - /// The shutdown method is careful to close nested - /// appenders before closing regular appenders. This is allows - /// configurations where a regular appender is attached to a logger - /// and again to a nested appender. - /// - /// - public static void Shutdown() - { - foreach(ILoggerRepository repository in GetAllRepositories()) - { - repository.Shutdown(); - } - } - - /// - /// Shuts down the repository for the repository specified. - /// - /// The repository to shutdown. - /// - /// - /// Calling this method will safely close and remove all - /// appenders in all the loggers including root contained in the - /// repository for the specified. - /// - /// - /// Some appenders need to be closed before the application exists. - /// Otherwise, pending logging events might be lost. - /// - /// - /// The shutdown method is careful to close nested - /// appenders before closing regular appenders. This is allows - /// configurations where a regular appender is attached to a logger - /// and again to a nested appender. - /// - /// - public static void ShutdownRepository(string repository) - { - if (repository == null) - { - throw new ArgumentNullException("repository"); - } - RepositorySelector.GetRepository(repository).Shutdown(); - } - - /// - /// Shuts down the repository for the repository specified. - /// - /// The assembly to use to lookup the repository. - /// - /// - /// Calling this method will safely close and remove all - /// appenders in all the loggers including root contained in the - /// repository for the repository. The repository is looked up using - /// the specified. - /// - /// - /// Some appenders need to be closed before the application exists. - /// Otherwise, pending logging events might be lost. - /// - /// - /// The shutdown method is careful to close nested - /// appenders before closing regular appenders. This is allows - /// configurations where a regular appender is attached to a logger - /// and again to a nested appender. - /// - /// - public static void ShutdownRepository(Assembly repositoryAssembly) - { - if (repositoryAssembly == null) - { - throw new ArgumentNullException("repositoryAssembly"); - } - RepositorySelector.GetRepository(repositoryAssembly).Shutdown(); - } - - /// - /// Resets all values contained in this repository instance to their defaults. - /// - /// The repository to reset. - /// - /// - /// Resets all values contained in the repository instance to their - /// defaults. This removes all appenders from all loggers, sets - /// the level of all non-root loggers to null, - /// sets their additivity flag to true and sets the level - /// of the root logger to . Moreover, - /// message disabling is set its default "off" value. - /// - /// - public static void ResetConfiguration(string repository) - { - if (repository == null) - { - throw new ArgumentNullException("repository"); - } - RepositorySelector.GetRepository(repository).ResetConfiguration(); - } - - /// - /// Resets all values contained in this repository instance to their defaults. - /// - /// The assembly to use to lookup the repository to reset. - /// - /// - /// Resets all values contained in the repository instance to their - /// defaults. This removes all appenders from all loggers, sets - /// the level of all non-root loggers to null, - /// sets their additivity flag to true and sets the level - /// of the root logger to . Moreover, - /// message disabling is set its default "off" value. - /// - /// - public static void ResetConfiguration(Assembly repositoryAssembly) - { - if (repositoryAssembly == null) - { - throw new ArgumentNullException("repositoryAssembly"); - } - RepositorySelector.GetRepository(repositoryAssembly).ResetConfiguration(); - } - - /// - /// Creates a repository with the specified name. - /// - /// The name of the repository, this must be unique amongst repositories. - /// The created for the repository. - /// - /// - /// CreateDomain is obsolete. Use CreateRepository instead of CreateDomain. - /// - /// - /// Creates the default type of which is a - /// object. - /// - /// - /// The name must be unique. Repositories cannot be redefined. - /// An will be thrown if the repository already exists. - /// - /// - /// The specified repository already exists. - [Obsolete("Use CreateRepository instead of CreateDomain")] - public static ILoggerRepository CreateDomain(string repository) - { - return CreateRepository(repository); - } - - /// - /// Creates a repository with the specified name. - /// - /// The name of the repository, this must be unique amongst repositories. - /// The created for the repository. - /// - /// - /// Creates the default type of which is a - /// object. - /// - /// - /// The name must be unique. Repositories cannot be redefined. - /// An will be thrown if the repository already exists. - /// - /// - /// The specified repository already exists. - public static ILoggerRepository CreateRepository(string repository) - { - if (repository == null) - { - throw new ArgumentNullException("repository"); - } - return RepositorySelector.CreateRepository(repository, null); - } - - /// - /// Creates a repository with the specified name and repository type. - /// - /// The name of the repository, this must be unique to the repository. - /// A that implements - /// and has a no arg constructor. An instance of this type will be created to act - /// as the for the repository specified. - /// The created for the repository. - /// - /// - /// CreateDomain is obsolete. Use CreateRepository instead of CreateDomain. - /// - /// - /// The name must be unique. Repositories cannot be redefined. - /// An Exception will be thrown if the repository already exists. - /// - /// - /// The specified repository already exists. - [Obsolete("Use CreateRepository instead of CreateDomain")] - public static ILoggerRepository CreateDomain(string repository, Type repositoryType) - { - return CreateRepository(repository, repositoryType); - } - - /// - /// Creates a repository with the specified name and repository type. - /// - /// The name of the repository, this must be unique to the repository. - /// A that implements - /// and has a no arg constructor. An instance of this type will be created to act - /// as the for the repository specified. - /// The created for the repository. - /// - /// - /// The name must be unique. Repositories cannot be redefined. - /// An Exception will be thrown if the repository already exists. - /// - /// - /// The specified repository already exists. - public static ILoggerRepository CreateRepository(string repository, Type repositoryType) - { - if (repository == null) - { - throw new ArgumentNullException("repository"); - } - if (repositoryType == null) - { - throw new ArgumentNullException("repositoryType"); - } - return RepositorySelector.CreateRepository(repository, repositoryType); - } - - /// - /// Creates a repository for the specified assembly and repository type. - /// - /// The assembly to use to get the name of the repository. - /// A that implements - /// and has a no arg constructor. An instance of this type will be created to act - /// as the for the repository specified. - /// The created for the repository. - /// - /// - /// CreateDomain is obsolete. Use CreateRepository instead of CreateDomain. - /// - /// - /// The created will be associated with the repository - /// specified such that a call to with the - /// same assembly specified will return the same repository instance. - /// - /// - [Obsolete("Use CreateRepository instead of CreateDomain")] - public static ILoggerRepository CreateDomain(Assembly repositoryAssembly, Type repositoryType) - { - return CreateRepository(repositoryAssembly, repositoryType); - } - - /// - /// Creates a repository for the specified assembly and repository type. - /// - /// The assembly to use to get the name of the repository. - /// A that implements - /// and has a no arg constructor. An instance of this type will be created to act - /// as the for the repository specified. - /// The created for the repository. - /// - /// - /// The created will be associated with the repository - /// specified such that a call to with the - /// same assembly specified will return the same repository instance. - /// - /// - public static ILoggerRepository CreateRepository(Assembly repositoryAssembly, Type repositoryType) - { - if (repositoryAssembly == null) - { - throw new ArgumentNullException("repositoryAssembly"); - } - if (repositoryType == null) - { - throw new ArgumentNullException("repositoryType"); - } - return RepositorySelector.CreateRepository(repositoryAssembly, repositoryType); - } - - /// - /// Gets an array of all currently defined repositories. - /// - /// An array of all the known objects. - /// - /// - /// Gets an array of all currently defined repositories. - /// - /// - public static ILoggerRepository[] GetAllRepositories() - { - return RepositorySelector.GetAllRepositories(); - } - - /// - /// Gets or sets the repository selector used by the . - /// - /// - /// The repository selector used by the . - /// - /// - /// - /// The repository selector () is used by - /// the to create and select repositories - /// (). - /// - /// - /// The caller to supplies either a string name - /// or an assembly (if not supplied the assembly is inferred using - /// ). - /// - /// - /// This context is used by the selector to lookup a specific repository. - /// - /// - /// For the full .NET Framework, the default repository is DefaultRepositorySelector; - /// for the .NET Compact Framework CompactRepositorySelector is the default - /// repository. - /// - /// - public static IRepositorySelector RepositorySelector - { - get { return s_repositorySelector; } - set { s_repositorySelector = value; } - } - - #endregion Public Static Methods - - #region Private Static Methods - - /// - /// Internal method to get pertinent version info. - /// - /// A string of version info. - private static string GetVersionInfo() - { - System.Text.StringBuilder sb = new System.Text.StringBuilder(); + } + + #endregion Static Constructor + + #region Public Static Methods + + /// + /// Return the default instance. + /// + /// the repository to lookup in + /// Return the default instance + /// + /// + /// Gets the for the repository specified + /// by the argument. + /// + /// + [Obsolete("Use GetRepository instead of GetLoggerRepository")] + public static ILoggerRepository GetLoggerRepository(string repository) + { + return GetRepository(repository); + } + + /// + /// Returns the default instance. + /// + /// The assembly to use to lookup the repository. + /// The default instance. + [Obsolete("Use GetRepository instead of GetLoggerRepository")] + public static ILoggerRepository GetLoggerRepository(Assembly repositoryAssembly) + { + return GetRepository(repositoryAssembly); + } + + /// + /// Return the default instance. + /// + /// the repository to lookup in + /// Return the default instance + /// + /// + /// Gets the for the repository specified + /// by the argument. + /// + /// + public static ILoggerRepository GetRepository(string repository) + { + if (repository == null) + { + throw new ArgumentNullException("repository"); + } + return RepositorySelector.GetRepository(repository); + } + + /// + /// Returns the default instance. + /// + /// The assembly to use to lookup the repository. + /// The default instance. + /// + /// + /// Returns the default instance. + /// + /// + public static ILoggerRepository GetRepository(Assembly repositoryAssembly) + { + if (repositoryAssembly == null) + { + throw new ArgumentNullException("repositoryAssembly"); + } + return RepositorySelector.GetRepository(repositoryAssembly); + } + + /// + /// Returns the named logger if it exists. + /// + /// The repository to lookup in. + /// The fully qualified logger name to look for. + /// + /// The logger found, or null if the named logger does not exist in the + /// specified repository. + /// + /// + /// + /// If the named logger exists (in the specified repository) then it + /// returns a reference to the logger, otherwise it returns + /// null. + /// + /// + public static ILogger Exists(string repository, string name) + { + if (repository == null) + { + throw new ArgumentNullException("repository"); + } + if (name == null) + { + throw new ArgumentNullException("name"); + } + return RepositorySelector.GetRepository(repository).Exists(name); + } + + /// + /// Returns the named logger if it exists. + /// + /// The assembly to use to lookup the repository. + /// The fully qualified logger name to look for. + /// + /// The logger found, or null if the named logger does not exist in the + /// specified assembly's repository. + /// + /// + /// + /// If the named logger exists (in the specified assembly's repository) then it + /// returns a reference to the logger, otherwise it returns + /// null. + /// + /// + public static ILogger Exists(Assembly repositoryAssembly, string name) + { + if (repositoryAssembly == null) + { + throw new ArgumentNullException("repositoryAssembly"); + } + if (name == null) + { + throw new ArgumentNullException("name"); + } + return RepositorySelector.GetRepository(repositoryAssembly).Exists(name); + } + + /// + /// Returns all the currently defined loggers in the specified repository. + /// + /// The repository to lookup in. + /// All the defined loggers. + /// + /// + /// The root logger is not included in the returned array. + /// + /// + public static ILogger[] GetCurrentLoggers(string repository) + { + if (repository == null) + { + throw new ArgumentNullException("repository"); + } + return RepositorySelector.GetRepository(repository).GetCurrentLoggers(); + } + + /// + /// Returns all the currently defined loggers in the specified assembly's repository. + /// + /// The assembly to use to lookup the repository. + /// All the defined loggers. + /// + /// + /// The root logger is not included in the returned array. + /// + /// + public static ILogger[] GetCurrentLoggers(Assembly repositoryAssembly) + { + if (repositoryAssembly == null) + { + throw new ArgumentNullException("repositoryAssembly"); + } + return RepositorySelector.GetRepository(repositoryAssembly).GetCurrentLoggers(); + } + + /// + /// Retrieves or creates a named logger. + /// + /// The repository to lookup in. + /// The name of the logger to retrieve. + /// The logger with the name specified. + /// + /// + /// Retrieves a logger named as the + /// parameter. If the named logger already exists, then the + /// existing instance will be returned. Otherwise, a new instance is + /// created. + /// + /// + /// By default, loggers do not have a set level but inherit + /// it from the hierarchy. This is one of the central features of + /// log4net. + /// + /// + public static ILogger GetLogger(string repository, string name) + { + if (repository == null) + { + throw new ArgumentNullException("repository"); + } + if (name == null) + { + throw new ArgumentNullException("name"); + } + return RepositorySelector.GetRepository(repository).GetLogger(name); + } + + /// + /// Retrieves or creates a named logger. + /// + /// The assembly to use to lookup the repository. + /// The name of the logger to retrieve. + /// The logger with the name specified. + /// + /// + /// Retrieves a logger named as the + /// parameter. If the named logger already exists, then the + /// existing instance will be returned. Otherwise, a new instance is + /// created. + /// + /// + /// By default, loggers do not have a set level but inherit + /// it from the hierarchy. This is one of the central features of + /// log4net. + /// + /// + public static ILogger GetLogger(Assembly repositoryAssembly, string name) + { + if (repositoryAssembly == null) + { + throw new ArgumentNullException("repositoryAssembly"); + } + if (name == null) + { + throw new ArgumentNullException("name"); + } + return RepositorySelector.GetRepository(repositoryAssembly).GetLogger(name); + } + + /// + /// Shorthand for . + /// + /// The repository to lookup in. + /// The of which the fullname will be used as the name of the logger to retrieve. + /// The logger with the name specified. + /// + /// + /// Gets the logger for the fully qualified name of the type specified. + /// + /// + public static ILogger GetLogger(string repository, Type type) + { + if (repository == null) + { + throw new ArgumentNullException("repository"); + } + if (type == null) + { + throw new ArgumentNullException("type"); + } + return RepositorySelector.GetRepository(repository).GetLogger(type.FullName); + } + + /// + /// Shorthand for . + /// + /// the assembly to use to lookup the repository + /// The of which the fullname will be used as the name of the logger to retrieve. + /// The logger with the name specified. + /// + /// + /// Gets the logger for the fully qualified name of the type specified. + /// + /// + public static ILogger GetLogger(Assembly repositoryAssembly, Type type) + { + if (repositoryAssembly == null) + { + throw new ArgumentNullException("repositoryAssembly"); + } + if (type == null) + { + throw new ArgumentNullException("type"); + } + return RepositorySelector.GetRepository(repositoryAssembly).GetLogger(type.FullName); + } + + /// + /// Shuts down the log4net system. + /// + /// + /// + /// Calling this method will safely close and remove all + /// appenders in all the loggers including root contained in all the + /// default repositories. + /// + /// + /// Some appenders need to be closed before the application exists. + /// Otherwise, pending logging events might be lost. + /// + /// + /// The shutdown method is careful to close nested + /// appenders before closing regular appenders. This is allows + /// configurations where a regular appender is attached to a logger + /// and again to a nested appender. + /// + /// + public static void Shutdown() + { + foreach(ILoggerRepository repository in GetAllRepositories()) + { + repository.Shutdown(); + } + } + + /// + /// Shuts down the repository for the repository specified. + /// + /// The repository to shutdown. + /// + /// + /// Calling this method will safely close and remove all + /// appenders in all the loggers including root contained in the + /// repository for the specified. + /// + /// + /// Some appenders need to be closed before the application exists. + /// Otherwise, pending logging events might be lost. + /// + /// + /// The shutdown method is careful to close nested + /// appenders before closing regular appenders. This is allows + /// configurations where a regular appender is attached to a logger + /// and again to a nested appender. + /// + /// + public static void ShutdownRepository(string repository) + { + if (repository == null) + { + throw new ArgumentNullException("repository"); + } + RepositorySelector.GetRepository(repository).Shutdown(); + } + + /// + /// Shuts down the repository for the repository specified. + /// + /// The assembly to use to lookup the repository. + /// + /// + /// Calling this method will safely close and remove all + /// appenders in all the loggers including root contained in the + /// repository for the repository. The repository is looked up using + /// the specified. + /// + /// + /// Some appenders need to be closed before the application exists. + /// Otherwise, pending logging events might be lost. + /// + /// + /// The shutdown method is careful to close nested + /// appenders before closing regular appenders. This is allows + /// configurations where a regular appender is attached to a logger + /// and again to a nested appender. + /// + /// + public static void ShutdownRepository(Assembly repositoryAssembly) + { + if (repositoryAssembly == null) + { + throw new ArgumentNullException("repositoryAssembly"); + } + RepositorySelector.GetRepository(repositoryAssembly).Shutdown(); + } + + /// + /// Resets all values contained in this repository instance to their defaults. + /// + /// The repository to reset. + /// + /// + /// Resets all values contained in the repository instance to their + /// defaults. This removes all appenders from all loggers, sets + /// the level of all non-root loggers to null, + /// sets their additivity flag to true and sets the level + /// of the root logger to . Moreover, + /// message disabling is set its default "off" value. + /// + /// + public static void ResetConfiguration(string repository) + { + if (repository == null) + { + throw new ArgumentNullException("repository"); + } + RepositorySelector.GetRepository(repository).ResetConfiguration(); + } + + /// + /// Resets all values contained in this repository instance to their defaults. + /// + /// The assembly to use to lookup the repository to reset. + /// + /// + /// Resets all values contained in the repository instance to their + /// defaults. This removes all appenders from all loggers, sets + /// the level of all non-root loggers to null, + /// sets their additivity flag to true and sets the level + /// of the root logger to . Moreover, + /// message disabling is set its default "off" value. + /// + /// + public static void ResetConfiguration(Assembly repositoryAssembly) + { + if (repositoryAssembly == null) + { + throw new ArgumentNullException("repositoryAssembly"); + } + RepositorySelector.GetRepository(repositoryAssembly).ResetConfiguration(); + } + + /// + /// Creates a repository with the specified name. + /// + /// The name of the repository, this must be unique amongst repositories. + /// The created for the repository. + /// + /// + /// CreateDomain is obsolete. Use CreateRepository instead of CreateDomain. + /// + /// + /// Creates the default type of which is a + /// object. + /// + /// + /// The name must be unique. Repositories cannot be redefined. + /// An will be thrown if the repository already exists. + /// + /// + /// The specified repository already exists. + [Obsolete("Use CreateRepository instead of CreateDomain")] + public static ILoggerRepository CreateDomain(string repository) + { + return CreateRepository(repository); + } + + /// + /// Creates a repository with the specified name. + /// + /// The name of the repository, this must be unique amongst repositories. + /// The created for the repository. + /// + /// + /// Creates the default type of which is a + /// object. + /// + /// + /// The name must be unique. Repositories cannot be redefined. + /// An will be thrown if the repository already exists. + /// + /// + /// The specified repository already exists. + public static ILoggerRepository CreateRepository(string repository) + { + if (repository == null) + { + throw new ArgumentNullException("repository"); + } + return RepositorySelector.CreateRepository(repository, null); + } + + /// + /// Creates a repository with the specified name and repository type. + /// + /// The name of the repository, this must be unique to the repository. + /// A that implements + /// and has a no arg constructor. An instance of this type will be created to act + /// as the for the repository specified. + /// The created for the repository. + /// + /// + /// CreateDomain is obsolete. Use CreateRepository instead of CreateDomain. + /// + /// + /// The name must be unique. Repositories cannot be redefined. + /// An Exception will be thrown if the repository already exists. + /// + /// + /// The specified repository already exists. + [Obsolete("Use CreateRepository instead of CreateDomain")] + public static ILoggerRepository CreateDomain(string repository, Type repositoryType) + { + return CreateRepository(repository, repositoryType); + } + + /// + /// Creates a repository with the specified name and repository type. + /// + /// The name of the repository, this must be unique to the repository. + /// A that implements + /// and has a no arg constructor. An instance of this type will be created to act + /// as the for the repository specified. + /// The created for the repository. + /// + /// + /// The name must be unique. Repositories cannot be redefined. + /// An Exception will be thrown if the repository already exists. + /// + /// + /// The specified repository already exists. + public static ILoggerRepository CreateRepository(string repository, Type repositoryType) + { + if (repository == null) + { + throw new ArgumentNullException("repository"); + } + if (repositoryType == null) + { + throw new ArgumentNullException("repositoryType"); + } + return RepositorySelector.CreateRepository(repository, repositoryType); + } + + /// + /// Creates a repository for the specified assembly and repository type. + /// + /// The assembly to use to get the name of the repository. + /// A that implements + /// and has a no arg constructor. An instance of this type will be created to act + /// as the for the repository specified. + /// The created for the repository. + /// + /// + /// CreateDomain is obsolete. Use CreateRepository instead of CreateDomain. + /// + /// + /// The created will be associated with the repository + /// specified such that a call to with the + /// same assembly specified will return the same repository instance. + /// + /// + [Obsolete("Use CreateRepository instead of CreateDomain")] + public static ILoggerRepository CreateDomain(Assembly repositoryAssembly, Type repositoryType) + { + return CreateRepository(repositoryAssembly, repositoryType); + } + + /// + /// Creates a repository for the specified assembly and repository type. + /// + /// The assembly to use to get the name of the repository. + /// A that implements + /// and has a no arg constructor. An instance of this type will be created to act + /// as the for the repository specified. + /// The created for the repository. + /// + /// + /// The created will be associated with the repository + /// specified such that a call to with the + /// same assembly specified will return the same repository instance. + /// + /// + public static ILoggerRepository CreateRepository(Assembly repositoryAssembly, Type repositoryType) + { + if (repositoryAssembly == null) + { + throw new ArgumentNullException("repositoryAssembly"); + } + if (repositoryType == null) + { + throw new ArgumentNullException("repositoryType"); + } + return RepositorySelector.CreateRepository(repositoryAssembly, repositoryType); + } + + /// + /// Gets an array of all currently defined repositories. + /// + /// An array of all the known objects. + /// + /// + /// Gets an array of all currently defined repositories. + /// + /// + public static ILoggerRepository[] GetAllRepositories() + { + return RepositorySelector.GetAllRepositories(); + } + + /// + /// Gets or sets the repository selector used by the . + /// + /// + /// The repository selector used by the . + /// + /// + /// + /// The repository selector () is used by + /// the to create and select repositories + /// (). + /// + /// + /// The caller to supplies either a string name + /// or an assembly (if not supplied the assembly is inferred using + /// ). + /// + /// + /// This context is used by the selector to lookup a specific repository. + /// + /// + /// For the full .NET Framework, the default repository is DefaultRepositorySelector; + /// for the .NET Compact Framework CompactRepositorySelector is the default + /// repository. + /// + /// + public static IRepositorySelector RepositorySelector + { + get { return s_repositorySelector; } + set { s_repositorySelector = value; } + } + + #endregion Public Static Methods + + #region Private Static Methods + + /// + /// Internal method to get pertinent version info. + /// + /// A string of version info. + private static string GetVersionInfo() + { + System.Text.StringBuilder sb = new System.Text.StringBuilder(); #if NETSTANDARD1_3 - Assembly myAssembly = typeof(LoggerManager).GetTypeInfo().Assembly; - sb.Append($"log4net assembly [{myAssembly.FullName}]. "); - //sb.Append($"Loaded from [{myAssembly.Location}]. "); // TODO Assembly.Location available in netstandard1.5 - sb.Append($"(.NET Framework [{RuntimeInformation.FrameworkDescription}] on {RuntimeInformation.OSDescription}"); + Assembly myAssembly = typeof(LoggerManager).GetTypeInfo().Assembly; + sb.Append($"log4net assembly [{myAssembly.FullName}]. "); + //sb.Append($"Loaded from [{myAssembly.Location}]. "); // TODO Assembly.Location available in netstandard1.5 + sb.Append($"(.NET Framework [{RuntimeInformation.FrameworkDescription}] on {RuntimeInformation.OSDescription}"); #else - Assembly myAssembly = Assembly.GetExecutingAssembly(); - sb.Append("log4net assembly [").Append(myAssembly.FullName).Append("]. "); - sb.Append("Loaded from [").Append(SystemInfo.AssemblyLocationInfo(myAssembly)).Append("]. "); - sb.Append("(.NET Runtime [").Append(Environment.Version.ToString()).Append("]"); + Assembly myAssembly = Assembly.GetExecutingAssembly(); + sb.Append("log4net assembly [").Append(myAssembly.FullName).Append("]. "); + sb.Append("Loaded from [").Append(SystemInfo.AssemblyLocationInfo(myAssembly)).Append("]. "); + sb.Append("(.NET Runtime [").Append(Environment.Version.ToString()).Append("]"); #if (!SSCLI) sb.Append(" on ").Append(Environment.OSVersion.ToString()); #endif #endif // NETSTANDARD1_3 - sb.Append(")"); - return sb.ToString(); - } + sb.Append(")"); + return sb.ToString(); + } #if (!NETCF) - /// - /// Called when the event fires - /// - /// the that is exiting - /// null - /// - /// - /// Called when the event fires. - /// - /// - /// When the event is triggered the log4net system is . - /// - /// - private static void OnDomainUnload(object sender, EventArgs e) - { - Shutdown(); - } - - /// - /// Called when the event fires - /// - /// the that is exiting - /// null - /// - /// - /// Called when the event fires. - /// - /// - /// When the event is triggered the log4net system is . - /// - /// - private static void OnProcessExit(object sender, EventArgs e) - { - Shutdown(); - } + /// + /// Called when the event fires + /// + /// the that is exiting + /// null + /// + /// + /// Called when the event fires. + /// + /// + /// When the event is triggered the log4net system is . + /// + /// + private static void OnDomainUnload(object sender, EventArgs e) + { + Shutdown(); + } + + /// + /// Called when the event fires + /// + /// the that is exiting + /// null + /// + /// + /// Called when the event fires. + /// + /// + /// When the event is triggered the log4net system is . + /// + /// + private static void OnProcessExit(object sender, EventArgs e) + { + Shutdown(); + } #endif - #endregion Private Static Methods + #endregion Private Static Methods - #region Private Static Fields + #region Private Static Fields - /// - /// The fully qualified type of the LoggerManager class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(LoggerManager); + /// + /// The fully qualified type of the LoggerManager class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(LoggerManager); - /// - /// Initialize the default repository selector - /// - private static IRepositorySelector s_repositorySelector; + /// + /// Initialize the default repository selector + /// + private static IRepositorySelector s_repositorySelector; - #endregion Private Static Fields - } + #endregion Private Static Fields + } } diff --git a/src/log4net/Core/LoggerWrapperImpl.cs b/src/log4net/Core/LoggerWrapperImpl.cs index 26f016df..fbc49a49 100644 --- a/src/log4net/Core/LoggerWrapperImpl.cs +++ b/src/log4net/Core/LoggerWrapperImpl.cs @@ -19,68 +19,68 @@ namespace log4net.Core { - /// - /// Implementation of the interface. - /// - /// - /// - /// This class should be used as the base for all wrapper implementations. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public abstract class LoggerWrapperImpl : ILoggerWrapper - { - #region Protected Instance Constructors + /// + /// Implementation of the interface. + /// + /// + /// + /// This class should be used as the base for all wrapper implementations. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public abstract class LoggerWrapperImpl : ILoggerWrapper + { + #region Protected Instance Constructors - /// - /// Constructs a new wrapper for the specified logger. - /// - /// The logger to wrap. - /// - /// - /// Constructs a new wrapper for the specified logger. - /// - /// - protected LoggerWrapperImpl(ILogger logger) - { - m_logger = logger; - } + /// + /// Constructs a new wrapper for the specified logger. + /// + /// The logger to wrap. + /// + /// + /// Constructs a new wrapper for the specified logger. + /// + /// + protected LoggerWrapperImpl(ILogger logger) + { + m_logger = logger; + } - #endregion Public Instance Constructors + #endregion Public Instance Constructors - #region Implementation of ILoggerWrapper + #region Implementation of ILoggerWrapper - /// - /// Gets the implementation behind this wrapper object. - /// - /// - /// The object that this object is implementing. - /// - /// - /// - /// The Logger object may not be the same object as this object - /// because of logger decorators. - /// - /// - /// This gets the actual underlying objects that is used to process - /// the log events. - /// - /// - public virtual ILogger Logger - { - get { return m_logger; } - } + /// + /// Gets the implementation behind this wrapper object. + /// + /// + /// The object that this object is implementing. + /// + /// + /// + /// The Logger object may not be the same object as this object + /// because of logger decorators. + /// + /// + /// This gets the actual underlying objects that is used to process + /// the log events. + /// + /// + public virtual ILogger Logger + { + get { return m_logger; } + } - #endregion + #endregion - #region Private Instance Fields + #region Private Instance Fields - /// - /// The logger that this object is wrapping - /// - private readonly ILogger m_logger; + /// + /// The logger that this object is wrapping + /// + private readonly ILogger m_logger; - #endregion Private Instance Fields - } + #endregion Private Instance Fields + } } diff --git a/src/log4net/Core/LoggingEvent.cs b/src/log4net/Core/LoggingEvent.cs index d6b2fb39..4d73ddb0 100644 --- a/src/log4net/Core/LoggingEvent.cs +++ b/src/log4net/Core/LoggingEvent.cs @@ -732,8 +732,8 @@ public string ThreadName if (m_data.ThreadName == null && this.m_cacheUpdatable) { #if NETCF - // Get thread ID only - m_data.ThreadName = + // Get thread ID only + m_data.ThreadName = SystemInfo.CurrentThreadId.ToString(System.Globalization.NumberFormatInfo.InvariantInfo); #else // '.NET ThreadPool Worker' appears as a default thread name in the .NET 6-7 thread pool. @@ -807,12 +807,12 @@ public string ThreadName /// Results /// /// - /// WindowsIdentity.GetCurrent() - /// 10000 loops, 00:00:00.2031250 seconds + /// WindowsIdentity.GetCurrent() + /// 10000 loops, 00:00:00.2031250 seconds /// /// - /// WindowsIdentity.GetCurrent().Name - /// 10000 loops, 00:00:08.0468750 seconds + /// WindowsIdentity.GetCurrent().Name + /// 10000 loops, 00:00:08.0468750 seconds /// /// /// @@ -827,8 +827,8 @@ public string ThreadName private string TryGetCurrentUserName() { #if (NETCF || SSCLI || NETSTANDARD1_3) - // On compact framework there's no notion of current Windows user - return SystemInfo.NotAvailableText; + // On compact framework there's no notion of current Windows user + return SystemInfo.NotAvailableText; #else if (_platformDoesNotSupportWindowsIdentity) { @@ -898,8 +898,8 @@ public string Identity if (m_data.Identity == null && this.m_cacheUpdatable) { #if (NETCF || SSCLI || NETSTANDARD1_3) - // On compact framework there's no notion of current thread principals - m_data.Identity = SystemInfo.NotAvailableText; + // On compact framework there's no notion of current thread principals + m_data.Identity = SystemInfo.NotAvailableText; #else try { @@ -1447,27 +1447,27 @@ private void CacheProperties() /// This event has composite properties that combine together properties from /// several different contexts in the following order: /// - /// - /// this events properties - /// - /// This event has that can be set. These - /// properties are specific to this event only. - /// - /// - /// - /// the thread properties - /// - /// The that are set on the current - /// thread. These properties are shared by all events logged on this thread. - /// - /// - /// - /// the global properties - /// - /// The that are set globally. These - /// properties are shared by all the threads in the AppDomain. - /// - /// + /// + /// this events properties + /// + /// This event has that can be set. These + /// properties are specific to this event only. + /// + /// + /// + /// the thread properties + /// + /// The that are set on the current + /// thread. These properties are shared by all events logged on this thread. + /// + /// + /// + /// the global properties + /// + /// The that are set globally. These + /// properties are shared by all the threads in the AppDomain. + /// + /// /// /// /// diff --git a/src/log4net/Core/MethodItem.cs b/src/log4net/Core/MethodItem.cs index 6d3ca198..f76ccdbf 100644 --- a/src/log4net/Core/MethodItem.cs +++ b/src/log4net/Core/MethodItem.cs @@ -23,148 +23,148 @@ namespace log4net.Core { - /// - /// provides method information without actually referencing a System.Reflection.MethodBase - /// as that would require that the containing assembly is loaded. - /// - /// + /// + /// provides method information without actually referencing a System.Reflection.MethodBase + /// as that would require that the containing assembly is loaded. + /// + /// #if !NETCF - [Serializable] + [Serializable] #endif - public class MethodItem - { - #region Public Instance Constructors - - /// - /// constructs a method item for an unknown method. - /// - public MethodItem() - { - m_name = NA; - m_parameters = new string[0]; - } - - /// - /// constructs a method item from the name of the method. - /// - /// - public MethodItem(string name) - : this() - { - m_name = name; - } - - /// - /// constructs a method item from the name of the method and its parameters. - /// - /// - /// - public MethodItem(string name, string[] parameters) - : this(name) - { - m_parameters = parameters; - } + public class MethodItem + { + #region Public Instance Constructors + + /// + /// constructs a method item for an unknown method. + /// + public MethodItem() + { + m_name = NA; + m_parameters = new string[0]; + } + + /// + /// constructs a method item from the name of the method. + /// + /// + public MethodItem(string name) + : this() + { + m_name = name; + } + + /// + /// constructs a method item from the name of the method and its parameters. + /// + /// + /// + public MethodItem(string name, string[] parameters) + : this(name) + { + m_parameters = parameters; + } /// /// constructs a method item from a method base by determining the method name and its parameters. /// /// - public MethodItem(System.Reflection.MethodBase methodBase) - : this(methodBase.Name, GetMethodParameterNames(methodBase)) + 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 - - /// - /// Gets the method name of the caller making the logging - /// request. - /// - /// - /// The method name of the caller making the logging - /// request. - /// - /// - /// - /// Gets the method name of the caller making the logging - /// request. - /// - /// - public string Name - { - get { return m_name; } - } - - /// - /// Gets the method parameters of the caller making - /// the logging request. - /// - /// - /// The method parameters of the caller making - /// the logging request - /// - /// - /// - /// Gets the method parameters of the caller making - /// the logging request. - /// - /// - 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 - - /// - /// The fully qualified type of the StackFrameItem class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(MethodItem); - - /// - /// When location information is not available the constant - /// NA is returned. Current value of this string - /// constant is ?. - /// - private const string NA = "?"; - - #endregion Private Static Fields - } + } + + #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 + + /// + /// Gets the method name of the caller making the logging + /// request. + /// + /// + /// The method name of the caller making the logging + /// request. + /// + /// + /// + /// Gets the method name of the caller making the logging + /// request. + /// + /// + public string Name + { + get { return m_name; } + } + + /// + /// Gets the method parameters of the caller making + /// the logging request. + /// + /// + /// The method parameters of the caller making + /// the logging request + /// + /// + /// + /// Gets the method parameters of the caller making + /// the logging request. + /// + /// + 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 + + /// + /// The fully qualified type of the StackFrameItem class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(MethodItem); + + /// + /// When location information is not available the constant + /// NA is returned. Current value of this string + /// constant is ?. + /// + private const string NA = "?"; + + #endregion Private Static Fields + } } diff --git a/src/log4net/Core/SecurityContext.cs b/src/log4net/Core/SecurityContext.cs index fecad2b2..e454c867 100644 --- a/src/log4net/Core/SecurityContext.cs +++ b/src/log4net/Core/SecurityContext.cs @@ -21,35 +21,35 @@ namespace log4net.Core { - /// - /// A SecurityContext used by log4net when interacting with protected resources - /// - /// - /// - /// A SecurityContext used by log4net when interacting with protected resources - /// for example with operating system services. This can be used to impersonate - /// a principal that has been granted privileges on the system resources. - /// - /// - /// Nicko Cadell - public abstract class SecurityContext - { - /// - /// Impersonate this SecurityContext - /// - /// State supplied by the caller - /// An instance that will - /// revoke the impersonation of this SecurityContext, or null - /// - /// - /// Impersonate this security context. Further calls on the current - /// thread should now be made in the security context provided - /// by this object. When the result - /// method is called the security - /// context of the thread should be reverted to the state it was in - /// before was called. - /// - /// - public abstract IDisposable Impersonate(object state); - } + /// + /// A SecurityContext used by log4net when interacting with protected resources + /// + /// + /// + /// A SecurityContext used by log4net when interacting with protected resources + /// for example with operating system services. This can be used to impersonate + /// a principal that has been granted privileges on the system resources. + /// + /// + /// Nicko Cadell + public abstract class SecurityContext + { + /// + /// Impersonate this SecurityContext + /// + /// State supplied by the caller + /// An instance that will + /// revoke the impersonation of this SecurityContext, or null + /// + /// + /// Impersonate this security context. Further calls on the current + /// thread should now be made in the security context provided + /// by this object. When the result + /// method is called the security + /// context of the thread should be reverted to the state it was in + /// before was called. + /// + /// + public abstract IDisposable Impersonate(object state); + } } diff --git a/src/log4net/Core/SecurityContextProvider.cs b/src/log4net/Core/SecurityContextProvider.cs index f6e99e6e..a887b044 100644 --- a/src/log4net/Core/SecurityContextProvider.cs +++ b/src/log4net/Core/SecurityContextProvider.cs @@ -23,102 +23,102 @@ namespace log4net.Core { - /// - /// The providers default instances. - /// - /// - /// - /// A configured component that interacts with potentially protected system - /// resources uses a to provide the elevated - /// privileges required. If the object has - /// been not been explicitly provided to the component then the component - /// will request one from this . - /// - /// - /// By default the is - /// an instance of which returns only - /// objects. This is a reasonable default - /// where the privileges required are not know by the system. - /// - /// - /// This default behavior can be overridden by subclassing the - /// and overriding the method to return - /// the desired objects. The default provider - /// can be replaced by programmatically setting the value of the - /// property. - /// - /// - /// An alternative is to use the log4net.Config.SecurityContextProviderAttribute - /// This attribute can be applied to an assembly in the same way as the - /// log4net.Config.XmlConfiguratorAttribute". The attribute takes - /// the type to use as the as an argument. - /// - /// - /// Nicko Cadell - public class SecurityContextProvider - { - /// - /// The default provider - /// - private static SecurityContextProvider s_defaultProvider = new SecurityContextProvider(); + /// + /// The providers default instances. + /// + /// + /// + /// A configured component that interacts with potentially protected system + /// resources uses a to provide the elevated + /// privileges required. If the object has + /// been not been explicitly provided to the component then the component + /// will request one from this . + /// + /// + /// By default the is + /// an instance of which returns only + /// objects. This is a reasonable default + /// where the privileges required are not know by the system. + /// + /// + /// This default behavior can be overridden by subclassing the + /// and overriding the method to return + /// the desired objects. The default provider + /// can be replaced by programmatically setting the value of the + /// property. + /// + /// + /// An alternative is to use the log4net.Config.SecurityContextProviderAttribute + /// This attribute can be applied to an assembly in the same way as the + /// log4net.Config.XmlConfiguratorAttribute". The attribute takes + /// the type to use as the as an argument. + /// + /// + /// Nicko Cadell + public class SecurityContextProvider + { + /// + /// The default provider + /// + private static SecurityContextProvider s_defaultProvider = new SecurityContextProvider(); - /// - /// Gets or sets the default SecurityContextProvider - /// - /// - /// The default SecurityContextProvider - /// - /// - /// - /// The default provider is used by configured components that - /// require a and have not had one - /// given to them. - /// - /// - /// By default this is an instance of - /// that returns objects. - /// - /// - /// The default provider can be set programmatically by setting - /// the value of this property to a sub class of - /// that has the desired behavior. - /// - /// - public static SecurityContextProvider DefaultProvider - { - get { return s_defaultProvider; } - set { s_defaultProvider = value; } - } + /// + /// Gets or sets the default SecurityContextProvider + /// + /// + /// The default SecurityContextProvider + /// + /// + /// + /// The default provider is used by configured components that + /// require a and have not had one + /// given to them. + /// + /// + /// By default this is an instance of + /// that returns objects. + /// + /// + /// The default provider can be set programmatically by setting + /// the value of this property to a sub class of + /// that has the desired behavior. + /// + /// + public static SecurityContextProvider DefaultProvider + { + get { return s_defaultProvider; } + set { s_defaultProvider = value; } + } - /// - /// Protected default constructor to allow subclassing - /// - /// - /// - /// Protected default constructor to allow subclassing - /// - /// - protected SecurityContextProvider() - { - } + /// + /// Protected default constructor to allow subclassing + /// + /// + /// + /// Protected default constructor to allow subclassing + /// + /// + protected SecurityContextProvider() + { + } - /// - /// Create a SecurityContext for a consumer - /// - /// The consumer requesting the SecurityContext - /// An impersonation context - /// - /// - /// The default implementation is to return a . - /// - /// - /// Subclasses should override this method to provide their own - /// behavior. - /// - /// - public virtual SecurityContext CreateSecurityContext(object consumer) - { - return NullSecurityContext.Instance; - } - } + /// + /// Create a SecurityContext for a consumer + /// + /// The consumer requesting the SecurityContext + /// An impersonation context + /// + /// + /// The default implementation is to return a . + /// + /// + /// Subclasses should override this method to provide their own + /// behavior. + /// + /// + public virtual SecurityContext CreateSecurityContext(object consumer) + { + return NullSecurityContext.Instance; + } + } } diff --git a/src/log4net/Core/StackFrameItem.cs b/src/log4net/Core/StackFrameItem.cs index 17193260..778703b9 100644 --- a/src/log4net/Core/StackFrameItem.cs +++ b/src/log4net/Core/StackFrameItem.cs @@ -47,24 +47,24 @@ public StackFrameItem(StackFrame frame) m_method = new MethodItem(); m_className = NA; - try - { - // 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) - { - if(method.DeclaringType != null) - m_className = method.DeclaringType.FullName; - m_method = new MethodItem(method); - } - } - catch (Exception ex) - { - LogLog.Error(declaringType, "An exception ocurred while retreiving stack frame information.", ex); - } + try + { + // 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) + { + if(method.DeclaringType != null) + m_className = method.DeclaringType.FullName; + m_method = new MethodItem(method); + } + } + catch (Exception ex) + { + LogLog.Error(declaringType, "An exception ocurred while retreiving stack frame information.", ex); + } // set full info m_fullInfo = m_className + '.' + m_method.Name + '(' + m_fileName + ':' + m_lineNumber + ')'; @@ -167,7 +167,7 @@ public string FullInfo private readonly string m_fileName; private readonly string m_className; private readonly string m_fullInfo; - private readonly MethodItem m_method; + private readonly MethodItem m_method; #endregion diff --git a/src/log4net/Core/WrapperMap.cs b/src/log4net/Core/WrapperMap.cs index d4f5b257..e9d6cada 100644 --- a/src/log4net/Core/WrapperMap.cs +++ b/src/log4net/Core/WrapperMap.cs @@ -24,236 +24,236 @@ namespace log4net.Core { - #region WrapperCreationHandler - - /// - /// Delegate used to handle creation of new wrappers. - /// - /// The logger to wrap in a wrapper. - /// - /// - /// Delegate used to handle creation of new wrappers. This delegate - /// is called from the - /// method to construct the wrapper for the specified logger. - /// - /// - /// The delegate to use is supplied to the - /// constructor. - /// - /// - public delegate ILoggerWrapper WrapperCreationHandler(ILogger logger); - - #endregion WrapperCreationHandler - - /// - /// Maps between logger objects and wrapper objects. - /// - /// - /// - /// This class maintains a mapping between objects and - /// objects. Use the method to - /// lookup the for the specified . - /// - /// - /// New wrapper instances are created by the - /// method. The default behavior is for this method to delegate construction - /// of the wrapper to the delegate supplied - /// to the constructor. This allows specialization of the behavior without - /// requiring subclassing of this type. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public class WrapperMap - { - #region Public Instance Constructors - - /// - /// Initializes a new instance of the - /// - /// The handler to use to create the wrapper objects. - /// - /// - /// Initializes a new instance of the class with - /// the specified handler to create the wrapper objects. - /// - /// - public WrapperMap(WrapperCreationHandler createWrapperHandler) - { - m_createWrapperHandler = createWrapperHandler; - - // Create the delegates for the event callbacks - m_shutdownHandler = new LoggerRepositoryShutdownEventHandler(ILoggerRepository_Shutdown); - } - - #endregion Public Instance Constructors - - #region Public Instance Properties - - /// - /// Gets the wrapper object for the specified logger. - /// - /// The wrapper object for the specified logger - /// - /// - /// If the logger is null then the corresponding wrapper is null. - /// - /// - /// Looks up the wrapper it it has previously been requested and - /// returns it. If the wrapper has never been requested before then - /// the virtual method is - /// called. - /// - /// - public virtual ILoggerWrapper GetWrapper(ILogger logger) - { - // If the logger is null then the corresponding wrapper is null - if (logger == null) - { - return null; - } - - lock(this) - { - // Lookup hierarchy in map. - Hashtable wrappersMap = (Hashtable)m_repositories[logger.Repository]; - - if (wrappersMap == null) - { - // Hierarchy does not exist in map. - // Must register with hierarchy - - wrappersMap = new Hashtable(); - m_repositories[logger.Repository] = wrappersMap; - - // Register for config reset & shutdown on repository - logger.Repository.ShutdownEvent += m_shutdownHandler; - } - - // Look for the wrapper object in the map - ILoggerWrapper wrapperObject = wrappersMap[logger] as ILoggerWrapper; - - if (wrapperObject == null) - { - // No wrapper object exists for the specified logger - - // Create a new wrapper wrapping the logger - wrapperObject = CreateNewWrapperObject(logger); - - // Store wrapper logger in map - wrappersMap[logger] = wrapperObject; - } - - return wrapperObject; - } - } - - #endregion Public Instance Properties - - #region Protected Instance Properties - - /// - /// Gets the map of logger repositories. - /// - /// - /// Map of logger repositories. - /// - /// - /// - /// Gets the hashtable that is keyed on . The - /// values are hashtables keyed on with the - /// value being the corresponding . - /// - /// - protected Hashtable Repositories - { - get { return this.m_repositories; } - } - - #endregion Protected Instance Properties - - #region Protected Instance Methods - - /// - /// Creates the wrapper object for the specified logger. - /// - /// The logger to wrap in a wrapper. - /// The wrapper object for the logger. - /// - /// - /// This implementation uses the - /// passed to the constructor to create the wrapper. This method - /// can be overridden in a subclass. - /// - /// - protected virtual ILoggerWrapper CreateNewWrapperObject(ILogger logger) - { - if (m_createWrapperHandler != null) - { - return m_createWrapperHandler(logger); - } - return null; - } - - /// - /// Called when a monitored repository shutdown event is received. - /// - /// The that is shutting down - /// - /// - /// This method is called when a that this - /// is holding loggers for has signaled its shutdown - /// event . The default - /// behavior of this method is to release the references to the loggers - /// and their wrappers generated for this repository. - /// - /// - protected virtual void RepositoryShutdown(ILoggerRepository repository) - { - lock(this) - { - // Remove the repository from map - m_repositories.Remove(repository); - - // Unhook events from the repository - repository.ShutdownEvent -= m_shutdownHandler; - } - } - - /// - /// Event handler for repository shutdown event. - /// - /// The sender of the event. - /// The event args. - private void ILoggerRepository_Shutdown(object sender, EventArgs e) - { - ILoggerRepository repository = sender as ILoggerRepository; - if (repository != null) - { - // Remove all repository from map - RepositoryShutdown(repository); - } - } - - #endregion Protected Instance Methods - - #region Private Instance Variables - - /// - /// Map of logger repositories to hashtables of ILogger to ILoggerWrapper mappings - /// - private readonly Hashtable m_repositories = new Hashtable(); - - /// - /// The handler to use to create the extension wrapper objects. - /// - private readonly WrapperCreationHandler m_createWrapperHandler; - - /// - /// Internal reference to the delegate used to register for repository shutdown events. - /// - private readonly LoggerRepositoryShutdownEventHandler m_shutdownHandler; + #region WrapperCreationHandler + + /// + /// Delegate used to handle creation of new wrappers. + /// + /// The logger to wrap in a wrapper. + /// + /// + /// Delegate used to handle creation of new wrappers. This delegate + /// is called from the + /// method to construct the wrapper for the specified logger. + /// + /// + /// The delegate to use is supplied to the + /// constructor. + /// + /// + public delegate ILoggerWrapper WrapperCreationHandler(ILogger logger); + + #endregion WrapperCreationHandler + + /// + /// Maps between logger objects and wrapper objects. + /// + /// + /// + /// This class maintains a mapping between objects and + /// objects. Use the method to + /// lookup the for the specified . + /// + /// + /// New wrapper instances are created by the + /// method. The default behavior is for this method to delegate construction + /// of the wrapper to the delegate supplied + /// to the constructor. This allows specialization of the behavior without + /// requiring subclassing of this type. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public class WrapperMap + { + #region Public Instance Constructors + + /// + /// Initializes a new instance of the + /// + /// The handler to use to create the wrapper objects. + /// + /// + /// Initializes a new instance of the class with + /// the specified handler to create the wrapper objects. + /// + /// + public WrapperMap(WrapperCreationHandler createWrapperHandler) + { + m_createWrapperHandler = createWrapperHandler; + + // Create the delegates for the event callbacks + m_shutdownHandler = new LoggerRepositoryShutdownEventHandler(ILoggerRepository_Shutdown); + } + + #endregion Public Instance Constructors + + #region Public Instance Properties + + /// + /// Gets the wrapper object for the specified logger. + /// + /// The wrapper object for the specified logger + /// + /// + /// If the logger is null then the corresponding wrapper is null. + /// + /// + /// Looks up the wrapper it it has previously been requested and + /// returns it. If the wrapper has never been requested before then + /// the virtual method is + /// called. + /// + /// + public virtual ILoggerWrapper GetWrapper(ILogger logger) + { + // If the logger is null then the corresponding wrapper is null + if (logger == null) + { + return null; + } + + lock(this) + { + // Lookup hierarchy in map. + Hashtable wrappersMap = (Hashtable)m_repositories[logger.Repository]; + + if (wrappersMap == null) + { + // Hierarchy does not exist in map. + // Must register with hierarchy + + wrappersMap = new Hashtable(); + m_repositories[logger.Repository] = wrappersMap; + + // Register for config reset & shutdown on repository + logger.Repository.ShutdownEvent += m_shutdownHandler; + } + + // Look for the wrapper object in the map + ILoggerWrapper wrapperObject = wrappersMap[logger] as ILoggerWrapper; + + if (wrapperObject == null) + { + // No wrapper object exists for the specified logger + + // Create a new wrapper wrapping the logger + wrapperObject = CreateNewWrapperObject(logger); + + // Store wrapper logger in map + wrappersMap[logger] = wrapperObject; + } + + return wrapperObject; + } + } + + #endregion Public Instance Properties + + #region Protected Instance Properties + + /// + /// Gets the map of logger repositories. + /// + /// + /// Map of logger repositories. + /// + /// + /// + /// Gets the hashtable that is keyed on . The + /// values are hashtables keyed on with the + /// value being the corresponding . + /// + /// + protected Hashtable Repositories + { + get { return this.m_repositories; } + } + + #endregion Protected Instance Properties + + #region Protected Instance Methods + + /// + /// Creates the wrapper object for the specified logger. + /// + /// The logger to wrap in a wrapper. + /// The wrapper object for the logger. + /// + /// + /// This implementation uses the + /// passed to the constructor to create the wrapper. This method + /// can be overridden in a subclass. + /// + /// + protected virtual ILoggerWrapper CreateNewWrapperObject(ILogger logger) + { + if (m_createWrapperHandler != null) + { + return m_createWrapperHandler(logger); + } + return null; + } + + /// + /// Called when a monitored repository shutdown event is received. + /// + /// The that is shutting down + /// + /// + /// This method is called when a that this + /// is holding loggers for has signaled its shutdown + /// event . The default + /// behavior of this method is to release the references to the loggers + /// and their wrappers generated for this repository. + /// + /// + protected virtual void RepositoryShutdown(ILoggerRepository repository) + { + lock(this) + { + // Remove the repository from map + m_repositories.Remove(repository); + + // Unhook events from the repository + repository.ShutdownEvent -= m_shutdownHandler; + } + } + + /// + /// Event handler for repository shutdown event. + /// + /// The sender of the event. + /// The event args. + private void ILoggerRepository_Shutdown(object sender, EventArgs e) + { + ILoggerRepository repository = sender as ILoggerRepository; + if (repository != null) + { + // Remove all repository from map + RepositoryShutdown(repository); + } + } + + #endregion Protected Instance Methods + + #region Private Instance Variables + + /// + /// Map of logger repositories to hashtables of ILogger to ILoggerWrapper mappings + /// + private readonly Hashtable m_repositories = new Hashtable(); + + /// + /// The handler to use to create the extension wrapper objects. + /// + private readonly WrapperCreationHandler m_createWrapperHandler; + + /// + /// Internal reference to the delegate used to register for repository shutdown events. + /// + private readonly LoggerRepositoryShutdownEventHandler m_shutdownHandler; - #endregion Private Instance Variables - } + #endregion Private Instance Variables + } } diff --git a/src/log4net/DateFormatter/AbsoluteTimeDateFormatter.cs b/src/log4net/DateFormatter/AbsoluteTimeDateFormatter.cs index c6333038..b19a1e0a 100644 --- a/src/log4net/DateFormatter/AbsoluteTimeDateFormatter.cs +++ b/src/log4net/DateFormatter/AbsoluteTimeDateFormatter.cs @@ -24,92 +24,92 @@ namespace log4net.DateFormatter { - /// - /// Formats a as "HH:mm:ss,fff". - /// - /// - /// - /// Formats a in the format "HH:mm:ss,fff" for example, "15:49:37,459". - /// - /// - /// Nicko Cadell - /// Gert Driesen - public class AbsoluteTimeDateFormatter : IDateFormatter - { - #region Protected Instance Methods - - /// - /// Renders the date into a string. Format is "HH:mm:ss". - /// - /// The date to render into a string. - /// The string builder to write to. - /// - /// - /// Subclasses should override this method to render the date - /// into a string using a precision up to the second. This method - /// will be called at most once per second and the result will be - /// reused if it is needed again during the same second. - /// - /// - protected virtual void FormatDateWithoutMillis(DateTime dateToFormat, StringBuilder buffer) - { - int hour = dateToFormat.Hour; - if (hour < 10) - { - buffer.Append('0'); - } - buffer.Append(hour); - buffer.Append(':'); - - int mins = dateToFormat.Minute; - if (mins < 10) - { - buffer.Append('0'); - } - buffer.Append(mins); - buffer.Append(':'); - - int secs = dateToFormat.Second; - if (secs < 10) - { - buffer.Append('0'); - } - buffer.Append(secs); - } - - #endregion Protected Instance Methods - - #region Implementation of IDateFormatter - - /// - /// Renders the date into a string. Format is "HH:mm:ss,fff". - /// - /// The date to render into a string. - /// The writer to write to. - /// - /// - /// Uses the method to generate the - /// time string up to the seconds and then appends the current - /// milliseconds. The results from are - /// cached and is called at most once - /// per second. - /// - /// - /// Sub classes should override - /// rather than . - /// - /// - public virtual void FormatDate(DateTime dateToFormat, TextWriter writer) - { + /// + /// Formats a as "HH:mm:ss,fff". + /// + /// + /// + /// Formats a in the format "HH:mm:ss,fff" for example, "15:49:37,459". + /// + /// + /// Nicko Cadell + /// Gert Driesen + public class AbsoluteTimeDateFormatter : IDateFormatter + { + #region Protected Instance Methods + + /// + /// Renders the date into a string. Format is "HH:mm:ss". + /// + /// The date to render into a string. + /// The string builder to write to. + /// + /// + /// Subclasses should override this method to render the date + /// into a string using a precision up to the second. This method + /// will be called at most once per second and the result will be + /// reused if it is needed again during the same second. + /// + /// + protected virtual void FormatDateWithoutMillis(DateTime dateToFormat, StringBuilder buffer) + { + int hour = dateToFormat.Hour; + if (hour < 10) + { + buffer.Append('0'); + } + buffer.Append(hour); + buffer.Append(':'); + + int mins = dateToFormat.Minute; + if (mins < 10) + { + buffer.Append('0'); + } + buffer.Append(mins); + buffer.Append(':'); + + int secs = dateToFormat.Second; + if (secs < 10) + { + buffer.Append('0'); + } + buffer.Append(secs); + } + + #endregion Protected Instance Methods + + #region Implementation of IDateFormatter + + /// + /// Renders the date into a string. Format is "HH:mm:ss,fff". + /// + /// The date to render into a string. + /// The writer to write to. + /// + /// + /// Uses the method to generate the + /// time string up to the seconds and then appends the current + /// milliseconds. The results from are + /// cached and is called at most once + /// per second. + /// + /// + /// Sub classes should override + /// rather than . + /// + /// + public virtual 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 + // 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(); @@ -121,93 +121,93 @@ public virtual void FormatDate(DateTime dateToFormat, TextWriter writer) if (timeString == null) { - // lock so that only one thread can use the buffer and - // update the s_lastTimeToTheSecond and s_lastTimeStrings + // lock so that only one thread can use the buffer and + // update the s_lastTimeToTheSecond and s_lastTimeStrings - // PERF: Try removing this lock and using a new StringBuilder each time - lock(s_lastTimeBuf) - { + // 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; + // 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 + // 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(); + // 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) + // 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); + 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); } - } + } - #endregion Implementation of IDateFormatter + #endregion Implementation of IDateFormatter - #region Public Static Fields + #region Public Static Fields - /// - /// String constant used to specify AbsoluteTimeDateFormat in layouts. Current value is ABSOLUTE. - /// - public const string AbsoluteTimeDateFormat = "ABSOLUTE"; + /// + /// String constant used to specify AbsoluteTimeDateFormat in layouts. Current value is ABSOLUTE. + /// + public const string AbsoluteTimeDateFormat = "ABSOLUTE"; - /// - /// String constant used to specify DateTimeDateFormat in layouts. Current value is DATE. - /// - public const string DateAndTimeDateFormat = "DATE"; + /// + /// String constant used to specify DateTimeDateFormat in layouts. Current value is DATE. + /// + public const string DateAndTimeDateFormat = "DATE"; - /// - /// String constant used to specify ISO8601DateFormat in layouts. Current value is ISO8601. - /// - public const string Iso8601TimeDateFormat = "ISO8601"; + /// + /// String constant used to specify ISO8601DateFormat in layouts. Current value is ISO8601. + /// + public const string Iso8601TimeDateFormat = "ISO8601"; - #endregion Public Static Fields + #endregion Public Static Fields - #region Private Static Fields + #region Private Static Fields - /// - /// Last stored time with precision up to the second. - /// - private static long s_lastTimeToTheSecond = 0; + /// + /// Last stored time with precision up to the second. + /// + private static long s_lastTimeToTheSecond = 0; - /// - /// Last stored time with precision up to the second, formatted - /// as a string. - /// - private static StringBuilder s_lastTimeBuf = new StringBuilder(); + /// + /// Last stored time with precision up to the second, formatted + /// as a string. + /// + private static StringBuilder s_lastTimeBuf = new StringBuilder(); - /// - /// Last stored time with precision up to the second, formatted - /// as a string. - /// - private static Hashtable s_lastTimeStrings = new Hashtable(); + /// + /// Last stored time with precision up to the second, formatted + /// as a string. + /// + private static Hashtable s_lastTimeStrings = new Hashtable(); - #endregion Private Static Fields - } + #endregion Private Static Fields + } } diff --git a/src/log4net/DateFormatter/DateTimeDateFormatter.cs b/src/log4net/DateFormatter/DateTimeDateFormatter.cs index 7411206c..90d529cd 100644 --- a/src/log4net/DateFormatter/DateTimeDateFormatter.cs +++ b/src/log4net/DateFormatter/DateTimeDateFormatter.cs @@ -23,84 +23,84 @@ namespace log4net.DateFormatter { - /// - /// Formats a as "dd MMM yyyy HH:mm:ss,fff" - /// - /// - /// - /// Formats a in the format - /// "dd MMM yyyy HH:mm:ss,fff" for example, - /// "06 Nov 1994 15:49:37,459". - /// - /// - /// Nicko Cadell - /// Gert Driesen - /// Angelika Schnagl - public class DateTimeDateFormatter : AbsoluteTimeDateFormatter - { - #region Public Instance Constructors + /// + /// Formats a as "dd MMM yyyy HH:mm:ss,fff" + /// + /// + /// + /// Formats a in the format + /// "dd MMM yyyy HH:mm:ss,fff" for example, + /// "06 Nov 1994 15:49:37,459". + /// + /// + /// Nicko Cadell + /// Gert Driesen + /// Angelika Schnagl + public class DateTimeDateFormatter : AbsoluteTimeDateFormatter + { + #region Public Instance Constructors - /// - /// Default constructor. - /// - /// - /// - /// Initializes a new instance of the class. - /// - /// - public DateTimeDateFormatter() - { - m_dateTimeFormatInfo = DateTimeFormatInfo.InvariantInfo; - } + /// + /// Default constructor. + /// + /// + /// + /// Initializes a new instance of the class. + /// + /// + public DateTimeDateFormatter() + { + m_dateTimeFormatInfo = DateTimeFormatInfo.InvariantInfo; + } - #endregion Public Instance Constructors + #endregion Public Instance Constructors - #region Override implementation of AbsoluteTimeDateFormatter + #region Override implementation of AbsoluteTimeDateFormatter - /// - /// Formats the date without the milliseconds part - /// - /// The date to format. - /// The string builder to write to. - /// - /// - /// Formats a DateTime in the format "dd MMM yyyy HH:mm:ss" - /// for example, "06 Nov 1994 15:49:37". - /// - /// - /// The base class will append the ",fff" milliseconds section. - /// This method will only be called at most once per second. - /// - /// - protected override void FormatDateWithoutMillis(DateTime dateToFormat, StringBuilder buffer) - { - int day = dateToFormat.Day; - if (day < 10) - { - buffer.Append('0'); - } - buffer.Append(day); - buffer.Append(' '); + /// + /// Formats the date without the milliseconds part + /// + /// The date to format. + /// The string builder to write to. + /// + /// + /// Formats a DateTime in the format "dd MMM yyyy HH:mm:ss" + /// for example, "06 Nov 1994 15:49:37". + /// + /// + /// The base class will append the ",fff" milliseconds section. + /// This method will only be called at most once per second. + /// + /// + protected override void FormatDateWithoutMillis(DateTime dateToFormat, StringBuilder buffer) + { + int day = dateToFormat.Day; + if (day < 10) + { + buffer.Append('0'); + } + buffer.Append(day); + buffer.Append(' '); - buffer.Append(m_dateTimeFormatInfo.GetAbbreviatedMonthName(dateToFormat.Month)); - buffer.Append(' '); + buffer.Append(m_dateTimeFormatInfo.GetAbbreviatedMonthName(dateToFormat.Month)); + buffer.Append(' '); - buffer.Append(dateToFormat.Year); - buffer.Append(' '); + buffer.Append(dateToFormat.Year); + buffer.Append(' '); - // Append the 'HH:mm:ss' - base.FormatDateWithoutMillis(dateToFormat, buffer); - } + // Append the 'HH:mm:ss' + base.FormatDateWithoutMillis(dateToFormat, buffer); + } - #endregion Override implementation of AbsoluteTimeDateFormatter + #endregion Override implementation of AbsoluteTimeDateFormatter - #region Private Instance Fields + #region Private Instance Fields - /// - /// The format info for the invariant culture. - /// - private readonly DateTimeFormatInfo m_dateTimeFormatInfo; + /// + /// The format info for the invariant culture. + /// + private readonly DateTimeFormatInfo m_dateTimeFormatInfo; - #endregion Private Instance Fields - } + #endregion Private Instance Fields + } } diff --git a/src/log4net/DateFormatter/IDateFormatter.cs b/src/log4net/DateFormatter/IDateFormatter.cs index f5074ee4..ebfb9811 100644 --- a/src/log4net/DateFormatter/IDateFormatter.cs +++ b/src/log4net/DateFormatter/IDateFormatter.cs @@ -22,34 +22,34 @@ namespace log4net.DateFormatter { - /// - /// Render a as a string. - /// - /// - /// - /// Interface to abstract the rendering of a - /// instance into a string. - /// - /// - /// The method is used to render the - /// date to a text writer. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public interface IDateFormatter - { - /// - /// Formats the specified date as a string. - /// - /// The date to format. - /// The writer to write to. - /// - /// - /// Format the as a string and write it - /// to the provided. - /// - /// - void FormatDate(DateTime dateToFormat, TextWriter writer); - } + /// + /// Render a as a string. + /// + /// + /// + /// Interface to abstract the rendering of a + /// instance into a string. + /// + /// + /// The method is used to render the + /// date to a text writer. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public interface IDateFormatter + { + /// + /// Formats the specified date as a string. + /// + /// The date to format. + /// The writer to write to. + /// + /// + /// Format the as a string and write it + /// to the provided. + /// + /// + void FormatDate(DateTime dateToFormat, TextWriter writer); + } } diff --git a/src/log4net/DateFormatter/Iso8601DateFormatter.cs b/src/log4net/DateFormatter/Iso8601DateFormatter.cs index 524c8a79..1ff299f1 100644 --- a/src/log4net/DateFormatter/Iso8601DateFormatter.cs +++ b/src/log4net/DateFormatter/Iso8601DateFormatter.cs @@ -22,75 +22,75 @@ namespace log4net.DateFormatter { - /// - /// Formats the as "yyyy-MM-dd HH:mm:ss,fff". - /// - /// - /// - /// Formats the specified as a string: "yyyy-MM-dd HH:mm:ss,fff". - /// - /// - /// Nicko Cadell - /// Gert Driesen - public class Iso8601DateFormatter : AbsoluteTimeDateFormatter - { - #region Public Instance Constructors + /// + /// Formats the as "yyyy-MM-dd HH:mm:ss,fff". + /// + /// + /// + /// Formats the specified as a string: "yyyy-MM-dd HH:mm:ss,fff". + /// + /// + /// Nicko Cadell + /// Gert Driesen + public class Iso8601DateFormatter : AbsoluteTimeDateFormatter + { + #region Public Instance Constructors - /// - /// Default constructor - /// - /// - /// - /// Initializes a new instance of the class. - /// - /// - public Iso8601DateFormatter() - { - } + /// + /// Default constructor + /// + /// + /// + /// Initializes a new instance of the class. + /// + /// + public Iso8601DateFormatter() + { + } - #endregion Public Instance Constructors + #endregion Public Instance Constructors - #region Override implementation of AbsoluteTimeDateFormatter + #region Override implementation of AbsoluteTimeDateFormatter - /// - /// Formats the date without the milliseconds part - /// - /// The date to format. - /// The string builder to write to. - /// - /// - /// Formats the date specified as a string: "yyyy-MM-dd HH:mm:ss". - /// - /// - /// The base class will append the ",fff" milliseconds section. - /// This method will only be called at most once per second. - /// - /// - protected override void FormatDateWithoutMillis(DateTime dateToFormat, StringBuilder buffer) - { - buffer.Append(dateToFormat.Year); + /// + /// Formats the date without the milliseconds part + /// + /// The date to format. + /// The string builder to write to. + /// + /// + /// Formats the date specified as a string: "yyyy-MM-dd HH:mm:ss". + /// + /// + /// The base class will append the ",fff" milliseconds section. + /// This method will only be called at most once per second. + /// + /// + protected override void FormatDateWithoutMillis(DateTime dateToFormat, StringBuilder buffer) + { + buffer.Append(dateToFormat.Year); - buffer.Append('-'); - int month = dateToFormat.Month; - if (month < 10) - { - buffer.Append('0'); - } - buffer.Append(month); - buffer.Append('-'); + buffer.Append('-'); + int month = dateToFormat.Month; + if (month < 10) + { + buffer.Append('0'); + } + buffer.Append(month); + buffer.Append('-'); - int day = dateToFormat.Day; - if (day < 10) - { - buffer.Append('0'); - } - buffer.Append(day); - buffer.Append(' '); + int day = dateToFormat.Day; + if (day < 10) + { + buffer.Append('0'); + } + buffer.Append(day); + buffer.Append(' '); - // Append the 'HH:mm:ss' - base.FormatDateWithoutMillis(dateToFormat, buffer); - } + // Append the 'HH:mm:ss' + base.FormatDateWithoutMillis(dateToFormat, buffer); + } - #endregion Override implementation of AbsoluteTimeDateFormatter - } + #endregion Override implementation of AbsoluteTimeDateFormatter + } } diff --git a/src/log4net/DateFormatter/SimpleDateFormatter.cs b/src/log4net/DateFormatter/SimpleDateFormatter.cs index 3efb1643..05e5e86c 100644 --- a/src/log4net/DateFormatter/SimpleDateFormatter.cs +++ b/src/log4net/DateFormatter/SimpleDateFormatter.cs @@ -22,74 +22,74 @@ namespace log4net.DateFormatter { - /// - /// Formats the using the method. - /// - /// - /// - /// Formats the using the method. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public class SimpleDateFormatter : IDateFormatter - { - #region Public Instance Constructors + /// + /// Formats the using the method. + /// + /// + /// + /// Formats the using the method. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public class SimpleDateFormatter : IDateFormatter + { + #region Public Instance Constructors - /// - /// Constructor - /// - /// The format string. - /// - /// - /// Initializes a new instance of the class - /// with the specified format string. - /// - /// - /// The format string must be compatible with the options - /// that can be supplied to . - /// - /// - public SimpleDateFormatter(string format) - { - m_formatString = format; - } + /// + /// Constructor + /// + /// The format string. + /// + /// + /// Initializes a new instance of the class + /// with the specified format string. + /// + /// + /// The format string must be compatible with the options + /// that can be supplied to . + /// + /// + public SimpleDateFormatter(string format) + { + m_formatString = format; + } - #endregion Public Instance Constructors + #endregion Public Instance Constructors - #region Implementation of IDateFormatter + #region Implementation of IDateFormatter - /// - /// Formats the date using . - /// - /// The date to convert to a string. - /// The writer to write to. - /// - /// - /// Uses the date format string supplied to the constructor to call - /// the method to format the date. - /// - /// - public virtual void FormatDate(DateTime dateToFormat, TextWriter writer) - { - writer.Write(dateToFormat.ToString(m_formatString, System.Globalization.DateTimeFormatInfo.InvariantInfo)); - } + /// + /// Formats the date using . + /// + /// The date to convert to a string. + /// The writer to write to. + /// + /// + /// Uses the date format string supplied to the constructor to call + /// the method to format the date. + /// + /// + public virtual void FormatDate(DateTime dateToFormat, TextWriter writer) + { + writer.Write(dateToFormat.ToString(m_formatString, System.Globalization.DateTimeFormatInfo.InvariantInfo)); + } - #endregion + #endregion - #region Private Instance Fields + #region Private Instance Fields - /// - /// The format string used to format the . - /// - /// - /// - /// The format string must be compatible with the options - /// that can be supplied to . - /// - /// - private readonly string m_formatString; + /// + /// The format string used to format the . + /// + /// + /// + /// The format string must be compatible with the options + /// that can be supplied to . + /// + /// + private readonly string m_formatString; - #endregion Private Instance Fields - } + #endregion Private Instance Fields + } } diff --git a/src/log4net/Filter/DenyAllFilter.cs b/src/log4net/Filter/DenyAllFilter.cs index ab377f1e..35c11387 100644 --- a/src/log4net/Filter/DenyAllFilter.cs +++ b/src/log4net/Filter/DenyAllFilter.cs @@ -23,53 +23,53 @@ namespace log4net.Filter { - /// - /// This filter drops all . - /// - /// - /// - /// You can add this filter to the end of a filter chain to - /// switch from the default "accept all unless instructed otherwise" - /// filtering behavior to a "deny all unless instructed otherwise" - /// behavior. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public sealed class DenyAllFilter : FilterSkeleton - { - #region Constructors + /// + /// This filter drops all . + /// + /// + /// + /// You can add this filter to the end of a filter chain to + /// switch from the default "accept all unless instructed otherwise" + /// filtering behavior to a "deny all unless instructed otherwise" + /// behavior. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public sealed class DenyAllFilter : FilterSkeleton + { + #region Constructors - /// - /// Default constructor - /// - public DenyAllFilter() - { - } + /// + /// Default constructor + /// + public DenyAllFilter() + { + } - #endregion + #endregion - #region Override implementation of FilterSkeleton + #region Override implementation of FilterSkeleton - /// - /// Always returns the integer constant - /// - /// the LoggingEvent to filter - /// Always returns - /// - /// - /// Ignores the event being logged and just returns - /// . This can be used to change the default filter - /// chain behavior from to . This filter - /// should only be used as the last filter in the chain - /// as any further filters will be ignored! - /// - /// - public override FilterDecision Decide(LoggingEvent loggingEvent) - { - return FilterDecision.Deny; - } + /// + /// Always returns the integer constant + /// + /// the LoggingEvent to filter + /// Always returns + /// + /// + /// Ignores the event being logged and just returns + /// . This can be used to change the default filter + /// chain behavior from to . This filter + /// should only be used as the last filter in the chain + /// as any further filters will be ignored! + /// + /// + public override FilterDecision Decide(LoggingEvent loggingEvent) + { + return FilterDecision.Deny; + } - #endregion - } + #endregion + } } diff --git a/src/log4net/Filter/FilterDecision.cs b/src/log4net/Filter/FilterDecision.cs index 1b5967b4..c81a156f 100644 --- a/src/log4net/Filter/FilterDecision.cs +++ b/src/log4net/Filter/FilterDecision.cs @@ -23,32 +23,32 @@ namespace log4net.Filter { - /// - /// The return result from - /// - /// - /// - /// The return result from - /// - /// - public enum FilterDecision : int - { - /// - /// The log event must be dropped immediately without - /// consulting with the remaining filters, if any, in the chain. - /// - Deny = -1, + /// + /// The return result from + /// + /// + /// + /// The return result from + /// + /// + public enum FilterDecision : int + { + /// + /// The log event must be dropped immediately without + /// consulting with the remaining filters, if any, in the chain. + /// + Deny = -1, - /// - /// This filter is neutral with respect to the log event. - /// The remaining filters, if any, should be consulted for a final decision. - /// - Neutral = 0, + /// + /// This filter is neutral with respect to the log event. + /// The remaining filters, if any, should be consulted for a final decision. + /// + Neutral = 0, - /// - /// The log event must be logged immediately without - /// consulting with the remaining filters, if any, in the chain. - /// - Accept = 1, - } + /// + /// The log event must be logged immediately without + /// consulting with the remaining filters, if any, in the chain. + /// + Accept = 1, + } } diff --git a/src/log4net/Filter/FilterSkeleton.cs b/src/log4net/Filter/FilterSkeleton.cs index 293d3ca5..158d6355 100644 --- a/src/log4net/Filter/FilterSkeleton.cs +++ b/src/log4net/Filter/FilterSkeleton.cs @@ -22,134 +22,134 @@ namespace log4net.Filter { - /// - /// Subclass this type to implement customized logging event filtering - /// - /// - /// - /// Users should extend this class to implement customized logging - /// event filtering. Note that and - /// , the parent class of all standard - /// appenders, have built-in filtering rules. It is suggested that you - /// first use and understand the built-in rules before rushing to write - /// your own custom filters. - /// - /// - /// This abstract class assumes and also imposes that filters be - /// organized in a linear chain. The - /// method of each filter is called sequentially, in the order of their - /// addition to the chain. - /// - /// - /// The method must return one - /// of the integer constants , - /// or . - /// - /// - /// If the value is returned, then the log event is dropped - /// immediately without consulting with the remaining filters. - /// - /// - /// If the value is returned, then the next filter - /// in the chain is consulted. If there are no more filters in the - /// chain, then the log event is logged. Thus, in the presence of no - /// filters, the default behavior is to log all logging events. - /// - /// - /// If the value is returned, then the log - /// event is logged without consulting the remaining filters. - /// - /// - /// The philosophy of log4net filters is largely inspired from the - /// Linux ipchains. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public abstract class FilterSkeleton : IFilter - { - #region Member Variables + /// + /// Subclass this type to implement customized logging event filtering + /// + /// + /// + /// Users should extend this class to implement customized logging + /// event filtering. Note that and + /// , the parent class of all standard + /// appenders, have built-in filtering rules. It is suggested that you + /// first use and understand the built-in rules before rushing to write + /// your own custom filters. + /// + /// + /// This abstract class assumes and also imposes that filters be + /// organized in a linear chain. The + /// method of each filter is called sequentially, in the order of their + /// addition to the chain. + /// + /// + /// The method must return one + /// of the integer constants , + /// or . + /// + /// + /// If the value is returned, then the log event is dropped + /// immediately without consulting with the remaining filters. + /// + /// + /// If the value is returned, then the next filter + /// in the chain is consulted. If there are no more filters in the + /// chain, then the log event is logged. Thus, in the presence of no + /// filters, the default behavior is to log all logging events. + /// + /// + /// If the value is returned, then the log + /// event is logged without consulting the remaining filters. + /// + /// + /// The philosophy of log4net filters is largely inspired from the + /// Linux ipchains. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public abstract class FilterSkeleton : IFilter + { + #region Member Variables - /// - /// Points to the next filter in the filter chain. - /// - /// - /// - /// See for more information. - /// - /// - private IFilter m_next; + /// + /// Points to the next filter in the filter chain. + /// + /// + /// + /// See for more information. + /// + /// + private IFilter m_next; - #endregion + #endregion - #region Implementation of IOptionHandler + #region Implementation of IOptionHandler - /// - /// Initialize the filter with the options set - /// - /// - /// - /// This is part of the delayed object - /// activation scheme. The method must - /// be called on this object after the configuration properties have - /// been set. Until is called this - /// object is in an undefined state and must not be used. - /// - /// - /// If any of the configuration properties are modified then - /// must be called again. - /// - /// - /// Typically filter's options become active immediately on set, - /// however this method must still be called. - /// - /// - public virtual void ActivateOptions() - { - } + /// + /// Initialize the filter with the options set + /// + /// + /// + /// This is part of the delayed object + /// activation scheme. The method must + /// be called on this object after the configuration properties have + /// been set. Until is called this + /// object is in an undefined state and must not be used. + /// + /// + /// If any of the configuration properties are modified then + /// must be called again. + /// + /// + /// Typically filter's options become active immediately on set, + /// however this method must still be called. + /// + /// + public virtual void ActivateOptions() + { + } - #endregion + #endregion - #region Implementation of IFilter + #region Implementation of IFilter - /// - /// Decide if the should be logged through an appender. - /// - /// The to decide upon - /// The decision of the filter - /// - /// - /// If the decision is , then the event will be - /// dropped. If the decision is , then the next - /// filter, if any, will be invoked. If the decision is then - /// the event will be logged without consulting with other filters in - /// the chain. - /// - /// - /// This method is marked abstract and must be implemented - /// in a subclass. - /// - /// - public abstract FilterDecision Decide(LoggingEvent loggingEvent); + /// + /// Decide if the should be logged through an appender. + /// + /// The to decide upon + /// The decision of the filter + /// + /// + /// If the decision is , then the event will be + /// dropped. If the decision is , then the next + /// filter, if any, will be invoked. If the decision is then + /// the event will be logged without consulting with other filters in + /// the chain. + /// + /// + /// This method is marked abstract and must be implemented + /// in a subclass. + /// + /// + public abstract FilterDecision Decide(LoggingEvent loggingEvent); - /// - /// Property to get and set the next filter - /// - /// - /// The next filter in the chain - /// - /// - /// - /// Filters are typically composed into chains. This property allows the next filter in - /// the chain to be accessed. - /// - /// - public IFilter Next - { - get { return m_next; } - set { m_next = value; } - } + /// + /// Property to get and set the next filter + /// + /// + /// The next filter in the chain + /// + /// + /// + /// Filters are typically composed into chains. This property allows the next filter in + /// the chain to be accessed. + /// + /// + public IFilter Next + { + get { return m_next; } + set { m_next = value; } + } - #endregion - } + #endregion + } } diff --git a/src/log4net/Filter/IFilter.cs b/src/log4net/Filter/IFilter.cs index 8c597a7c..66cc91b0 100644 --- a/src/log4net/Filter/IFilter.cs +++ b/src/log4net/Filter/IFilter.cs @@ -23,80 +23,80 @@ namespace log4net.Filter { - /// - /// Implement this interface to provide customized logging event filtering - /// - /// - /// - /// Users should implement this interface to implement customized logging - /// event filtering. Note that and - /// , the parent class of all standard - /// appenders, have built-in filtering rules. It is suggested that you - /// first use and understand the built-in rules before rushing to write - /// your own custom filters. - /// - /// - /// This abstract class assumes and also imposes that filters be - /// organized in a linear chain. The - /// method of each filter is called sequentially, in the order of their - /// addition to the chain. - /// - /// - /// The method must return one - /// of the integer constants , - /// or . - /// - /// - /// If the value is returned, then the log event is dropped - /// immediately without consulting with the remaining filters. - /// - /// - /// If the value is returned, then the next filter - /// in the chain is consulted. If there are no more filters in the - /// chain, then the log event is logged. Thus, in the presence of no - /// filters, the default behavior is to log all logging events. - /// - /// - /// If the value is returned, then the log - /// event is logged without consulting the remaining filters. - /// - /// - /// The philosophy of log4net filters is largely inspired from the - /// Linux ipchains. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public interface IFilter : IOptionHandler - { - /// - /// Decide if the logging event should be logged through an appender. - /// - /// The LoggingEvent to decide upon - /// The decision of the filter - /// - /// - /// If the decision is , then the event will be - /// dropped. If the decision is , then the next - /// filter, if any, will be invoked. If the decision is then - /// the event will be logged without consulting with other filters in - /// the chain. - /// - /// - FilterDecision Decide(LoggingEvent loggingEvent); + /// + /// Implement this interface to provide customized logging event filtering + /// + /// + /// + /// Users should implement this interface to implement customized logging + /// event filtering. Note that and + /// , the parent class of all standard + /// appenders, have built-in filtering rules. It is suggested that you + /// first use and understand the built-in rules before rushing to write + /// your own custom filters. + /// + /// + /// This abstract class assumes and also imposes that filters be + /// organized in a linear chain. The + /// method of each filter is called sequentially, in the order of their + /// addition to the chain. + /// + /// + /// The method must return one + /// of the integer constants , + /// or . + /// + /// + /// If the value is returned, then the log event is dropped + /// immediately without consulting with the remaining filters. + /// + /// + /// If the value is returned, then the next filter + /// in the chain is consulted. If there are no more filters in the + /// chain, then the log event is logged. Thus, in the presence of no + /// filters, the default behavior is to log all logging events. + /// + /// + /// If the value is returned, then the log + /// event is logged without consulting the remaining filters. + /// + /// + /// The philosophy of log4net filters is largely inspired from the + /// Linux ipchains. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public interface IFilter : IOptionHandler + { + /// + /// Decide if the logging event should be logged through an appender. + /// + /// The LoggingEvent to decide upon + /// The decision of the filter + /// + /// + /// If the decision is , then the event will be + /// dropped. If the decision is , then the next + /// filter, if any, will be invoked. If the decision is then + /// the event will be logged without consulting with other filters in + /// the chain. + /// + /// + FilterDecision Decide(LoggingEvent loggingEvent); - /// - /// Property to get and set the next filter - /// - /// - /// The next filter in the chain - /// - /// - /// - /// Filters are typically composed into chains. This property allows the next filter in - /// the chain to be accessed. - /// - /// - IFilter Next { get; set; } - } + /// + /// Property to get and set the next filter + /// + /// + /// The next filter in the chain + /// + /// + /// + /// Filters are typically composed into chains. This property allows the next filter in + /// the chain to be accessed. + /// + /// + IFilter Next { get; set; } + } } diff --git a/src/log4net/Filter/LevelMatchFilter.cs b/src/log4net/Filter/LevelMatchFilter.cs index 34a21b3f..50d291f0 100644 --- a/src/log4net/Filter/LevelMatchFilter.cs +++ b/src/log4net/Filter/LevelMatchFilter.cs @@ -25,118 +25,118 @@ namespace log4net.Filter { - /// - /// This is a very simple filter based on matching. - /// - /// - /// - /// The filter admits two options and - /// . If there is an exact match between the value - /// of the option and the of the - /// , then the method returns in - /// case the option value is set - /// to true, if it is false then - /// is returned. If the does not match then - /// the result will be . - /// - /// - /// Nicko Cadell - /// Gert Driesen - public class LevelMatchFilter : FilterSkeleton - { - #region Member Variables + /// + /// This is a very simple filter based on matching. + /// + /// + /// + /// The filter admits two options and + /// . If there is an exact match between the value + /// of the option and the of the + /// , then the method returns in + /// case the option value is set + /// to true, if it is false then + /// is returned. If the does not match then + /// the result will be . + /// + /// + /// Nicko Cadell + /// Gert Driesen + public class LevelMatchFilter : FilterSkeleton + { + #region Member Variables - /// - /// flag to indicate if the filter should on a match - /// - private bool m_acceptOnMatch = true; + /// + /// flag to indicate if the filter should on a match + /// + private bool m_acceptOnMatch = true; - /// - /// the to match against - /// - private Level m_levelToMatch; + /// + /// the to match against + /// + private Level m_levelToMatch; - #endregion + #endregion - #region Constructors + #region Constructors - /// - /// Default constructor - /// - public LevelMatchFilter() - { - } + /// + /// Default constructor + /// + public LevelMatchFilter() + { + } - #endregion + #endregion - /// - /// when matching - /// - /// - /// - /// The property is a flag that determines - /// the behavior when a matching is found. If the - /// flag is set to true then the filter will the - /// logging event, otherwise it will the event. - /// - /// - /// The default is true i.e. to the event. - /// - /// - public bool AcceptOnMatch - { - get { return m_acceptOnMatch; } - set { m_acceptOnMatch = value; } - } + /// + /// when matching + /// + /// + /// + /// The property is a flag that determines + /// the behavior when a matching is found. If the + /// flag is set to true then the filter will the + /// logging event, otherwise it will the event. + /// + /// + /// The default is true i.e. to the event. + /// + /// + public bool AcceptOnMatch + { + get { return m_acceptOnMatch; } + set { m_acceptOnMatch = value; } + } - /// - /// The that the filter will match - /// - /// - /// - /// The level that this filter will attempt to match against the - /// level. If a match is found then - /// the result depends on the value of . - /// - /// - public Level LevelToMatch - { - get { return m_levelToMatch; } - set { m_levelToMatch = value; } - } + /// + /// The that the filter will match + /// + /// + /// + /// The level that this filter will attempt to match against the + /// level. If a match is found then + /// the result depends on the value of . + /// + /// + public Level LevelToMatch + { + get { return m_levelToMatch; } + set { m_levelToMatch = value; } + } - #region Override implementation of FilterSkeleton + #region Override implementation of FilterSkeleton - /// - /// Tests if the of the logging event matches that of the filter - /// - /// the event to filter - /// see remarks - /// - /// - /// If the of the event matches the level of the - /// filter then the result of the function depends on the - /// value of . If it is true then - /// the function will return , it it is false then it - /// will return . If the does not match then - /// the result will be . - /// - /// - public override FilterDecision Decide(LoggingEvent loggingEvent) - { - if (loggingEvent == null) - { - throw new ArgumentNullException("loggingEvent"); - } + /// + /// Tests if the of the logging event matches that of the filter + /// + /// the event to filter + /// see remarks + /// + /// + /// If the of the event matches the level of the + /// filter then the result of the function depends on the + /// value of . If it is true then + /// the function will return , it it is false then it + /// will return . If the does not match then + /// the result will be . + /// + /// + public override FilterDecision Decide(LoggingEvent loggingEvent) + { + if (loggingEvent == null) + { + throw new ArgumentNullException("loggingEvent"); + } - if (m_levelToMatch != null && m_levelToMatch == loggingEvent.Level) - { - // Found match - return m_acceptOnMatch ? FilterDecision.Accept : FilterDecision.Deny; - } - return FilterDecision.Neutral; - } + if (m_levelToMatch != null && m_levelToMatch == loggingEvent.Level) + { + // Found match + return m_acceptOnMatch ? FilterDecision.Accept : FilterDecision.Deny; + } + return FilterDecision.Neutral; + } - #endregion - } + #endregion + } } diff --git a/src/log4net/Filter/LevelRangeFilter.cs b/src/log4net/Filter/LevelRangeFilter.cs index f6e0be00..e2bb676c 100644 --- a/src/log4net/Filter/LevelRangeFilter.cs +++ b/src/log4net/Filter/LevelRangeFilter.cs @@ -25,161 +25,161 @@ namespace log4net.Filter { - /// - /// This is a simple filter based on matching. - /// - /// - /// - /// The filter admits three options and - /// that determine the range of priorities that are matched, and - /// . If there is a match between the range - /// of priorities and the of the , then the - /// method returns in case the - /// option value is set to true, if it is false - /// then is returned. If there is no match, is returned. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public class LevelRangeFilter : FilterSkeleton - { - #region Member Variables - - /// - /// Flag to indicate the behavior when matching a - /// - private bool m_acceptOnMatch = true; - - /// - /// the minimum value to match - /// - private Level m_levelMin; - - /// - /// the maximum value to match - /// - private Level m_levelMax; - - #endregion - - #region Constructors - - /// - /// Default constructor - /// - public LevelRangeFilter() - { - } - - #endregion - - /// - /// when matching and - /// - /// - /// - /// The property is a flag that determines - /// the behavior when a matching is found. If the - /// flag is set to true then the filter will the - /// logging event, otherwise it will the event. - /// - /// - /// The default is true i.e. to the event. - /// - /// - public bool AcceptOnMatch - { - get { return m_acceptOnMatch; } - set { m_acceptOnMatch = value; } - } - - /// - /// Set the minimum matched - /// - /// - /// - /// The minimum level that this filter will attempt to match against the - /// level. If a match is found then - /// the result depends on the value of . - /// - /// - public Level LevelMin - { - get { return m_levelMin; } - set { m_levelMin = value; } - } - - /// - /// Sets the maximum matched - /// - /// - /// - /// The maximum level that this filter will attempt to match against the - /// level. If a match is found then - /// the result depends on the value of . - /// - /// - public Level LevelMax - { - get { return m_levelMax; } - set { m_levelMax = value; } - } - - #region Override implementation of FilterSkeleton - - /// - /// Check if the event should be logged. - /// - /// the logging event to check - /// see remarks - /// - /// - /// If the of the logging event is outside the range - /// matched by this filter then - /// is returned. If the is matched then the value of - /// is checked. If it is true then - /// is returned, otherwise - /// is returned. - /// - /// - public override FilterDecision Decide(LoggingEvent loggingEvent) - { - if (loggingEvent == null) - { - throw new ArgumentNullException("loggingEvent"); - } - - if (m_levelMin != null) - { - if (loggingEvent.Level < m_levelMin) - { - // level of event is less than minimum - return FilterDecision.Deny; - } - } - - if (m_levelMax != null) - { - if (loggingEvent.Level > m_levelMax) - { - // level of event is greater than maximum - return FilterDecision.Deny; - } - } - - if (m_acceptOnMatch) - { - // this filter set up to bypass later filters and always return - // accept if level in range - return FilterDecision.Accept; - } - else - { - // event is ok for this filter; allow later filters to have a look.. - return FilterDecision.Neutral; - } - } - - #endregion - } + /// + /// This is a simple filter based on matching. + /// + /// + /// + /// The filter admits three options and + /// that determine the range of priorities that are matched, and + /// . If there is a match between the range + /// of priorities and the of the , then the + /// method returns in case the + /// option value is set to true, if it is false + /// then is returned. If there is no match, is returned. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public class LevelRangeFilter : FilterSkeleton + { + #region Member Variables + + /// + /// Flag to indicate the behavior when matching a + /// + private bool m_acceptOnMatch = true; + + /// + /// the minimum value to match + /// + private Level m_levelMin; + + /// + /// the maximum value to match + /// + private Level m_levelMax; + + #endregion + + #region Constructors + + /// + /// Default constructor + /// + public LevelRangeFilter() + { + } + + #endregion + + /// + /// when matching and + /// + /// + /// + /// The property is a flag that determines + /// the behavior when a matching is found. If the + /// flag is set to true then the filter will the + /// logging event, otherwise it will the event. + /// + /// + /// The default is true i.e. to the event. + /// + /// + public bool AcceptOnMatch + { + get { return m_acceptOnMatch; } + set { m_acceptOnMatch = value; } + } + + /// + /// Set the minimum matched + /// + /// + /// + /// The minimum level that this filter will attempt to match against the + /// level. If a match is found then + /// the result depends on the value of . + /// + /// + public Level LevelMin + { + get { return m_levelMin; } + set { m_levelMin = value; } + } + + /// + /// Sets the maximum matched + /// + /// + /// + /// The maximum level that this filter will attempt to match against the + /// level. If a match is found then + /// the result depends on the value of . + /// + /// + public Level LevelMax + { + get { return m_levelMax; } + set { m_levelMax = value; } + } + + #region Override implementation of FilterSkeleton + + /// + /// Check if the event should be logged. + /// + /// the logging event to check + /// see remarks + /// + /// + /// If the of the logging event is outside the range + /// matched by this filter then + /// is returned. If the is matched then the value of + /// is checked. If it is true then + /// is returned, otherwise + /// is returned. + /// + /// + public override FilterDecision Decide(LoggingEvent loggingEvent) + { + if (loggingEvent == null) + { + throw new ArgumentNullException("loggingEvent"); + } + + if (m_levelMin != null) + { + if (loggingEvent.Level < m_levelMin) + { + // level of event is less than minimum + return FilterDecision.Deny; + } + } + + if (m_levelMax != null) + { + if (loggingEvent.Level > m_levelMax) + { + // level of event is greater than maximum + return FilterDecision.Deny; + } + } + + if (m_acceptOnMatch) + { + // this filter set up to bypass later filters and always return + // accept if level in range + return FilterDecision.Accept; + } + else + { + // event is ok for this filter; allow later filters to have a look.. + return FilterDecision.Neutral; + } + } + + #endregion + } } diff --git a/src/log4net/Filter/LoggerMatchFilter.cs b/src/log4net/Filter/LoggerMatchFilter.cs index 28264ec1..0bc5e65d 100644 --- a/src/log4net/Filter/LoggerMatchFilter.cs +++ b/src/log4net/Filter/LoggerMatchFilter.cs @@ -25,136 +25,136 @@ namespace log4net.Filter { - /// - /// Simple filter to match a string in the event's logger name. - /// - /// - /// - /// The works very similar to the . It admits two - /// options and . If the - /// of the starts - /// with the value of the option, then the - /// method returns in - /// case the option value is set to true, - /// if it is false then is returned. - /// - /// - /// Daniel Cazzulino - public class LoggerMatchFilter : FilterSkeleton - { - #region Member Variables - - /// - /// Flag to indicate the behavior when we have a match - /// - private bool m_acceptOnMatch = true; - - /// - /// The logger name string to substring match against the event - /// - private string m_loggerToMatch; - - #endregion - - #region Constructors - - /// - /// Default constructor - /// - public LoggerMatchFilter() - { - } - - #endregion - - #region Properties - - /// - /// when matching - /// - /// - /// - /// The property is a flag that determines - /// the behavior when a matching is found. If the - /// flag is set to true then the filter will the - /// logging event, otherwise it will the event. - /// - /// - /// The default is true i.e. to the event. - /// - /// - public bool AcceptOnMatch - { - get { return m_acceptOnMatch; } - set { m_acceptOnMatch = value; } - } - - /// - /// The that the filter will match - /// - /// - /// - /// This filter will attempt to match this value against logger name in - /// the following way. The match will be done against the beginning of the - /// logger name (using ). The match is - /// case sensitive. If a match is found then - /// the result depends on the value of . - /// - /// - public string LoggerToMatch - { - get { return m_loggerToMatch; } - set { m_loggerToMatch = value; } - } - - #endregion - - #region Override implementation of FilterSkeleton - - /// - /// Check if this filter should allow the event to be logged - /// - /// the event being logged - /// see remarks - /// - /// - /// The rendered message is matched against the . - /// If the equals the beginning of - /// the incoming () - /// then a match will have occurred. If no match occurs - /// this function will return - /// allowing other filters to check the event. If a match occurs then - /// the value of is checked. If it is - /// true then is returned otherwise - /// is returned. - /// - /// - public override FilterDecision Decide(LoggingEvent loggingEvent) - { - if (loggingEvent == null) - { - throw new ArgumentNullException("loggingEvent"); - } - - // Check if we have been setup to filter - if ((m_loggerToMatch != null && m_loggerToMatch.Length != 0) && - loggingEvent.LoggerName.StartsWith(m_loggerToMatch)) - { - // we've got a match - if (m_acceptOnMatch) - { - return FilterDecision.Accept; - } - return FilterDecision.Deny; - } - else - { - // We cannot filter so allow the filter chain - // to continue processing - return FilterDecision.Neutral; - } - } - - #endregion - } + /// + /// Simple filter to match a string in the event's logger name. + /// + /// + /// + /// The works very similar to the . It admits two + /// options and . If the + /// of the starts + /// with the value of the option, then the + /// method returns in + /// case the option value is set to true, + /// if it is false then is returned. + /// + /// + /// Daniel Cazzulino + public class LoggerMatchFilter : FilterSkeleton + { + #region Member Variables + + /// + /// Flag to indicate the behavior when we have a match + /// + private bool m_acceptOnMatch = true; + + /// + /// The logger name string to substring match against the event + /// + private string m_loggerToMatch; + + #endregion + + #region Constructors + + /// + /// Default constructor + /// + public LoggerMatchFilter() + { + } + + #endregion + + #region Properties + + /// + /// when matching + /// + /// + /// + /// The property is a flag that determines + /// the behavior when a matching is found. If the + /// flag is set to true then the filter will the + /// logging event, otherwise it will the event. + /// + /// + /// The default is true i.e. to the event. + /// + /// + public bool AcceptOnMatch + { + get { return m_acceptOnMatch; } + set { m_acceptOnMatch = value; } + } + + /// + /// The that the filter will match + /// + /// + /// + /// This filter will attempt to match this value against logger name in + /// the following way. The match will be done against the beginning of the + /// logger name (using ). The match is + /// case sensitive. If a match is found then + /// the result depends on the value of . + /// + /// + public string LoggerToMatch + { + get { return m_loggerToMatch; } + set { m_loggerToMatch = value; } + } + + #endregion + + #region Override implementation of FilterSkeleton + + /// + /// Check if this filter should allow the event to be logged + /// + /// the event being logged + /// see remarks + /// + /// + /// The rendered message is matched against the . + /// If the equals the beginning of + /// the incoming () + /// then a match will have occurred. If no match occurs + /// this function will return + /// allowing other filters to check the event. If a match occurs then + /// the value of is checked. If it is + /// true then is returned otherwise + /// is returned. + /// + /// + public override FilterDecision Decide(LoggingEvent loggingEvent) + { + if (loggingEvent == null) + { + throw new ArgumentNullException("loggingEvent"); + } + + // Check if we have been setup to filter + if ((m_loggerToMatch != null && m_loggerToMatch.Length != 0) && + loggingEvent.LoggerName.StartsWith(m_loggerToMatch)) + { + // we've got a match + if (m_acceptOnMatch) + { + return FilterDecision.Accept; + } + return FilterDecision.Deny; + } + else + { + // We cannot filter so allow the filter chain + // to continue processing + return FilterDecision.Neutral; + } + } + + #endregion + } } diff --git a/src/log4net/Filter/MdcFilter.cs b/src/log4net/Filter/MdcFilter.cs index 3ca7953a..adfa6eff 100644 --- a/src/log4net/Filter/MdcFilter.cs +++ b/src/log4net/Filter/MdcFilter.cs @@ -26,22 +26,22 @@ namespace log4net.Filter { - /// - /// Simple filter to match a keyed string in the - /// - /// - /// - /// Simple filter to match a keyed string in the - /// - /// - /// As the MDC has been replaced with layered properties the - /// should be used instead. - /// - /// - /// Nicko Cadell - /// Gert Driesen - /*[Obsolete("MdcFilter has been replaced by PropertyFilter")]*/ - public class MdcFilter : PropertyFilter - { - } + /// + /// Simple filter to match a keyed string in the + /// + /// + /// + /// Simple filter to match a keyed string in the + /// + /// + /// As the MDC has been replaced with layered properties the + /// should be used instead. + /// + /// + /// Nicko Cadell + /// Gert Driesen + /*[Obsolete("MdcFilter has been replaced by PropertyFilter")]*/ + public class MdcFilter : PropertyFilter + { + } } diff --git a/src/log4net/Filter/NdcFilter.cs b/src/log4net/Filter/NdcFilter.cs index e1659fe1..4b0a3e0d 100644 --- a/src/log4net/Filter/NdcFilter.cs +++ b/src/log4net/Filter/NdcFilter.cs @@ -26,35 +26,35 @@ namespace log4net.Filter { - /// - /// Simple filter to match a string in the - /// - /// - /// - /// Simple filter to match a string in the - /// - /// - /// As the MDC has been replaced with named stacks stored in the - /// properties collections the should - /// be used instead. - /// - /// - /// Nicko Cadell - /// Gert Driesen - /*[Obsolete("NdcFilter has been replaced by PropertyFilter")]*/ - public class NdcFilter : PropertyFilter - { - /// - /// Default constructor - /// - /// - /// - /// Sets the to "NDC". - /// - /// - public NdcFilter() - { - base.Key = "NDC"; - } - } + /// + /// Simple filter to match a string in the + /// + /// + /// + /// Simple filter to match a string in the + /// + /// + /// As the MDC has been replaced with named stacks stored in the + /// properties collections the should + /// be used instead. + /// + /// + /// Nicko Cadell + /// Gert Driesen + /*[Obsolete("NdcFilter has been replaced by PropertyFilter")]*/ + public class NdcFilter : PropertyFilter + { + /// + /// Default constructor + /// + /// + /// + /// Sets the to "NDC". + /// + /// + public NdcFilter() + { + base.Key = "NDC"; + } + } } diff --git a/src/log4net/Filter/PropertyFilter.cs b/src/log4net/Filter/PropertyFilter.cs index a74a03b0..b8815d17 100644 --- a/src/log4net/Filter/PropertyFilter.cs +++ b/src/log4net/Filter/PropertyFilter.cs @@ -26,140 +26,140 @@ namespace log4net.Filter { - /// - /// Simple filter to match a string an event property - /// - /// - /// - /// Simple filter to match a string in the value for a - /// specific event property - /// - /// - /// Nicko Cadell - public class PropertyFilter : StringMatchFilter - { - #region Member Variables - - /// - /// The key to use to lookup the string from the event properties - /// - private string m_key; - - #endregion - - #region Constructors - - /// - /// Default constructor - /// - public PropertyFilter() - { - } - - #endregion - - /// - /// The key to lookup in the event properties and then match against. - /// - /// - /// - /// The key name to use to lookup in the properties map of the - /// . The match will be performed against - /// the value of this property if it exists. - /// - /// - public string Key - { - get { return m_key; } - set { m_key = value; } - } - - #region Override implementation of FilterSkeleton - - /// - /// Check if this filter should allow the event to be logged - /// - /// the event being logged - /// see remarks - /// - /// - /// The event property for the is matched against - /// the . - /// If the occurs as a substring within - /// the property value then a match will have occurred. If no match occurs - /// this function will return - /// allowing other filters to check the event. If a match occurs then - /// the value of is checked. If it is - /// true then is returned otherwise - /// is returned. - /// - /// - public override 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; - } + /// + /// Simple filter to match a string an event property + /// + /// + /// + /// Simple filter to match a string in the value for a + /// specific event property + /// + /// + /// Nicko Cadell + public class PropertyFilter : StringMatchFilter + { + #region Member Variables + + /// + /// The key to use to lookup the string from the event properties + /// + private string m_key; + + #endregion + + #region Constructors + + /// + /// Default constructor + /// + public PropertyFilter() + { + } + + #endregion + + /// + /// The key to lookup in the event properties and then match against. + /// + /// + /// + /// The key name to use to lookup in the properties map of the + /// . The match will be performed against + /// the value of this property if it exists. + /// + /// + public string Key + { + get { return m_key; } + set { m_key = value; } + } + + #region Override implementation of FilterSkeleton + + /// + /// Check if this filter should allow the event to be logged + /// + /// the event being logged + /// see remarks + /// + /// + /// The event property for the is matched against + /// the . + /// If the occurs as a substring within + /// the property value then a match will have occurred. If no match occurs + /// this function will return + /// allowing other filters to check the event. If a match occurs then + /// the value of is checked. If it is + /// true then is returned otherwise + /// is returned. + /// + /// + public override 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 - } + // 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 + } } diff --git a/src/log4net/Filter/StringMatchFilter.cs b/src/log4net/Filter/StringMatchFilter.cs index 840a95d0..b2695861 100644 --- a/src/log4net/Filter/StringMatchFilter.cs +++ b/src/log4net/Filter/StringMatchFilter.cs @@ -26,220 +26,220 @@ namespace log4net.Filter { - /// - /// Simple filter to match a string in the rendered message - /// - /// - /// - /// Simple filter to match a string in the rendered message - /// - /// - /// Nicko Cadell - /// Gert Driesen - public class StringMatchFilter : FilterSkeleton - { - #region Member Variables - - /// - /// Flag to indicate the behavior when we have a match - /// - protected bool m_acceptOnMatch = true; - - /// - /// The string to substring match against the message - /// - protected string m_stringToMatch; - - /// - /// A string regex to match - /// - protected string m_stringRegexToMatch; - - /// - /// A regex object to match (generated from m_stringRegexToMatch) - /// - protected Regex m_regexToMatch; - - #endregion - - #region Constructors - - /// - /// Default constructor - /// - public StringMatchFilter() - { - } - - #endregion - - #region Implementation of IOptionHandler - - /// - /// Initialize and precompile the Regex if required - /// - /// - /// - /// This is part of the delayed object - /// activation scheme. The method must - /// be called on this object after the configuration properties have - /// been set. Until is called this - /// object is in an undefined state and must not be used. - /// - /// - /// If any of the configuration properties are modified then - /// must be called again. - /// - /// - public override void ActivateOptions() - { - if (m_stringRegexToMatch != null) - { + /// + /// Simple filter to match a string in the rendered message + /// + /// + /// + /// Simple filter to match a string in the rendered message + /// + /// + /// Nicko Cadell + /// Gert Driesen + public class StringMatchFilter : FilterSkeleton + { + #region Member Variables + + /// + /// Flag to indicate the behavior when we have a match + /// + protected bool m_acceptOnMatch = true; + + /// + /// The string to substring match against the message + /// + protected string m_stringToMatch; + + /// + /// A string regex to match + /// + protected string m_stringRegexToMatch; + + /// + /// A regex object to match (generated from m_stringRegexToMatch) + /// + protected Regex m_regexToMatch; + + #endregion + + #region Constructors + + /// + /// Default constructor + /// + public StringMatchFilter() + { + } + + #endregion + + #region Implementation of IOptionHandler + + /// + /// Initialize and precompile the Regex if required + /// + /// + /// + /// This is part of the delayed object + /// activation scheme. The method must + /// be called on this object after the configuration properties have + /// been set. Until is called this + /// object is in an undefined state and must not be used. + /// + /// + /// If any of the configuration properties are modified then + /// must be called again. + /// + /// + public override void ActivateOptions() + { + if (m_stringRegexToMatch != null) + { #if NETSTANDARD1_3 - m_regexToMatch = new Regex(m_stringRegexToMatch); + m_regexToMatch = new Regex(m_stringRegexToMatch); #else - m_regexToMatch = new Regex(m_stringRegexToMatch, RegexOptions.Compiled); + m_regexToMatch = new Regex(m_stringRegexToMatch, RegexOptions.Compiled); #endif - } - } - - #endregion - - /// - /// when matching or - /// - /// - /// - /// The property is a flag that determines - /// the behavior when a matching is found. If the - /// flag is set to true then the filter will the - /// logging event, otherwise it will the event. - /// - /// - /// The default is true i.e. to the event. - /// - /// - public bool AcceptOnMatch - { - get { return m_acceptOnMatch; } - set { m_acceptOnMatch = value; } - } - - /// - /// Sets the static string to match - /// - /// - /// - /// The string that will be substring matched against - /// the rendered message. If the message contains this - /// string then the filter will match. If a match is found then - /// the result depends on the value of . - /// - /// - /// One of or - /// must be specified. - /// - /// - public string StringToMatch - { - get { return m_stringToMatch; } - set { m_stringToMatch = value; } - } - - /// - /// Sets the regular expression to match - /// - /// - /// - /// The regular expression pattern that will be matched against - /// the rendered message. If the message matches this - /// pattern then the filter will match. If a match is found then - /// the result depends on the value of . - /// - /// - /// One of or - /// must be specified. - /// - /// - public string RegexToMatch - { - get { return m_stringRegexToMatch; } - set { m_stringRegexToMatch = value; } - } - - #region Override implementation of FilterSkeleton - - /// - /// Check if this filter should allow the event to be logged - /// - /// the event being logged - /// see remarks - /// - /// - /// The rendered message is matched against the . - /// If the occurs as a substring within - /// the message then a match will have occurred. If no match occurs - /// this function will return - /// allowing other filters to check the event. If a match occurs then - /// the value of is checked. If it is - /// true then is returned otherwise - /// is returned. - /// - /// - public override FilterDecision Decide(LoggingEvent loggingEvent) - { - if (loggingEvent == null) - { - throw new ArgumentNullException("loggingEvent"); - } - - string msg = loggingEvent.RenderedMessage; - - // 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; - } + } + } + + #endregion + + /// + /// when matching or + /// + /// + /// + /// The property is a flag that determines + /// the behavior when a matching is found. If the + /// flag is set to true then the filter will the + /// logging event, otherwise it will the event. + /// + /// + /// The default is true i.e. to the event. + /// + /// + public bool AcceptOnMatch + { + get { return m_acceptOnMatch; } + set { m_acceptOnMatch = value; } + } + + /// + /// Sets the static string to match + /// + /// + /// + /// The string that will be substring matched against + /// the rendered message. If the message contains this + /// string then the filter will match. If a match is found then + /// the result depends on the value of . + /// + /// + /// One of or + /// must be specified. + /// + /// + public string StringToMatch + { + get { return m_stringToMatch; } + set { m_stringToMatch = value; } + } + + /// + /// Sets the regular expression to match + /// + /// + /// + /// The regular expression pattern that will be matched against + /// the rendered message. If the message matches this + /// pattern then the filter will match. If a match is found then + /// the result depends on the value of . + /// + /// + /// One of or + /// must be specified. + /// + /// + public string RegexToMatch + { + get { return m_stringRegexToMatch; } + set { m_stringRegexToMatch = value; } + } + + #region Override implementation of FilterSkeleton + + /// + /// Check if this filter should allow the event to be logged + /// + /// the event being logged + /// see remarks + /// + /// + /// The rendered message is matched against the . + /// If the occurs as a substring within + /// the message then a match will have occurred. If no match occurs + /// this function will return + /// allowing other filters to check the event. If a match occurs then + /// the value of is checked. If it is + /// true then is returned otherwise + /// is returned. + /// + /// + public override FilterDecision Decide(LoggingEvent loggingEvent) + { + if (loggingEvent == null) + { + throw new ArgumentNullException("loggingEvent"); + } + + string msg = loggingEvent.RenderedMessage; + + // 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 - } + // 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 + } } diff --git a/src/log4net/GlobalContext.cs b/src/log4net/GlobalContext.cs index 222b90c8..d698858d 100644 --- a/src/log4net/GlobalContext.cs +++ b/src/log4net/GlobalContext.cs @@ -24,79 +24,79 @@ namespace log4net { - /// - /// The log4net Global Context. - /// - /// - /// - /// The GlobalContext provides a location for global debugging - /// information to be stored. - /// - /// - /// The global context has a properties map and these properties can - /// be included in the output of log messages. The - /// supports selecting and outputing these properties. - /// - /// - /// By default the log4net:HostName property is set to the name of - /// the current machine. - /// - /// - /// - /// - /// GlobalContext.Properties["hostname"] = Environment.MachineName; - /// - /// - /// - /// Nicko Cadell - public sealed class GlobalContext - { - #region Private Instance Constructors + /// + /// The log4net Global Context. + /// + /// + /// + /// The GlobalContext provides a location for global debugging + /// information to be stored. + /// + /// + /// The global context has a properties map and these properties can + /// be included in the output of log messages. The + /// supports selecting and outputing these properties. + /// + /// + /// By default the log4net:HostName property is set to the name of + /// the current machine. + /// + /// + /// + /// + /// GlobalContext.Properties["hostname"] = Environment.MachineName; + /// + /// + /// + /// Nicko Cadell + public sealed class GlobalContext + { + #region Private Instance Constructors - /// - /// Private Constructor. - /// - /// - /// Uses a private access modifier to prevent instantiation of this class. - /// - private GlobalContext() - { - } + /// + /// Private Constructor. + /// + /// + /// Uses a private access modifier to prevent instantiation of this class. + /// + private GlobalContext() + { + } - #endregion Private Instance Constructors + #endregion Private Instance Constructors - static GlobalContext() - { - Properties[log4net.Core.LoggingEvent.HostNameProperty] = SystemInfo.HostName; - } + static GlobalContext() + { + Properties[log4net.Core.LoggingEvent.HostNameProperty] = SystemInfo.HostName; + } - #region Public Static Properties + #region Public Static Properties - /// - /// The global properties map. - /// - /// - /// The global properties map. - /// - /// - /// - /// The global properties map. - /// - /// - public static GlobalContextProperties Properties - { - get { return s_properties; } - } + /// + /// The global properties map. + /// + /// + /// The global properties map. + /// + /// + /// + /// The global properties map. + /// + /// + public static GlobalContextProperties Properties + { + get { return s_properties; } + } - #endregion Public Static Properties + #endregion Public Static Properties - #region Private Static Fields + #region Private Static Fields - /// - /// The global context properties instance - /// - private static readonly GlobalContextProperties s_properties = new GlobalContextProperties(); + /// + /// The global context properties instance + /// + private static readonly GlobalContextProperties s_properties = new GlobalContextProperties(); - #endregion Private Static Fields - } + #endregion Private Static Fields + } } diff --git a/src/log4net/ILog.cs b/src/log4net/ILog.cs index 89d01c75..ed39c164 100644 --- a/src/log4net/ILog.cs +++ b/src/log4net/ILog.cs @@ -24,937 +24,937 @@ namespace log4net { - /// - /// The ILog interface is use by application to log messages into - /// the log4net framework. - /// - /// - /// - /// Use the to obtain logger instances - /// that implement this interface. The - /// static method is used to get logger instances. - /// - /// - /// This class contains methods for logging at different levels and also - /// has properties for determining if those logging levels are - /// enabled in the current configuration. - /// - /// - /// This interface can be implemented in different ways. This documentation - /// specifies reasonable behavior that a caller can expect from the actual - /// implementation, however different implementations reserve the right to - /// do things differently. - /// - /// - /// Simple example of logging messages - /// - /// ILog log = LogManager.GetLogger("application-log"); - /// - /// log.Info("Application Start"); - /// log.Debug("This is a debug message"); - /// - /// if (log.IsDebugEnabled) - /// { - /// log.Debug("This is another debug message"); - /// } - /// - /// - /// - /// - /// Nicko Cadell - /// Gert Driesen - public interface ILog : ILoggerWrapper - { - /// Log a message object with the level. - /// - /// Log a message object with the level. - /// - /// The message object to log. - /// - /// - /// This method first checks if this logger is DEBUG - /// enabled by comparing the level of this logger with the - /// level. If this logger is - /// DEBUG enabled, then it converts the message object - /// (passed as parameter) to a string by invoking the appropriate - /// . It then - /// proceeds to call all the registered appenders in this logger - /// and also higher in the hierarchy depending on the value of - /// the additivity flag. - /// - /// WARNING Note that passing an - /// to this method will print the name of the - /// but no stack trace. To print a stack trace use the - /// form instead. - /// - /// - /// - /// - void Debug(object message); + /// + /// The ILog interface is use by application to log messages into + /// the log4net framework. + /// + /// + /// + /// Use the to obtain logger instances + /// that implement this interface. The + /// static method is used to get logger instances. + /// + /// + /// This class contains methods for logging at different levels and also + /// has properties for determining if those logging levels are + /// enabled in the current configuration. + /// + /// + /// This interface can be implemented in different ways. This documentation + /// specifies reasonable behavior that a caller can expect from the actual + /// implementation, however different implementations reserve the right to + /// do things differently. + /// + /// + /// Simple example of logging messages + /// + /// ILog log = LogManager.GetLogger("application-log"); + /// + /// log.Info("Application Start"); + /// log.Debug("This is a debug message"); + /// + /// if (log.IsDebugEnabled) + /// { + /// log.Debug("This is another debug message"); + /// } + /// + /// + /// + /// + /// Nicko Cadell + /// Gert Driesen + public interface ILog : ILoggerWrapper + { + /// Log a message object with the level. + /// + /// Log a message object with the level. + /// + /// The message object to log. + /// + /// + /// This method first checks if this logger is DEBUG + /// enabled by comparing the level of this logger with the + /// level. If this logger is + /// DEBUG enabled, then it converts the message object + /// (passed as parameter) to a string by invoking the appropriate + /// . It then + /// proceeds to call all the registered appenders in this logger + /// and also higher in the hierarchy depending on the value of + /// the additivity flag. + /// + /// WARNING Note that passing an + /// to this method will print the name of the + /// but no stack trace. To print a stack trace use the + /// form instead. + /// + /// + /// + /// + void Debug(object message); - /// - /// Log a message object with the level including - /// the stack trace of the passed - /// as a parameter. - /// - /// The message object to log. - /// The exception to log, including its stack trace. - /// - /// - /// See the form for more detailed information. - /// - /// - /// - /// - void Debug(object message, Exception exception); - - /// Log a formatted string with the level. - /// - /// Logs a formatted message string with the level. - /// - /// A String containing zero or more format items - /// An Object array containing zero or more objects to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - void DebugFormat(string format, params object[] args); - - /// - /// Logs a formatted message string with the level. - /// - /// A String containing zero or more format items - /// An Object to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - void DebugFormat(string format, object arg0); - - /// - /// Logs a formatted message string with the level. - /// - /// A String containing zero or more format items - /// An Object to format - /// An Object to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - void DebugFormat(string format, object arg0, object arg1); - - /// - /// Logs a formatted message string with the level. - /// - /// A String containing zero or more format items - /// An Object to format - /// An Object to format - /// An Object to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - void DebugFormat(string format, object arg0, object arg1, object arg2); - - /// - /// Logs a formatted message string with the level. - /// - /// An that supplies culture-specific formatting information - /// A String containing zero or more format items - /// An Object array containing zero or more objects to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - void DebugFormat(IFormatProvider provider, string format, params object[] args); - - /// Log a message object with the level. - /// - /// Logs a message object with the level. - /// - /// - /// - /// This method first checks if this logger is INFO - /// enabled by comparing the level of this logger with the - /// level. If this logger is - /// INFO enabled, then it converts the message object - /// (passed as parameter) to a string by invoking the appropriate - /// . It then - /// proceeds to call all the registered appenders in this logger - /// and also higher in the hierarchy depending on the value of the - /// additivity flag. - /// - /// WARNING Note that passing an - /// to this method will print the name of the - /// but no stack trace. To print a stack trace use the - /// form instead. - /// - /// - /// The message object to log. - /// - /// - void Info(object message); + /// + /// Log a message object with the level including + /// the stack trace of the passed + /// as a parameter. + /// + /// The message object to log. + /// The exception to log, including its stack trace. + /// + /// + /// See the form for more detailed information. + /// + /// + /// + /// + void Debug(object message, Exception exception); + + /// Log a formatted string with the level. + /// + /// Logs a formatted message string with the level. + /// + /// A String containing zero or more format items + /// An Object array containing zero or more objects to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + void DebugFormat(string format, params object[] args); + + /// + /// Logs a formatted message string with the level. + /// + /// A String containing zero or more format items + /// An Object to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + void DebugFormat(string format, object arg0); + + /// + /// Logs a formatted message string with the level. + /// + /// A String containing zero or more format items + /// An Object to format + /// An Object to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + void DebugFormat(string format, object arg0, object arg1); + + /// + /// Logs a formatted message string with the level. + /// + /// A String containing zero or more format items + /// An Object to format + /// An Object to format + /// An Object to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + void DebugFormat(string format, object arg0, object arg1, object arg2); + + /// + /// Logs a formatted message string with the level. + /// + /// An that supplies culture-specific formatting information + /// A String containing zero or more format items + /// An Object array containing zero or more objects to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + void DebugFormat(IFormatProvider provider, string format, params object[] args); + + /// Log a message object with the level. + /// + /// Logs a message object with the level. + /// + /// + /// + /// This method first checks if this logger is INFO + /// enabled by comparing the level of this logger with the + /// level. If this logger is + /// INFO enabled, then it converts the message object + /// (passed as parameter) to a string by invoking the appropriate + /// . It then + /// proceeds to call all the registered appenders in this logger + /// and also higher in the hierarchy depending on the value of the + /// additivity flag. + /// + /// WARNING Note that passing an + /// to this method will print the name of the + /// but no stack trace. To print a stack trace use the + /// form instead. + /// + /// + /// The message object to log. + /// + /// + void Info(object message); - /// - /// Logs a message object with the INFO level including - /// the stack trace of the passed - /// as a parameter. - /// - /// The message object to log. - /// The exception to log, including its stack trace. - /// - /// - /// See the form for more detailed information. - /// - /// - /// - /// - void Info(object message, Exception exception); - - /// Log a formatted message string with the level. - /// - /// Logs a formatted message string with the level. - /// - /// A String containing zero or more format items - /// An Object array containing zero or more objects to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - void InfoFormat(string format, params object[] args); - - /// - /// Logs a formatted message string with the level. - /// - /// A String containing zero or more format items - /// An Object to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - void InfoFormat(string format, object arg0); - - /// - /// Logs a formatted message string with the level. - /// - /// A String containing zero or more format items - /// An Object to format - /// An Object to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - void InfoFormat(string format, object arg0, object arg1); - - /// - /// Logs a formatted message string with the level. - /// - /// A String containing zero or more format items - /// An Object to format - /// An Object to format - /// An Object to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - void InfoFormat(string format, object arg0, object arg1, object arg2); - - /// - /// Logs a formatted message string with the level. - /// - /// An that supplies culture-specific formatting information - /// A String containing zero or more format items - /// An Object array containing zero or more objects to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - void InfoFormat(IFormatProvider provider, string format, params object[] args); - - /// Log a message object with the level. - /// - /// Log a message object with the level. - /// - /// - /// - /// This method first checks if this logger is WARN - /// enabled by comparing the level of this logger with the - /// level. If this logger is - /// WARN enabled, then it converts the message object - /// (passed as parameter) to a string by invoking the appropriate - /// . It then - /// proceeds to call all the registered appenders in this logger - /// and also higher in the hierarchy depending on the value of the - /// additivity flag. - /// - /// WARNING Note that passing an - /// to this method will print the name of the - /// but no stack trace. To print a stack trace use the - /// form instead. - /// - /// - /// The message object to log. - /// - /// - void Warn(object message); + /// + /// Logs a message object with the INFO level including + /// the stack trace of the passed + /// as a parameter. + /// + /// The message object to log. + /// The exception to log, including its stack trace. + /// + /// + /// See the form for more detailed information. + /// + /// + /// + /// + void Info(object message, Exception exception); + + /// Log a formatted message string with the level. + /// + /// Logs a formatted message string with the level. + /// + /// A String containing zero or more format items + /// An Object array containing zero or more objects to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + void InfoFormat(string format, params object[] args); + + /// + /// Logs a formatted message string with the level. + /// + /// A String containing zero or more format items + /// An Object to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + void InfoFormat(string format, object arg0); + + /// + /// Logs a formatted message string with the level. + /// + /// A String containing zero or more format items + /// An Object to format + /// An Object to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + void InfoFormat(string format, object arg0, object arg1); + + /// + /// Logs a formatted message string with the level. + /// + /// A String containing zero or more format items + /// An Object to format + /// An Object to format + /// An Object to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + void InfoFormat(string format, object arg0, object arg1, object arg2); + + /// + /// Logs a formatted message string with the level. + /// + /// An that supplies culture-specific formatting information + /// A String containing zero or more format items + /// An Object array containing zero or more objects to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + void InfoFormat(IFormatProvider provider, string format, params object[] args); + + /// Log a message object with the level. + /// + /// Log a message object with the level. + /// + /// + /// + /// This method first checks if this logger is WARN + /// enabled by comparing the level of this logger with the + /// level. If this logger is + /// WARN enabled, then it converts the message object + /// (passed as parameter) to a string by invoking the appropriate + /// . It then + /// proceeds to call all the registered appenders in this logger + /// and also higher in the hierarchy depending on the value of the + /// additivity flag. + /// + /// WARNING Note that passing an + /// to this method will print the name of the + /// but no stack trace. To print a stack trace use the + /// form instead. + /// + /// + /// The message object to log. + /// + /// + void Warn(object message); - /// - /// Log a message object with the level including - /// the stack trace of the passed - /// as a parameter. - /// - /// The message object to log. - /// The exception to log, including its stack trace. - /// - /// - /// See the form for more detailed information. - /// - /// - /// - /// - void Warn(object message, Exception exception); - - /// Log a formatted message string with the level. - /// - /// Logs a formatted message string with the level. - /// - /// A String containing zero or more format items - /// An Object array containing zero or more objects to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - void WarnFormat(string format, params object[] args); - - /// - /// Logs a formatted message string with the level. - /// - /// A String containing zero or more format items - /// An Object to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - void WarnFormat(string format, object arg0); - - /// - /// Logs a formatted message string with the level. - /// - /// A String containing zero or more format items - /// An Object to format - /// An Object to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - void WarnFormat(string format, object arg0, object arg1); - - /// - /// Logs a formatted message string with the level. - /// - /// A String containing zero or more format items - /// An Object to format - /// An Object to format - /// An Object to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - void WarnFormat(string format, object arg0, object arg1, object arg2); - - /// - /// Logs a formatted message string with the level. - /// - /// An that supplies culture-specific formatting information - /// A String containing zero or more format items - /// An Object array containing zero or more objects to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - void WarnFormat(IFormatProvider provider, string format, params object[] args); - - /// Log a message object with the level. - /// - /// Logs a message object with the level. - /// - /// The message object to log. - /// - /// - /// This method first checks if this logger is ERROR - /// enabled by comparing the level of this logger with the - /// level. If this logger is - /// ERROR enabled, then it converts the message object - /// (passed as parameter) to a string by invoking the appropriate - /// . It then - /// proceeds to call all the registered appenders in this logger - /// and also higher in the hierarchy depending on the value of the - /// additivity flag. - /// - /// WARNING Note that passing an - /// to this method will print the name of the - /// but no stack trace. To print a stack trace use the - /// form instead. - /// - /// - /// - /// - void Error(object message); - - /// - /// Log a message object with the level including - /// the stack trace of the passed - /// as a parameter. - /// - /// The message object to log. - /// The exception to log, including its stack trace. - /// - /// - /// See the form for more detailed information. - /// - /// - /// - /// - void Error(object message, Exception exception); - - /// Log a formatted message string with the level. - /// - /// Logs a formatted message string with the level. - /// - /// A String containing zero or more format items - /// An Object array containing zero or more objects to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - void ErrorFormat(string format, params object[] args); - - /// - /// Logs a formatted message string with the level. - /// - /// A String containing zero or more format items - /// An Object to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - void ErrorFormat(string format, object arg0); - - /// - /// Logs a formatted message string with the level. - /// - /// A String containing zero or more format items - /// An Object to format - /// An Object to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - void ErrorFormat(string format, object arg0, object arg1); - - /// - /// Logs a formatted message string with the level. - /// - /// A String containing zero or more format items - /// An Object to format - /// An Object to format - /// An Object to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - void ErrorFormat(string format, object arg0, object arg1, object arg2); - - /// - /// Logs a formatted message string with the level. - /// - /// An that supplies culture-specific formatting information - /// A String containing zero or more format items - /// An Object array containing zero or more objects to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - void ErrorFormat(IFormatProvider provider, string format, params object[] args); - - /// Log a message object with the level. - /// - /// Log a message object with the level. - /// - /// - /// - /// This method first checks if this logger is FATAL - /// enabled by comparing the level of this logger with the - /// level. If this logger is - /// FATAL enabled, then it converts the message object - /// (passed as parameter) to a string by invoking the appropriate - /// . It then - /// proceeds to call all the registered appenders in this logger - /// and also higher in the hierarchy depending on the value of the - /// additivity flag. - /// - /// WARNING Note that passing an - /// to this method will print the name of the - /// but no stack trace. To print a stack trace use the - /// form instead. - /// - /// - /// The message object to log. - /// - /// - void Fatal(object message); + /// + /// Log a message object with the level including + /// the stack trace of the passed + /// as a parameter. + /// + /// The message object to log. + /// The exception to log, including its stack trace. + /// + /// + /// See the form for more detailed information. + /// + /// + /// + /// + void Warn(object message, Exception exception); + + /// Log a formatted message string with the level. + /// + /// Logs a formatted message string with the level. + /// + /// A String containing zero or more format items + /// An Object array containing zero or more objects to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + void WarnFormat(string format, params object[] args); + + /// + /// Logs a formatted message string with the level. + /// + /// A String containing zero or more format items + /// An Object to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + void WarnFormat(string format, object arg0); + + /// + /// Logs a formatted message string with the level. + /// + /// A String containing zero or more format items + /// An Object to format + /// An Object to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + void WarnFormat(string format, object arg0, object arg1); + + /// + /// Logs a formatted message string with the level. + /// + /// A String containing zero or more format items + /// An Object to format + /// An Object to format + /// An Object to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + void WarnFormat(string format, object arg0, object arg1, object arg2); + + /// + /// Logs a formatted message string with the level. + /// + /// An that supplies culture-specific formatting information + /// A String containing zero or more format items + /// An Object array containing zero or more objects to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + void WarnFormat(IFormatProvider provider, string format, params object[] args); + + /// Log a message object with the level. + /// + /// Logs a message object with the level. + /// + /// The message object to log. + /// + /// + /// This method first checks if this logger is ERROR + /// enabled by comparing the level of this logger with the + /// level. If this logger is + /// ERROR enabled, then it converts the message object + /// (passed as parameter) to a string by invoking the appropriate + /// . It then + /// proceeds to call all the registered appenders in this logger + /// and also higher in the hierarchy depending on the value of the + /// additivity flag. + /// + /// WARNING Note that passing an + /// to this method will print the name of the + /// but no stack trace. To print a stack trace use the + /// form instead. + /// + /// + /// + /// + void Error(object message); + + /// + /// Log a message object with the level including + /// the stack trace of the passed + /// as a parameter. + /// + /// The message object to log. + /// The exception to log, including its stack trace. + /// + /// + /// See the form for more detailed information. + /// + /// + /// + /// + void Error(object message, Exception exception); + + /// Log a formatted message string with the level. + /// + /// Logs a formatted message string with the level. + /// + /// A String containing zero or more format items + /// An Object array containing zero or more objects to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + void ErrorFormat(string format, params object[] args); + + /// + /// Logs a formatted message string with the level. + /// + /// A String containing zero or more format items + /// An Object to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + void ErrorFormat(string format, object arg0); + + /// + /// Logs a formatted message string with the level. + /// + /// A String containing zero or more format items + /// An Object to format + /// An Object to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + void ErrorFormat(string format, object arg0, object arg1); + + /// + /// Logs a formatted message string with the level. + /// + /// A String containing zero or more format items + /// An Object to format + /// An Object to format + /// An Object to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + void ErrorFormat(string format, object arg0, object arg1, object arg2); + + /// + /// Logs a formatted message string with the level. + /// + /// An that supplies culture-specific formatting information + /// A String containing zero or more format items + /// An Object array containing zero or more objects to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + void ErrorFormat(IFormatProvider provider, string format, params object[] args); + + /// Log a message object with the level. + /// + /// Log a message object with the level. + /// + /// + /// + /// This method first checks if this logger is FATAL + /// enabled by comparing the level of this logger with the + /// level. If this logger is + /// FATAL enabled, then it converts the message object + /// (passed as parameter) to a string by invoking the appropriate + /// . It then + /// proceeds to call all the registered appenders in this logger + /// and also higher in the hierarchy depending on the value of the + /// additivity flag. + /// + /// WARNING Note that passing an + /// to this method will print the name of the + /// but no stack trace. To print a stack trace use the + /// form instead. + /// + /// + /// The message object to log. + /// + /// + void Fatal(object message); - /// - /// Log a message object with the level including - /// the stack trace of the passed - /// as a parameter. - /// - /// The message object to log. - /// The exception to log, including its stack trace. - /// - /// - /// See the form for more detailed information. - /// - /// - /// - /// - void Fatal(object message, Exception exception); - - /// Log a formatted message string with the level. - /// - /// Logs a formatted message string with the level. - /// - /// A String containing zero or more format items - /// An Object array containing zero or more objects to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - void FatalFormat(string format, params object[] args); - - /// - /// Logs a formatted message string with the level. - /// - /// A String containing zero or more format items - /// An Object to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - void FatalFormat(string format, object arg0); - - /// - /// Logs a formatted message string with the level. - /// - /// A String containing zero or more format items - /// An Object to format - /// An Object to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - void FatalFormat(string format, object arg0, object arg1); - - /// - /// Logs a formatted message string with the level. - /// - /// A String containing zero or more format items - /// An Object to format - /// An Object to format - /// An Object to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - void FatalFormat(string format, object arg0, object arg1, object arg2); - - /// - /// Logs a formatted message string with the level. - /// - /// An that supplies culture-specific formatting information - /// A String containing zero or more format items - /// An Object array containing zero or more objects to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - void FatalFormat(IFormatProvider provider, string format, params object[] args); - - /// - /// Checks if this logger is enabled for the level. - /// - /// - /// true if this logger is enabled for events, false otherwise. - /// - /// - /// - /// This function is intended to lessen the computational cost of - /// disabled log debug statements. - /// - /// For some ILog interface log, when you write: - /// - /// log.Debug("This is entry number: " + i ); - /// - /// - /// You incur the cost constructing the message, string construction and concatenation in - /// this case, regardless of whether the message is logged or not. - /// - /// - /// If you are worried about speed (who isn't), then you should write: - /// - /// - /// if (log.IsDebugEnabled) - /// { - /// log.Debug("This is entry number: " + i ); - /// } - /// - /// - /// This way you will not incur the cost of parameter - /// construction if debugging is disabled for log. On - /// the other hand, if the log is debug enabled, you - /// will incur the cost of evaluating whether the logger is debug - /// enabled twice. Once in and once in - /// the . This is an insignificant overhead - /// since evaluating a logger takes about 1% of the time it - /// takes to actually log. This is the preferred style of logging. - /// - /// Alternatively if your logger is available statically then the is debug - /// enabled state can be stored in a static variable like this: - /// - /// - /// private static readonly bool isDebugEnabled = log.IsDebugEnabled; - /// - /// - /// Then when you come to log you can write: - /// - /// - /// if (isDebugEnabled) - /// { - /// log.Debug("This is entry number: " + i ); - /// } - /// - /// - /// This way the debug enabled state is only queried once - /// when the class is loaded. Using a private static readonly - /// variable is the most efficient because it is a run time constant - /// and can be heavily optimized by the JIT compiler. - /// - /// - /// Of course if you use a static readonly variable to - /// hold the enabled state of the logger then you cannot - /// change the enabled state at runtime to vary the logging - /// that is produced. You have to decide if you need absolute - /// speed or runtime flexibility. - /// - /// - /// - /// - bool IsDebugEnabled { get; } + /// + /// Log a message object with the level including + /// the stack trace of the passed + /// as a parameter. + /// + /// The message object to log. + /// The exception to log, including its stack trace. + /// + /// + /// See the form for more detailed information. + /// + /// + /// + /// + void Fatal(object message, Exception exception); + + /// Log a formatted message string with the level. + /// + /// Logs a formatted message string with the level. + /// + /// A String containing zero or more format items + /// An Object array containing zero or more objects to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + void FatalFormat(string format, params object[] args); + + /// + /// Logs a formatted message string with the level. + /// + /// A String containing zero or more format items + /// An Object to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + void FatalFormat(string format, object arg0); + + /// + /// Logs a formatted message string with the level. + /// + /// A String containing zero or more format items + /// An Object to format + /// An Object to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + void FatalFormat(string format, object arg0, object arg1); + + /// + /// Logs a formatted message string with the level. + /// + /// A String containing zero or more format items + /// An Object to format + /// An Object to format + /// An Object to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + void FatalFormat(string format, object arg0, object arg1, object arg2); + + /// + /// Logs a formatted message string with the level. + /// + /// An that supplies culture-specific formatting information + /// A String containing zero or more format items + /// An Object array containing zero or more objects to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + void FatalFormat(IFormatProvider provider, string format, params object[] args); + + /// + /// Checks if this logger is enabled for the level. + /// + /// + /// true if this logger is enabled for events, false otherwise. + /// + /// + /// + /// This function is intended to lessen the computational cost of + /// disabled log debug statements. + /// + /// For some ILog interface log, when you write: + /// + /// log.Debug("This is entry number: " + i ); + /// + /// + /// You incur the cost constructing the message, string construction and concatenation in + /// this case, regardless of whether the message is logged or not. + /// + /// + /// If you are worried about speed (who isn't), then you should write: + /// + /// + /// if (log.IsDebugEnabled) + /// { + /// log.Debug("This is entry number: " + i ); + /// } + /// + /// + /// This way you will not incur the cost of parameter + /// construction if debugging is disabled for log. On + /// the other hand, if the log is debug enabled, you + /// will incur the cost of evaluating whether the logger is debug + /// enabled twice. Once in and once in + /// the . This is an insignificant overhead + /// since evaluating a logger takes about 1% of the time it + /// takes to actually log. This is the preferred style of logging. + /// + /// Alternatively if your logger is available statically then the is debug + /// enabled state can be stored in a static variable like this: + /// + /// + /// private static readonly bool isDebugEnabled = log.IsDebugEnabled; + /// + /// + /// Then when you come to log you can write: + /// + /// + /// if (isDebugEnabled) + /// { + /// log.Debug("This is entry number: " + i ); + /// } + /// + /// + /// This way the debug enabled state is only queried once + /// when the class is loaded. Using a private static readonly + /// variable is the most efficient because it is a run time constant + /// and can be heavily optimized by the JIT compiler. + /// + /// + /// Of course if you use a static readonly variable to + /// hold the enabled state of the logger then you cannot + /// change the enabled state at runtime to vary the logging + /// that is produced. You have to decide if you need absolute + /// speed or runtime flexibility. + /// + /// + /// + /// + bool IsDebugEnabled { get; } - /// - /// Checks if this logger is enabled for the level. - /// - /// - /// true if this logger is enabled for events, false otherwise. - /// - /// - /// For more information see . - /// - /// - /// - /// - bool IsInfoEnabled { get; } - - /// - /// Checks if this logger is enabled for the level. - /// - /// - /// true if this logger is enabled for events, false otherwise. - /// - /// - /// For more information see . - /// - /// - /// - /// - bool IsWarnEnabled { get; } - - /// - /// Checks if this logger is enabled for the level. - /// - /// - /// true if this logger is enabled for events, false otherwise. - /// - /// - /// For more information see . - /// - /// - /// - /// - bool IsErrorEnabled { get; } - - /// - /// Checks if this logger is enabled for the level. - /// - /// - /// true if this logger is enabled for events, false otherwise. - /// - /// - /// For more information see . - /// - /// - /// - /// - bool IsFatalEnabled { get; } - } + /// + /// Checks if this logger is enabled for the level. + /// + /// + /// true if this logger is enabled for events, false otherwise. + /// + /// + /// For more information see . + /// + /// + /// + /// + bool IsInfoEnabled { get; } + + /// + /// Checks if this logger is enabled for the level. + /// + /// + /// true if this logger is enabled for events, false otherwise. + /// + /// + /// For more information see . + /// + /// + /// + /// + bool IsWarnEnabled { get; } + + /// + /// Checks if this logger is enabled for the level. + /// + /// + /// true if this logger is enabled for events, false otherwise. + /// + /// + /// For more information see . + /// + /// + /// + /// + bool IsErrorEnabled { get; } + + /// + /// Checks if this logger is enabled for the level. + /// + /// + /// true if this logger is enabled for events, false otherwise. + /// + /// + /// For more information see . + /// + /// + /// + /// + bool IsFatalEnabled { get; } + } } diff --git a/src/log4net/Layout/DynamicPatternLayout.cs b/src/log4net/Layout/DynamicPatternLayout.cs index 28174be1..2f3e0022 100644 --- a/src/log4net/Layout/DynamicPatternLayout.cs +++ b/src/log4net/Layout/DynamicPatternLayout.cs @@ -28,116 +28,116 @@ namespace log4net.Layout { - /// - /// A flexible layout configurable with pattern string that re-evaluates on each call. - /// - /// - /// This class is built on and provides all the - /// features and capabilities of PatternLayout. PatternLayout is a 'static' class - /// in that its layout is done once at configuration time. This class will recreate - /// the layout on each reference. - /// One important difference between PatternLayout and DynamicPatternLayout is the - /// treatment of the Header and Footer parameters in the configuration. The Header and Footer - /// parameters for DynamicPatternLayout must be syntactically in the form of a PatternString, - /// but should not be marked as type log4net.Util.PatternString. Doing so causes the - /// pattern to be statically converted at configuration time and causes DynamicPatternLayout - /// to perform the same as PatternLayout. - /// Please see for complete documentation. - /// - /// <layout type="log4net.Layout.DynamicPatternLayout"> - /// <param name="Header" value="%newline**** Trace Opened Local: %date{yyyy-MM-dd HH:mm:ss.fff} UTC: %utcdate{yyyy-MM-dd HH:mm:ss.fff} ****%newline" /> - /// <param name="Footer" value="**** Trace Closed %date{yyyy-MM-dd HH:mm:ss.fff} ****%newline" /> - /// </layout> - /// - /// - public class DynamicPatternLayout: PatternLayout - { - #region Member Variables - /// - /// The header PatternString - /// - private PatternString m_headerPatternString = new PatternString(""); + /// + /// A flexible layout configurable with pattern string that re-evaluates on each call. + /// + /// + /// This class is built on and provides all the + /// features and capabilities of PatternLayout. PatternLayout is a 'static' class + /// in that its layout is done once at configuration time. This class will recreate + /// the layout on each reference. + /// One important difference between PatternLayout and DynamicPatternLayout is the + /// treatment of the Header and Footer parameters in the configuration. The Header and Footer + /// parameters for DynamicPatternLayout must be syntactically in the form of a PatternString, + /// but should not be marked as type log4net.Util.PatternString. Doing so causes the + /// pattern to be statically converted at configuration time and causes DynamicPatternLayout + /// to perform the same as PatternLayout. + /// Please see for complete documentation. + /// + /// <layout type="log4net.Layout.DynamicPatternLayout"> + /// <param name="Header" value="%newline**** Trace Opened Local: %date{yyyy-MM-dd HH:mm:ss.fff} UTC: %utcdate{yyyy-MM-dd HH:mm:ss.fff} ****%newline" /> + /// <param name="Footer" value="**** Trace Closed %date{yyyy-MM-dd HH:mm:ss.fff} ****%newline" /> + /// </layout> + /// + /// + public class DynamicPatternLayout: PatternLayout + { + #region Member Variables + /// + /// The header PatternString + /// + private PatternString m_headerPatternString = new PatternString(""); - /// - /// The footer PatternString - /// - private PatternString m_footerPatternString = new PatternString(""); - #endregion + /// + /// The footer PatternString + /// + private PatternString m_footerPatternString = new PatternString(""); + #endregion - #region Constructors - /// - /// Constructs a DynamicPatternLayout using the DefaultConversionPattern - /// - /// - /// - /// The default pattern just produces the application supplied message. - /// - /// - public DynamicPatternLayout() - : base() - { - } + #region Constructors + /// + /// Constructs a DynamicPatternLayout using the DefaultConversionPattern + /// + /// + /// + /// The default pattern just produces the application supplied message. + /// + /// + public DynamicPatternLayout() + : base() + { + } - /// - /// Constructs a DynamicPatternLayout using the supplied conversion pattern - /// - /// the pattern to use - /// - /// - public DynamicPatternLayout (string pattern) - : base(pattern) - { - } - #endregion + /// + /// Constructs a DynamicPatternLayout using the supplied conversion pattern + /// + /// the pattern to use + /// + /// + public DynamicPatternLayout (string pattern) + : base(pattern) + { + } + #endregion - #region Override implementation of LayoutSkeleton - /// - /// The header for the layout format. - /// - /// the layout header - /// - /// - /// The Header text will be appended before any logging events - /// are formatted and appended. - /// - /// The pattern will be formatted on each get operation. - /// - public override string Header - { - get - { - return m_headerPatternString.Format(); - } - set - { - base.Header = value; - m_headerPatternString = new PatternString(value); - } - } /* property DynamicPatternLayout Header */ + #region Override implementation of LayoutSkeleton + /// + /// The header for the layout format. + /// + /// the layout header + /// + /// + /// The Header text will be appended before any logging events + /// are formatted and appended. + /// + /// The pattern will be formatted on each get operation. + /// + public override string Header + { + get + { + return m_headerPatternString.Format(); + } + set + { + base.Header = value; + m_headerPatternString = new PatternString(value); + } + } /* property DynamicPatternLayout Header */ - /// - /// The footer for the layout format. - /// - /// the layout footer - /// - /// - /// The Footer text will be appended after all the logging events - /// have been formatted and appended. - /// - /// The pattern will be formatted on each get operation. - /// - public override string Footer - { - get - { - return m_footerPatternString.Format(); - } - set - { - base.Footer = value; - m_footerPatternString = new PatternString(value); - } - } /* property DynamicPatternLayout Footer */ - #endregion - } /* class DynamicPatternLayout */ -} /* namespace log4net.Layout */ + /// + /// The footer for the layout format. + /// + /// the layout footer + /// + /// + /// The Footer text will be appended after all the logging events + /// have been formatted and appended. + /// + /// The pattern will be formatted on each get operation. + /// + public override string Footer + { + get + { + return m_footerPatternString.Format(); + } + set + { + base.Footer = value; + m_footerPatternString = new PatternString(value); + } + } /* property DynamicPatternLayout Footer */ + #endregion + } /* class DynamicPatternLayout */ +} /* namespace log4net.Layout */ diff --git a/src/log4net/Layout/ExceptionLayout.cs b/src/log4net/Layout/ExceptionLayout.cs index 90217077..2748b0db 100644 --- a/src/log4net/Layout/ExceptionLayout.cs +++ b/src/log4net/Layout/ExceptionLayout.cs @@ -26,83 +26,83 @@ namespace log4net.Layout { - /// - /// A Layout that renders only the Exception text from the logging event - /// - /// - /// - /// A Layout that renders only the Exception text from the logging event. - /// - /// - /// This Layout should only be used with appenders that utilize multiple - /// layouts (e.g. ). - /// - /// - /// Nicko Cadell - /// Gert Driesen - public class ExceptionLayout : LayoutSkeleton - { - #region Constructors + /// + /// A Layout that renders only the Exception text from the logging event + /// + /// + /// + /// A Layout that renders only the Exception text from the logging event. + /// + /// + /// This Layout should only be used with appenders that utilize multiple + /// layouts (e.g. ). + /// + /// + /// Nicko Cadell + /// Gert Driesen + public class ExceptionLayout : LayoutSkeleton + { + #region Constructors - /// - /// Default constructor - /// - /// - /// - /// Constructs a ExceptionLayout - /// - /// - public ExceptionLayout() - { - this.IgnoresException = false; - } + /// + /// Default constructor + /// + /// + /// + /// Constructs a ExceptionLayout + /// + /// + public ExceptionLayout() + { + this.IgnoresException = false; + } - #endregion + #endregion - #region Implementation of IOptionHandler + #region Implementation of IOptionHandler - /// - /// Activate component options - /// - /// - /// - /// Part of the component activation - /// framework. - /// - /// - /// This method does nothing as options become effective immediately. - /// - /// - public override void ActivateOptions() - { - // nothing to do. - } + /// + /// Activate component options + /// + /// + /// + /// Part of the component activation + /// framework. + /// + /// + /// This method does nothing as options become effective immediately. + /// + /// + public override void ActivateOptions() + { + // nothing to do. + } - #endregion + #endregion - #region Override implementation of LayoutSkeleton + #region Override implementation of LayoutSkeleton - /// - /// Gets the exception text from the logging event - /// - /// The TextWriter to write the formatted event to - /// the event being logged - /// - /// - /// Write the exception string to the . - /// The exception string is retrieved from . - /// - /// - public override void Format(TextWriter writer, LoggingEvent loggingEvent) - { - if (loggingEvent == null) - { - throw new ArgumentNullException("loggingEvent"); - } + /// + /// Gets the exception text from the logging event + /// + /// The TextWriter to write the formatted event to + /// the event being logged + /// + /// + /// Write the exception string to the . + /// The exception string is retrieved from . + /// + /// + public override void Format(TextWriter writer, LoggingEvent loggingEvent) + { + if (loggingEvent == null) + { + throw new ArgumentNullException("loggingEvent"); + } - writer.Write(loggingEvent.GetExceptionString()); - } + writer.Write(loggingEvent.GetExceptionString()); + } - #endregion - } + #endregion + } } diff --git a/src/log4net/Layout/ILayout.cs b/src/log4net/Layout/ILayout.cs index 2bb6aef4..6e2e9971 100644 --- a/src/log4net/Layout/ILayout.cs +++ b/src/log4net/Layout/ILayout.cs @@ -25,97 +25,97 @@ namespace log4net.Layout { - /// - /// Interface implemented by layout objects - /// - /// - /// - /// An object is used to format a - /// as text. The method is called by an - /// appender to transform the into a string. - /// - /// - /// The layout can also supply and - /// text that is appender before any events and after all the events respectively. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public interface ILayout - { - /// - /// Implement this method to create your own layout format. - /// - /// The TextWriter to write the formatted event to - /// The event to format - /// - /// - /// This method is called by an appender to format - /// the as text and output to a writer. - /// - /// - /// If the caller does not have a and prefers the - /// event to be formatted as a then the following - /// code can be used to format the event into a . - /// - /// - /// StringWriter writer = new StringWriter(); - /// Layout.Format(writer, loggingEvent); - /// string formattedEvent = writer.ToString(); - /// - /// - void Format(TextWriter writer, LoggingEvent loggingEvent); + /// + /// Interface implemented by layout objects + /// + /// + /// + /// An object is used to format a + /// as text. The method is called by an + /// appender to transform the into a string. + /// + /// + /// The layout can also supply and + /// text that is appender before any events and after all the events respectively. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public interface ILayout + { + /// + /// Implement this method to create your own layout format. + /// + /// The TextWriter to write the formatted event to + /// The event to format + /// + /// + /// This method is called by an appender to format + /// the as text and output to a writer. + /// + /// + /// If the caller does not have a and prefers the + /// event to be formatted as a then the following + /// code can be used to format the event into a . + /// + /// + /// StringWriter writer = new StringWriter(); + /// Layout.Format(writer, loggingEvent); + /// string formattedEvent = writer.ToString(); + /// + /// + void Format(TextWriter writer, LoggingEvent loggingEvent); - /// - /// The content type output by this layout. - /// - /// The content type - /// - /// - /// The content type output by this layout. - /// - /// - /// This is a MIME type e.g. "text/plain". - /// - /// - string ContentType { get; } + /// + /// The content type output by this layout. + /// + /// The content type + /// + /// + /// The content type output by this layout. + /// + /// + /// This is a MIME type e.g. "text/plain". + /// + /// + string ContentType { get; } - /// - /// The header for the layout format. - /// - /// the layout header - /// - /// - /// The Header text will be appended before any logging events - /// are formatted and appended. - /// - /// - string Header { get; } + /// + /// The header for the layout format. + /// + /// the layout header + /// + /// + /// The Header text will be appended before any logging events + /// are formatted and appended. + /// + /// + string Header { get; } - /// - /// The footer for the layout format. - /// - /// the layout footer - /// - /// - /// The Footer text will be appended after all the logging events - /// have been formatted and appended. - /// - /// - string Footer { get; } + /// + /// The footer for the layout format. + /// + /// the layout footer + /// + /// + /// The Footer text will be appended after all the logging events + /// have been formatted and appended. + /// + /// + string Footer { get; } - /// - /// Flag indicating if this layout handle exceptions - /// - /// false if this layout handles exceptions - /// - /// - /// If this layout handles the exception object contained within - /// , then the layout should return - /// false. Otherwise, if the layout ignores the exception - /// object, then the layout should return true. - /// - /// - bool IgnoresException { get; } - } + /// + /// Flag indicating if this layout handle exceptions + /// + /// false if this layout handles exceptions + /// + /// + /// If this layout handles the exception object contained within + /// , then the layout should return + /// false. Otherwise, if the layout ignores the exception + /// object, then the layout should return true. + /// + /// + bool IgnoresException { get; } + } } diff --git a/src/log4net/Layout/IRawLayout.cs b/src/log4net/Layout/IRawLayout.cs index 41cbf975..4f93b017 100644 --- a/src/log4net/Layout/IRawLayout.cs +++ b/src/log4net/Layout/IRawLayout.cs @@ -25,37 +25,37 @@ namespace log4net.Layout { - /// - /// Interface for raw layout objects - /// - /// - /// - /// Interface used to format a - /// to an object. - /// - /// - /// This interface should not be confused with the - /// interface. This interface is used in - /// only certain specialized situations where a raw object is - /// required rather than a formatted string. The - /// is not generally useful than this interface. - /// - /// - /// Nicko Cadell - /// Gert Driesen - [TypeConverter(typeof(RawLayoutConverter))] - public interface IRawLayout - { - /// - /// Implement this method to create your own layout format. - /// - /// The event to format - /// returns the formatted event - /// - /// - /// Implement this method to create your own layout format. - /// - /// - object Format(LoggingEvent loggingEvent); - } + /// + /// Interface for raw layout objects + /// + /// + /// + /// Interface used to format a + /// to an object. + /// + /// + /// This interface should not be confused with the + /// interface. This interface is used in + /// only certain specialized situations where a raw object is + /// required rather than a formatted string. The + /// is not generally useful than this interface. + /// + /// + /// Nicko Cadell + /// Gert Driesen + [TypeConverter(typeof(RawLayoutConverter))] + public interface IRawLayout + { + /// + /// Implement this method to create your own layout format. + /// + /// The event to format + /// returns the formatted event + /// + /// + /// Implement this method to create your own layout format. + /// + /// + object Format(LoggingEvent loggingEvent); + } } diff --git a/src/log4net/Layout/Layout2RawLayoutAdapter.cs b/src/log4net/Layout/Layout2RawLayoutAdapter.cs index 9b92bf46..7f8ff254 100644 --- a/src/log4net/Layout/Layout2RawLayoutAdapter.cs +++ b/src/log4net/Layout/Layout2RawLayoutAdapter.cs @@ -25,69 +25,69 @@ namespace log4net.Layout { - /// - /// Adapts any to a - /// - /// - /// - /// Where an is required this adapter - /// allows a to be specified. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public class Layout2RawLayoutAdapter : IRawLayout - { - #region Member Variables + /// + /// Adapts any to a + /// + /// + /// + /// Where an is required this adapter + /// allows a to be specified. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public class Layout2RawLayoutAdapter : IRawLayout + { + #region Member Variables - /// - /// The layout to adapt - /// - private ILayout m_layout; + /// + /// The layout to adapt + /// + private ILayout m_layout; - #endregion + #endregion - #region Constructors + #region Constructors - /// - /// Construct a new adapter - /// - /// the layout to adapt - /// - /// - /// Create the adapter for the specified . - /// - /// - public Layout2RawLayoutAdapter(ILayout layout) - { - m_layout = layout; - } + /// + /// Construct a new adapter + /// + /// the layout to adapt + /// + /// + /// Create the adapter for the specified . + /// + /// + public Layout2RawLayoutAdapter(ILayout layout) + { + m_layout = layout; + } - #endregion + #endregion - #region Implementation of IRawLayout + #region Implementation of IRawLayout - /// - /// Format the logging event as an object. - /// - /// The event to format - /// returns the formatted event - /// - /// - /// Format the logging event as an object. - /// - /// - /// Uses the object supplied to - /// the constructor to perform the formatting. - /// - /// - public virtual object Format(LoggingEvent loggingEvent) - { - using StringWriter writer = new StringWriter(System.Globalization.CultureInfo.InvariantCulture); - m_layout.Format(writer, loggingEvent); - return writer.ToString(); - } + /// + /// Format the logging event as an object. + /// + /// The event to format + /// returns the formatted event + /// + /// + /// Format the logging event as an object. + /// + /// + /// Uses the object supplied to + /// the constructor to perform the formatting. + /// + /// + public virtual object Format(LoggingEvent loggingEvent) + { + using StringWriter writer = new StringWriter(System.Globalization.CultureInfo.InvariantCulture); + m_layout.Format(writer, loggingEvent); + return writer.ToString(); + } - #endregion - } + #endregion + } } diff --git a/src/log4net/Layout/LayoutSkeleton.cs b/src/log4net/Layout/LayoutSkeleton.cs index 1f26c8e6..e61374de 100644 --- a/src/log4net/Layout/LayoutSkeleton.cs +++ b/src/log4net/Layout/LayoutSkeleton.cs @@ -25,208 +25,208 @@ namespace log4net.Layout { - /// - /// Extend this abstract class to create your own log layout format. - /// - /// - /// - /// This is the base implementation of the - /// interface. Most layout objects should extend this class. - /// - /// - /// - /// - /// - /// Subclasses must implement the - /// method. - /// - /// - /// Subclasses should set the in their default - /// constructor. - /// - /// - /// - /// Nicko Cadell - /// Gert Driesen - public abstract class LayoutSkeleton : ILayout, IOptionHandler - { - #region Member Variables - - /// - /// The header text - /// - /// - /// - /// See for more information. - /// - /// - private string m_header = null; - - /// - /// The footer text - /// - /// - /// - /// See for more information. - /// - /// - private string m_footer = null; - - /// - /// Flag indicating if this layout handles exceptions - /// - /// - /// - /// false if this layout handles exceptions - /// - /// - private bool m_ignoresException = true; - - #endregion - - #region Constructors - - /// - /// Empty default constructor - /// - /// - /// - /// Empty default constructor - /// - /// - protected LayoutSkeleton() - { - } - - #endregion - - #region Implementation of IOptionHandler - - /// - /// Activate component options - /// - /// - /// - /// This is part of the delayed object - /// activation scheme. The method must - /// be called on this object after the configuration properties have - /// been set. Until is called this - /// object is in an undefined state and must not be used. - /// - /// - /// If any of the configuration properties are modified then - /// must be called again. - /// - /// - /// This method must be implemented by the subclass. - /// - /// - public abstract void ActivateOptions(); - - #endregion - - #region Implementation of ILayout - - /// - /// Implement this method to create your own layout format. - /// - /// The TextWriter to write the formatted event to - /// The event to format - /// - /// - /// This method is called by an appender to format - /// the as text. - /// - /// - public abstract void Format(TextWriter writer, LoggingEvent loggingEvent); - - /// - /// Convenience method for easily formatting the logging event into a string variable. - /// - /// - /// - /// Creates a new StringWriter instance to store the formatted logging event. - /// - public string Format(LoggingEvent loggingEvent) - { - using StringWriter writer = new StringWriter(System.Globalization.CultureInfo.InvariantCulture); - Format(writer, loggingEvent); - return writer.ToString(); - } - - /// - /// The content type output by this layout. - /// - /// The content type is "text/plain" - /// - /// - /// The content type output by this layout. - /// - /// - /// This base class uses the value "text/plain". - /// To change this value a subclass must override this - /// property. - /// - /// - public virtual string ContentType - { - get { return "text/plain"; } - } - - /// - /// The header for the layout format. - /// - /// the layout header - /// - /// - /// The Header text will be appended before any logging events - /// are formatted and appended. - /// - /// - public virtual string Header - { - get { return m_header; } - set { m_header = value; } - } - - /// - /// The footer for the layout format. - /// - /// the layout footer - /// - /// - /// The Footer text will be appended after all the logging events - /// have been formatted and appended. - /// - /// - public virtual string Footer - { - get { return m_footer; } - set { m_footer = value; } - } - - /// - /// Flag indicating if this layout handles exceptions - /// - /// false if this layout handles exceptions - /// - /// - /// If this layout handles the exception object contained within - /// , then the layout should return - /// false. Otherwise, if the layout ignores the exception - /// object, then the layout should return true. - /// - /// - /// Set this value to override a this default setting. The default - /// value is true, this layout does not handle the exception. - /// - /// - public virtual bool IgnoresException - { - get { return m_ignoresException; } - set { m_ignoresException = value; } - } - - #endregion - } + /// + /// Extend this abstract class to create your own log layout format. + /// + /// + /// + /// This is the base implementation of the + /// interface. Most layout objects should extend this class. + /// + /// + /// + /// + /// + /// Subclasses must implement the + /// method. + /// + /// + /// Subclasses should set the in their default + /// constructor. + /// + /// + /// + /// Nicko Cadell + /// Gert Driesen + public abstract class LayoutSkeleton : ILayout, IOptionHandler + { + #region Member Variables + + /// + /// The header text + /// + /// + /// + /// See for more information. + /// + /// + private string m_header = null; + + /// + /// The footer text + /// + /// + /// + /// See for more information. + /// + /// + private string m_footer = null; + + /// + /// Flag indicating if this layout handles exceptions + /// + /// + /// + /// false if this layout handles exceptions + /// + /// + private bool m_ignoresException = true; + + #endregion + + #region Constructors + + /// + /// Empty default constructor + /// + /// + /// + /// Empty default constructor + /// + /// + protected LayoutSkeleton() + { + } + + #endregion + + #region Implementation of IOptionHandler + + /// + /// Activate component options + /// + /// + /// + /// This is part of the delayed object + /// activation scheme. The method must + /// be called on this object after the configuration properties have + /// been set. Until is called this + /// object is in an undefined state and must not be used. + /// + /// + /// If any of the configuration properties are modified then + /// must be called again. + /// + /// + /// This method must be implemented by the subclass. + /// + /// + public abstract void ActivateOptions(); + + #endregion + + #region Implementation of ILayout + + /// + /// Implement this method to create your own layout format. + /// + /// The TextWriter to write the formatted event to + /// The event to format + /// + /// + /// This method is called by an appender to format + /// the as text. + /// + /// + public abstract void Format(TextWriter writer, LoggingEvent loggingEvent); + + /// + /// Convenience method for easily formatting the logging event into a string variable. + /// + /// + /// + /// Creates a new StringWriter instance to store the formatted logging event. + /// + public string Format(LoggingEvent loggingEvent) + { + using StringWriter writer = new StringWriter(System.Globalization.CultureInfo.InvariantCulture); + Format(writer, loggingEvent); + return writer.ToString(); + } + + /// + /// The content type output by this layout. + /// + /// The content type is "text/plain" + /// + /// + /// The content type output by this layout. + /// + /// + /// This base class uses the value "text/plain". + /// To change this value a subclass must override this + /// property. + /// + /// + public virtual string ContentType + { + get { return "text/plain"; } + } + + /// + /// The header for the layout format. + /// + /// the layout header + /// + /// + /// The Header text will be appended before any logging events + /// are formatted and appended. + /// + /// + public virtual string Header + { + get { return m_header; } + set { m_header = value; } + } + + /// + /// The footer for the layout format. + /// + /// the layout footer + /// + /// + /// The Footer text will be appended after all the logging events + /// have been formatted and appended. + /// + /// + public virtual string Footer + { + get { return m_footer; } + set { m_footer = value; } + } + + /// + /// Flag indicating if this layout handles exceptions + /// + /// false if this layout handles exceptions + /// + /// + /// If this layout handles the exception object contained within + /// , then the layout should return + /// false. Otherwise, if the layout ignores the exception + /// object, then the layout should return true. + /// + /// + /// Set this value to override a this default setting. The default + /// value is true, this layout does not handle the exception. + /// + /// + public virtual bool IgnoresException + { + get { return m_ignoresException; } + set { m_ignoresException = value; } + } + + #endregion + } } diff --git a/src/log4net/Layout/Pattern/AppDomainPatternConverter.cs b/src/log4net/Layout/Pattern/AppDomainPatternConverter.cs index 30b7f096..83eb2d5f 100644 --- a/src/log4net/Layout/Pattern/AppDomainPatternConverter.cs +++ b/src/log4net/Layout/Pattern/AppDomainPatternConverter.cs @@ -25,31 +25,31 @@ namespace log4net.Layout.Pattern { - /// - /// Write the event appdomain name to the output - /// - /// - /// - /// Writes the to the output writer. - /// - /// - /// Daniel Cazzulino - /// Nicko Cadell - internal sealed class AppDomainPatternConverter : PatternLayoutConverter - { - /// - /// Write the event appdomain name to the output - /// - /// that will receive the formatted result. - /// the event being logged - /// - /// - /// Writes the to the output . - /// - /// - protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) - { - writer.Write(loggingEvent.Domain); - } - } + /// + /// Write the event appdomain name to the output + /// + /// + /// + /// Writes the to the output writer. + /// + /// + /// Daniel Cazzulino + /// Nicko Cadell + internal sealed class AppDomainPatternConverter : PatternLayoutConverter + { + /// + /// Write the event appdomain name to the output + /// + /// that will receive the formatted result. + /// the event being logged + /// + /// + /// Writes the to the output . + /// + /// + protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) + { + writer.Write(loggingEvent.Domain); + } + } } diff --git a/src/log4net/Layout/Pattern/AspNetCachePatternConverter.cs b/src/log4net/Layout/Pattern/AspNetCachePatternConverter.cs index 31f2fc46..32c8cca8 100644 --- a/src/log4net/Layout/Pattern/AspNetCachePatternConverter.cs +++ b/src/log4net/Layout/Pattern/AspNetCachePatternConverter.cs @@ -29,50 +29,50 @@ namespace log4net.Layout.Pattern { - /// - /// Converter for items in the ASP.Net Cache. - /// - /// - /// - /// Outputs an item from the . - /// - /// - /// Ron Grabowski - internal sealed class AspNetCachePatternConverter : AspNetPatternLayoutConverter - { - /// - /// Write the ASP.Net Cache item to the output - /// - /// that will receive the formatted result. - /// The on which the pattern converter should be executed. - /// The under which the ASP.Net request is running. - /// - /// - /// Writes out the value of a named property. The property name - /// should be set in the - /// property. If no property has been set, all key value pairs from the Cache will - /// be written to the output. - /// - /// - protected override void Convert(TextWriter writer, LoggingEvent loggingEvent, HttpContext httpContext) - { - if (HttpRuntime.Cache != null) - { - if (Option != null) - { - WriteObject(writer, loggingEvent.Repository, HttpRuntime.Cache[Option]); - } - else - { - WriteObject(writer, loggingEvent.Repository, HttpRuntime.Cache.GetEnumerator()); - } - } - else - { - writer.Write(SystemInfo.NotAvailableText); - } - } - } + /// + /// Converter for items in the ASP.Net Cache. + /// + /// + /// + /// Outputs an item from the . + /// + /// + /// Ron Grabowski + internal sealed class AspNetCachePatternConverter : AspNetPatternLayoutConverter + { + /// + /// Write the ASP.Net Cache item to the output + /// + /// that will receive the formatted result. + /// The on which the pattern converter should be executed. + /// The under which the ASP.Net request is running. + /// + /// + /// Writes out the value of a named property. The property name + /// should be set in the + /// property. If no property has been set, all key value pairs from the Cache will + /// be written to the output. + /// + /// + protected override void Convert(TextWriter writer, LoggingEvent loggingEvent, HttpContext httpContext) + { + if (HttpRuntime.Cache != null) + { + if (Option != null) + { + WriteObject(writer, loggingEvent.Repository, HttpRuntime.Cache[Option]); + } + else + { + WriteObject(writer, loggingEvent.Repository, HttpRuntime.Cache.GetEnumerator()); + } + } + else + { + writer.Write(SystemInfo.NotAvailableText); + } + } + } } #endif // !NETCF && !SSCLI && !CLIENT_PROFILE diff --git a/src/log4net/Layout/Pattern/AspNetContextPatternConverter.cs b/src/log4net/Layout/Pattern/AspNetContextPatternConverter.cs index effefe1a..1cd902fe 100644 --- a/src/log4net/Layout/Pattern/AspNetContextPatternConverter.cs +++ b/src/log4net/Layout/Pattern/AspNetContextPatternConverter.cs @@ -28,42 +28,42 @@ namespace log4net.Layout.Pattern { - /// - /// Converter for items in the . - /// - /// - /// - /// Outputs an item from the . - /// - /// - /// Ron Grabowski - internal sealed class AspNetContextPatternConverter : AspNetPatternLayoutConverter - { - /// - /// Write the ASP.Net HttpContext item to the output - /// - /// that will receive the formatted result. - /// The on which the pattern converter should be executed. - /// The under which the ASP.Net request is running. - /// - /// - /// Writes out the value of a named property. The property name - /// should be set in the - /// property. - /// - /// - protected override void Convert(TextWriter writer, LoggingEvent loggingEvent, HttpContext httpContext) - { - if (Option != null) - { - WriteObject(writer, loggingEvent.Repository, httpContext.Items[Option]); - } - else - { - WriteObject(writer, loggingEvent.Repository, httpContext.Items); - } - } - } + /// + /// Converter for items in the . + /// + /// + /// + /// Outputs an item from the . + /// + /// + /// Ron Grabowski + internal sealed class AspNetContextPatternConverter : AspNetPatternLayoutConverter + { + /// + /// Write the ASP.Net HttpContext item to the output + /// + /// that will receive the formatted result. + /// The on which the pattern converter should be executed. + /// The under which the ASP.Net request is running. + /// + /// + /// Writes out the value of a named property. The property name + /// should be set in the + /// property. + /// + /// + protected override void Convert(TextWriter writer, LoggingEvent loggingEvent, HttpContext httpContext) + { + if (Option != null) + { + WriteObject(writer, loggingEvent.Repository, httpContext.Items[Option]); + } + else + { + WriteObject(writer, loggingEvent.Repository, httpContext.Items); + } + } + } } #endif // !NETCF && !SSCLI && !CLIENT_PROFILE diff --git a/src/log4net/Layout/Pattern/AspNetPatternConverter.cs b/src/log4net/Layout/Pattern/AspNetPatternConverter.cs index f7647907..17d2ca1c 100644 --- a/src/log4net/Layout/Pattern/AspNetPatternConverter.cs +++ b/src/log4net/Layout/Pattern/AspNetPatternConverter.cs @@ -29,38 +29,38 @@ namespace log4net.Layout.Pattern { - /// - /// Abstract class that provides access to the current HttpContext () that - /// derived classes need. - /// - /// - /// This class handles the case when HttpContext.Current is null by writing - /// to the writer. - /// - /// Ron Grabowski - internal abstract class AspNetPatternLayoutConverter : PatternLayoutConverter - { - protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) - { - if (HttpContext.Current == null) - { - writer.Write(SystemInfo.NotAvailableText); - } - else - { - Convert(writer, loggingEvent, HttpContext.Current); - } - } + /// + /// Abstract class that provides access to the current HttpContext () that + /// derived classes need. + /// + /// + /// This class handles the case when HttpContext.Current is null by writing + /// to the writer. + /// + /// Ron Grabowski + internal abstract class AspNetPatternLayoutConverter : PatternLayoutConverter + { + protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) + { + if (HttpContext.Current == null) + { + writer.Write(SystemInfo.NotAvailableText); + } + else + { + Convert(writer, loggingEvent, HttpContext.Current); + } + } - /// - /// Derived pattern converters must override this method in order to - /// convert conversion specifiers in the correct way. - /// - /// that will receive the formatted result. - /// The on which the pattern converter should be executed. - /// The under which the ASP.Net request is running. - protected abstract void Convert(TextWriter writer, LoggingEvent loggingEvent, HttpContext httpContext); - } + /// + /// Derived pattern converters must override this method in order to + /// convert conversion specifiers in the correct way. + /// + /// that will receive the formatted result. + /// The on which the pattern converter should be executed. + /// The under which the ASP.Net request is running. + protected abstract void Convert(TextWriter writer, LoggingEvent loggingEvent, HttpContext httpContext); + } } #endif // !NETCF && !SSCLI && !CLIENT_PROFILE diff --git a/src/log4net/Layout/Pattern/AspNetRequestPatternConverter.cs b/src/log4net/Layout/Pattern/AspNetRequestPatternConverter.cs index 9a7c67bf..2be50431 100644 --- a/src/log4net/Layout/Pattern/AspNetRequestPatternConverter.cs +++ b/src/log4net/Layout/Pattern/AspNetRequestPatternConverter.cs @@ -29,59 +29,59 @@ namespace log4net.Layout.Pattern { - /// - /// Converter for items in the ASP.Net Cache. - /// - /// - /// - /// Outputs an item from the . - /// - /// - /// Ron Grabowski - internal sealed class AspNetRequestPatternConverter : AspNetPatternLayoutConverter - { - /// - /// Write the ASP.Net Cache item to the output - /// - /// that will receive the formatted result. - /// The on which the pattern converter should be executed. - /// The under which the ASP.Net request is running. - /// - /// - /// Writes out the value of a named property. The property name - /// should be set in the - /// property. - /// - /// - protected override void Convert(TextWriter writer, LoggingEvent loggingEvent, HttpContext httpContext) - { - HttpRequest request = null; - try { - request = httpContext.Request; - } catch (HttpException) { - // likely a case of running in IIS integrated mode - // when inside an Application_Start event. - // treat it like a case of the Request - // property returning null - } + /// + /// Converter for items in the ASP.Net Cache. + /// + /// + /// + /// Outputs an item from the . + /// + /// + /// Ron Grabowski + internal sealed class AspNetRequestPatternConverter : AspNetPatternLayoutConverter + { + /// + /// Write the ASP.Net Cache item to the output + /// + /// that will receive the formatted result. + /// The on which the pattern converter should be executed. + /// The under which the ASP.Net request is running. + /// + /// + /// Writes out the value of a named property. The property name + /// should be set in the + /// property. + /// + /// + protected override void Convert(TextWriter writer, LoggingEvent loggingEvent, HttpContext httpContext) + { + HttpRequest request = null; + try { + request = httpContext.Request; + } catch (HttpException) { + // likely a case of running in IIS integrated mode + // when inside an Application_Start event. + // treat it like a case of the Request + // property returning null + } - if (request != null) - { - if (Option != null) - { - WriteObject(writer, loggingEvent.Repository, httpContext.Request.Params[Option]); - } - else - { - WriteObject(writer, loggingEvent.Repository, httpContext.Request.Params); - } - } - else - { - writer.Write(SystemInfo.NotAvailableText); - } - } - } + if (request != null) + { + if (Option != null) + { + WriteObject(writer, loggingEvent.Repository, httpContext.Request.Params[Option]); + } + else + { + WriteObject(writer, loggingEvent.Repository, httpContext.Request.Params); + } + } + else + { + writer.Write(SystemInfo.NotAvailableText); + } + } + } } #endif // !NETCF && !SSCLI && !CLIENT_PROFILE diff --git a/src/log4net/Layout/Pattern/AspNetSessionPatternConverter.cs b/src/log4net/Layout/Pattern/AspNetSessionPatternConverter.cs index d7e52b2c..8cbcae6e 100644 --- a/src/log4net/Layout/Pattern/AspNetSessionPatternConverter.cs +++ b/src/log4net/Layout/Pattern/AspNetSessionPatternConverter.cs @@ -29,50 +29,50 @@ namespace log4net.Layout.Pattern { - /// - /// Converter for items in the ASP.Net Cache. - /// - /// - /// - /// Outputs an item from the . - /// - /// - /// Ron Grabowski - internal sealed class AspNetSessionPatternConverter : AspNetPatternLayoutConverter - { - /// - /// Write the ASP.Net Cache item to the output - /// - /// that will receive the formatted result. - /// The on which the pattern converter should be executed. - /// The under which the ASP.Net request is running. - /// - /// - /// Writes out the value of a named property. The property name - /// should be set in the - /// property. If no property has been set, all key value pairs from the Session will - /// be written to the output. - /// - /// - protected override void Convert(TextWriter writer, LoggingEvent loggingEvent, HttpContext httpContext) - { - if (httpContext.Session != null) - { - if (Option != null) - { - WriteObject(writer, loggingEvent.Repository, httpContext.Session.Contents[Option]); - } - else - { - WriteObject(writer, loggingEvent.Repository, httpContext.Session); - } - } - else - { - writer.Write(SystemInfo.NotAvailableText); - } - } - } + /// + /// Converter for items in the ASP.Net Cache. + /// + /// + /// + /// Outputs an item from the . + /// + /// + /// Ron Grabowski + internal sealed class AspNetSessionPatternConverter : AspNetPatternLayoutConverter + { + /// + /// Write the ASP.Net Cache item to the output + /// + /// that will receive the formatted result. + /// The on which the pattern converter should be executed. + /// The under which the ASP.Net request is running. + /// + /// + /// Writes out the value of a named property. The property name + /// should be set in the + /// property. If no property has been set, all key value pairs from the Session will + /// be written to the output. + /// + /// + protected override void Convert(TextWriter writer, LoggingEvent loggingEvent, HttpContext httpContext) + { + if (httpContext.Session != null) + { + if (Option != null) + { + WriteObject(writer, loggingEvent.Repository, httpContext.Session.Contents[Option]); + } + else + { + WriteObject(writer, loggingEvent.Repository, httpContext.Session); + } + } + else + { + writer.Write(SystemInfo.NotAvailableText); + } + } + } } #endif // !NETCF && !SSCLI && !CLIENT_PROFILE diff --git a/src/log4net/Layout/Pattern/DatePatternConverter.cs b/src/log4net/Layout/Pattern/DatePatternConverter.cs index c283ba1f..a111b8f4 100644 --- a/src/log4net/Layout/Pattern/DatePatternConverter.cs +++ b/src/log4net/Layout/Pattern/DatePatternConverter.cs @@ -26,164 +26,164 @@ namespace log4net.Layout.Pattern { - /// - /// Date pattern converter, uses a to format - /// the date of a . - /// - /// - /// - /// Render the to the writer as a string. - /// - /// - /// The value of the determines - /// the formatting of the date. The following values are allowed: - /// - /// - /// Option value - /// Output - /// - /// - /// ISO8601 - /// - /// Uses the formatter. - /// Formats using the "yyyy-MM-dd HH:mm:ss,fff" pattern. - /// - /// - /// - /// DATE - /// - /// Uses the formatter. - /// Formats using the "dd MMM yyyy HH:mm:ss,fff" for example, "06 Nov 1994 15:49:37,459". - /// - /// - /// - /// ABSOLUTE - /// - /// Uses the formatter. - /// Formats using the "HH:mm:ss,yyyy" for example, "15:49:37,459". - /// - /// - /// - /// other - /// - /// Any other pattern string uses the formatter. - /// This formatter passes the pattern string to the - /// method. - /// For details on valid patterns see - /// DateTimeFormatInfo Class. - /// - /// - /// - /// - /// - /// The is in the local time zone and is rendered in that zone. - /// To output the time in Universal time see . - /// - /// - /// Nicko Cadell - internal class DatePatternConverter : PatternLayoutConverter, IOptionHandler - { - /// - /// The used to render the date to a string - /// - /// - /// - /// The used to render the date to a string - /// - /// - protected IDateFormatter m_dateFormatter; - - #region Implementation of IOptionHandler + /// + /// Date pattern converter, uses a to format + /// the date of a . + /// + /// + /// + /// Render the to the writer as a string. + /// + /// + /// The value of the determines + /// the formatting of the date. The following values are allowed: + /// + /// + /// Option value + /// Output + /// + /// + /// ISO8601 + /// + /// Uses the formatter. + /// Formats using the "yyyy-MM-dd HH:mm:ss,fff" pattern. + /// + /// + /// + /// DATE + /// + /// Uses the formatter. + /// Formats using the "dd MMM yyyy HH:mm:ss,fff" for example, "06 Nov 1994 15:49:37,459". + /// + /// + /// + /// ABSOLUTE + /// + /// Uses the formatter. + /// Formats using the "HH:mm:ss,yyyy" for example, "15:49:37,459". + /// + /// + /// + /// other + /// + /// Any other pattern string uses the formatter. + /// This formatter passes the pattern string to the + /// method. + /// For details on valid patterns see + /// DateTimeFormatInfo Class. + /// + /// + /// + /// + /// + /// The is in the local time zone and is rendered in that zone. + /// To output the time in Universal time see . + /// + /// + /// Nicko Cadell + internal class DatePatternConverter : PatternLayoutConverter, IOptionHandler + { + /// + /// The used to render the date to a string + /// + /// + /// + /// The used to render the date to a string + /// + /// + protected IDateFormatter m_dateFormatter; + + #region Implementation of IOptionHandler - /// - /// Initialize the converter pattern based on the property. - /// - /// - /// - /// This is part of the delayed object - /// activation scheme. The method must - /// be called on this object after the configuration properties have - /// been set. Until is called this - /// object is in an undefined state and must not be used. - /// - /// - /// If any of the configuration properties are modified then - /// must be called again. - /// - /// - public void ActivateOptions() - { - string dateFormatStr = Option; - if (dateFormatStr == null) - { - dateFormatStr = AbsoluteTimeDateFormatter.Iso8601TimeDateFormat; - } + /// + /// Initialize the converter pattern based on the property. + /// + /// + /// + /// This is part of the delayed object + /// activation scheme. The method must + /// be called on this object after the configuration properties have + /// been set. Until is called this + /// object is in an undefined state and must not be used. + /// + /// + /// If any of the configuration properties are modified then + /// must be called again. + /// + /// + public void ActivateOptions() + { + string dateFormatStr = Option; + if (dateFormatStr == null) + { + dateFormatStr = AbsoluteTimeDateFormatter.Iso8601TimeDateFormat; + } - if (SystemInfo.EqualsIgnoringCase(dateFormatStr, AbsoluteTimeDateFormatter.Iso8601TimeDateFormat)) - { - m_dateFormatter = new Iso8601DateFormatter(); - } - else if (SystemInfo.EqualsIgnoringCase(dateFormatStr, AbsoluteTimeDateFormatter.AbsoluteTimeDateFormat)) - { - m_dateFormatter = new AbsoluteTimeDateFormatter(); - } - else if (SystemInfo.EqualsIgnoringCase(dateFormatStr, AbsoluteTimeDateFormatter.DateAndTimeDateFormat)) - { - m_dateFormatter = new DateTimeDateFormatter(); - } - else - { - try - { - m_dateFormatter = new SimpleDateFormatter(dateFormatStr); - } - catch (Exception e) - { - LogLog.Error(declaringType, "Could not instantiate SimpleDateFormatter with ["+dateFormatStr+"]", e); - m_dateFormatter = new Iso8601DateFormatter(); - } - } - } + if (SystemInfo.EqualsIgnoringCase(dateFormatStr, AbsoluteTimeDateFormatter.Iso8601TimeDateFormat)) + { + m_dateFormatter = new Iso8601DateFormatter(); + } + else if (SystemInfo.EqualsIgnoringCase(dateFormatStr, AbsoluteTimeDateFormatter.AbsoluteTimeDateFormat)) + { + m_dateFormatter = new AbsoluteTimeDateFormatter(); + } + else if (SystemInfo.EqualsIgnoringCase(dateFormatStr, AbsoluteTimeDateFormatter.DateAndTimeDateFormat)) + { + m_dateFormatter = new DateTimeDateFormatter(); + } + else + { + try + { + m_dateFormatter = new SimpleDateFormatter(dateFormatStr); + } + catch (Exception e) + { + LogLog.Error(declaringType, "Could not instantiate SimpleDateFormatter with ["+dateFormatStr+"]", e); + m_dateFormatter = new Iso8601DateFormatter(); + } + } + } - #endregion + #endregion - /// - /// Convert the pattern into the rendered message - /// - /// that will receive the formatted result. - /// the event being logged - /// - /// - /// Pass the to the - /// for it to render it to the writer. - /// - /// - /// The passed is in the local time zone. - /// - /// - protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) - { - try - { - m_dateFormatter.FormatDate(loggingEvent.TimeStamp, writer); - } - catch (Exception ex) - { - LogLog.Error(declaringType, "Error occurred while converting date.", ex); - } - } + /// + /// Convert the pattern into the rendered message + /// + /// that will receive the formatted result. + /// the event being logged + /// + /// + /// Pass the to the + /// for it to render it to the writer. + /// + /// + /// The passed is in the local time zone. + /// + /// + protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) + { + try + { + m_dateFormatter.FormatDate(loggingEvent.TimeStamp, writer); + } + catch (Exception ex) + { + LogLog.Error(declaringType, "Error occurred while converting date.", ex); + } + } - #region Private Static Fields + #region Private Static Fields - /// - /// The fully qualified type of the DatePatternConverter class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(DatePatternConverter); + /// + /// The fully qualified type of the DatePatternConverter class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(DatePatternConverter); - #endregion Private Static Fields - } + #endregion Private Static Fields + } } diff --git a/src/log4net/Layout/Pattern/ExceptionPatternConverter.cs b/src/log4net/Layout/Pattern/ExceptionPatternConverter.cs index 00913049..275959be 100644 --- a/src/log4net/Layout/Pattern/ExceptionPatternConverter.cs +++ b/src/log4net/Layout/Pattern/ExceptionPatternConverter.cs @@ -23,115 +23,115 @@ namespace log4net.Layout.Pattern { - /// - /// Write the exception text to the output - /// - /// - /// - /// If an exception object is stored in the logging event - /// it will be rendered into the pattern output with a - /// trailing newline. - /// - /// - /// If there is no exception then nothing will be output - /// and no trailing newline will be appended. - /// It is typical to put a newline before the exception - /// and to have the exception as the last data in the pattern. - /// - /// - /// Nicko Cadell - internal sealed class ExceptionPatternConverter : PatternLayoutConverter - { - /// - /// Default constructor - /// - public ExceptionPatternConverter() - { - // This converter handles the exception - IgnoresException = false; - } + /// + /// Write the exception text to the output + /// + /// + /// + /// If an exception object is stored in the logging event + /// it will be rendered into the pattern output with a + /// trailing newline. + /// + /// + /// If there is no exception then nothing will be output + /// and no trailing newline will be appended. + /// It is typical to put a newline before the exception + /// and to have the exception as the last data in the pattern. + /// + /// + /// Nicko Cadell + internal sealed class ExceptionPatternConverter : PatternLayoutConverter + { + /// + /// Default constructor + /// + public ExceptionPatternConverter() + { + // This converter handles the exception + IgnoresException = false; + } - /// - /// Write the exception text to the output - /// - /// that will receive the formatted result. - /// the event being logged - /// - /// - /// If an exception object is stored in the logging event - /// it will be rendered into the pattern output with a - /// trailing newline. - /// - /// - /// If there is no exception or the exception property specified - /// by the Option value does not exist then nothing will be output - /// and no trailing newline will be appended. - /// It is typical to put a newline before the exception - /// and to have the exception as the last data in the pattern. - /// - /// - /// Recognized values for the Option parameter are: - /// - /// - /// - /// Message - /// - /// - /// Source - /// - /// - /// StackTrace - /// - /// - /// TargetSite - /// - /// - /// HelpLink - /// - /// - /// - protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) - { - if (loggingEvent.ExceptionObject != null && Option != null && Option.Length > 0) - { - switch (Option.ToLower()) - { - case "message": - WriteObject(writer, loggingEvent.Repository, loggingEvent.ExceptionObject.Message); - break; -#if !NETCF - case "source": - WriteObject(writer, loggingEvent.Repository, loggingEvent.ExceptionObject.Source); - break; - case "stacktrace": - WriteObject(writer, loggingEvent.Repository, loggingEvent.ExceptionObject.StackTrace); - break; + /// + /// Write the exception text to the output + /// + /// that will receive the formatted result. + /// the event being logged + /// + /// + /// If an exception object is stored in the logging event + /// it will be rendered into the pattern output with a + /// trailing newline. + /// + /// + /// If there is no exception or the exception property specified + /// by the Option value does not exist then nothing will be output + /// and no trailing newline will be appended. + /// It is typical to put a newline before the exception + /// and to have the exception as the last data in the pattern. + /// + /// + /// Recognized values for the Option parameter are: + /// + /// + /// + /// Message + /// + /// + /// Source + /// + /// + /// StackTrace + /// + /// + /// TargetSite + /// + /// + /// HelpLink + /// + /// + /// + protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) + { + if (loggingEvent.ExceptionObject != null && Option != null && Option.Length > 0) + { + switch (Option.ToLower()) + { + case "message": + WriteObject(writer, loggingEvent.Repository, loggingEvent.ExceptionObject.Message); + break; +#if !NETCF + case "source": + WriteObject(writer, loggingEvent.Repository, loggingEvent.ExceptionObject.Source); + break; + case "stacktrace": + WriteObject(writer, loggingEvent.Repository, loggingEvent.ExceptionObject.StackTrace); + break; #if !NETSTANDARD - case "targetsite": - WriteObject(writer, loggingEvent.Repository, loggingEvent.ExceptionObject.TargetSite); - break; + case "targetsite": + WriteObject(writer, loggingEvent.Repository, loggingEvent.ExceptionObject.TargetSite); + break; #endif - case "helplink": - WriteObject(writer, loggingEvent.Repository, loggingEvent.ExceptionObject.HelpLink); - break; -#endif - default: - // do not output SystemInfo.NotAvailableText - break; - } - } - else - { - string exceptionString = loggingEvent.GetExceptionString(); - if (exceptionString != null && exceptionString.Length > 0) - { - writer.WriteLine(exceptionString); - } - else - { - // do not output SystemInfo.NotAvailableText - } - } - } - } + case "helplink": + WriteObject(writer, loggingEvent.Repository, loggingEvent.ExceptionObject.HelpLink); + break; +#endif + default: + // do not output SystemInfo.NotAvailableText + break; + } + } + else + { + string exceptionString = loggingEvent.GetExceptionString(); + if (exceptionString != null && exceptionString.Length > 0) + { + writer.WriteLine(exceptionString); + } + else + { + // do not output SystemInfo.NotAvailableText + } + } + } + } } diff --git a/src/log4net/Layout/Pattern/FileLocationPatternConverter.cs b/src/log4net/Layout/Pattern/FileLocationPatternConverter.cs index d555c61c..7f87e755 100644 --- a/src/log4net/Layout/Pattern/FileLocationPatternConverter.cs +++ b/src/log4net/Layout/Pattern/FileLocationPatternConverter.cs @@ -25,32 +25,32 @@ namespace log4net.Layout.Pattern { - /// - /// Writes the caller location file name to the output - /// - /// - /// - /// Writes the value of the for - /// the event to the output writer. - /// - /// - /// Nicko Cadell - internal sealed class FileLocationPatternConverter : PatternLayoutConverter - { - /// - /// Write the caller location file name to the output - /// - /// that will receive the formatted result. - /// the event being logged - /// - /// - /// Writes the value of the for - /// the to the output . - /// - /// - protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) - { - writer.Write(loggingEvent.LocationInformation.FileName); - } - } + /// + /// Writes the caller location file name to the output + /// + /// + /// + /// Writes the value of the for + /// the event to the output writer. + /// + /// + /// Nicko Cadell + internal sealed class FileLocationPatternConverter : PatternLayoutConverter + { + /// + /// Write the caller location file name to the output + /// + /// that will receive the formatted result. + /// the event being logged + /// + /// + /// Writes the value of the for + /// the to the output . + /// + /// + protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) + { + writer.Write(loggingEvent.LocationInformation.FileName); + } + } } diff --git a/src/log4net/Layout/Pattern/FullLocationPatternConverter.cs b/src/log4net/Layout/Pattern/FullLocationPatternConverter.cs index ac5dab66..bb39c0d4 100644 --- a/src/log4net/Layout/Pattern/FullLocationPatternConverter.cs +++ b/src/log4net/Layout/Pattern/FullLocationPatternConverter.cs @@ -25,30 +25,30 @@ namespace log4net.Layout.Pattern { - /// - /// Write the caller location info to the output - /// - /// - /// - /// Writes the to the output writer. - /// - /// - /// Nicko Cadell - internal sealed class FullLocationPatternConverter : PatternLayoutConverter - { - /// - /// Write the caller location info to the output - /// - /// that will receive the formatted result. - /// the event being logged - /// - /// - /// Writes the to the output writer. - /// - /// - protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) - { - writer.Write( loggingEvent.LocationInformation.FullInfo ); - } - } + /// + /// Write the caller location info to the output + /// + /// + /// + /// Writes the to the output writer. + /// + /// + /// Nicko Cadell + internal sealed class FullLocationPatternConverter : PatternLayoutConverter + { + /// + /// Write the caller location info to the output + /// + /// that will receive the formatted result. + /// the event being logged + /// + /// + /// Writes the to the output writer. + /// + /// + protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) + { + writer.Write( loggingEvent.LocationInformation.FullInfo ); + } + } } diff --git a/src/log4net/Layout/Pattern/IdentityPatternConverter.cs b/src/log4net/Layout/Pattern/IdentityPatternConverter.cs index 0ef245c0..c13a7885 100644 --- a/src/log4net/Layout/Pattern/IdentityPatternConverter.cs +++ b/src/log4net/Layout/Pattern/IdentityPatternConverter.cs @@ -25,34 +25,34 @@ namespace log4net.Layout.Pattern { - /// - /// Writes the event identity to the output - /// - /// - /// - /// Writes the value of the to - /// the output writer. - /// - /// - /// Daniel Cazzulino - /// Nicko Cadell - internal sealed class IdentityPatternConverter : PatternLayoutConverter - { - /// - /// Writes the event identity to the output - /// - /// that will receive the formatted result. - /// the event being logged - /// - /// - /// Writes the value of the - /// to - /// the output . - /// - /// - protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) - { - writer.Write(loggingEvent.Identity); - } - } + /// + /// Writes the event identity to the output + /// + /// + /// + /// Writes the value of the to + /// the output writer. + /// + /// + /// Daniel Cazzulino + /// Nicko Cadell + internal sealed class IdentityPatternConverter : PatternLayoutConverter + { + /// + /// Writes the event identity to the output + /// + /// that will receive the formatted result. + /// the event being logged + /// + /// + /// Writes the value of the + /// to + /// the output . + /// + /// + protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) + { + writer.Write(loggingEvent.Identity); + } + } } diff --git a/src/log4net/Layout/Pattern/LevelPatternConverter.cs b/src/log4net/Layout/Pattern/LevelPatternConverter.cs index 21af92b1..75b57ec2 100644 --- a/src/log4net/Layout/Pattern/LevelPatternConverter.cs +++ b/src/log4net/Layout/Pattern/LevelPatternConverter.cs @@ -25,32 +25,32 @@ namespace log4net.Layout.Pattern { - /// - /// Write the event level to the output - /// - /// - /// - /// Writes the display name of the event - /// to the writer. - /// - /// - /// Nicko Cadell - internal sealed class LevelPatternConverter : PatternLayoutConverter - { - /// - /// Write the event level to the output - /// - /// that will receive the formatted result. - /// the event being logged - /// - /// - /// Writes the of the - /// to the . - /// - /// - protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) - { - writer.Write( loggingEvent.Level.DisplayName ); - } - } + /// + /// Write the event level to the output + /// + /// + /// + /// Writes the display name of the event + /// to the writer. + /// + /// + /// Nicko Cadell + internal sealed class LevelPatternConverter : PatternLayoutConverter + { + /// + /// Write the event level to the output + /// + /// that will receive the formatted result. + /// the event being logged + /// + /// + /// Writes the of the + /// to the . + /// + /// + protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) + { + writer.Write( loggingEvent.Level.DisplayName ); + } + } } diff --git a/src/log4net/Layout/Pattern/LineLocationPatternConverter.cs b/src/log4net/Layout/Pattern/LineLocationPatternConverter.cs index 07c91e8a..b9ce0a3d 100644 --- a/src/log4net/Layout/Pattern/LineLocationPatternConverter.cs +++ b/src/log4net/Layout/Pattern/LineLocationPatternConverter.cs @@ -25,32 +25,32 @@ namespace log4net.Layout.Pattern { - /// - /// Write the caller location line number to the output - /// - /// - /// - /// Writes the value of the for - /// the event to the output writer. - /// - /// - /// Nicko Cadell - internal sealed class LineLocationPatternConverter : PatternLayoutConverter - { - /// - /// Write the caller location line number to the output - /// - /// that will receive the formatted result. - /// the event being logged - /// - /// - /// Writes the value of the for - /// the to the output . - /// - /// - protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) - { - writer.Write(loggingEvent.LocationInformation.LineNumber); - } - } + /// + /// Write the caller location line number to the output + /// + /// + /// + /// Writes the value of the for + /// the event to the output writer. + /// + /// + /// Nicko Cadell + internal sealed class LineLocationPatternConverter : PatternLayoutConverter + { + /// + /// Write the caller location line number to the output + /// + /// that will receive the formatted result. + /// the event being logged + /// + /// + /// Writes the value of the for + /// the to the output . + /// + /// + protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) + { + writer.Write(loggingEvent.LocationInformation.LineNumber); + } + } } diff --git a/src/log4net/Layout/Pattern/LoggerPatternConverter.cs b/src/log4net/Layout/Pattern/LoggerPatternConverter.cs index 471b4aa2..087ab013 100644 --- a/src/log4net/Layout/Pattern/LoggerPatternConverter.cs +++ b/src/log4net/Layout/Pattern/LoggerPatternConverter.cs @@ -25,30 +25,30 @@ namespace log4net.Layout.Pattern { - /// - /// Converter for logger name - /// - /// - /// - /// Outputs the of the event. - /// - /// - /// Nicko Cadell - internal sealed class LoggerPatternConverter : NamedPatternConverter - { - /// - /// Gets the fully qualified name of the logger - /// - /// the event being logged - /// The fully qualified logger name - /// - /// - /// Returns the of the . - /// - /// - protected override string GetFullyQualifiedName(LoggingEvent loggingEvent) - { - return loggingEvent.LoggerName; - } - } + /// + /// Converter for logger name + /// + /// + /// + /// Outputs the of the event. + /// + /// + /// Nicko Cadell + internal sealed class LoggerPatternConverter : NamedPatternConverter + { + /// + /// Gets the fully qualified name of the logger + /// + /// the event being logged + /// The fully qualified logger name + /// + /// + /// Returns the of the . + /// + /// + protected override string GetFullyQualifiedName(LoggingEvent loggingEvent) + { + return loggingEvent.LoggerName; + } + } } diff --git a/src/log4net/Layout/Pattern/MessagePatternConverter.cs b/src/log4net/Layout/Pattern/MessagePatternConverter.cs index cf0f5afc..25fc4210 100644 --- a/src/log4net/Layout/Pattern/MessagePatternConverter.cs +++ b/src/log4net/Layout/Pattern/MessagePatternConverter.cs @@ -25,32 +25,32 @@ namespace log4net.Layout.Pattern { - /// - /// Writes the event message to the output - /// - /// - /// - /// Uses the method - /// to write out the event message. - /// - /// - /// Nicko Cadell - internal sealed class MessagePatternConverter : PatternLayoutConverter - { - /// - /// Writes the event message to the output - /// - /// that will receive the formatted result. - /// the event being logged - /// - /// - /// Uses the method - /// to write out the event message. - /// - /// - protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) - { - loggingEvent.WriteRenderedMessage(writer); - } - } + /// + /// Writes the event message to the output + /// + /// + /// + /// Uses the method + /// to write out the event message. + /// + /// + /// Nicko Cadell + internal sealed class MessagePatternConverter : PatternLayoutConverter + { + /// + /// Writes the event message to the output + /// + /// that will receive the formatted result. + /// the event being logged + /// + /// + /// Uses the method + /// to write out the event message. + /// + /// + protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) + { + loggingEvent.WriteRenderedMessage(writer); + } + } } diff --git a/src/log4net/Layout/Pattern/MethodLocationPatternConverter.cs b/src/log4net/Layout/Pattern/MethodLocationPatternConverter.cs index 90fa7559..cbbbc6df 100644 --- a/src/log4net/Layout/Pattern/MethodLocationPatternConverter.cs +++ b/src/log4net/Layout/Pattern/MethodLocationPatternConverter.cs @@ -25,32 +25,32 @@ namespace log4net.Layout.Pattern { - /// - /// Write the method name to the output - /// - /// - /// - /// Writes the caller location to - /// the output. - /// - /// - /// Nicko Cadell - internal sealed class MethodLocationPatternConverter : PatternLayoutConverter - { - /// - /// Write the method name to the output - /// - /// that will receive the formatted result. - /// the event being logged - /// - /// - /// Writes the caller location to - /// the output. - /// - /// - protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) - { - writer.Write(loggingEvent.LocationInformation.MethodName); - } - } + /// + /// Write the method name to the output + /// + /// + /// + /// Writes the caller location to + /// the output. + /// + /// + /// Nicko Cadell + internal sealed class MethodLocationPatternConverter : PatternLayoutConverter + { + /// + /// Write the method name to the output + /// + /// that will receive the formatted result. + /// the event being logged + /// + /// + /// Writes the caller location to + /// the output. + /// + /// + protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) + { + writer.Write(loggingEvent.LocationInformation.MethodName); + } + } } diff --git a/src/log4net/Layout/Pattern/NamedPatternConverter.cs b/src/log4net/Layout/Pattern/NamedPatternConverter.cs index d94a9c81..2fba1f55 100644 --- a/src/log4net/Layout/Pattern/NamedPatternConverter.cs +++ b/src/log4net/Layout/Pattern/NamedPatternConverter.cs @@ -27,109 +27,109 @@ namespace log4net.Layout.Pattern { - /// - /// Converter to output and truncate '.' separated strings - /// - /// - /// - /// This abstract class supports truncating a '.' separated string - /// to show a specified number of elements from the right hand side. - /// This is used to truncate class names that are fully qualified. - /// - /// - /// Subclasses should override the method to - /// return the fully qualified string. - /// - /// - /// Nicko Cadell - public abstract class NamedPatternConverter : PatternLayoutConverter, IOptionHandler - { - private int m_precision = 0; + /// + /// Converter to output and truncate '.' separated strings + /// + /// + /// + /// This abstract class supports truncating a '.' separated string + /// to show a specified number of elements from the right hand side. + /// This is used to truncate class names that are fully qualified. + /// + /// + /// Subclasses should override the method to + /// return the fully qualified string. + /// + /// + /// Nicko Cadell + public abstract class NamedPatternConverter : PatternLayoutConverter, IOptionHandler + { + private int m_precision = 0; - #region Implementation of IOptionHandler + #region Implementation of IOptionHandler - /// - /// Initialize the converter - /// - /// - /// - /// This is part of the delayed object - /// activation scheme. The method must - /// be called on this object after the configuration properties have - /// been set. Until is called this - /// object is in an undefined state and must not be used. - /// - /// - /// If any of the configuration properties are modified then - /// must be called again. - /// - /// - public void ActivateOptions() - { - m_precision = 0; + /// + /// Initialize the converter + /// + /// + /// + /// This is part of the delayed object + /// activation scheme. The method must + /// be called on this object after the configuration properties have + /// been set. Until is called this + /// object is in an undefined state and must not be used. + /// + /// + /// If any of the configuration properties are modified then + /// must be called again. + /// + /// + public void ActivateOptions() + { + m_precision = 0; - if (Option != null) - { - string optStr = Option.Trim(); - if (optStr.Length > 0) - { - int precisionVal; - if (SystemInfo.TryParse(optStr, out precisionVal)) - { - if (precisionVal <= 0) - { - LogLog.Error(declaringType, "NamedPatternConverter: Precision option (" + optStr + ") isn't a positive integer."); - } - else - { - m_precision = precisionVal; - } - } - else - { - LogLog.Error(declaringType, "NamedPatternConverter: Precision option \"" + optStr + "\" not a decimal integer."); - } - } - } - } + if (Option != null) + { + string optStr = Option.Trim(); + if (optStr.Length > 0) + { + int precisionVal; + if (SystemInfo.TryParse(optStr, out precisionVal)) + { + if (precisionVal <= 0) + { + LogLog.Error(declaringType, "NamedPatternConverter: Precision option (" + optStr + ") isn't a positive integer."); + } + else + { + m_precision = precisionVal; + } + } + else + { + LogLog.Error(declaringType, "NamedPatternConverter: Precision option \"" + optStr + "\" not a decimal integer."); + } + } + } + } - #endregion + #endregion - /// - /// Get the fully qualified string data - /// - /// the event being logged - /// the fully qualified name - /// - /// - /// Overridden by subclasses to get the fully qualified name before the - /// precision is applied to it. - /// - /// - /// Return the fully qualified '.' (dot/period) separated string. - /// - /// - protected abstract string GetFullyQualifiedName(LoggingEvent loggingEvent); - - /// - /// Convert the pattern to the rendered message - /// - /// that will receive the formatted result. - /// the event being logged - /// - /// Render the to the precision - /// specified by the property. - /// - protected sealed override void Convert(TextWriter writer, LoggingEvent loggingEvent) - { - string name = GetFullyQualifiedName(loggingEvent); - if (m_precision <= 0 || name == null || name.Length < 2) - { - writer.Write(name); - } - else - { - int len = name.Length; + /// + /// Get the fully qualified string data + /// + /// the event being logged + /// the fully qualified name + /// + /// + /// Overridden by subclasses to get the fully qualified name before the + /// precision is applied to it. + /// + /// + /// Return the fully qualified '.' (dot/period) separated string. + /// + /// + protected abstract string GetFullyQualifiedName(LoggingEvent loggingEvent); + + /// + /// Convert the pattern to the rendered message + /// + /// that will receive the formatted result. + /// the event being logged + /// + /// Render the to the precision + /// specified by the property. + /// + protected sealed override void Convert(TextWriter writer, LoggingEvent loggingEvent) + { + string name = GetFullyQualifiedName(loggingEvent); + if (m_precision <= 0 || name == null || name.Length < 2) + { + writer.Write(name); + } + else + { + int len = name.Length; string trailingDot = string.Empty; if (name.EndsWith(DOT)) { @@ -139,8 +139,8 @@ protected sealed override void Convert(TextWriter writer, LoggingEvent loggingEv } int end = name.LastIndexOf(DOT); - for(int i = 1; end > 0 && i < m_precision; i++) - { + for(int i = 1; end > 0 && i < m_precision; i++) + { end = name.LastIndexOf('.', end - 1); } if (end == -1) @@ -151,21 +151,21 @@ protected sealed override void Convert(TextWriter writer, LoggingEvent loggingEv { writer.Write(name.Substring(end + 1, len - end - 1) + trailingDot); } - } - } + } + } - #region Private Static Fields + #region Private Static Fields - /// - /// The fully qualified type of the NamedPatternConverter class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(NamedPatternConverter); + /// + /// The fully qualified type of the NamedPatternConverter class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(NamedPatternConverter); private const string DOT = "."; - #endregion Private Static Fields - } + #endregion Private Static Fields + } } diff --git a/src/log4net/Layout/Pattern/NdcPatternConverter.cs b/src/log4net/Layout/Pattern/NdcPatternConverter.cs index 57216814..edf1ff10 100644 --- a/src/log4net/Layout/Pattern/NdcPatternConverter.cs +++ b/src/log4net/Layout/Pattern/NdcPatternConverter.cs @@ -25,38 +25,38 @@ namespace log4net.Layout.Pattern { - /// - /// Converter to include event NDC - /// - /// - /// - /// Outputs the value of the event property named NDC. - /// - /// - /// The should be used instead. - /// - /// - /// Nicko Cadell - internal sealed class NdcPatternConverter : PatternLayoutConverter - { - /// - /// Write the event NDC to the output - /// - /// that will receive the formatted result. - /// the event being logged - /// - /// - /// As the thread context stacks are now stored in named event properties - /// this converter simply looks up the value of the NDC property. - /// - /// - /// The should be used instead. - /// - /// - protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) - { - // Write the value for the specified key - WriteObject(writer, loggingEvent.Repository, loggingEvent.LookupProperty("NDC")); - } - } + /// + /// Converter to include event NDC + /// + /// + /// + /// Outputs the value of the event property named NDC. + /// + /// + /// The should be used instead. + /// + /// + /// Nicko Cadell + internal sealed class NdcPatternConverter : PatternLayoutConverter + { + /// + /// Write the event NDC to the output + /// + /// that will receive the formatted result. + /// the event being logged + /// + /// + /// As the thread context stacks are now stored in named event properties + /// this converter simply looks up the value of the NDC property. + /// + /// + /// The should be used instead. + /// + /// + protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) + { + // Write the value for the specified key + WriteObject(writer, loggingEvent.Repository, loggingEvent.LookupProperty("NDC")); + } + } } diff --git a/src/log4net/Layout/Pattern/PatternLayoutConverter.cs b/src/log4net/Layout/Pattern/PatternLayoutConverter.cs index b805b395..4886f7fd 100644 --- a/src/log4net/Layout/Pattern/PatternLayoutConverter.cs +++ b/src/log4net/Layout/Pattern/PatternLayoutConverter.cs @@ -28,96 +28,96 @@ namespace log4net.Layout.Pattern { - /// - /// Abstract class that provides the formatting functionality that - /// derived classes need. - /// - /// - /// Conversion specifiers in a conversion patterns are parsed to - /// individual PatternConverters. Each of which is responsible for - /// converting a logging event in a converter specific manner. - /// - /// Nicko Cadell - public abstract class PatternLayoutConverter : PatternConverter - { - #region Protected Instance Constructors + /// + /// Abstract class that provides the formatting functionality that + /// derived classes need. + /// + /// + /// Conversion specifiers in a conversion patterns are parsed to + /// individual PatternConverters. Each of which is responsible for + /// converting a logging event in a converter specific manner. + /// + /// Nicko Cadell + public abstract class PatternLayoutConverter : PatternConverter + { + #region Protected Instance Constructors - /// - /// Initializes a new instance of the class. - /// - protected PatternLayoutConverter() - { - } + /// + /// Initializes a new instance of the class. + /// + protected PatternLayoutConverter() + { + } - #endregion Protected Instance Constructors + #endregion Protected Instance Constructors - #region Public Properties + #region Public Properties - /// - /// Flag indicating if this converter handles the logging event exception - /// - /// false if this converter handles the logging event exception - /// - /// - /// If this converter handles the exception object contained within - /// , then this property should be set to - /// false. Otherwise, if the layout ignores the exception - /// object, then the property should be set to true. - /// - /// - /// Set this value to override a this default setting. The default - /// value is true, this converter does not handle the exception. - /// - /// - public virtual bool IgnoresException - { - get { return m_ignoresException; } - set { m_ignoresException = value; } - } + /// + /// Flag indicating if this converter handles the logging event exception + /// + /// false if this converter handles the logging event exception + /// + /// + /// If this converter handles the exception object contained within + /// , then this property should be set to + /// false. Otherwise, if the layout ignores the exception + /// object, then the property should be set to true. + /// + /// + /// Set this value to override a this default setting. The default + /// value is true, this converter does not handle the exception. + /// + /// + public virtual bool IgnoresException + { + get { return m_ignoresException; } + set { m_ignoresException = value; } + } - #endregion Public Properties + #endregion Public Properties - #region Protected Abstract Methods + #region Protected Abstract Methods - /// - /// Derived pattern converters must override this method in order to - /// convert conversion specifiers in the correct way. - /// - /// that will receive the formatted result. - /// The on which the pattern converter should be executed. - protected abstract void Convert(TextWriter writer, LoggingEvent loggingEvent); + /// + /// Derived pattern converters must override this method in order to + /// convert conversion specifiers in the correct way. + /// + /// that will receive the formatted result. + /// The on which the pattern converter should be executed. + protected abstract void Convert(TextWriter writer, LoggingEvent loggingEvent); - #endregion Protected Abstract Methods + #endregion Protected Abstract Methods - #region Protected Methods + #region Protected Methods - /// - /// Derived pattern converters must override this method in order to - /// convert conversion specifiers in the correct way. - /// - /// that will receive the formatted result. - /// The state object on which the pattern converter should be executed. - protected override void Convert(TextWriter writer, object state) - { - LoggingEvent loggingEvent = state as LoggingEvent; - if (loggingEvent != null) - { - Convert(writer, loggingEvent); - } - else - { - throw new ArgumentException("state must be of type ["+typeof(LoggingEvent).FullName+"]", "state"); - } - } + /// + /// Derived pattern converters must override this method in order to + /// convert conversion specifiers in the correct way. + /// + /// that will receive the formatted result. + /// The state object on which the pattern converter should be executed. + protected override void Convert(TextWriter writer, object state) + { + LoggingEvent loggingEvent = state as LoggingEvent; + if (loggingEvent != null) + { + Convert(writer, loggingEvent); + } + else + { + throw new ArgumentException("state must be of type ["+typeof(LoggingEvent).FullName+"]", "state"); + } + } - #endregion Protected Methods + #endregion Protected Methods - /// - /// Flag indicating if this converter handles exceptions - /// - /// - /// false if this converter handles exceptions - /// - private bool m_ignoresException = true; - } + /// + /// Flag indicating if this converter handles exceptions + /// + /// + /// false if this converter handles exceptions + /// + private bool m_ignoresException = true; + } } diff --git a/src/log4net/Layout/Pattern/PropertyPatternConverter.cs b/src/log4net/Layout/Pattern/PropertyPatternConverter.cs index 44a096b9..1857f033 100644 --- a/src/log4net/Layout/Pattern/PropertyPatternConverter.cs +++ b/src/log4net/Layout/Pattern/PropertyPatternConverter.cs @@ -27,51 +27,51 @@ namespace log4net.Layout.Pattern { - /// - /// Property pattern converter - /// - /// - /// - /// Writes out the value of a named property. The property name - /// should be set in the - /// property. - /// - /// - /// If the is set to null - /// then all the properties are written as key value pairs. - /// - /// - /// Nicko Cadell - internal sealed class PropertyPatternConverter : PatternLayoutConverter - { - /// - /// Write the property value to the output - /// - /// that will receive the formatted result. - /// the event being logged - /// - /// - /// Writes out the value of a named property. The property name - /// should be set in the - /// property. - /// - /// - /// If the is set to null - /// then all the properties are written as key value pairs. - /// - /// - protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) - { - if (Option != null) - { - // Write the value for the specified key - WriteObject(writer, loggingEvent.Repository, loggingEvent.LookupProperty(Option)); - } - else - { - // Write all the key value pairs - WriteDictionary(writer, loggingEvent.Repository, loggingEvent.GetProperties()); - } - } - } + /// + /// Property pattern converter + /// + /// + /// + /// Writes out the value of a named property. The property name + /// should be set in the + /// property. + /// + /// + /// If the is set to null + /// then all the properties are written as key value pairs. + /// + /// + /// Nicko Cadell + internal sealed class PropertyPatternConverter : PatternLayoutConverter + { + /// + /// Write the property value to the output + /// + /// that will receive the formatted result. + /// the event being logged + /// + /// + /// Writes out the value of a named property. The property name + /// should be set in the + /// property. + /// + /// + /// If the is set to null + /// then all the properties are written as key value pairs. + /// + /// + protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) + { + if (Option != null) + { + // Write the value for the specified key + WriteObject(writer, loggingEvent.Repository, loggingEvent.LookupProperty(Option)); + } + else + { + // Write all the key value pairs + WriteDictionary(writer, loggingEvent.Repository, loggingEvent.GetProperties()); + } + } + } } diff --git a/src/log4net/Layout/Pattern/RelativeTimePatternConverter.cs b/src/log4net/Layout/Pattern/RelativeTimePatternConverter.cs index 01b9ae2b..70204007 100644 --- a/src/log4net/Layout/Pattern/RelativeTimePatternConverter.cs +++ b/src/log4net/Layout/Pattern/RelativeTimePatternConverter.cs @@ -25,46 +25,46 @@ namespace log4net.Layout.Pattern { - /// - /// Converter to output the relative time of the event - /// - /// - /// - /// Converter to output the time of the event relative to the start of the program. - /// - /// - /// Nicko Cadell - internal sealed class RelativeTimePatternConverter : PatternLayoutConverter - { - /// - /// Write the relative time to the output - /// - /// that will receive the formatted result. - /// the event being logged - /// - /// - /// Writes out the relative time of the event in milliseconds. - /// That is the number of milliseconds between the event - /// and the . - /// - /// - protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) - { - writer.Write( TimeDifferenceInMillis(LoggingEvent.StartTimeUtc, loggingEvent.TimeStampUtc).ToString(System.Globalization.NumberFormatInfo.InvariantInfo) ); - } + /// + /// Converter to output the relative time of the event + /// + /// + /// + /// Converter to output the time of the event relative to the start of the program. + /// + /// + /// Nicko Cadell + internal sealed class RelativeTimePatternConverter : PatternLayoutConverter + { + /// + /// Write the relative time to the output + /// + /// that will receive the formatted result. + /// the event being logged + /// + /// + /// Writes out the relative time of the event in milliseconds. + /// That is the number of milliseconds between the event + /// and the . + /// + /// + protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) + { + writer.Write( TimeDifferenceInMillis(LoggingEvent.StartTimeUtc, loggingEvent.TimeStampUtc).ToString(System.Globalization.NumberFormatInfo.InvariantInfo) ); + } - /// - /// Helper method to get the time difference between two DateTime objects - /// - /// start time (in the current local time zone) - /// end time (in the current local time zone) - /// the time difference in milliseconds - private static long TimeDifferenceInMillis(DateTime start, DateTime end) - { - // We must convert all times to UTC before performing any mathematical - // operations on them. This allows use to take into account discontinuities - // caused by daylight savings time transitions. - return (long)(end.ToUniversalTime() - start.ToUniversalTime()).TotalMilliseconds; - } - } + /// + /// Helper method to get the time difference between two DateTime objects + /// + /// start time (in the current local time zone) + /// end time (in the current local time zone) + /// the time difference in milliseconds + private static long TimeDifferenceInMillis(DateTime start, DateTime end) + { + // We must convert all times to UTC before performing any mathematical + // operations on them. This allows use to take into account discontinuities + // caused by daylight savings time transitions. + return (long)(end.ToUniversalTime() - start.ToUniversalTime()).TotalMilliseconds; + } + } } diff --git a/src/log4net/Layout/Pattern/StackTracePatternConverter.cs b/src/log4net/Layout/Pattern/StackTracePatternConverter.cs index 7773868d..022113cd 100644 --- a/src/log4net/Layout/Pattern/StackTracePatternConverter.cs +++ b/src/log4net/Layout/Pattern/StackTracePatternConverter.cs @@ -25,101 +25,101 @@ namespace log4net.Layout.Pattern { - /// - /// Write the caller stack frames to the output - /// - /// - /// - /// Writes the to the output writer, using format: - /// type3.MethodCall3 > type2.MethodCall2 > type1.MethodCall1 - /// - /// - /// Michael Cromwell - internal class StackTracePatternConverter : PatternLayoutConverter, IOptionHandler - { - private int m_stackFrameLevel = 1; - - /// - /// Initialize the converter - /// - /// - /// - /// This is part of the delayed object - /// activation scheme. The method must - /// be called on this object after the configuration properties have - /// been set. Until is called this - /// object is in an undefined state and must not be used. - /// - /// - /// If any of the configuration properties are modified then - /// must be called again. - /// - /// - public void ActivateOptions() - { - if (Option == null) - return; - - string optStr = Option.Trim(); - if (optStr.Length != 0) - { - int stackLevelVal; - if (SystemInfo.TryParse(optStr, out stackLevelVal)) - { - if (stackLevelVal <= 0) - { - LogLog.Error(declaringType, "StackTracePatternConverter: StackeFrameLevel option (" + optStr + ") isn't a positive integer."); - } - else - { - m_stackFrameLevel = stackLevelVal; - } - } - else - { - LogLog.Error(declaringType, "StackTracePatternConverter: StackFrameLevel option \"" + optStr + "\" not a decimal integer."); - } - } - } - - /// - /// Write the strack frames to the output - /// - /// that will receive the formatted result. - /// the event being logged - /// - /// - /// Writes the to the output writer. - /// - /// - protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) - { - StackFrameItem[] stackframes = loggingEvent.LocationInformation.StackFrames; - if ((stackframes == null) || (stackframes.Length <= 0)) - { - LogLog.Error(declaringType, "loggingEvent.LocationInformation.StackFrames was null or empty."); - return; - } - - int stackFrameIndex = m_stackFrameLevel - 1; - while (stackFrameIndex >= 0) - { - if (stackFrameIndex >= stackframes.Length) - { - stackFrameIndex--; - continue; - } - - StackFrameItem stackFrame = stackframes[stackFrameIndex]; + /// + /// Write the caller stack frames to the output + /// + /// + /// + /// Writes the to the output writer, using format: + /// type3.MethodCall3 > type2.MethodCall2 > type1.MethodCall1 + /// + /// + /// Michael Cromwell + internal class StackTracePatternConverter : PatternLayoutConverter, IOptionHandler + { + private int m_stackFrameLevel = 1; + + /// + /// Initialize the converter + /// + /// + /// + /// This is part of the delayed object + /// activation scheme. The method must + /// be called on this object after the configuration properties have + /// been set. Until is called this + /// object is in an undefined state and must not be used. + /// + /// + /// If any of the configuration properties are modified then + /// must be called again. + /// + /// + public void ActivateOptions() + { + if (Option == null) + return; + + string optStr = Option.Trim(); + if (optStr.Length != 0) + { + int stackLevelVal; + if (SystemInfo.TryParse(optStr, out stackLevelVal)) + { + if (stackLevelVal <= 0) + { + LogLog.Error(declaringType, "StackTracePatternConverter: StackeFrameLevel option (" + optStr + ") isn't a positive integer."); + } + else + { + m_stackFrameLevel = stackLevelVal; + } + } + else + { + LogLog.Error(declaringType, "StackTracePatternConverter: StackFrameLevel option \"" + optStr + "\" not a decimal integer."); + } + } + } + + /// + /// Write the strack frames to the output + /// + /// that will receive the formatted result. + /// the event being logged + /// + /// + /// Writes the to the output writer. + /// + /// + protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) + { + StackFrameItem[] stackframes = loggingEvent.LocationInformation.StackFrames; + if ((stackframes == null) || (stackframes.Length <= 0)) + { + LogLog.Error(declaringType, "loggingEvent.LocationInformation.StackFrames was null or empty."); + return; + } + + int stackFrameIndex = m_stackFrameLevel - 1; + while (stackFrameIndex >= 0) + { + if (stackFrameIndex >= stackframes.Length) + { + stackFrameIndex--; + continue; + } + + StackFrameItem stackFrame = stackframes[stackFrameIndex]; writer.Write("{0}.{1}", stackFrame.ClassName, GetMethodInformation(stackFrame.Method)); - if (stackFrameIndex > 0) - { + if (stackFrameIndex > 0) + { // TODO: make this user settable? - writer.Write(" > "); - } - stackFrameIndex--; - } - } + writer.Write(" > "); + } + stackFrameIndex--; + } + } /// /// Returns the Name of the method @@ -131,19 +131,19 @@ internal virtual string GetMethodInformation(MethodItem method) { return method.Name; } - - #region Private Static Fields + + #region Private Static Fields - /// - /// The fully qualified type of the StackTracePatternConverter class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(StackTracePatternConverter); + /// + /// The fully qualified type of the StackTracePatternConverter class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(StackTracePatternConverter); - #endregion Private Static Fields - } + #endregion Private Static Fields + } } #endif // !NETCF && NET_2_0 diff --git a/src/log4net/Layout/Pattern/ThreadPatternConverter.cs b/src/log4net/Layout/Pattern/ThreadPatternConverter.cs index 122c361e..faae9a95 100644 --- a/src/log4net/Layout/Pattern/ThreadPatternConverter.cs +++ b/src/log4net/Layout/Pattern/ThreadPatternConverter.cs @@ -25,30 +25,30 @@ namespace log4net.Layout.Pattern { - /// - /// Converter to include event thread name - /// - /// - /// - /// Writes the to the output. - /// - /// - /// Nicko Cadell - internal sealed class ThreadPatternConverter : PatternLayoutConverter - { - /// - /// Write the ThreadName to the output - /// - /// that will receive the formatted result. - /// the event being logged - /// - /// - /// Writes the to the . - /// - /// - protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) - { - writer.Write(loggingEvent.ThreadName); - } - } + /// + /// Converter to include event thread name + /// + /// + /// + /// Writes the to the output. + /// + /// + /// Nicko Cadell + internal sealed class ThreadPatternConverter : PatternLayoutConverter + { + /// + /// Write the ThreadName to the output + /// + /// that will receive the formatted result. + /// the event being logged + /// + /// + /// Writes the to the . + /// + /// + protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) + { + writer.Write(loggingEvent.ThreadName); + } + } } diff --git a/src/log4net/Layout/Pattern/TypeNamePatternConverter.cs b/src/log4net/Layout/Pattern/TypeNamePatternConverter.cs index 8b5fce81..faa47d25 100644 --- a/src/log4net/Layout/Pattern/TypeNamePatternConverter.cs +++ b/src/log4net/Layout/Pattern/TypeNamePatternConverter.cs @@ -25,40 +25,40 @@ namespace log4net.Layout.Pattern { - /// - /// Pattern converter for the class name - /// - /// - /// - /// Outputs the of the event. - /// - /// - /// Nicko Cadell - internal sealed class TypeNamePatternConverter : NamedPatternConverter - { - /// - /// Gets the fully qualified name of the class - /// - /// the event being logged - /// The fully qualified type name for the caller location - /// - /// - /// Returns the of the . - /// - /// - protected override string GetFullyQualifiedName(LoggingEvent loggingEvent) - { - if (loggingEvent == null) - { - return string.Empty; - } - - if (loggingEvent.LocationInformation == null) - { - return string.Empty; - } - - return loggingEvent.LocationInformation.ClassName; - } - } + /// + /// Pattern converter for the class name + /// + /// + /// + /// Outputs the of the event. + /// + /// + /// Nicko Cadell + internal sealed class TypeNamePatternConverter : NamedPatternConverter + { + /// + /// Gets the fully qualified name of the class + /// + /// the event being logged + /// The fully qualified type name for the caller location + /// + /// + /// Returns the of the . + /// + /// + protected override string GetFullyQualifiedName(LoggingEvent loggingEvent) + { + if (loggingEvent == null) + { + return string.Empty; + } + + if (loggingEvent.LocationInformation == null) + { + return string.Empty; + } + + return loggingEvent.LocationInformation.ClassName; + } + } } diff --git a/src/log4net/Layout/Pattern/UserNamePatternConverter.cs b/src/log4net/Layout/Pattern/UserNamePatternConverter.cs index 1f64c0cb..932f40de 100644 --- a/src/log4net/Layout/Pattern/UserNamePatternConverter.cs +++ b/src/log4net/Layout/Pattern/UserNamePatternConverter.cs @@ -25,21 +25,21 @@ namespace log4net.Layout.Pattern { - /// - /// Converter to include event user name - /// - /// Douglas de la Torre - /// Nicko Cadell - internal sealed class UserNamePatternConverter : PatternLayoutConverter - { - /// - /// Convert the pattern to the rendered message - /// - /// that will receive the formatted result. - /// the event being logged - protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) - { - writer.Write( loggingEvent.UserName ); - } - } + /// + /// Converter to include event user name + /// + /// Douglas de la Torre + /// Nicko Cadell + internal sealed class UserNamePatternConverter : PatternLayoutConverter + { + /// + /// Convert the pattern to the rendered message + /// + /// that will receive the formatted result. + /// the event being logged + protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) + { + writer.Write( loggingEvent.UserName ); + } + } } diff --git a/src/log4net/Layout/Pattern/UtcDatePatternConverter.cs b/src/log4net/Layout/Pattern/UtcDatePatternConverter.cs index 95227f75..5e6b9126 100644 --- a/src/log4net/Layout/Pattern/UtcDatePatternConverter.cs +++ b/src/log4net/Layout/Pattern/UtcDatePatternConverter.cs @@ -27,65 +27,65 @@ namespace log4net.Layout.Pattern { - /// - /// Write the TimeStamp to the output - /// - /// - /// - /// Date pattern converter, uses a to format - /// the date of a . - /// - /// - /// Uses a to format the - /// in Universal time. - /// - /// - /// See the for details on the date pattern syntax. - /// - /// - /// - /// Nicko Cadell - internal class UtcDatePatternConverter : DatePatternConverter - { - /// - /// Write the TimeStamp to the output - /// - /// that will receive the formatted result. - /// the event being logged - /// - /// - /// Pass the to the - /// for it to render it to the writer. - /// - /// - /// The passed is in the local time zone, this is converted - /// to Universal time before it is rendered. - /// - /// - /// - protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) - { - try - { - m_dateFormatter.FormatDate(loggingEvent.TimeStampUtc, writer); - } - catch (Exception ex) - { - LogLog.Error(declaringType, "Error occurred while converting date.", ex); - } - } + /// + /// Write the TimeStamp to the output + /// + /// + /// + /// Date pattern converter, uses a to format + /// the date of a . + /// + /// + /// Uses a to format the + /// in Universal time. + /// + /// + /// See the for details on the date pattern syntax. + /// + /// + /// + /// Nicko Cadell + internal class UtcDatePatternConverter : DatePatternConverter + { + /// + /// Write the TimeStamp to the output + /// + /// that will receive the formatted result. + /// the event being logged + /// + /// + /// Pass the to the + /// for it to render it to the writer. + /// + /// + /// The passed is in the local time zone, this is converted + /// to Universal time before it is rendered. + /// + /// + /// + protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) + { + try + { + m_dateFormatter.FormatDate(loggingEvent.TimeStampUtc, writer); + } + catch (Exception ex) + { + LogLog.Error(declaringType, "Error occurred while converting date.", ex); + } + } - #region Private Static Fields + #region Private Static Fields - /// - /// The fully qualified type of the UtcDatePatternConverter class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(UtcDatePatternConverter); + /// + /// The fully qualified type of the UtcDatePatternConverter class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(UtcDatePatternConverter); - #endregion Private Static Fields - } + #endregion Private Static Fields + } } diff --git a/src/log4net/Layout/PatternLayout.cs b/src/log4net/Layout/PatternLayout.cs index 49cad595..60a1495b 100644 --- a/src/log4net/Layout/PatternLayout.cs +++ b/src/log4net/Layout/PatternLayout.cs @@ -34,89 +34,89 @@ namespace log4net.Layout { - /// - /// A flexible layout configurable with pattern string. - /// - /// - /// - /// The goal of this class is to a - /// as a string. The results - /// depend on the conversion pattern. - /// - /// - /// The conversion pattern is closely related to the conversion - /// pattern of the printf function in C. A conversion pattern is - /// composed of literal text and format control expressions called - /// conversion specifiers. - /// - /// - /// You are free to insert any literal text within the conversion - /// pattern. - /// - /// - /// Each conversion specifier starts with a percent sign (%) and is - /// followed by optional format modifiers and a conversion - /// pattern name. The conversion pattern name specifies the type of - /// data, e.g. logger, level, date, thread name. The format - /// modifiers control such things as field width, padding, left and - /// right justification. The following is a simple example. - /// - /// - /// Let the conversion pattern be "%-5level [%thread]: %message%newline" and assume - /// that the log4net environment was set to use a PatternLayout. Then the - /// statements - /// - /// - /// ILog log = LogManager.GetLogger(typeof(TestApp)); - /// log.Debug("Message 1"); - /// log.Warn("Message 2"); - /// - /// would yield the output - /// - /// DEBUG [main]: Message 1 - /// WARN [main]: Message 2 - /// - /// - /// Note that there is no explicit separator between text and - /// conversion specifiers. The pattern parser knows when it has reached - /// the end of a conversion specifier when it reads a conversion - /// character. In the example above the conversion specifier - /// %-5level means the level of the logging event should be left - /// justified to a width of five characters. - /// - /// - /// The recognized conversion pattern names are: - /// - /// - /// - /// Conversion Pattern Name - /// Effect - /// - /// - /// a - /// Equivalent to appdomain - /// - /// - /// appdomain - /// - /// Used to output the friendly name of the AppDomain where the - /// logging event was generated. - /// - /// - /// - /// aspnet-cache - /// + /// + /// A flexible layout configurable with pattern string. + /// + /// + /// + /// The goal of this class is to a + /// as a string. The results + /// depend on the conversion pattern. + /// + /// + /// The conversion pattern is closely related to the conversion + /// pattern of the printf function in C. A conversion pattern is + /// composed of literal text and format control expressions called + /// conversion specifiers. + /// + /// + /// You are free to insert any literal text within the conversion + /// pattern. + /// + /// + /// Each conversion specifier starts with a percent sign (%) and is + /// followed by optional format modifiers and a conversion + /// pattern name. The conversion pattern name specifies the type of + /// data, e.g. logger, level, date, thread name. The format + /// modifiers control such things as field width, padding, left and + /// right justification. The following is a simple example. + /// + /// + /// Let the conversion pattern be "%-5level [%thread]: %message%newline" and assume + /// that the log4net environment was set to use a PatternLayout. Then the + /// statements + /// + /// + /// ILog log = LogManager.GetLogger(typeof(TestApp)); + /// log.Debug("Message 1"); + /// log.Warn("Message 2"); + /// + /// would yield the output + /// + /// DEBUG [main]: Message 1 + /// WARN [main]: Message 2 + /// + /// + /// Note that there is no explicit separator between text and + /// conversion specifiers. The pattern parser knows when it has reached + /// the end of a conversion specifier when it reads a conversion + /// character. In the example above the conversion specifier + /// %-5level means the level of the logging event should be left + /// justified to a width of five characters. + /// + /// + /// The recognized conversion pattern names are: + /// + /// + /// + /// Conversion Pattern Name + /// Effect + /// + /// + /// a + /// Equivalent to appdomain + /// + /// + /// appdomain + /// + /// Used to output the friendly name of the AppDomain where the + /// logging event was generated. + /// + /// + /// + /// aspnet-cache + /// /// /// Used to output all cache items in the case of %aspnet-cache or just one named item if used as %aspnet-cache{key} /// /// /// This pattern is not available for Compact Framework or Client Profile assemblies. /// - /// - /// - /// - /// aspnet-context - /// + /// + /// + /// + /// aspnet-context + /// /// /// Used to output all context items in the case of %aspnet-context or just one named item if used as %aspnet-context{key} /// @@ -124,10 +124,10 @@ namespace log4net.Layout /// This pattern is not available for Compact Framework or Client Profile assemblies. /// /// - /// - /// - /// aspnet-request - /// + /// + /// + /// aspnet-request + /// /// /// Used to output all request parameters in the case of %aspnet-request or just one named param if used as %aspnet-request{key} /// @@ -135,10 +135,10 @@ namespace log4net.Layout /// This pattern is not available for Compact Framework or Client Profile assemblies. /// /// - /// - /// - /// aspnet-session - /// + /// + /// + /// aspnet-session + /// /// /// Used to output all session items in the case of %aspnet-session or just one named item if used as %aspnet-session{key} /// @@ -146,990 +146,990 @@ namespace log4net.Layout /// This pattern is not available for Compact Framework or Client Profile assemblies. /// /// - /// - /// - /// c - /// Equivalent to logger - /// - /// - /// C - /// Equivalent to type - /// - /// - /// class - /// Equivalent to type - /// - /// - /// d - /// Equivalent to date - /// - /// - /// date - /// - /// - /// Used to output the date of the logging event in the local time zone. - /// To output the date in universal time use the %utcdate pattern. - /// The date conversion - /// specifier may be followed by a date format specifier enclosed - /// between braces. For example, %date{HH:mm:ss,fff} or - /// %date{dd MMM yyyy HH:mm:ss,fff}. If no date format specifier is - /// given then ISO8601 format is - /// assumed (). - /// - /// - /// The date format specifier admits the same syntax as the - /// time pattern string of the . - /// - /// - /// For better results it is recommended to use the log4net date - /// formatters. These can be specified using one of the strings - /// "ABSOLUTE", "DATE" and "ISO8601" for specifying - /// , - /// and respectively - /// . For example, - /// %date{ISO8601} or %date{ABSOLUTE}. - /// - /// - /// These dedicated date formatters perform significantly - /// better than . - /// - /// - /// - /// - /// exception - /// - /// - /// Used to output the exception passed in with the log message. - /// - /// - /// If an exception object is stored in the logging event - /// it will be rendered into the pattern output with a - /// trailing newline. - /// If there is no exception then nothing will be output - /// and no trailing newline will be appended. - /// It is typical to put a newline before the exception - /// and to have the exception as the last data in the pattern. - /// - /// - /// - /// - /// F - /// Equivalent to file - /// - /// - /// file - /// - /// - /// Used to output the file name where the logging request was - /// issued. - /// - /// - /// WARNING Generating caller location information is - /// extremely slow. Its use should be avoided unless execution speed - /// is not an issue. - /// - /// - /// See the note below on the availability of caller location information. - /// - /// - /// - /// - /// identity - /// - /// - /// Used to output the user name for the currently active user - /// (Principal.Identity.Name). - /// - /// - /// WARNING Generating caller information is - /// extremely slow. Its use should be avoided unless execution speed - /// is not an issue. - /// - /// - /// - /// - /// l - /// Equivalent to location - /// - /// - /// L - /// Equivalent to line - /// - /// - /// location - /// - /// - /// Used to output location information of the caller which generated - /// the logging event. - /// - /// - /// The location information depends on the CLI implementation but - /// usually consists of the fully qualified name of the calling - /// method followed by the callers source the file name and line - /// number between parentheses. - /// - /// - /// The location information can be very useful. However, its - /// generation is extremely slow. Its use should be avoided - /// unless execution speed is not an issue. - /// - /// - /// See the note below on the availability of caller location information. - /// - /// - /// - /// - /// level - /// - /// - /// Used to output the level of the logging event. - /// - /// - /// - /// - /// line - /// - /// - /// Used to output the line number from where the logging request - /// was issued. - /// - /// - /// WARNING Generating caller location information is - /// extremely slow. Its use should be avoided unless execution speed - /// is not an issue. - /// - /// - /// See the note below on the availability of caller location information. - /// - /// - /// - /// - /// logger - /// - /// - /// Used to output the logger of the logging event. The - /// logger conversion specifier can be optionally followed by - /// precision specifier, that is a decimal constant in - /// brackets. - /// - /// - /// If a precision specifier is given, then only the corresponding - /// number of right most components of the logger name will be - /// printed. By default the logger name is printed in full. - /// - /// - /// For example, for the logger name "a.b.c" the pattern - /// %logger{2} will output "b.c". - /// - /// - /// - /// - /// m - /// Equivalent to message - /// - /// - /// M - /// Equivalent to method - /// - /// - /// message - /// - /// - /// Used to output the application supplied message associated with - /// the logging event. - /// - /// - /// - /// - /// mdc - /// - /// - /// 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 property. - /// - /// - /// - /// - /// method - /// - /// - /// Used to output the method name where the logging request was - /// issued. - /// - /// - /// WARNING Generating caller location information is - /// extremely slow. Its use should be avoided unless execution speed - /// is not an issue. - /// - /// - /// See the note below on the availability of caller location information. - /// - /// - /// - /// - /// n - /// Equivalent to newline - /// - /// - /// newline - /// - /// - /// Outputs the platform dependent line separator character or - /// characters. - /// - /// - /// This conversion pattern offers the same performance as using - /// non-portable line separator strings such as "\n", or "\r\n". - /// Thus, it is the preferred way of specifying a line separator. - /// - /// - /// - /// - /// ndc - /// - /// - /// Used to output the NDC (nested diagnostic context) associated - /// with the thread that generated the logging event. - /// - /// - /// - /// - /// p - /// Equivalent to level - /// - /// - /// P - /// Equivalent to property - /// - /// - /// properties - /// Equivalent to property - /// - /// - /// property - /// - /// - /// Used to output the an event specific property. The key to - /// lookup must be specified within braces and directly following the - /// pattern specifier, e.g. %property{user} 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 - /// the log4net:HostName property is set to the name of machine on - /// which the event was originally logged. - /// - /// - /// If no key is specified, e.g. %property then all the keys and their - /// values are printed in a comma separated list. - /// - /// - /// 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. - /// - /// - /// - /// the event properties - /// - /// The event has that can be set. These - /// properties are specific to this event only. - /// - /// - /// - /// the thread properties - /// - /// The that are set on the current - /// thread. These properties are shared by all events logged on this thread. - /// - /// - /// - /// the global properties - /// - /// The that are set globally. These - /// properties are shared by all the threads in the AppDomain. - /// - /// - /// - /// - /// - /// - /// - /// r - /// Equivalent to timestamp - /// - /// - /// stacktrace - /// - /// - /// Used to output the stack trace of the logging event - /// The stack trace level specifier may be enclosed - /// between braces. For example, %stacktrace{level}. - /// If no stack trace level specifier is given then 1 is assumed - /// - /// - /// Output uses the format: - /// type3.MethodCall3 > type2.MethodCall2 > type1.MethodCall1 - /// + /// + /// + /// c + /// Equivalent to logger + /// + /// + /// C + /// Equivalent to type + /// + /// + /// class + /// Equivalent to type + /// + /// + /// d + /// Equivalent to date + /// + /// + /// date + /// + /// + /// Used to output the date of the logging event in the local time zone. + /// To output the date in universal time use the %utcdate pattern. + /// The date conversion + /// specifier may be followed by a date format specifier enclosed + /// between braces. For example, %date{HH:mm:ss,fff} or + /// %date{dd MMM yyyy HH:mm:ss,fff}. If no date format specifier is + /// given then ISO8601 format is + /// assumed (). + /// + /// + /// The date format specifier admits the same syntax as the + /// time pattern string of the . + /// + /// + /// For better results it is recommended to use the log4net date + /// formatters. These can be specified using one of the strings + /// "ABSOLUTE", "DATE" and "ISO8601" for specifying + /// , + /// and respectively + /// . For example, + /// %date{ISO8601} or %date{ABSOLUTE}. + /// + /// + /// These dedicated date formatters perform significantly + /// better than . + /// + /// + /// + /// + /// exception + /// + /// + /// Used to output the exception passed in with the log message. + /// + /// + /// If an exception object is stored in the logging event + /// it will be rendered into the pattern output with a + /// trailing newline. + /// If there is no exception then nothing will be output + /// and no trailing newline will be appended. + /// It is typical to put a newline before the exception + /// and to have the exception as the last data in the pattern. + /// + /// + /// + /// + /// F + /// Equivalent to file + /// + /// + /// file + /// + /// + /// Used to output the file name where the logging request was + /// issued. + /// + /// + /// WARNING Generating caller location information is + /// extremely slow. Its use should be avoided unless execution speed + /// is not an issue. + /// + /// + /// See the note below on the availability of caller location information. + /// + /// + /// + /// + /// identity + /// + /// + /// Used to output the user name for the currently active user + /// (Principal.Identity.Name). + /// + /// + /// WARNING Generating caller information is + /// extremely slow. Its use should be avoided unless execution speed + /// is not an issue. + /// + /// + /// + /// + /// l + /// Equivalent to location + /// + /// + /// L + /// Equivalent to line + /// + /// + /// location + /// + /// + /// Used to output location information of the caller which generated + /// the logging event. + /// + /// + /// The location information depends on the CLI implementation but + /// usually consists of the fully qualified name of the calling + /// method followed by the callers source the file name and line + /// number between parentheses. + /// + /// + /// The location information can be very useful. However, its + /// generation is extremely slow. Its use should be avoided + /// unless execution speed is not an issue. + /// + /// + /// See the note below on the availability of caller location information. + /// + /// + /// + /// + /// level + /// + /// + /// Used to output the level of the logging event. + /// + /// + /// + /// + /// line + /// + /// + /// Used to output the line number from where the logging request + /// was issued. + /// + /// + /// WARNING Generating caller location information is + /// extremely slow. Its use should be avoided unless execution speed + /// is not an issue. + /// + /// + /// See the note below on the availability of caller location information. + /// + /// + /// + /// + /// logger + /// + /// + /// Used to output the logger of the logging event. The + /// logger conversion specifier can be optionally followed by + /// precision specifier, that is a decimal constant in + /// brackets. + /// + /// + /// If a precision specifier is given, then only the corresponding + /// number of right most components of the logger name will be + /// printed. By default the logger name is printed in full. + /// + /// + /// For example, for the logger name "a.b.c" the pattern + /// %logger{2} will output "b.c". + /// + /// + /// + /// + /// m + /// Equivalent to message + /// + /// + /// M + /// Equivalent to method + /// + /// + /// message + /// + /// + /// Used to output the application supplied message associated with + /// the logging event. + /// + /// + /// + /// + /// mdc + /// + /// + /// 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 property. + /// + /// + /// + /// + /// method + /// + /// + /// Used to output the method name where the logging request was + /// issued. + /// + /// + /// WARNING Generating caller location information is + /// extremely slow. Its use should be avoided unless execution speed + /// is not an issue. + /// + /// + /// See the note below on the availability of caller location information. + /// + /// + /// + /// + /// n + /// Equivalent to newline + /// + /// + /// newline + /// + /// + /// Outputs the platform dependent line separator character or + /// characters. + /// + /// + /// This conversion pattern offers the same performance as using + /// non-portable line separator strings such as "\n", or "\r\n". + /// Thus, it is the preferred way of specifying a line separator. + /// + /// + /// + /// + /// ndc + /// + /// + /// Used to output the NDC (nested diagnostic context) associated + /// with the thread that generated the logging event. + /// + /// + /// + /// + /// p + /// Equivalent to level + /// + /// + /// P + /// Equivalent to property + /// + /// + /// properties + /// Equivalent to property + /// + /// + /// property + /// + /// + /// Used to output the an event specific property. The key to + /// lookup must be specified within braces and directly following the + /// pattern specifier, e.g. %property{user} 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 + /// the log4net:HostName property is set to the name of machine on + /// which the event was originally logged. + /// + /// + /// If no key is specified, e.g. %property then all the keys and their + /// values are printed in a comma separated list. + /// + /// + /// 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. + /// + /// + /// + /// the event properties + /// + /// The event has that can be set. These + /// properties are specific to this event only. + /// + /// + /// + /// the thread properties + /// + /// The that are set on the current + /// thread. These properties are shared by all events logged on this thread. + /// + /// + /// + /// the global properties + /// + /// The that are set globally. These + /// properties are shared by all the threads in the AppDomain. + /// + /// + /// + /// + /// + /// + /// + /// r + /// Equivalent to timestamp + /// + /// + /// stacktrace + /// + /// + /// Used to output the stack trace of the logging event + /// The stack trace level specifier may be enclosed + /// between braces. For example, %stacktrace{level}. + /// If no stack trace level specifier is given then 1 is assumed + /// + /// + /// Output uses the format: + /// type3.MethodCall3 > type2.MethodCall2 > type1.MethodCall1 + /// /// /// This pattern is not available for Compact Framework assemblies. /// - /// - /// - /// - /// stacktracedetail - /// - /// - /// Used to output the stack trace of the logging event - /// The stack trace level specifier may be enclosed - /// between braces. For example, %stacktracedetail{level}. - /// If no stack trace level specifier is given then 1 is assumed - /// - /// - /// Output uses the format: + /// + /// + /// + /// stacktracedetail + /// + /// + /// Used to output the stack trace of the logging event + /// The stack trace level specifier may be enclosed + /// between braces. For example, %stacktracedetail{level}. + /// If no stack trace level specifier is given then 1 is assumed + /// + /// + /// Output uses the format: /// type3.MethodCall3(type param,...) > type2.MethodCall2(type param,...) > type1.MethodCall1(type param,...) - /// + /// /// /// This pattern is not available for Compact Framework assemblies. /// - /// - /// + /// + /// /// - /// t - /// Equivalent to thread - /// - /// - /// timestamp - /// - /// - /// Used to output the number of milliseconds elapsed since the start - /// of the application until the creation of the logging event. - /// - /// - /// - /// - /// thread - /// - /// - /// Used to output the name of the thread that generated the - /// logging event. Uses the thread number if no name is available. - /// - /// - /// - /// - /// type - /// - /// - /// Used to output the fully qualified type name of the caller - /// issuing the logging request. This conversion specifier - /// can be optionally followed by precision specifier, that - /// is a decimal constant in brackets. - /// - /// - /// If a precision specifier is given, then only the corresponding - /// number of right most components of the class name will be - /// printed. By default the class name is output in fully qualified form. - /// - /// - /// For example, for the class name "log4net.Layout.PatternLayout", the - /// pattern %type{1} will output "PatternLayout". - /// - /// - /// WARNING Generating the caller class information is - /// slow. Thus, its use should be avoided unless execution speed is - /// not an issue. - /// - /// - /// See the note below on the availability of caller location information. - /// - /// - /// - /// - /// u - /// Equivalent to identity - /// - /// - /// username - /// - /// - /// Used to output the WindowsIdentity for the currently - /// active user. - /// - /// - /// WARNING Generating caller WindowsIdentity information is - /// extremely slow. Its use should be avoided unless execution speed - /// is not an issue. - /// - /// - /// - /// - /// utcdate - /// - /// - /// Used to output the date of the logging event in universal time. - /// The date conversion - /// specifier may be followed by a date format specifier enclosed - /// between braces. For example, %utcdate{HH:mm:ss,fff} or - /// %utcdate{dd MMM yyyy HH:mm:ss,fff}. If no date format specifier is - /// given then ISO8601 format is - /// assumed (). - /// - /// - /// The date format specifier admits the same syntax as the - /// time pattern string of the . - /// - /// - /// For better results it is recommended to use the log4net date - /// formatters. These can be specified using one of the strings - /// "ABSOLUTE", "DATE" and "ISO8601" for specifying - /// , - /// and respectively - /// . For example, - /// %utcdate{ISO8601} or %utcdate{ABSOLUTE}. - /// - /// - /// These dedicated date formatters perform significantly - /// better than . - /// - /// - /// - /// - /// w - /// Equivalent to username - /// - /// - /// x - /// Equivalent to ndc - /// - /// - /// X - /// Equivalent to mdc - /// - /// - /// % - /// - /// - /// The sequence %% outputs a single percent sign. - /// - /// - /// - /// - /// - /// The single letter patterns are deprecated in favor of the - /// longer more descriptive pattern names. - /// - /// - /// By default the relevant information is output as is. However, - /// with the aid of format modifiers it is possible to change the - /// minimum field width, the maximum field width and justification. - /// - /// - /// The optional format modifier is placed between the percent sign - /// and the conversion pattern name. - /// - /// - /// The first optional format modifier is the left justification - /// flag which is just the minus (-) character. Then comes the - /// optional minimum field width modifier. This is a decimal - /// constant that represents the minimum number of characters to - /// output. If the data item requires fewer characters, it is padded on - /// either the left or the right until the minimum width is - /// reached. The default is to pad on the left (right justify) but you - /// can specify right padding with the left justification flag. The - /// padding character is space. If the data item is larger than the - /// minimum field width, the field is expanded to accommodate the - /// data. The value is never truncated. - /// - /// - /// This behavior can be changed using the maximum field - /// width modifier which is designated by a period followed by a - /// decimal constant. If the data item is longer than the maximum - /// field, then the extra characters are removed from the - /// beginning of the data item and not from the end. For - /// example, it the maximum field width is eight and the data item is - /// ten characters long, then the first two characters of the data item - /// are dropped. This behavior deviates from the printf function in C - /// where truncation is done from the end. - /// - /// - /// Below are various format modifier examples for the logger - /// conversion specifier. - /// - ///
- /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - ///
Format modifierleft justifyminimum widthmaximum widthcomment
%20loggerfalse20none - /// - /// Left pad with spaces if the logger name is less than 20 - /// characters long. - /// - ///
%-20loggertrue20none - /// - /// Right pad with spaces if the logger - /// name is less than 20 characters long. - /// - ///
%.30loggerNAnone30 - /// - /// Truncate from the beginning if the logger - /// name is longer than 30 characters. - /// - ///
%20.30loggerfalse2030 - /// - /// Left pad with spaces if the logger name is shorter than 20 - /// characters. However, if logger name is longer than 30 characters, - /// then truncate from the beginning. - /// - ///
%-20.30loggertrue2030 - /// - /// Right pad with spaces if the logger name is shorter than 20 - /// characters. However, if logger name is longer than 30 characters, - /// then truncate from the beginning. - /// - ///
- ///
- /// - /// Note about caller location information.
- /// The following patterns %type %file %line %method %location %class %C %F %L %l %M - /// all generate caller location information. - /// Location information uses the System.Diagnostics.StackTrace class to generate - /// a call stack. The caller's information is then extracted from this stack. - ///
- /// - /// - /// The System.Diagnostics.StackTrace class is not supported on the - /// .NET Compact Framework 1.0 therefore caller location information is not - /// available on that framework. - /// - /// - /// - /// - /// The System.Diagnostics.StackTrace class has this to say about Release builds: - /// - /// - /// "StackTrace information will be most informative with Debug build configurations. - /// By default, Debug builds include debug symbols, while Release builds do not. The - /// debug symbols contain most of the file, method name, line number, and column - /// information used in constructing StackFrame and StackTrace objects. StackTrace - /// might not report as many method calls as expected, due to code transformations - /// that occur during optimization." - /// - /// - /// This means that in a Release build the caller information may be incomplete or may - /// not exist at all! Therefore caller location information cannot be relied upon in a Release build. - /// - /// - /// - /// Additional pattern converters may be registered with a specific - /// instance using the method. - /// - ///
- /// - /// This is a more detailed pattern. - /// %timestamp [%thread] %level %logger %ndc - %message%newline - /// - /// - /// A similar pattern except that the relative time is - /// right padded if less than 6 digits, thread name is right padded if - /// less than 15 characters and truncated if longer and the logger - /// name is left padded if shorter than 30 characters and truncated if - /// longer. - /// %-6timestamp [%15.15thread] %-5level %30.30logger %ndc - %message%newline - /// - /// Nicko Cadell - /// Gert Driesen - /// Douglas de la Torre - /// Daniel Cazzulino - public class PatternLayout : LayoutSkeleton - { - #region Constants + /// t + /// Equivalent to thread + /// + /// + /// timestamp + /// + /// + /// Used to output the number of milliseconds elapsed since the start + /// of the application until the creation of the logging event. + /// + /// + /// + /// + /// thread + /// + /// + /// Used to output the name of the thread that generated the + /// logging event. Uses the thread number if no name is available. + /// + /// + /// + /// + /// type + /// + /// + /// Used to output the fully qualified type name of the caller + /// issuing the logging request. This conversion specifier + /// can be optionally followed by precision specifier, that + /// is a decimal constant in brackets. + /// + /// + /// If a precision specifier is given, then only the corresponding + /// number of right most components of the class name will be + /// printed. By default the class name is output in fully qualified form. + /// + /// + /// For example, for the class name "log4net.Layout.PatternLayout", the + /// pattern %type{1} will output "PatternLayout". + /// + /// + /// WARNING Generating the caller class information is + /// slow. Thus, its use should be avoided unless execution speed is + /// not an issue. + /// + /// + /// See the note below on the availability of caller location information. + /// + /// + /// + /// + /// u + /// Equivalent to identity + /// + /// + /// username + /// + /// + /// Used to output the WindowsIdentity for the currently + /// active user. + /// + /// + /// WARNING Generating caller WindowsIdentity information is + /// extremely slow. Its use should be avoided unless execution speed + /// is not an issue. + /// + /// + /// + /// + /// utcdate + /// + /// + /// Used to output the date of the logging event in universal time. + /// The date conversion + /// specifier may be followed by a date format specifier enclosed + /// between braces. For example, %utcdate{HH:mm:ss,fff} or + /// %utcdate{dd MMM yyyy HH:mm:ss,fff}. If no date format specifier is + /// given then ISO8601 format is + /// assumed (). + /// + /// + /// The date format specifier admits the same syntax as the + /// time pattern string of the . + /// + /// + /// For better results it is recommended to use the log4net date + /// formatters. These can be specified using one of the strings + /// "ABSOLUTE", "DATE" and "ISO8601" for specifying + /// , + /// and respectively + /// . For example, + /// %utcdate{ISO8601} or %utcdate{ABSOLUTE}. + /// + /// + /// These dedicated date formatters perform significantly + /// better than . + /// + /// + /// + /// + /// w + /// Equivalent to username + /// + /// + /// x + /// Equivalent to ndc + /// + /// + /// X + /// Equivalent to mdc + /// + /// + /// % + /// + /// + /// The sequence %% outputs a single percent sign. + /// + /// + /// + /// + /// + /// The single letter patterns are deprecated in favor of the + /// longer more descriptive pattern names. + /// + /// + /// By default the relevant information is output as is. However, + /// with the aid of format modifiers it is possible to change the + /// minimum field width, the maximum field width and justification. + /// + /// + /// The optional format modifier is placed between the percent sign + /// and the conversion pattern name. + /// + /// + /// The first optional format modifier is the left justification + /// flag which is just the minus (-) character. Then comes the + /// optional minimum field width modifier. This is a decimal + /// constant that represents the minimum number of characters to + /// output. If the data item requires fewer characters, it is padded on + /// either the left or the right until the minimum width is + /// reached. The default is to pad on the left (right justify) but you + /// can specify right padding with the left justification flag. The + /// padding character is space. If the data item is larger than the + /// minimum field width, the field is expanded to accommodate the + /// data. The value is never truncated. + /// + /// + /// This behavior can be changed using the maximum field + /// width modifier which is designated by a period followed by a + /// decimal constant. If the data item is longer than the maximum + /// field, then the extra characters are removed from the + /// beginning of the data item and not from the end. For + /// example, it the maximum field width is eight and the data item is + /// ten characters long, then the first two characters of the data item + /// are dropped. This behavior deviates from the printf function in C + /// where truncation is done from the end. + /// + /// + /// Below are various format modifier examples for the logger + /// conversion specifier. + /// + ///
+ /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///
Format modifierleft justifyminimum widthmaximum widthcomment
%20loggerfalse20none + /// + /// Left pad with spaces if the logger name is less than 20 + /// characters long. + /// + ///
%-20loggertrue20none + /// + /// Right pad with spaces if the logger + /// name is less than 20 characters long. + /// + ///
%.30loggerNAnone30 + /// + /// Truncate from the beginning if the logger + /// name is longer than 30 characters. + /// + ///
%20.30loggerfalse2030 + /// + /// Left pad with spaces if the logger name is shorter than 20 + /// characters. However, if logger name is longer than 30 characters, + /// then truncate from the beginning. + /// + ///
%-20.30loggertrue2030 + /// + /// Right pad with spaces if the logger name is shorter than 20 + /// characters. However, if logger name is longer than 30 characters, + /// then truncate from the beginning. + /// + ///
+ ///
+ /// + /// Note about caller location information.
+ /// The following patterns %type %file %line %method %location %class %C %F %L %l %M + /// all generate caller location information. + /// Location information uses the System.Diagnostics.StackTrace class to generate + /// a call stack. The caller's information is then extracted from this stack. + ///
+ /// + /// + /// The System.Diagnostics.StackTrace class is not supported on the + /// .NET Compact Framework 1.0 therefore caller location information is not + /// available on that framework. + /// + /// + /// + /// + /// The System.Diagnostics.StackTrace class has this to say about Release builds: + /// + /// + /// "StackTrace information will be most informative with Debug build configurations. + /// By default, Debug builds include debug symbols, while Release builds do not. The + /// debug symbols contain most of the file, method name, line number, and column + /// information used in constructing StackFrame and StackTrace objects. StackTrace + /// might not report as many method calls as expected, due to code transformations + /// that occur during optimization." + /// + /// + /// This means that in a Release build the caller information may be incomplete or may + /// not exist at all! Therefore caller location information cannot be relied upon in a Release build. + /// + /// + /// + /// Additional pattern converters may be registered with a specific + /// instance using the method. + /// + /// + /// + /// This is a more detailed pattern. + /// %timestamp [%thread] %level %logger %ndc - %message%newline + /// + /// + /// A similar pattern except that the relative time is + /// right padded if less than 6 digits, thread name is right padded if + /// less than 15 characters and truncated if longer and the logger + /// name is left padded if shorter than 30 characters and truncated if + /// longer. + /// %-6timestamp [%15.15thread] %-5level %30.30logger %ndc - %message%newline + /// + /// Nicko Cadell + /// Gert Driesen + /// Douglas de la Torre + /// Daniel Cazzulino + public class PatternLayout : LayoutSkeleton + { + #region Constants - /// - /// Default pattern string for log output. - /// - /// - /// - /// Default pattern string for log output. - /// Currently set to the string "%message%newline" - /// which just prints the application supplied message. - /// - /// - public const string DefaultConversionPattern ="%message%newline"; + /// + /// Default pattern string for log output. + /// + /// + /// + /// Default pattern string for log output. + /// Currently set to the string "%message%newline" + /// which just prints the application supplied message. + /// + /// + public const string DefaultConversionPattern ="%message%newline"; - /// - /// A detailed conversion pattern - /// - /// - /// - /// A conversion pattern which includes Time, Thread, Logger, and Nested Context. - /// Current value is %timestamp [%thread] %level %logger %ndc - %message%newline. - /// - /// - public const string DetailConversionPattern = "%timestamp [%thread] %level %logger %ndc - %message%newline"; + /// + /// A detailed conversion pattern + /// + /// + /// + /// A conversion pattern which includes Time, Thread, Logger, and Nested Context. + /// Current value is %timestamp [%thread] %level %logger %ndc - %message%newline. + /// + /// + public const string DetailConversionPattern = "%timestamp [%thread] %level %logger %ndc - %message%newline"; - #endregion + #endregion - #region Static Fields + #region Static Fields - /// - /// Internal map of converter identifiers to converter types. - /// - /// - /// - /// This static map is overridden by the m_converterRegistry instance map - /// - /// - private static Hashtable s_globalRulesRegistry; + /// + /// Internal map of converter identifiers to converter types. + /// + /// + /// + /// This static map is overridden by the m_converterRegistry instance map + /// + /// + private static Hashtable s_globalRulesRegistry; - #endregion Static Fields + #endregion Static Fields - #region Member Variables + #region Member Variables - /// - /// the pattern - /// - private string m_pattern; + /// + /// the pattern + /// + private string m_pattern; - /// - /// the head of the pattern converter chain - /// - private PatternConverter m_head; + /// + /// the head of the pattern converter chain + /// + private PatternConverter m_head; - /// - /// patterns defined on this PatternLayout only - /// - private Hashtable m_instanceRulesRegistry = new Hashtable(); + /// + /// patterns defined on this PatternLayout only + /// + private Hashtable m_instanceRulesRegistry = new Hashtable(); - #endregion + #endregion - #region Static Constructor + #region Static Constructor - /// - /// Initialize the global registry - /// - /// - /// - /// Defines the builtin global rules. - /// - /// - static PatternLayout() - { - s_globalRulesRegistry = new Hashtable(45); + /// + /// Initialize the global registry + /// + /// + /// + /// Defines the builtin global rules. + /// + /// + static PatternLayout() + { + s_globalRulesRegistry = new Hashtable(45); - s_globalRulesRegistry.Add("literal", typeof(LiteralPatternConverter)); - s_globalRulesRegistry.Add("newline", typeof(NewLinePatternConverter)); - s_globalRulesRegistry.Add("n", typeof(NewLinePatternConverter)); + s_globalRulesRegistry.Add("literal", typeof(LiteralPatternConverter)); + s_globalRulesRegistry.Add("newline", typeof(NewLinePatternConverter)); + s_globalRulesRegistry.Add("n", typeof(NewLinePatternConverter)); // .NET Compact Framework 1.0 has no support for ASP.NET // SSCLI 1.0 has no support for ASP.NET #if !NETCF && !SSCLI && !CLIENT_PROFILE && !NETSTANDARD - s_globalRulesRegistry.Add("aspnet-cache", typeof(AspNetCachePatternConverter)); - s_globalRulesRegistry.Add("aspnet-context", typeof(AspNetContextPatternConverter)); - s_globalRulesRegistry.Add("aspnet-request", typeof(AspNetRequestPatternConverter)); - s_globalRulesRegistry.Add("aspnet-session", typeof(AspNetSessionPatternConverter)); + s_globalRulesRegistry.Add("aspnet-cache", typeof(AspNetCachePatternConverter)); + s_globalRulesRegistry.Add("aspnet-context", typeof(AspNetContextPatternConverter)); + s_globalRulesRegistry.Add("aspnet-request", typeof(AspNetRequestPatternConverter)); + s_globalRulesRegistry.Add("aspnet-session", typeof(AspNetSessionPatternConverter)); #endif - s_globalRulesRegistry.Add("c", typeof(LoggerPatternConverter)); - s_globalRulesRegistry.Add("logger", typeof(LoggerPatternConverter)); + s_globalRulesRegistry.Add("c", typeof(LoggerPatternConverter)); + s_globalRulesRegistry.Add("logger", typeof(LoggerPatternConverter)); - s_globalRulesRegistry.Add("C", typeof(TypeNamePatternConverter)); - s_globalRulesRegistry.Add("class", typeof(TypeNamePatternConverter)); - s_globalRulesRegistry.Add("type", typeof(TypeNamePatternConverter)); + s_globalRulesRegistry.Add("C", typeof(TypeNamePatternConverter)); + s_globalRulesRegistry.Add("class", typeof(TypeNamePatternConverter)); + s_globalRulesRegistry.Add("type", typeof(TypeNamePatternConverter)); - s_globalRulesRegistry.Add("d", typeof(DatePatternConverter)); - s_globalRulesRegistry.Add("date", typeof(DatePatternConverter)); + s_globalRulesRegistry.Add("d", typeof(DatePatternConverter)); + s_globalRulesRegistry.Add("date", typeof(DatePatternConverter)); - s_globalRulesRegistry.Add("exception", typeof(ExceptionPatternConverter)); + s_globalRulesRegistry.Add("exception", typeof(ExceptionPatternConverter)); - s_globalRulesRegistry.Add("F", typeof(FileLocationPatternConverter)); - s_globalRulesRegistry.Add("file", typeof(FileLocationPatternConverter)); + s_globalRulesRegistry.Add("F", typeof(FileLocationPatternConverter)); + s_globalRulesRegistry.Add("file", typeof(FileLocationPatternConverter)); - s_globalRulesRegistry.Add("l", typeof(FullLocationPatternConverter)); - s_globalRulesRegistry.Add("location", typeof(FullLocationPatternConverter)); + s_globalRulesRegistry.Add("l", typeof(FullLocationPatternConverter)); + s_globalRulesRegistry.Add("location", typeof(FullLocationPatternConverter)); - s_globalRulesRegistry.Add("L", typeof(LineLocationPatternConverter)); - s_globalRulesRegistry.Add("line", typeof(LineLocationPatternConverter)); + s_globalRulesRegistry.Add("L", typeof(LineLocationPatternConverter)); + s_globalRulesRegistry.Add("line", typeof(LineLocationPatternConverter)); - s_globalRulesRegistry.Add("m", typeof(MessagePatternConverter)); - s_globalRulesRegistry.Add("message", typeof(MessagePatternConverter)); + s_globalRulesRegistry.Add("m", typeof(MessagePatternConverter)); + s_globalRulesRegistry.Add("message", typeof(MessagePatternConverter)); - s_globalRulesRegistry.Add("M", typeof(MethodLocationPatternConverter)); - s_globalRulesRegistry.Add("method", typeof(MethodLocationPatternConverter)); + s_globalRulesRegistry.Add("M", typeof(MethodLocationPatternConverter)); + s_globalRulesRegistry.Add("method", typeof(MethodLocationPatternConverter)); - s_globalRulesRegistry.Add("p", typeof(LevelPatternConverter)); - s_globalRulesRegistry.Add("level", typeof(LevelPatternConverter)); + s_globalRulesRegistry.Add("p", typeof(LevelPatternConverter)); + s_globalRulesRegistry.Add("level", typeof(LevelPatternConverter)); - s_globalRulesRegistry.Add("P", typeof(PropertyPatternConverter)); - s_globalRulesRegistry.Add("property", typeof(PropertyPatternConverter)); - s_globalRulesRegistry.Add("properties", typeof(PropertyPatternConverter)); + 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)); - + s_globalRulesRegistry.Add("r", typeof(RelativeTimePatternConverter)); + s_globalRulesRegistry.Add("timestamp", typeof(RelativeTimePatternConverter)); + #if !NETCF && !NETSTANDARD1_3 - s_globalRulesRegistry.Add("stacktrace", typeof(StackTracePatternConverter)); + s_globalRulesRegistry.Add("stacktrace", typeof(StackTracePatternConverter)); s_globalRulesRegistry.Add("stacktracedetail", typeof(StackTraceDetailPatternConverter)); #endif - s_globalRulesRegistry.Add("t", typeof(ThreadPatternConverter)); - s_globalRulesRegistry.Add("thread", typeof(ThreadPatternConverter)); + s_globalRulesRegistry.Add("t", typeof(ThreadPatternConverter)); + s_globalRulesRegistry.Add("thread", typeof(ThreadPatternConverter)); - // For backwards compatibility the NDC patterns - s_globalRulesRegistry.Add("x", typeof(NdcPatternConverter)); - s_globalRulesRegistry.Add("ndc", typeof(NdcPatternConverter)); + // For backwards compatibility the NDC patterns + s_globalRulesRegistry.Add("x", typeof(NdcPatternConverter)); + s_globalRulesRegistry.Add("ndc", typeof(NdcPatternConverter)); - // For backwards compatibility the MDC patterns just do a property lookup - s_globalRulesRegistry.Add("X", typeof(PropertyPatternConverter)); - s_globalRulesRegistry.Add("mdc", typeof(PropertyPatternConverter)); + // For backwards compatibility the MDC patterns 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)); + s_globalRulesRegistry.Add("a", typeof(AppDomainPatternConverter)); + s_globalRulesRegistry.Add("appdomain", typeof(AppDomainPatternConverter)); - s_globalRulesRegistry.Add("u", typeof(IdentityPatternConverter)); - s_globalRulesRegistry.Add("identity", typeof(IdentityPatternConverter)); + s_globalRulesRegistry.Add("u", typeof(IdentityPatternConverter)); + s_globalRulesRegistry.Add("identity", typeof(IdentityPatternConverter)); - s_globalRulesRegistry.Add("utcdate", typeof(UtcDatePatternConverter)); - s_globalRulesRegistry.Add("utcDate", typeof(UtcDatePatternConverter)); - s_globalRulesRegistry.Add("UtcDate", typeof(UtcDatePatternConverter)); + s_globalRulesRegistry.Add("utcdate", typeof(UtcDatePatternConverter)); + s_globalRulesRegistry.Add("utcDate", typeof(UtcDatePatternConverter)); + s_globalRulesRegistry.Add("UtcDate", typeof(UtcDatePatternConverter)); - s_globalRulesRegistry.Add("w", typeof(UserNamePatternConverter)); - s_globalRulesRegistry.Add("username", typeof(UserNamePatternConverter)); - } + s_globalRulesRegistry.Add("w", typeof(UserNamePatternConverter)); + s_globalRulesRegistry.Add("username", typeof(UserNamePatternConverter)); + } - #endregion Static Constructor + #endregion Static Constructor - #region Constructors + #region Constructors - /// - /// Constructs a PatternLayout using the DefaultConversionPattern - /// - /// - /// - /// The default pattern just produces the application supplied message. - /// - /// - /// Note to Inheritors: This constructor calls the virtual method - /// . If you override this method be - /// aware that it will be called before your is called constructor. - /// - /// - /// As per the contract the - /// method must be called after the properties on this object have been - /// configured. - /// - /// - public PatternLayout() : this(DefaultConversionPattern) - { - } + /// + /// Constructs a PatternLayout using the DefaultConversionPattern + /// + /// + /// + /// The default pattern just produces the application supplied message. + /// + /// + /// Note to Inheritors: This constructor calls the virtual method + /// . If you override this method be + /// aware that it will be called before your is called constructor. + /// + /// + /// As per the contract the + /// method must be called after the properties on this object have been + /// configured. + /// + /// + public PatternLayout() : this(DefaultConversionPattern) + { + } - /// - /// Constructs a PatternLayout using the supplied conversion pattern - /// - /// the pattern to use - /// - /// - /// Note to Inheritors: This constructor calls the virtual method - /// . If you override this method be - /// aware that it will be called before your is called constructor. - /// - /// - /// When using this constructor the method - /// need not be called. This may not be the case when using a subclass. - /// - /// - public PatternLayout(string pattern) - { - // By default we do not process the exception - IgnoresException = true; + /// + /// Constructs a PatternLayout using the supplied conversion pattern + /// + /// the pattern to use + /// + /// + /// Note to Inheritors: This constructor calls the virtual method + /// . If you override this method be + /// aware that it will be called before your is called constructor. + /// + /// + /// When using this constructor the method + /// need not be called. This may not be the case when using a subclass. + /// + /// + public PatternLayout(string pattern) + { + // By default we do not process the exception + IgnoresException = true; - m_pattern = pattern; - if (m_pattern == null) - { - m_pattern = DefaultConversionPattern; - } + m_pattern = pattern; + if (m_pattern == null) + { + m_pattern = DefaultConversionPattern; + } - ActivateOptions(); - } + ActivateOptions(); + } - #endregion + #endregion - /// - /// The pattern formatting string - /// - /// - /// - /// The ConversionPattern option. This is the string which - /// controls formatting and consists of a mix of literal content and - /// conversion specifiers. - /// - /// - public string ConversionPattern - { - get { return m_pattern; } - set { m_pattern = value; } - } + /// + /// The pattern formatting string + /// + /// + /// + /// The ConversionPattern option. This is the string which + /// controls formatting and consists of a mix of literal content and + /// conversion specifiers. + /// + /// + public string ConversionPattern + { + get { return m_pattern; } + set { m_pattern = value; } + } - /// - /// Create the pattern parser instance - /// - /// the pattern to parse - /// The that will format the event - /// - /// - /// Creates the used to parse the conversion string. Sets the - /// global and instance rules on the . - /// - /// - protected virtual PatternParser CreatePatternParser(string pattern) - { - PatternParser patternParser = new PatternParser(pattern); + /// + /// Create the pattern parser instance + /// + /// the pattern to parse + /// The that will format the event + /// + /// + /// Creates the used to parse the conversion string. Sets the + /// global and instance rules on the . + /// + /// + protected virtual PatternParser CreatePatternParser(string pattern) + { + PatternParser patternParser = new PatternParser(pattern); - // Add all the builtin patterns - foreach(DictionaryEntry entry in s_globalRulesRegistry) - { + // Add all the builtin patterns + foreach(DictionaryEntry entry in s_globalRulesRegistry) + { ConverterInfo converterInfo = new ConverterInfo(); converterInfo.Name = (string)entry.Key; converterInfo.Type = (Type)entry.Value; patternParser.PatternConverters[entry.Key] = converterInfo; - } - // Add the instance patterns - foreach(DictionaryEntry entry in m_instanceRulesRegistry) - { - patternParser.PatternConverters[entry.Key] = entry.Value; - } + } + // Add the instance patterns + foreach(DictionaryEntry entry in m_instanceRulesRegistry) + { + patternParser.PatternConverters[entry.Key] = entry.Value; + } - return patternParser; - } + return patternParser; + } - #region Implementation of IOptionHandler + #region Implementation of IOptionHandler - /// - /// Initialize layout options - /// - /// - /// - /// This is part of the delayed object - /// activation scheme. The method must - /// be called on this object after the configuration properties have - /// been set. Until is called this - /// object is in an undefined state and must not be used. - /// - /// - /// If any of the configuration properties are modified then - /// must be called again. - /// - /// - public override void ActivateOptions() - { - m_head = CreatePatternParser(m_pattern).Parse(); + /// + /// Initialize layout options + /// + /// + /// + /// This is part of the delayed object + /// activation scheme. The method must + /// be called on this object after the configuration properties have + /// been set. Until is called this + /// object is in an undefined state and must not be used. + /// + /// + /// If any of the configuration properties are modified then + /// must be called again. + /// + /// + public override void ActivateOptions() + { + m_head = CreatePatternParser(m_pattern).Parse(); - PatternConverter curConverter = m_head; - while(curConverter != null) - { - PatternLayoutConverter layoutConverter = curConverter as PatternLayoutConverter; - if (layoutConverter != null) - { - if (!layoutConverter.IgnoresException) - { - // Found converter that handles the exception - this.IgnoresException = false; + PatternConverter curConverter = m_head; + while(curConverter != null) + { + PatternLayoutConverter layoutConverter = curConverter as PatternLayoutConverter; + if (layoutConverter != null) + { + if (!layoutConverter.IgnoresException) + { + // Found converter that handles the exception + this.IgnoresException = false; - break; - } - } - curConverter = curConverter.Next; - } - } + break; + } + } + curConverter = curConverter.Next; + } + } - #endregion + #endregion - #region Override implementation of LayoutSkeleton + #region Override implementation of LayoutSkeleton - /// - /// Produces a formatted string as specified by the conversion pattern. - /// - /// the event being logged - /// The TextWriter to write the formatted event to - /// - /// - /// Parse the using the patter format - /// specified in the property. - /// - /// - public override void Format(TextWriter writer, LoggingEvent loggingEvent) - { - if (writer == null) - { - throw new ArgumentNullException("writer"); - } - if (loggingEvent == null) - { - throw new ArgumentNullException("loggingEvent"); - } + /// + /// Produces a formatted string as specified by the conversion pattern. + /// + /// the event being logged + /// The TextWriter to write the formatted event to + /// + /// + /// Parse the using the patter format + /// specified in the property. + /// + /// + public override void Format(TextWriter writer, LoggingEvent loggingEvent) + { + if (writer == null) + { + throw new ArgumentNullException("writer"); + } + if (loggingEvent == null) + { + throw new ArgumentNullException("loggingEvent"); + } - PatternConverter c = m_head; + PatternConverter c = m_head; - // loop through the chain of pattern converters - while(c != null) - { - c.Format(writer, loggingEvent); - c = c.Next; - } - } + // loop through the chain of pattern converters + while(c != null) + { + c.Format(writer, loggingEvent); + c = c.Next; + } + } - #endregion + #endregion - /// - /// Add a converter to this PatternLayout - /// - /// the converter info - /// - /// - /// This version of the method is used by the configurator. - /// Programmatic users should use the alternative method. - /// - /// - public void AddConverter(ConverterInfo converterInfo) - { + /// + /// Add a converter to this PatternLayout + /// + /// the converter info + /// + /// + /// This version of the method is used by the configurator. + /// Programmatic users should use the alternative method. + /// + /// + public void AddConverter(ConverterInfo converterInfo) + { if (converterInfo == null) throw new ArgumentNullException("converterInfo"); if (!typeof(PatternConverter).IsAssignableFrom(converterInfo.Type)) @@ -1137,26 +1137,26 @@ public void AddConverter(ConverterInfo converterInfo) throw new ArgumentException("The converter type specified [" + converterInfo.Type + "] must be a subclass of log4net.Util.PatternConverter", "converterInfo"); } m_instanceRulesRegistry[converterInfo.Name] = converterInfo; - } + } - /// - /// Add a converter to this PatternLayout - /// - /// the name of the conversion pattern for this converter - /// the type of the converter - /// - /// - /// Add a named pattern converter to this instance. This - /// converter will be used in the formatting of the event. - /// This method must be called before . - /// - /// - /// The specified must extend the - /// type. - /// - /// - public void AddConverter(string name, Type type) - { + /// + /// Add a converter to this PatternLayout + /// + /// the name of the conversion pattern for this converter + /// the type of the converter + /// + /// + /// Add a named pattern converter to this instance. This + /// converter will be used in the formatting of the event. + /// This method must be called before . + /// + /// + /// The specified must extend the + /// type. + /// + /// + public void AddConverter(string name, Type type) + { if (name == null) throw new ArgumentNullException("name"); if (type == null) throw new ArgumentNullException("type"); @@ -1165,6 +1165,6 @@ public void AddConverter(string name, Type type) converterInfo.Type = type; AddConverter(converterInfo); - } - } + } + } } diff --git a/src/log4net/Layout/RawLayoutConverter.cs b/src/log4net/Layout/RawLayoutConverter.cs index 1a210e60..3667f814 100644 --- a/src/log4net/Layout/RawLayoutConverter.cs +++ b/src/log4net/Layout/RawLayoutConverter.cs @@ -23,64 +23,64 @@ namespace log4net.Layout { - /// - /// Type converter for the interface - /// - /// - /// - /// Used to convert objects to the interface. - /// Supports converting from the interface to - /// the interface using the . - /// - /// - /// Nicko Cadell - /// Gert Driesen - public class RawLayoutConverter : IConvertFrom - { - #region Override Implementation of IRawLayout + /// + /// Type converter for the interface + /// + /// + /// + /// Used to convert objects to the interface. + /// Supports converting from the interface to + /// the interface using the . + /// + /// + /// Nicko Cadell + /// Gert Driesen + public class RawLayoutConverter : IConvertFrom + { + #region Override Implementation of IRawLayout - /// - /// Can the sourceType be converted to an - /// - /// the source to be to be converted - /// true if the source type can be converted to - /// - /// - /// Test if the can be converted to a - /// . Only is supported - /// as the . - /// - /// - public bool CanConvertFrom(Type sourceType) - { - // Accept an ILayout object - return (typeof(ILayout).IsAssignableFrom(sourceType)); - } + /// + /// Can the sourceType be converted to an + /// + /// the source to be to be converted + /// true if the source type can be converted to + /// + /// + /// Test if the can be converted to a + /// . Only is supported + /// as the . + /// + /// + public bool CanConvertFrom(Type sourceType) + { + // Accept an ILayout object + return (typeof(ILayout).IsAssignableFrom(sourceType)); + } - /// - /// Convert the value to a object - /// - /// the value to convert - /// the object - /// - /// - /// Convert the object to a - /// object. If the object - /// is a then the - /// is used to adapt between the two interfaces, otherwise an - /// exception is thrown. - /// - /// - public object ConvertFrom(object source) - { - ILayout layout = source as ILayout; - if (layout != null) - { - return new Layout2RawLayoutAdapter(layout); - } - throw ConversionNotSupportedException.Create(typeof(IRawLayout), source); - } + /// + /// Convert the value to a object + /// + /// the value to convert + /// the object + /// + /// + /// Convert the object to a + /// object. If the object + /// is a then the + /// is used to adapt between the two interfaces, otherwise an + /// exception is thrown. + /// + /// + public object ConvertFrom(object source) + { + ILayout layout = source as ILayout; + if (layout != null) + { + return new Layout2RawLayoutAdapter(layout); + } + throw ConversionNotSupportedException.Create(typeof(IRawLayout), source); + } - #endregion - } + #endregion + } } diff --git a/src/log4net/Layout/RawPropertyLayout.cs b/src/log4net/Layout/RawPropertyLayout.cs index f50dda2c..6c4303e7 100644 --- a/src/log4net/Layout/RawPropertyLayout.cs +++ b/src/log4net/Layout/RawPropertyLayout.cs @@ -25,66 +25,66 @@ namespace log4net.Layout { - /// - /// Extract the value of a property from the - /// - /// - /// - /// Extract the value of a property from the - /// - /// - /// Nicko Cadell - public class RawPropertyLayout : IRawLayout - { - #region Constructors + /// + /// Extract the value of a property from the + /// + /// + /// + /// Extract the value of a property from the + /// + /// + /// Nicko Cadell + public class RawPropertyLayout : IRawLayout + { + #region Constructors - /// - /// Constructs a RawPropertyLayout - /// - public RawPropertyLayout() - { - } + /// + /// Constructs a RawPropertyLayout + /// + public RawPropertyLayout() + { + } - #endregion + #endregion - private string m_key; + private string m_key; - /// - /// The name of the value to lookup in the LoggingEvent Properties collection. - /// - /// - /// Value to lookup in the LoggingEvent Properties collection - /// - /// - /// - /// String name of the property to lookup in the . - /// - /// - public string Key - { - get { return m_key; } - set { m_key = value; } - } + /// + /// The name of the value to lookup in the LoggingEvent Properties collection. + /// + /// + /// Value to lookup in the LoggingEvent Properties collection + /// + /// + /// + /// String name of the property to lookup in the . + /// + /// + public string Key + { + get { return m_key; } + set { m_key = value; } + } - #region Implementation of IRawLayout + #region Implementation of IRawLayout - /// - /// Lookup the property for - /// - /// The event to format - /// returns property value - /// - /// - /// Looks up and returns the object value of the property - /// named . If there is no property defined - /// with than name then null will be returned. - /// - /// - public virtual object Format(LoggingEvent loggingEvent) - { - return loggingEvent.LookupProperty(m_key); - } + /// + /// Lookup the property for + /// + /// The event to format + /// returns property value + /// + /// + /// Looks up and returns the object value of the property + /// named . If there is no property defined + /// with than name then null will be returned. + /// + /// + public virtual object Format(LoggingEvent loggingEvent) + { + return loggingEvent.LookupProperty(m_key); + } - #endregion - } + #endregion + } } diff --git a/src/log4net/Layout/RawTimeStampLayout.cs b/src/log4net/Layout/RawTimeStampLayout.cs index 66a4dec5..81c37b4c 100644 --- a/src/log4net/Layout/RawTimeStampLayout.cs +++ b/src/log4net/Layout/RawTimeStampLayout.cs @@ -25,50 +25,50 @@ namespace log4net.Layout { - /// - /// Extract the date from the - /// - /// - /// - /// Extract the date from the - /// - /// - /// Nicko Cadell - /// Gert Driesen - public class RawTimeStampLayout : IRawLayout - { - #region Constructors + /// + /// Extract the date from the + /// + /// + /// + /// Extract the date from the + /// + /// + /// Nicko Cadell + /// Gert Driesen + public class RawTimeStampLayout : IRawLayout + { + #region Constructors - /// - /// Constructs a RawTimeStampLayout - /// - public RawTimeStampLayout() - { - } + /// + /// Constructs a RawTimeStampLayout + /// + public RawTimeStampLayout() + { + } - #endregion + #endregion - #region Implementation of IRawLayout + #region Implementation of IRawLayout - /// - /// Gets the as a . - /// - /// The event to format - /// returns the time stamp - /// - /// - /// Gets the as a . - /// - /// - /// The time stamp is in local time. To format the time stamp - /// in universal time use . - /// - /// - public virtual object Format(LoggingEvent loggingEvent) - { - return loggingEvent.TimeStamp; - } + /// + /// Gets the as a . + /// + /// The event to format + /// returns the time stamp + /// + /// + /// Gets the as a . + /// + /// + /// The time stamp is in local time. To format the time stamp + /// in universal time use . + /// + /// + public virtual object Format(LoggingEvent loggingEvent) + { + return loggingEvent.TimeStamp; + } - #endregion - } + #endregion + } } diff --git a/src/log4net/Layout/RawUtcTimeStampLayout.cs b/src/log4net/Layout/RawUtcTimeStampLayout.cs index 2c232ae4..55bec72e 100644 --- a/src/log4net/Layout/RawUtcTimeStampLayout.cs +++ b/src/log4net/Layout/RawUtcTimeStampLayout.cs @@ -25,50 +25,50 @@ namespace log4net.Layout { - /// - /// Extract the date from the - /// - /// - /// - /// Extract the date from the - /// - /// - /// Nicko Cadell - /// Gert Driesen - public class RawUtcTimeStampLayout : IRawLayout - { - #region Constructors + /// + /// Extract the date from the + /// + /// + /// + /// Extract the date from the + /// + /// + /// Nicko Cadell + /// Gert Driesen + public class RawUtcTimeStampLayout : IRawLayout + { + #region Constructors - /// - /// Constructs a RawUtcTimeStampLayout - /// - public RawUtcTimeStampLayout() - { - } + /// + /// Constructs a RawUtcTimeStampLayout + /// + public RawUtcTimeStampLayout() + { + } - #endregion + #endregion - #region Implementation of IRawLayout + #region Implementation of IRawLayout - /// - /// Gets the as a . - /// - /// The event to format - /// returns the time stamp - /// - /// - /// Gets the as a . - /// - /// - /// The time stamp is in universal time. To format the time stamp - /// in local time use . - /// - /// - public virtual object Format(LoggingEvent loggingEvent) - { - return loggingEvent.TimeStampUtc; - } + /// + /// Gets the as a . + /// + /// The event to format + /// returns the time stamp + /// + /// + /// Gets the as a . + /// + /// + /// The time stamp is in universal time. To format the time stamp + /// in local time use . + /// + /// + public virtual object Format(LoggingEvent loggingEvent) + { + return loggingEvent.TimeStampUtc; + } - #endregion - } + #endregion + } } diff --git a/src/log4net/Layout/SimpleLayout.cs b/src/log4net/Layout/SimpleLayout.cs index 5efe0d08..8d4640aa 100644 --- a/src/log4net/Layout/SimpleLayout.cs +++ b/src/log4net/Layout/SimpleLayout.cs @@ -26,86 +26,86 @@ namespace log4net.Layout { - /// - /// A very simple layout - /// - /// - /// - /// SimpleLayout consists of the level of the log statement, - /// followed by " - " and then the log message itself. For example, - /// - /// DEBUG - Hello world - /// - /// - /// - /// Nicko Cadell - /// Gert Driesen - public class SimpleLayout : LayoutSkeleton - { - #region Constructors + /// + /// A very simple layout + /// + /// + /// + /// SimpleLayout consists of the level of the log statement, + /// followed by " - " and then the log message itself. For example, + /// + /// DEBUG - Hello world + /// + /// + /// + /// Nicko Cadell + /// Gert Driesen + public class SimpleLayout : LayoutSkeleton + { + #region Constructors - /// - /// Constructs a SimpleLayout - /// - public SimpleLayout() - { - IgnoresException = true; - } + /// + /// Constructs a SimpleLayout + /// + public SimpleLayout() + { + IgnoresException = true; + } - #endregion + #endregion - #region Implementation of IOptionHandler + #region Implementation of IOptionHandler - /// - /// Initialize layout options - /// - /// - /// - /// This is part of the delayed object - /// activation scheme. The method must - /// be called on this object after the configuration properties have - /// been set. Until is called this - /// object is in an undefined state and must not be used. - /// - /// - /// If any of the configuration properties are modified then - /// must be called again. - /// - /// - public override void ActivateOptions() - { - // nothing to do. - } + /// + /// Initialize layout options + /// + /// + /// + /// This is part of the delayed object + /// activation scheme. The method must + /// be called on this object after the configuration properties have + /// been set. Until is called this + /// object is in an undefined state and must not be used. + /// + /// + /// If any of the configuration properties are modified then + /// must be called again. + /// + /// + public override void ActivateOptions() + { + // nothing to do. + } - #endregion + #endregion - #region Override implementation of LayoutSkeleton + #region Override implementation of LayoutSkeleton - /// - /// Produces a simple formatted output. - /// - /// the event being logged - /// The TextWriter to write the formatted event to - /// - /// - /// Formats the event as the level of the even, - /// followed by " - " and then the log message itself. The - /// output is terminated by a newline. - /// - /// - public override void Format(TextWriter writer, LoggingEvent loggingEvent) - { - if (loggingEvent == null) - { - throw new ArgumentNullException("loggingEvent"); - } + /// + /// Produces a simple formatted output. + /// + /// the event being logged + /// The TextWriter to write the formatted event to + /// + /// + /// Formats the event as the level of the even, + /// followed by " - " and then the log message itself. The + /// output is terminated by a newline. + /// + /// + public override void Format(TextWriter writer, LoggingEvent loggingEvent) + { + if (loggingEvent == null) + { + throw new ArgumentNullException("loggingEvent"); + } - writer.Write(loggingEvent.Level.DisplayName); - writer.Write(" - "); - loggingEvent.WriteRenderedMessage(writer); - writer.WriteLine(); - } + writer.Write(loggingEvent.Level.DisplayName); + writer.Write(" - "); + loggingEvent.WriteRenderedMessage(writer); + writer.WriteLine(); + } - #endregion - } + #endregion + } } diff --git a/src/log4net/Layout/XmlLayout.cs b/src/log4net/Layout/XmlLayout.cs index 7c5c0c29..15c925ef 100644 --- a/src/log4net/Layout/XmlLayout.cs +++ b/src/log4net/Layout/XmlLayout.cs @@ -26,362 +26,362 @@ namespace log4net.Layout { - /// - /// Layout that formats the log events as XML elements. - /// - /// - /// - /// The output of the consists of a series of - /// log4net:event elements. It does not output a complete well-formed XML - /// file. The output is designed to be included as an external entity - /// in a separate file to form a correct XML file. - /// - /// - /// For example, if abc is the name of the file where - /// the output goes, then a well-formed XML file would - /// be: - /// - /// - /// <?xml version="1.0" ?> - /// - /// <!DOCTYPE log4net:events SYSTEM "log4net-events.dtd" [<!ENTITY data SYSTEM "abc">]> - /// - /// <log4net:events version="1.2" xmlns:log4net="http://logging.apache.org/log4net/schemas/log4net-events-1.2> - /// &data; - /// </log4net:events> - /// - /// - /// This approach enforces the independence of the - /// and the appender where it is embedded. - /// - /// - /// The version attribute helps components to correctly - /// interpret output generated by . The value of - /// this attribute should be "1.2" for release 1.2 and later. - /// - /// - /// Alternatively the Header and Footer properties can be - /// configured to output the correct XML header, open tag and close tag. - /// When setting the Header and Footer properties it is essential - /// that the underlying data store not be appendable otherwise the data - /// will become invalid XML. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public class XmlLayout : XmlLayoutBase - { - #region Public Instance Constructors - - /// - /// Constructs an XmlLayout - /// - public XmlLayout() : base() - { - } - - /// - /// Constructs an XmlLayout. - /// - /// - /// - /// The LocationInfo option takes a boolean value. By - /// default, it is set to false which means there will be no location - /// information output by this layout. If the the option is set to - /// true, then the file name and line number of the statement - /// at the origin of the log statement will be output. - /// - /// - /// If you are embedding this layout within an SmtpAppender - /// then make sure to set the LocationInfo option of that - /// appender as well. - /// - /// - public XmlLayout(bool locationInfo) : base(locationInfo) - { - } - - #endregion Public Instance Constructors - - #region Public Instance Properties - - /// - /// The prefix to use for all element names - /// - /// - /// - /// The default prefix is log4net. Set this property - /// to change the prefix. If the prefix is set to an empty string - /// then no prefix will be written. - /// - /// - public string Prefix - { - get { return m_prefix; } - set { m_prefix = value; } - } - - - /// - /// Set whether or not to base64 encode the message. - /// - /// - /// - /// By default the log message will be written as text to the xml - /// output. This can cause problems when the message contains binary - /// data. By setting this to true the contents of the message will be - /// base64 encoded. If this is set then invalid character replacement - /// (see ) will not be performed - /// on the log message. - /// - /// - public bool Base64EncodeMessage - { - get {return m_base64Message;} - set {m_base64Message=value;} - } - - /// - /// Set whether or not to base64 encode the property values. - /// - /// - /// - /// By default the properties will be written as text to the xml - /// output. This can cause problems when one or more properties contain - /// binary data. By setting this to true the values of the properties - /// will be base64 encoded. If this is set then invalid character replacement - /// (see ) will not be performed - /// on the property values. - /// - /// - public bool Base64EncodeProperties - { - get {return m_base64Properties;} - set {m_base64Properties=value;} - } - - #endregion Public Instance Properties - - #region Implementation of IOptionHandler - - /// - /// Initialize layout options - /// - /// - /// - /// This is part of the delayed object - /// activation scheme. The method must - /// be called on this object after the configuration properties have - /// been set. Until is called this - /// object is in an undefined state and must not be used. - /// - /// - /// If any of the configuration properties are modified then - /// must be called again. - /// - /// - /// Builds a cache of the element names - /// - /// - public override void ActivateOptions() - { - base.ActivateOptions(); - - // Cache the full element names including the prefix - if (m_prefix != null && m_prefix.Length > 0) - { - m_elmEvent = m_prefix + ":" + ELM_EVENT; - m_elmMessage = m_prefix + ":" + ELM_MESSAGE; - m_elmProperties = m_prefix + ":" + ELM_PROPERTIES; - m_elmData = m_prefix + ":" + ELM_DATA; - m_elmException = m_prefix + ":" + ELM_EXCEPTION; - m_elmLocation = m_prefix + ":" + ELM_LOCATION; - } - } - - #endregion Implementation of IOptionHandler - - #region Override implementation of XMLLayoutBase - - /// - /// Does the actual writing of the XML. - /// - /// The writer to use to output the event to. - /// The event to write. - /// - /// - /// Override the base class method - /// to write the to the . - /// - /// - protected override void FormatXml(XmlWriter writer, LoggingEvent loggingEvent) - { - #if NETSTANDARD - writer.WriteStartElement(m_prefix, ELM_EVENT, m_prefix); - // writer.WriteAttributeString("xmlns", "log4net", null, "http://logging.apache.org/log4net/schemas/log4net-events-1.2"); - #else - writer.WriteStartElement(m_elmEvent); - #endif - writer.WriteAttributeString(ATTR_LOGGER, loggingEvent.LoggerName); + /// + /// Layout that formats the log events as XML elements. + /// + /// + /// + /// The output of the consists of a series of + /// log4net:event elements. It does not output a complete well-formed XML + /// file. The output is designed to be included as an external entity + /// in a separate file to form a correct XML file. + /// + /// + /// For example, if abc is the name of the file where + /// the output goes, then a well-formed XML file would + /// be: + /// + /// + /// <?xml version="1.0" ?> + /// + /// <!DOCTYPE log4net:events SYSTEM "log4net-events.dtd" [<!ENTITY data SYSTEM "abc">]> + /// + /// <log4net:events version="1.2" xmlns:log4net="http://logging.apache.org/log4net/schemas/log4net-events-1.2> + /// &data; + /// </log4net:events> + /// + /// + /// This approach enforces the independence of the + /// and the appender where it is embedded. + /// + /// + /// The version attribute helps components to correctly + /// interpret output generated by . The value of + /// this attribute should be "1.2" for release 1.2 and later. + /// + /// + /// Alternatively the Header and Footer properties can be + /// configured to output the correct XML header, open tag and close tag. + /// When setting the Header and Footer properties it is essential + /// that the underlying data store not be appendable otherwise the data + /// will become invalid XML. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public class XmlLayout : XmlLayoutBase + { + #region Public Instance Constructors + + /// + /// Constructs an XmlLayout + /// + public XmlLayout() : base() + { + } + + /// + /// Constructs an XmlLayout. + /// + /// + /// + /// The LocationInfo option takes a boolean value. By + /// default, it is set to false which means there will be no location + /// information output by this layout. If the the option is set to + /// true, then the file name and line number of the statement + /// at the origin of the log statement will be output. + /// + /// + /// If you are embedding this layout within an SmtpAppender + /// then make sure to set the LocationInfo option of that + /// appender as well. + /// + /// + public XmlLayout(bool locationInfo) : base(locationInfo) + { + } + + #endregion Public Instance Constructors + + #region Public Instance Properties + + /// + /// The prefix to use for all element names + /// + /// + /// + /// The default prefix is log4net. Set this property + /// to change the prefix. If the prefix is set to an empty string + /// then no prefix will be written. + /// + /// + public string Prefix + { + get { return m_prefix; } + set { m_prefix = value; } + } + + + /// + /// Set whether or not to base64 encode the message. + /// + /// + /// + /// By default the log message will be written as text to the xml + /// output. This can cause problems when the message contains binary + /// data. By setting this to true the contents of the message will be + /// base64 encoded. If this is set then invalid character replacement + /// (see ) will not be performed + /// on the log message. + /// + /// + public bool Base64EncodeMessage + { + get {return m_base64Message;} + set {m_base64Message=value;} + } + + /// + /// Set whether or not to base64 encode the property values. + /// + /// + /// + /// By default the properties will be written as text to the xml + /// output. This can cause problems when one or more properties contain + /// binary data. By setting this to true the values of the properties + /// will be base64 encoded. If this is set then invalid character replacement + /// (see ) will not be performed + /// on the property values. + /// + /// + public bool Base64EncodeProperties + { + get {return m_base64Properties;} + set {m_base64Properties=value;} + } + + #endregion Public Instance Properties + + #region Implementation of IOptionHandler + + /// + /// Initialize layout options + /// + /// + /// + /// This is part of the delayed object + /// activation scheme. The method must + /// be called on this object after the configuration properties have + /// been set. Until is called this + /// object is in an undefined state and must not be used. + /// + /// + /// If any of the configuration properties are modified then + /// must be called again. + /// + /// + /// Builds a cache of the element names + /// + /// + public override void ActivateOptions() + { + base.ActivateOptions(); + + // Cache the full element names including the prefix + if (m_prefix != null && m_prefix.Length > 0) + { + m_elmEvent = m_prefix + ":" + ELM_EVENT; + m_elmMessage = m_prefix + ":" + ELM_MESSAGE; + m_elmProperties = m_prefix + ":" + ELM_PROPERTIES; + m_elmData = m_prefix + ":" + ELM_DATA; + m_elmException = m_prefix + ":" + ELM_EXCEPTION; + m_elmLocation = m_prefix + ":" + ELM_LOCATION; + } + } + + #endregion Implementation of IOptionHandler + + #region Override implementation of XMLLayoutBase + + /// + /// Does the actual writing of the XML. + /// + /// The writer to use to output the event to. + /// The event to write. + /// + /// + /// Override the base class method + /// to write the to the . + /// + /// + protected override void FormatXml(XmlWriter writer, LoggingEvent loggingEvent) + { + #if NETSTANDARD + writer.WriteStartElement(m_prefix, ELM_EVENT, m_prefix); + // writer.WriteAttributeString("xmlns", "log4net", null, "http://logging.apache.org/log4net/schemas/log4net-events-1.2"); + #else + writer.WriteStartElement(m_elmEvent); + #endif + writer.WriteAttributeString(ATTR_LOGGER, loggingEvent.LoggerName); #if NET_2_0 || NETCF_2_0 || MONO_2_0 || NETSTANDARD - writer.WriteAttributeString(ATTR_TIMESTAMP, XmlConvert.ToString(loggingEvent.TimeStamp, XmlDateTimeSerializationMode.Local)); + writer.WriteAttributeString(ATTR_TIMESTAMP, XmlConvert.ToString(loggingEvent.TimeStamp, XmlDateTimeSerializationMode.Local)); #else - writer.WriteAttributeString(ATTR_TIMESTAMP, XmlConvert.ToString(loggingEvent.TimeStamp)); + writer.WriteAttributeString(ATTR_TIMESTAMP, XmlConvert.ToString(loggingEvent.TimeStamp)); #endif - writer.WriteAttributeString(ATTR_LEVEL, loggingEvent.Level.DisplayName); - writer.WriteAttributeString(ATTR_THREAD, loggingEvent.ThreadName); - - if (loggingEvent.Domain != null && loggingEvent.Domain.Length > 0) - { - writer.WriteAttributeString(ATTR_DOMAIN, loggingEvent.Domain); - } - if (loggingEvent.Identity != null && loggingEvent.Identity.Length > 0) - { - writer.WriteAttributeString(ATTR_IDENTITY, loggingEvent.Identity); - } - if (loggingEvent.UserName != null && loggingEvent.UserName.Length > 0) - { - writer.WriteAttributeString(ATTR_USERNAME, loggingEvent.UserName); - } + writer.WriteAttributeString(ATTR_LEVEL, loggingEvent.Level.DisplayName); + writer.WriteAttributeString(ATTR_THREAD, loggingEvent.ThreadName); + + if (loggingEvent.Domain != null && loggingEvent.Domain.Length > 0) + { + writer.WriteAttributeString(ATTR_DOMAIN, loggingEvent.Domain); + } + if (loggingEvent.Identity != null && loggingEvent.Identity.Length > 0) + { + writer.WriteAttributeString(ATTR_IDENTITY, loggingEvent.Identity); + } + if (loggingEvent.UserName != null && loggingEvent.UserName.Length > 0) + { + writer.WriteAttributeString(ATTR_USERNAME, loggingEvent.UserName); + } - // Append the message text - #if NETSTANDARD - writer.WriteStartElement(m_prefix, ELM_MESSAGE, m_prefix); - #else - writer.WriteStartElement(m_elmMessage); - #endif - if (!this.Base64EncodeMessage) - { - Transform.WriteEscapedXmlString(writer, loggingEvent.RenderedMessage, this.InvalidCharReplacement); - } - else - { - byte[] messageBytes = Encoding.UTF8.GetBytes(loggingEvent.RenderedMessage); - string base64Message = Convert.ToBase64String(messageBytes, 0, messageBytes.Length); - Transform.WriteEscapedXmlString(writer, base64Message,this.InvalidCharReplacement); - } - writer.WriteEndElement(); - - PropertiesDictionary properties = loggingEvent.GetProperties(); - - // Append the properties text - if (properties.Count > 0) - { - #if NETSTANDARD - writer.WriteStartElement(m_prefix, ELM_PROPERTIES, m_prefix); - #else - writer.WriteStartElement(m_elmProperties); - #endif - foreach(System.Collections.DictionaryEntry entry in properties) - { - #if NETSTANDARD - writer.WriteStartElement(m_prefix, ELM_DATA, m_prefix); - #else - writer.WriteStartElement(m_elmData); - #endif - writer.WriteAttributeString(ATTR_NAME, Transform.MaskXmlInvalidCharacters((string)entry.Key,this.InvalidCharReplacement)); - - // Use an ObjectRenderer to convert the object to a string - string valueStr =null; - if (!this.Base64EncodeProperties) - { - valueStr = Transform.MaskXmlInvalidCharacters(loggingEvent.Repository.RendererMap.FindAndRender(entry.Value),this.InvalidCharReplacement); - } - else - { - byte[] propertyValueBytes = Encoding.UTF8.GetBytes(loggingEvent.Repository.RendererMap.FindAndRender(entry.Value)); - valueStr = Convert.ToBase64String(propertyValueBytes, 0, propertyValueBytes.Length); - } - writer.WriteAttributeString(ATTR_VALUE, valueStr); - - writer.WriteEndElement(); - } - writer.WriteEndElement(); - } - - string exceptionStr = loggingEvent.GetExceptionString(); - if (exceptionStr != null && exceptionStr.Length > 0) - { - // Append the stack trace line - #if NETSTANDARD - writer.WriteStartElement(m_prefix, ELM_EXCEPTION, m_prefix); - #else - writer.WriteStartElement(m_elmException); - #endif - Transform.WriteEscapedXmlString(writer, exceptionStr,this.InvalidCharReplacement); - writer.WriteEndElement(); - } - - if (LocationInfo) - { - LocationInfo locationInfo = loggingEvent.LocationInformation; - - #if NETSTANDARD - writer.WriteStartElement(m_prefix, ELM_LOCATION, m_prefix); - #else - writer.WriteStartElement(m_elmLocation); - #endif - writer.WriteAttributeString(ATTR_CLASS, locationInfo.ClassName); - writer.WriteAttributeString(ATTR_METHOD, locationInfo.MethodName); - writer.WriteAttributeString(ATTR_FILE, locationInfo.FileName); - writer.WriteAttributeString(ATTR_LINE, locationInfo.LineNumber); - writer.WriteEndElement(); - } - - writer.WriteEndElement(); - } - - #endregion Override implementation of XMLLayoutBase - - #region Private Instance Fields + // Append the message text + #if NETSTANDARD + writer.WriteStartElement(m_prefix, ELM_MESSAGE, m_prefix); + #else + writer.WriteStartElement(m_elmMessage); + #endif + if (!this.Base64EncodeMessage) + { + Transform.WriteEscapedXmlString(writer, loggingEvent.RenderedMessage, this.InvalidCharReplacement); + } + else + { + byte[] messageBytes = Encoding.UTF8.GetBytes(loggingEvent.RenderedMessage); + string base64Message = Convert.ToBase64String(messageBytes, 0, messageBytes.Length); + Transform.WriteEscapedXmlString(writer, base64Message,this.InvalidCharReplacement); + } + writer.WriteEndElement(); + + PropertiesDictionary properties = loggingEvent.GetProperties(); + + // Append the properties text + if (properties.Count > 0) + { + #if NETSTANDARD + writer.WriteStartElement(m_prefix, ELM_PROPERTIES, m_prefix); + #else + writer.WriteStartElement(m_elmProperties); + #endif + foreach(System.Collections.DictionaryEntry entry in properties) + { + #if NETSTANDARD + writer.WriteStartElement(m_prefix, ELM_DATA, m_prefix); + #else + writer.WriteStartElement(m_elmData); + #endif + writer.WriteAttributeString(ATTR_NAME, Transform.MaskXmlInvalidCharacters((string)entry.Key,this.InvalidCharReplacement)); + + // Use an ObjectRenderer to convert the object to a string + string valueStr =null; + if (!this.Base64EncodeProperties) + { + valueStr = Transform.MaskXmlInvalidCharacters(loggingEvent.Repository.RendererMap.FindAndRender(entry.Value),this.InvalidCharReplacement); + } + else + { + byte[] propertyValueBytes = Encoding.UTF8.GetBytes(loggingEvent.Repository.RendererMap.FindAndRender(entry.Value)); + valueStr = Convert.ToBase64String(propertyValueBytes, 0, propertyValueBytes.Length); + } + writer.WriteAttributeString(ATTR_VALUE, valueStr); + + writer.WriteEndElement(); + } + writer.WriteEndElement(); + } + + string exceptionStr = loggingEvent.GetExceptionString(); + if (exceptionStr != null && exceptionStr.Length > 0) + { + // Append the stack trace line + #if NETSTANDARD + writer.WriteStartElement(m_prefix, ELM_EXCEPTION, m_prefix); + #else + writer.WriteStartElement(m_elmException); + #endif + Transform.WriteEscapedXmlString(writer, exceptionStr,this.InvalidCharReplacement); + writer.WriteEndElement(); + } + + if (LocationInfo) + { + LocationInfo locationInfo = loggingEvent.LocationInformation; + + #if NETSTANDARD + writer.WriteStartElement(m_prefix, ELM_LOCATION, m_prefix); + #else + writer.WriteStartElement(m_elmLocation); + #endif + writer.WriteAttributeString(ATTR_CLASS, locationInfo.ClassName); + writer.WriteAttributeString(ATTR_METHOD, locationInfo.MethodName); + writer.WriteAttributeString(ATTR_FILE, locationInfo.FileName); + writer.WriteAttributeString(ATTR_LINE, locationInfo.LineNumber); + writer.WriteEndElement(); + } + + writer.WriteEndElement(); + } + + #endregion Override implementation of XMLLayoutBase + + #region Private Instance Fields - /// - /// The prefix to use for all generated element names - /// - private string m_prefix = PREFIX; - - private string m_elmEvent = ELM_EVENT; - private string m_elmMessage = ELM_MESSAGE; - private string m_elmData = ELM_DATA; - private string m_elmProperties = ELM_PROPERTIES; - private string m_elmException = ELM_EXCEPTION; - private string m_elmLocation = ELM_LOCATION; - - private bool m_base64Message=false; - private bool m_base64Properties=false; - - #endregion Private Instance Fields - - #region Private Static Fields - - private const string PREFIX = "log4net"; - - private const string ELM_EVENT = "event"; - private const string ELM_MESSAGE = "message"; - private const string ELM_PROPERTIES = "properties"; - private const string ELM_GLOBAL_PROPERTIES = "global-properties"; - private const string ELM_DATA = "data"; - private const string ELM_EXCEPTION = "exception"; - private const string ELM_LOCATION = "locationInfo"; - - private const string ATTR_LOGGER = "logger"; - private const string ATTR_TIMESTAMP = "timestamp"; - private const string ATTR_LEVEL = "level"; - private const string ATTR_THREAD = "thread"; - private const string ATTR_DOMAIN = "domain"; - private const string ATTR_IDENTITY = "identity"; - private const string ATTR_USERNAME = "username"; - private const string ATTR_CLASS = "class"; - private const string ATTR_METHOD = "method"; - private const string ATTR_FILE = "file"; - private const string ATTR_LINE = "line"; - private const string ATTR_NAME = "name"; - private const string ATTR_VALUE = "value"; - - - #endregion Private Static Fields - } + /// + /// The prefix to use for all generated element names + /// + private string m_prefix = PREFIX; + + private string m_elmEvent = ELM_EVENT; + private string m_elmMessage = ELM_MESSAGE; + private string m_elmData = ELM_DATA; + private string m_elmProperties = ELM_PROPERTIES; + private string m_elmException = ELM_EXCEPTION; + private string m_elmLocation = ELM_LOCATION; + + private bool m_base64Message=false; + private bool m_base64Properties=false; + + #endregion Private Instance Fields + + #region Private Static Fields + + private const string PREFIX = "log4net"; + + private const string ELM_EVENT = "event"; + private const string ELM_MESSAGE = "message"; + private const string ELM_PROPERTIES = "properties"; + private const string ELM_GLOBAL_PROPERTIES = "global-properties"; + private const string ELM_DATA = "data"; + private const string ELM_EXCEPTION = "exception"; + private const string ELM_LOCATION = "locationInfo"; + + private const string ATTR_LOGGER = "logger"; + private const string ATTR_TIMESTAMP = "timestamp"; + private const string ATTR_LEVEL = "level"; + private const string ATTR_THREAD = "thread"; + private const string ATTR_DOMAIN = "domain"; + private const string ATTR_IDENTITY = "identity"; + private const string ATTR_USERNAME = "username"; + private const string ATTR_CLASS = "class"; + private const string ATTR_METHOD = "method"; + private const string ATTR_FILE = "file"; + private const string ATTR_LINE = "line"; + private const string ATTR_NAME = "name"; + private const string ATTR_VALUE = "value"; + + + #endregion Private Static Fields + } } diff --git a/src/log4net/Layout/XmlLayoutBase.cs b/src/log4net/Layout/XmlLayoutBase.cs index 2f35f8b7..3bee490d 100644 --- a/src/log4net/Layout/XmlLayoutBase.cs +++ b/src/log4net/Layout/XmlLayoutBase.cs @@ -27,229 +27,229 @@ namespace log4net.Layout { - /// - /// Layout that formats the log events as XML elements. - /// - /// - /// - /// This is an abstract class that must be subclassed by an implementation - /// to conform to a specific schema. - /// - /// - /// Deriving classes must implement the method. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public abstract class XmlLayoutBase : LayoutSkeleton - { - #region Protected Instance Constructors - - /// - /// Protected constructor to support subclasses - /// - /// - /// - /// Initializes a new instance of the class - /// with no location info. - /// - /// - protected XmlLayoutBase() : this(false) - { - IgnoresException = false; - } - - /// - /// Protected constructor to support subclasses - /// - /// - /// - /// The parameter determines whether - /// location information will be output by the layout. If - /// is set to true, then the - /// file name and line number of the statement at the origin of the log - /// statement will be output. - /// - /// - /// If you are embedding this layout within an SMTPAppender - /// then make sure to set the LocationInfo option of that - /// appender as well. - /// - /// - protected XmlLayoutBase(bool locationInfo) - { - IgnoresException = false; - m_locationInfo = locationInfo; - } - - #endregion Protected Instance Constructors - - #region Public Instance Properties - - /// - /// Gets a value indicating whether to include location information in - /// the XML events. - /// - /// - /// true if location information should be included in the XML - /// events; otherwise, false. - /// - /// - /// - /// If is set to true, then the file - /// name and line number of the statement at the origin of the log - /// statement will be output. - /// - /// - /// If you are embedding this layout within an SMTPAppender - /// then make sure to set the LocationInfo option of that - /// appender as well. - /// - /// - public bool LocationInfo - { - get { return m_locationInfo; } - set { m_locationInfo = value; } - } - /// - /// The string to replace characters that can not be expressed in XML with. - /// - /// - /// Not all characters may be expressed in XML. This property contains the - /// string to replace those that can not with. This defaults to a ?. Set it - /// to the empty string to simply remove offending characters. For more - /// details on the allowed character ranges see http://www.w3.org/TR/REC-xml/#charsets - /// Character replacement will occur in the log message, the property names - /// and the property values. - /// - /// - /// - public string InvalidCharReplacement - { - get {return m_invalidCharReplacement;} - set {m_invalidCharReplacement=value;} - } - #endregion - - #region Implementation of IOptionHandler - - /// - /// Initialize layout options - /// - /// - /// - /// This is part of the delayed object - /// activation scheme. The method must - /// be called on this object after the configuration properties have - /// been set. Until is called this - /// object is in an undefined state and must not be used. - /// - /// - /// If any of the configuration properties are modified then - /// must be called again. - /// - /// - public override void ActivateOptions() - { - // nothing to do - } - - #endregion Implementation of IOptionHandler - - #region Override implementation of LayoutSkeleton - - /// - /// Gets the content type output by this layout. - /// - /// - /// As this is the XML layout, the value is always "text/xml". - /// - /// - /// - /// As this is the XML layout, the value is always "text/xml". - /// - /// - public override string ContentType - { - get { return "text/xml"; } - } - - /// - /// Produces a formatted string. - /// - /// The event being logged. - /// The TextWriter to write the formatted event to - /// - /// - /// Format the and write it to the . - /// - /// - /// This method creates an that writes to the - /// . The is passed - /// to the method. Subclasses should override the - /// method rather than this method. - /// - /// - public override void Format(TextWriter writer, LoggingEvent loggingEvent) - { - if (loggingEvent == null) - { - throw new ArgumentNullException("loggingEvent"); - } + /// + /// Layout that formats the log events as XML elements. + /// + /// + /// + /// This is an abstract class that must be subclassed by an implementation + /// to conform to a specific schema. + /// + /// + /// Deriving classes must implement the method. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public abstract class XmlLayoutBase : LayoutSkeleton + { + #region Protected Instance Constructors + + /// + /// Protected constructor to support subclasses + /// + /// + /// + /// Initializes a new instance of the class + /// with no location info. + /// + /// + protected XmlLayoutBase() : this(false) + { + IgnoresException = false; + } + + /// + /// Protected constructor to support subclasses + /// + /// + /// + /// The parameter determines whether + /// location information will be output by the layout. If + /// is set to true, then the + /// file name and line number of the statement at the origin of the log + /// statement will be output. + /// + /// + /// If you are embedding this layout within an SMTPAppender + /// then make sure to set the LocationInfo option of that + /// appender as well. + /// + /// + protected XmlLayoutBase(bool locationInfo) + { + IgnoresException = false; + m_locationInfo = locationInfo; + } + + #endregion Protected Instance Constructors + + #region Public Instance Properties + + /// + /// Gets a value indicating whether to include location information in + /// the XML events. + /// + /// + /// true if location information should be included in the XML + /// events; otherwise, false. + /// + /// + /// + /// If is set to true, then the file + /// name and line number of the statement at the origin of the log + /// statement will be output. + /// + /// + /// If you are embedding this layout within an SMTPAppender + /// then make sure to set the LocationInfo option of that + /// appender as well. + /// + /// + public bool LocationInfo + { + get { return m_locationInfo; } + set { m_locationInfo = value; } + } + /// + /// The string to replace characters that can not be expressed in XML with. + /// + /// + /// Not all characters may be expressed in XML. This property contains the + /// string to replace those that can not with. This defaults to a ?. Set it + /// to the empty string to simply remove offending characters. For more + /// details on the allowed character ranges see http://www.w3.org/TR/REC-xml/#charsets + /// Character replacement will occur in the log message, the property names + /// and the property values. + /// + /// + /// + public string InvalidCharReplacement + { + get {return m_invalidCharReplacement;} + set {m_invalidCharReplacement=value;} + } + #endregion + + #region Implementation of IOptionHandler + + /// + /// Initialize layout options + /// + /// + /// + /// This is part of the delayed object + /// activation scheme. The method must + /// be called on this object after the configuration properties have + /// been set. Until is called this + /// object is in an undefined state and must not be used. + /// + /// + /// If any of the configuration properties are modified then + /// must be called again. + /// + /// + public override void ActivateOptions() + { + // nothing to do + } + + #endregion Implementation of IOptionHandler + + #region Override implementation of LayoutSkeleton + + /// + /// Gets the content type output by this layout. + /// + /// + /// As this is the XML layout, the value is always "text/xml". + /// + /// + /// + /// As this is the XML layout, the value is always "text/xml". + /// + /// + public override string ContentType + { + get { return "text/xml"; } + } + + /// + /// Produces a formatted string. + /// + /// The event being logged. + /// The TextWriter to write the formatted event to + /// + /// + /// Format the and write it to the . + /// + /// + /// This method creates an that writes to the + /// . The is passed + /// to the method. Subclasses should override the + /// method rather than this method. + /// + /// + public override void Format(TextWriter writer, LoggingEvent loggingEvent) + { + if (loggingEvent == null) + { + throw new ArgumentNullException("loggingEvent"); + } #if NETSTANDARD - var settings = new XmlWriterSettings - { - Indent = false, - OmitXmlDeclaration = true - }; - using var xmlWriter = XmlWriter.Create(new ProtectCloseTextWriter(writer), settings); + var settings = new XmlWriterSettings + { + Indent = false, + OmitXmlDeclaration = true + }; + using var xmlWriter = XmlWriter.Create(new ProtectCloseTextWriter(writer), settings); #else - using XmlTextWriter xmlWriter = new XmlTextWriter(new ProtectCloseTextWriter(writer)); - xmlWriter.Formatting = Formatting.None; - xmlWriter.Namespaces = false; + using XmlTextWriter xmlWriter = new XmlTextWriter(new ProtectCloseTextWriter(writer)); + xmlWriter.Formatting = Formatting.None; + xmlWriter.Namespaces = false; #endif - // Write the event to the writer - FormatXml(xmlWriter, loggingEvent); + // Write the event to the writer + FormatXml(xmlWriter, loggingEvent); - xmlWriter.WriteWhitespace(SystemInfo.NewLine); + xmlWriter.WriteWhitespace(SystemInfo.NewLine); - // Close on xmlWriter will ensure xml is flushed - // the protected writer will ignore the actual close - // -> Dispose from using var will close & flush - } + // Close on xmlWriter will ensure xml is flushed + // the protected writer will ignore the actual close + // -> Dispose from using var will close & flush + } - #endregion Override implementation of LayoutSkeleton + #endregion Override implementation of LayoutSkeleton - #region Protected Instance Methods + #region Protected Instance Methods - /// - /// Does the actual writing of the XML. - /// - /// The writer to use to output the event to. - /// The event to write. - /// - /// - /// Subclasses should override this method to format - /// the as XML. - /// - /// - protected abstract void FormatXml(XmlWriter writer, LoggingEvent loggingEvent); + /// + /// Does the actual writing of the XML. + /// + /// The writer to use to output the event to. + /// The event to write. + /// + /// + /// Subclasses should override this method to format + /// the as XML. + /// + /// + protected abstract void FormatXml(XmlWriter writer, LoggingEvent loggingEvent); - #endregion Protected Instance Methods + #endregion Protected Instance Methods - #region Private Instance Fields + #region Private Instance Fields - /// - /// Flag to indicate if location information should be included in - /// the XML events. - /// - private bool m_locationInfo = false; - - /// - /// The string to replace invalid chars with - /// - private string m_invalidCharReplacement="?"; - - #endregion Private Instance Fields - } + /// + /// Flag to indicate if location information should be included in + /// the XML events. + /// + private bool m_locationInfo = false; + + /// + /// The string to replace invalid chars with + /// + private string m_invalidCharReplacement="?"; + + #endregion Private Instance Fields + } } diff --git a/src/log4net/Layout/XmlLayoutSchemaLog4j.cs b/src/log4net/Layout/XmlLayoutSchemaLog4j.cs index d5ac73fd..db6fb5a2 100644 --- a/src/log4net/Layout/XmlLayoutSchemaLog4j.cs +++ b/src/log4net/Layout/XmlLayoutSchemaLog4j.cs @@ -27,83 +27,83 @@ namespace log4net.Layout { - /// - /// Layout that formats the log events as XML elements compatible with the log4j schema - /// - /// - /// - /// Formats the log events according to the http://logging.apache.org/log4j schema. - /// - /// - /// Nicko Cadell - public class XmlLayoutSchemaLog4j : XmlLayoutBase - { - #region Static Members - - /// - /// The 1st of January 1970 in UTC - /// - private static readonly DateTime s_date1970 = new DateTime(1970, 1, 1); - - #endregion - - #region Constructors - - /// - /// Constructs an XMLLayoutSchemaLog4j - /// - public XmlLayoutSchemaLog4j() : base() - { - } - - /// - /// Constructs an XMLLayoutSchemaLog4j. - /// - /// - /// - /// The LocationInfo option takes a boolean value. By - /// default, it is set to false which means there will be no location - /// information output by this layout. If the the option is set to - /// true, then the file name and line number of the statement - /// at the origin of the log statement will be output. - /// - /// - /// If you are embedding this layout within an SMTPAppender - /// then make sure to set the LocationInfo option of that - /// appender as well. - /// - /// - public XmlLayoutSchemaLog4j(bool locationInfo) : base(locationInfo) - { - } - - #endregion - - #region Public Properties - - /// - /// The version of the log4j schema to use. - /// - /// - /// - /// Only version 1.2 of the log4j schema is supported. - /// - /// - public string Version - { - get { return "1.2"; } - set - { - if (value != "1.2") - { - throw new ArgumentException("Only version 1.2 of the log4j schema is currently supported"); - } - } - } - - #endregion - - /* Example log4j schema event + /// + /// Layout that formats the log events as XML elements compatible with the log4j schema + /// + /// + /// + /// Formats the log events according to the http://logging.apache.org/log4j schema. + /// + /// + /// Nicko Cadell + public class XmlLayoutSchemaLog4j : XmlLayoutBase + { + #region Static Members + + /// + /// The 1st of January 1970 in UTC + /// + private static readonly DateTime s_date1970 = new DateTime(1970, 1, 1); + + #endregion + + #region Constructors + + /// + /// Constructs an XMLLayoutSchemaLog4j + /// + public XmlLayoutSchemaLog4j() : base() + { + } + + /// + /// Constructs an XMLLayoutSchemaLog4j. + /// + /// + /// + /// The LocationInfo option takes a boolean value. By + /// default, it is set to false which means there will be no location + /// information output by this layout. If the the option is set to + /// true, then the file name and line number of the statement + /// at the origin of the log statement will be output. + /// + /// + /// If you are embedding this layout within an SMTPAppender + /// then make sure to set the LocationInfo option of that + /// appender as well. + /// + /// + public XmlLayoutSchemaLog4j(bool locationInfo) : base(locationInfo) + { + } + + #endregion + + #region Public Properties + + /// + /// The version of the log4j schema to use. + /// + /// + /// + /// Only version 1.2 of the log4j schema is supported. + /// + /// + public string Version + { + get { return "1.2"; } + set + { + if (value != "1.2") + { + throw new ArgumentException("Only version 1.2 of the log4j schema is currently supported"); + } + } + } + + #endregion + + /* Example log4j schema event @@ -112,7 +112,7 @@ public string Version @@ -122,159 +122,159 @@ at org.apache.log4j.chainsaw.Generator.run(Generator.java:94) - */ - - /* Since log4j 1.3 the log4j:MDC has been combined into the log4j:properties element */ - - /// - /// Actually do the writing of the xml - /// - /// the writer to use - /// the event to write - /// - /// - /// Generate XML that is compatible with the log4j schema. - /// - /// - protected override void FormatXml(XmlWriter writer, LoggingEvent loggingEvent) - { - // Translate logging events for log4j - - // Translate hostname property - if (loggingEvent.LookupProperty(LoggingEvent.HostNameProperty) != null && - loggingEvent.LookupProperty("log4jmachinename") == null) - { - loggingEvent.GetProperties()["log4jmachinename"] = loggingEvent.LookupProperty(LoggingEvent.HostNameProperty); - } - - // translate appdomain name - if (loggingEvent.LookupProperty("log4japp") == null && - loggingEvent.Domain != null && - loggingEvent.Domain.Length > 0) - { - loggingEvent.GetProperties()["log4japp"] = loggingEvent.Domain; - } - - // translate identity name - if (loggingEvent.Identity != null && - loggingEvent.Identity.Length > 0 && - loggingEvent.LookupProperty(LoggingEvent.IdentityProperty) == null) - { - loggingEvent.GetProperties()[LoggingEvent.IdentityProperty] = loggingEvent.Identity; - } - - // translate user name - if (loggingEvent.UserName != null && - loggingEvent.UserName.Length > 0 && - loggingEvent.LookupProperty(LoggingEvent.UserNameProperty) == null) - { - loggingEvent.GetProperties()[LoggingEvent.UserNameProperty] = loggingEvent.UserName; - } - - // Write the start element - #if NETSTANDARD - writer.WriteStartElement("log4j", "event", "log4net"); - #else - writer.WriteStartElement("log4j:event"); - #endif - writer.WriteAttributeString("logger", loggingEvent.LoggerName); - - // Calculate the timestamp as the number of milliseconds since january 1970 - // - // We must convert the TimeStamp to UTC before performing any mathematical - // operations. This allows use to take into account discontinuities - // caused by daylight savings time transitions. - TimeSpan timeSince1970 = loggingEvent.TimeStampUtc - s_date1970; - - writer.WriteAttributeString("timestamp", XmlConvert.ToString((long)timeSince1970.TotalMilliseconds)); - writer.WriteAttributeString("level", loggingEvent.Level.DisplayName); - writer.WriteAttributeString("thread", loggingEvent.ThreadName); + */ + + /* Since log4j 1.3 the log4j:MDC has been combined into the log4j:properties element */ + + /// + /// Actually do the writing of the xml + /// + /// the writer to use + /// the event to write + /// + /// + /// Generate XML that is compatible with the log4j schema. + /// + /// + protected override void FormatXml(XmlWriter writer, LoggingEvent loggingEvent) + { + // Translate logging events for log4j + + // Translate hostname property + if (loggingEvent.LookupProperty(LoggingEvent.HostNameProperty) != null && + loggingEvent.LookupProperty("log4jmachinename") == null) + { + loggingEvent.GetProperties()["log4jmachinename"] = loggingEvent.LookupProperty(LoggingEvent.HostNameProperty); + } + + // translate appdomain name + if (loggingEvent.LookupProperty("log4japp") == null && + loggingEvent.Domain != null && + loggingEvent.Domain.Length > 0) + { + loggingEvent.GetProperties()["log4japp"] = loggingEvent.Domain; + } + + // translate identity name + if (loggingEvent.Identity != null && + loggingEvent.Identity.Length > 0 && + loggingEvent.LookupProperty(LoggingEvent.IdentityProperty) == null) + { + loggingEvent.GetProperties()[LoggingEvent.IdentityProperty] = loggingEvent.Identity; + } + + // translate user name + if (loggingEvent.UserName != null && + loggingEvent.UserName.Length > 0 && + loggingEvent.LookupProperty(LoggingEvent.UserNameProperty) == null) + { + loggingEvent.GetProperties()[LoggingEvent.UserNameProperty] = loggingEvent.UserName; + } + + // Write the start element + #if NETSTANDARD + writer.WriteStartElement("log4j", "event", "log4net"); + #else + writer.WriteStartElement("log4j:event"); + #endif + writer.WriteAttributeString("logger", loggingEvent.LoggerName); + + // Calculate the timestamp as the number of milliseconds since january 1970 + // + // We must convert the TimeStamp to UTC before performing any mathematical + // operations. This allows use to take into account discontinuities + // caused by daylight savings time transitions. + TimeSpan timeSince1970 = loggingEvent.TimeStampUtc - s_date1970; + + writer.WriteAttributeString("timestamp", XmlConvert.ToString((long)timeSince1970.TotalMilliseconds)); + writer.WriteAttributeString("level", loggingEvent.Level.DisplayName); + writer.WriteAttributeString("thread", loggingEvent.ThreadName); - // Append the message text - #if NETSTANDARD - writer.WriteStartElement("log4j", "message", "log4net"); - #else - writer.WriteStartElement("log4j:message"); - #endif - Transform.WriteEscapedXmlString(writer, loggingEvent.RenderedMessage,this.InvalidCharReplacement); - writer.WriteEndElement(); - - object ndcObj = loggingEvent.LookupProperty("NDC"); - if (ndcObj != null) - { - string valueStr = loggingEvent.Repository.RendererMap.FindAndRender(ndcObj); - - if (valueStr != null && valueStr.Length > 0) - { - // Append the NDC text - #if NETSTANDARD - writer.WriteStartElement("log4j", "NDC", "log4net"); - #else - writer.WriteStartElement("log4j:NDC"); - #endif - Transform.WriteEscapedXmlString(writer, valueStr,this.InvalidCharReplacement); - writer.WriteEndElement(); - } - } - - // Append the properties text - PropertiesDictionary properties = loggingEvent.GetProperties(); - if (properties.Count > 0) - { - #if NETSTANDARD - writer.WriteStartElement("log4j", "properties", "log4net"); - #else - writer.WriteStartElement("log4j:properties"); - #endif - foreach(System.Collections.DictionaryEntry entry in properties) - { - #if NETSTANDARD - writer.WriteStartElement("log4j", "data", "log4net"); - #else - writer.WriteStartElement("log4j:data"); - #endif - 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(); - if (exceptionStr != null && exceptionStr.Length > 0) - { - // Append the stack trace line - #if NETSTANDARD - writer.WriteStartElement("log4j", "throwable", "log4net"); - #else - writer.WriteStartElement("log4j:throwable"); - #endif - Transform.WriteEscapedXmlString(writer, exceptionStr,this.InvalidCharReplacement); - writer.WriteEndElement(); - } - - if (LocationInfo) - { - LocationInfo locationInfo = loggingEvent.LocationInformation; - - #if NETSTANDARD - writer.WriteStartElement("log4j", "locationInfo", "log4net"); - #else - writer.WriteStartElement("log4j:locationInfo"); - #endif - writer.WriteAttributeString("class", locationInfo.ClassName); - writer.WriteAttributeString("method", locationInfo.MethodName); - writer.WriteAttributeString("file", locationInfo.FileName); - writer.WriteAttributeString("line", locationInfo.LineNumber); - writer.WriteEndElement(); - } - - writer.WriteEndElement(); - } - } + // Append the message text + #if NETSTANDARD + writer.WriteStartElement("log4j", "message", "log4net"); + #else + writer.WriteStartElement("log4j:message"); + #endif + Transform.WriteEscapedXmlString(writer, loggingEvent.RenderedMessage,this.InvalidCharReplacement); + writer.WriteEndElement(); + + object ndcObj = loggingEvent.LookupProperty("NDC"); + if (ndcObj != null) + { + string valueStr = loggingEvent.Repository.RendererMap.FindAndRender(ndcObj); + + if (valueStr != null && valueStr.Length > 0) + { + // Append the NDC text + #if NETSTANDARD + writer.WriteStartElement("log4j", "NDC", "log4net"); + #else + writer.WriteStartElement("log4j:NDC"); + #endif + Transform.WriteEscapedXmlString(writer, valueStr,this.InvalidCharReplacement); + writer.WriteEndElement(); + } + } + + // Append the properties text + PropertiesDictionary properties = loggingEvent.GetProperties(); + if (properties.Count > 0) + { + #if NETSTANDARD + writer.WriteStartElement("log4j", "properties", "log4net"); + #else + writer.WriteStartElement("log4j:properties"); + #endif + foreach(System.Collections.DictionaryEntry entry in properties) + { + #if NETSTANDARD + writer.WriteStartElement("log4j", "data", "log4net"); + #else + writer.WriteStartElement("log4j:data"); + #endif + 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(); + if (exceptionStr != null && exceptionStr.Length > 0) + { + // Append the stack trace line + #if NETSTANDARD + writer.WriteStartElement("log4j", "throwable", "log4net"); + #else + writer.WriteStartElement("log4j:throwable"); + #endif + Transform.WriteEscapedXmlString(writer, exceptionStr,this.InvalidCharReplacement); + writer.WriteEndElement(); + } + + if (LocationInfo) + { + LocationInfo locationInfo = loggingEvent.LocationInformation; + + #if NETSTANDARD + writer.WriteStartElement("log4j", "locationInfo", "log4net"); + #else + writer.WriteStartElement("log4j:locationInfo"); + #endif + writer.WriteAttributeString("class", locationInfo.ClassName); + writer.WriteAttributeString("method", locationInfo.MethodName); + writer.WriteAttributeString("file", locationInfo.FileName); + writer.WriteAttributeString("line", locationInfo.LineNumber); + writer.WriteEndElement(); + } + + writer.WriteEndElement(); + } + } } diff --git a/src/log4net/LogManager.cs b/src/log4net/LogManager.cs index b3598e2a..664d39cd 100644 --- a/src/log4net/LogManager.cs +++ b/src/log4net/LogManager.cs @@ -25,107 +25,107 @@ namespace log4net { - /// - /// This class is used by client applications to request logger instances. - /// - /// - /// - /// This class has static methods that are used by a client to request - /// a logger instance. The method is - /// used to retrieve a logger. - /// - /// - /// See the interface for more details. - /// - /// - /// Simple example of logging messages - /// - /// ILog log = LogManager.GetLogger("application-log"); - /// - /// log.Info("Application Start"); - /// log.Debug("This is a debug message"); - /// - /// if (log.IsDebugEnabled) - /// { - /// log.Debug("This is another debug message"); - /// } - /// - /// - /// - /// - /// Nicko Cadell - /// Gert Driesen - public sealed class LogManager - { - #region Private Instance Constructors - - /// - /// Initializes a new instance of the class. - /// - /// - /// Uses a private access modifier to prevent instantiation of this class. - /// - private LogManager() - { - } - - #endregion Private Instance Constructors - - #region Type Specific Manager Methods + /// + /// This class is used by client applications to request logger instances. + /// + /// + /// + /// This class has static methods that are used by a client to request + /// a logger instance. The method is + /// used to retrieve a logger. + /// + /// + /// See the interface for more details. + /// + /// + /// Simple example of logging messages + /// + /// ILog log = LogManager.GetLogger("application-log"); + /// + /// log.Info("Application Start"); + /// log.Debug("This is a debug message"); + /// + /// if (log.IsDebugEnabled) + /// { + /// log.Debug("This is another debug message"); + /// } + /// + /// + /// + /// + /// Nicko Cadell + /// Gert Driesen + public sealed class LogManager + { + #region Private Instance Constructors + + /// + /// Initializes a new instance of the class. + /// + /// + /// Uses a private access modifier to prevent instantiation of this class. + /// + private LogManager() + { + } + + #endregion Private Instance Constructors + + #region Type Specific Manager Methods #if !NETSTANDARD1_3 // Excluded because GetCallingAssembly() is not available in CoreFX (https://github.com/dotnet/corefx/issues/2221). - /// Returns the named logger if it exists. - /// - /// Returns the named logger if it exists. - /// - /// - /// - /// If the named logger exists (in the default repository) then it - /// returns a reference to the logger, otherwise it returns null. - /// - /// - /// The fully qualified logger name to look for. - /// The logger found, or null if no logger could be found. - public static ILog Exists(string name) - { - return Exists(Assembly.GetCallingAssembly(), name); - } + /// Returns the named logger if it exists. + /// + /// Returns the named logger if it exists. + /// + /// + /// + /// If the named logger exists (in the default repository) then it + /// returns a reference to the logger, otherwise it returns null. + /// + /// + /// The fully qualified logger name to look for. + /// The logger found, or null if no logger could be found. + public static ILog Exists(string name) + { + return Exists(Assembly.GetCallingAssembly(), name); + } - /// Get the currently defined loggers. - /// - /// Returns all the currently defined loggers in the default repository. - /// - /// - /// The root logger is not included in the returned array. - /// - /// All the defined loggers. - public static ILog[] GetCurrentLoggers() - { - return GetCurrentLoggers(Assembly.GetCallingAssembly()); - } + /// Get the currently defined loggers. + /// + /// Returns all the currently defined loggers in the default repository. + /// + /// + /// The root logger is not included in the returned array. + /// + /// All the defined loggers. + public static ILog[] GetCurrentLoggers() + { + return GetCurrentLoggers(Assembly.GetCallingAssembly()); + } - /// Get or create a logger. - /// - /// Retrieves or creates a named logger. - /// - /// - /// - /// Retrieves a logger named as the - /// parameter. If the named logger already exists, then the - /// existing instance will be returned. Otherwise, a new instance is - /// created. - /// - /// By default, loggers do not have a set level but inherit - /// it from the hierarchy. This is one of the central features of - /// log4net. - /// - /// - /// The name of the logger to retrieve. - /// The logger with the name specified. - public static ILog GetLogger(string name) - { - return GetLogger(Assembly.GetCallingAssembly(), name); - } + /// Get or create a logger. + /// + /// Retrieves or creates a named logger. + /// + /// + /// + /// Retrieves a logger named as the + /// parameter. If the named logger already exists, then the + /// existing instance will be returned. Otherwise, a new instance is + /// created. + /// + /// By default, loggers do not have a set level but inherit + /// it from the hierarchy. This is one of the central features of + /// log4net. + /// + /// + /// The name of the logger to retrieve. + /// The logger with the name specified. + public static ILog GetLogger(string name) + { + return GetLogger(Assembly.GetCallingAssembly(), name); + } #endif // !NETSTANDARD1_3 /// @@ -145,611 +145,611 @@ public static ILog GetLogger(string name) /// repository. /// public static ILog Exists(string repository, string name) - { - return WrapLogger(LoggerManager.Exists(repository, name)); - } - - /// - /// Returns the named logger if it exists. - /// - /// - /// - /// If the named logger exists (in the repository for the specified assembly) then it - /// returns a reference to the logger, otherwise it returns - /// null. - /// - /// - /// The assembly to use to lookup the repository. - /// The fully qualified logger name to look for. - /// - /// The logger, or null if the logger doesn't exist in the specified - /// assembly's repository. - /// - public static ILog Exists(Assembly repositoryAssembly, string name) - { - return WrapLogger(LoggerManager.Exists(repositoryAssembly, name)); - } - - /// - /// Returns all the currently defined loggers in the specified repository. - /// - /// The repository to lookup in. - /// - /// The root logger is not included in the returned array. - /// - /// All the defined loggers. - public static ILog[] GetCurrentLoggers(string repository) - { - return WrapLoggers(LoggerManager.GetCurrentLoggers(repository)); - } - - /// - /// Returns all the currently defined loggers in the specified assembly's repository. - /// - /// The assembly to use to lookup the repository. - /// - /// The root logger is not included in the returned array. - /// - /// All the defined loggers. - public static ILog[] GetCurrentLoggers(Assembly repositoryAssembly) - { - return WrapLoggers(LoggerManager.GetCurrentLoggers(repositoryAssembly)); - } - - /// - /// Retrieves or creates a named logger. - /// - /// - /// - /// Retrieve a logger named as the - /// parameter. If the named logger already exists, then the - /// existing instance will be returned. Otherwise, a new instance is - /// created. - /// - /// - /// By default, loggers do not have a set level but inherit - /// it from the hierarchy. This is one of the central features of - /// log4net. - /// - /// - /// The repository to lookup in. - /// The name of the logger to retrieve. - /// The logger with the name specified. - public static ILog GetLogger(string repository, string name) - { - return WrapLogger(LoggerManager.GetLogger(repository, name)); - } - - /// - /// Retrieves or creates a named logger. - /// - /// - /// - /// Retrieve a logger named as the - /// parameter. If the named logger already exists, then the - /// existing instance will be returned. Otherwise, a new instance is - /// created. - /// - /// - /// By default, loggers do not have a set level but inherit - /// it from the hierarchy. This is one of the central features of - /// log4net. - /// - /// - /// The assembly to use to lookup the repository. - /// The name of the logger to retrieve. - /// The logger with the name specified. - public static ILog GetLogger(Assembly repositoryAssembly, string name) - { - return WrapLogger(LoggerManager.GetLogger(repositoryAssembly, name)); - } - - /// - /// Shorthand for . - /// - /// - /// Get the logger for the fully qualified name of the type specified. - /// - /// The full name of will be used as the name of the logger to retrieve. - /// The logger with the name specified. - public static ILog GetLogger(Type type) - { + { + return WrapLogger(LoggerManager.Exists(repository, name)); + } + + /// + /// Returns the named logger if it exists. + /// + /// + /// + /// If the named logger exists (in the repository for the specified assembly) then it + /// returns a reference to the logger, otherwise it returns + /// null. + /// + /// + /// The assembly to use to lookup the repository. + /// The fully qualified logger name to look for. + /// + /// The logger, or null if the logger doesn't exist in the specified + /// assembly's repository. + /// + public static ILog Exists(Assembly repositoryAssembly, string name) + { + return WrapLogger(LoggerManager.Exists(repositoryAssembly, name)); + } + + /// + /// Returns all the currently defined loggers in the specified repository. + /// + /// The repository to lookup in. + /// + /// The root logger is not included in the returned array. + /// + /// All the defined loggers. + public static ILog[] GetCurrentLoggers(string repository) + { + return WrapLoggers(LoggerManager.GetCurrentLoggers(repository)); + } + + /// + /// Returns all the currently defined loggers in the specified assembly's repository. + /// + /// The assembly to use to lookup the repository. + /// + /// The root logger is not included in the returned array. + /// + /// All the defined loggers. + public static ILog[] GetCurrentLoggers(Assembly repositoryAssembly) + { + return WrapLoggers(LoggerManager.GetCurrentLoggers(repositoryAssembly)); + } + + /// + /// Retrieves or creates a named logger. + /// + /// + /// + /// Retrieve a logger named as the + /// parameter. If the named logger already exists, then the + /// existing instance will be returned. Otherwise, a new instance is + /// created. + /// + /// + /// By default, loggers do not have a set level but inherit + /// it from the hierarchy. This is one of the central features of + /// log4net. + /// + /// + /// The repository to lookup in. + /// The name of the logger to retrieve. + /// The logger with the name specified. + public static ILog GetLogger(string repository, string name) + { + return WrapLogger(LoggerManager.GetLogger(repository, name)); + } + + /// + /// Retrieves or creates a named logger. + /// + /// + /// + /// Retrieve a logger named as the + /// parameter. If the named logger already exists, then the + /// existing instance will be returned. Otherwise, a new instance is + /// created. + /// + /// + /// By default, loggers do not have a set level but inherit + /// it from the hierarchy. This is one of the central features of + /// log4net. + /// + /// + /// The assembly to use to lookup the repository. + /// The name of the logger to retrieve. + /// The logger with the name specified. + public static ILog GetLogger(Assembly repositoryAssembly, string name) + { + return WrapLogger(LoggerManager.GetLogger(repositoryAssembly, name)); + } + + /// + /// Shorthand for . + /// + /// + /// Get the logger for the fully qualified name of the type specified. + /// + /// The full name of will be used as the name of the logger to retrieve. + /// The logger with the name specified. + public static ILog GetLogger(Type type) + { #if NETSTANDARD1_3 - return GetLogger(type.GetTypeInfo().Assembly, type.FullName); + return GetLogger(type.GetTypeInfo().Assembly, type.FullName); #else - return GetLogger(Assembly.GetCallingAssembly(), type.FullName); + return GetLogger(Assembly.GetCallingAssembly(), type.FullName); #endif - } - - /// - /// Shorthand for . - /// - /// - /// Gets the logger for the fully qualified name of the type specified. - /// - /// The repository to lookup in. - /// The full name of will be used as the name of the logger to retrieve. - /// The logger with the name specified. - public static ILog GetLogger(string repository, Type type) - { - return WrapLogger(LoggerManager.GetLogger(repository, type)); - } - - /// - /// Shorthand for . - /// - /// - /// Gets the logger for the fully qualified name of the type specified. - /// - /// The assembly to use to lookup the repository. - /// The full name of will be used as the name of the logger to retrieve. - /// The logger with the name specified. - public static ILog GetLogger(Assembly repositoryAssembly, Type type) - { - return WrapLogger(LoggerManager.GetLogger(repositoryAssembly, type)); - } - - #endregion Type Specific Manager Methods - - #region Domain & Repository Manager Methods - - /// - /// Shuts down the log4net system. - /// - /// - /// - /// Calling this method will safely close and remove all - /// appenders in all the loggers including root contained in all the - /// default repositories. - /// - /// - /// Some appenders need to be closed before the application exists. - /// Otherwise, pending logging events might be lost. - /// - /// The shutdown method is careful to close nested - /// appenders before closing regular appenders. This is allows - /// configurations where a regular appender is attached to a logger - /// and again to a nested appender. - /// - /// - public static void Shutdown() - { - LoggerManager.Shutdown(); - } + } + + /// + /// Shorthand for . + /// + /// + /// Gets the logger for the fully qualified name of the type specified. + /// + /// The repository to lookup in. + /// The full name of will be used as the name of the logger to retrieve. + /// The logger with the name specified. + public static ILog GetLogger(string repository, Type type) + { + return WrapLogger(LoggerManager.GetLogger(repository, type)); + } + + /// + /// Shorthand for . + /// + /// + /// Gets the logger for the fully qualified name of the type specified. + /// + /// The assembly to use to lookup the repository. + /// The full name of will be used as the name of the logger to retrieve. + /// The logger with the name specified. + public static ILog GetLogger(Assembly repositoryAssembly, Type type) + { + return WrapLogger(LoggerManager.GetLogger(repositoryAssembly, type)); + } + + #endregion Type Specific Manager Methods + + #region Domain & Repository Manager Methods + + /// + /// Shuts down the log4net system. + /// + /// + /// + /// Calling this method will safely close and remove all + /// appenders in all the loggers including root contained in all the + /// default repositories. + /// + /// + /// Some appenders need to be closed before the application exists. + /// Otherwise, pending logging events might be lost. + /// + /// The shutdown method is careful to close nested + /// appenders before closing regular appenders. This is allows + /// configurations where a regular appender is attached to a logger + /// and again to a nested appender. + /// + /// + public static void Shutdown() + { + LoggerManager.Shutdown(); + } #if !NETSTANDARD1_3 - /// Shutdown a logger repository. - /// - /// Shuts down the default repository. - /// - /// - /// - /// Calling this method will safely close and remove all - /// appenders in all the loggers including root contained in the - /// default repository. - /// - /// Some appenders need to be closed before the application exists. - /// Otherwise, pending logging events might be lost. - /// - /// The shutdown method is careful to close nested - /// appenders before closing regular appenders. This is allows - /// configurations where a regular appender is attached to a logger - /// and again to a nested appender. - /// - /// - public static void ShutdownRepository() - { - ShutdownRepository(Assembly.GetCallingAssembly()); - } + /// Shutdown a logger repository. + /// + /// Shuts down the default repository. + /// + /// + /// + /// Calling this method will safely close and remove all + /// appenders in all the loggers including root contained in the + /// default repository. + /// + /// Some appenders need to be closed before the application exists. + /// Otherwise, pending logging events might be lost. + /// + /// The shutdown method is careful to close nested + /// appenders before closing regular appenders. This is allows + /// configurations where a regular appender is attached to a logger + /// and again to a nested appender. + /// + /// + public static void ShutdownRepository() + { + ShutdownRepository(Assembly.GetCallingAssembly()); + } #endif - /// - /// Shuts down the repository for the repository specified. - /// - /// - /// - /// Calling this method will safely close and remove all - /// appenders in all the loggers including root contained in the - /// specified. - /// - /// - /// Some appenders need to be closed before the application exists. - /// Otherwise, pending logging events might be lost. - /// - /// The shutdown method is careful to close nested - /// appenders before closing regular appenders. This is allows - /// configurations where a regular appender is attached to a logger - /// and again to a nested appender. - /// - /// - /// The repository to shutdown. - public static void ShutdownRepository(string repository) - { - LoggerManager.ShutdownRepository(repository); - } - - /// - /// Shuts down the repository specified. - /// - /// - /// - /// Calling this method will safely close and remove all - /// appenders in all the loggers including root contained in the - /// repository. The repository is looked up using - /// the specified. - /// - /// - /// Some appenders need to be closed before the application exists. - /// Otherwise, pending logging events might be lost. - /// - /// - /// The shutdown method is careful to close nested - /// appenders before closing regular appenders. This is allows - /// configurations where a regular appender is attached to a logger - /// and again to a nested appender. - /// - /// - /// The assembly to use to lookup the repository. - public static void ShutdownRepository(Assembly repositoryAssembly) - { - LoggerManager.ShutdownRepository(repositoryAssembly); - } + /// + /// Shuts down the repository for the repository specified. + /// + /// + /// + /// Calling this method will safely close and remove all + /// appenders in all the loggers including root contained in the + /// specified. + /// + /// + /// Some appenders need to be closed before the application exists. + /// Otherwise, pending logging events might be lost. + /// + /// The shutdown method is careful to close nested + /// appenders before closing regular appenders. This is allows + /// configurations where a regular appender is attached to a logger + /// and again to a nested appender. + /// + /// + /// The repository to shutdown. + public static void ShutdownRepository(string repository) + { + LoggerManager.ShutdownRepository(repository); + } + + /// + /// Shuts down the repository specified. + /// + /// + /// + /// Calling this method will safely close and remove all + /// appenders in all the loggers including root contained in the + /// repository. The repository is looked up using + /// the specified. + /// + /// + /// Some appenders need to be closed before the application exists. + /// Otherwise, pending logging events might be lost. + /// + /// + /// The shutdown method is careful to close nested + /// appenders before closing regular appenders. This is allows + /// configurations where a regular appender is attached to a logger + /// and again to a nested appender. + /// + /// + /// The assembly to use to lookup the repository. + public static void ShutdownRepository(Assembly repositoryAssembly) + { + LoggerManager.ShutdownRepository(repositoryAssembly); + } #if !NETSTANDARD1_3 - /// Reset the configuration of a repository - /// - /// Resets all values contained in this repository instance to their defaults. - /// - /// - /// - /// Resets all values contained in the repository instance to their - /// defaults. This removes all appenders from all loggers, sets - /// the level of all non-root loggers to null, - /// sets their additivity flag to true and sets the level - /// of the root logger to . Moreover, - /// message disabling is set to its default "off" value. - /// - /// - public static void ResetConfiguration() - { - ResetConfiguration(Assembly.GetCallingAssembly()); - } + /// Reset the configuration of a repository + /// + /// Resets all values contained in this repository instance to their defaults. + /// + /// + /// + /// Resets all values contained in the repository instance to their + /// defaults. This removes all appenders from all loggers, sets + /// the level of all non-root loggers to null, + /// sets their additivity flag to true and sets the level + /// of the root logger to . Moreover, + /// message disabling is set to its default "off" value. + /// + /// + public static void ResetConfiguration() + { + ResetConfiguration(Assembly.GetCallingAssembly()); + } #endif - /// - /// Resets all values contained in this repository instance to their defaults. - /// - /// - /// - /// Reset all values contained in the repository instance to their - /// defaults. This removes all appenders from all loggers, sets - /// the level of all non-root loggers to null, - /// sets their additivity flag to true and sets the level - /// of the root logger to . Moreover, - /// message disabling is set to its default "off" value. - /// - /// - /// The repository to reset. - public static void ResetConfiguration(string repository) - { - LoggerManager.ResetConfiguration(repository); - } - - /// - /// Resets all values contained in this repository instance to their defaults. - /// - /// - /// - /// Reset all values contained in the repository instance to their - /// defaults. This removes all appenders from all loggers, sets - /// the level of all non-root loggers to null, - /// sets their additivity flag to true and sets the level - /// of the root logger to . Moreover, - /// message disabling is set to its default "off" value. - /// - /// - /// The assembly to use to lookup the repository to reset. - public static void ResetConfiguration(Assembly repositoryAssembly) - { - LoggerManager.ResetConfiguration(repositoryAssembly); - } + /// + /// Resets all values contained in this repository instance to their defaults. + /// + /// + /// + /// Reset all values contained in the repository instance to their + /// defaults. This removes all appenders from all loggers, sets + /// the level of all non-root loggers to null, + /// sets their additivity flag to true and sets the level + /// of the root logger to . Moreover, + /// message disabling is set to its default "off" value. + /// + /// + /// The repository to reset. + public static void ResetConfiguration(string repository) + { + LoggerManager.ResetConfiguration(repository); + } + + /// + /// Resets all values contained in this repository instance to their defaults. + /// + /// + /// + /// Reset all values contained in the repository instance to their + /// defaults. This removes all appenders from all loggers, sets + /// the level of all non-root loggers to null, + /// sets their additivity flag to true and sets the level + /// of the root logger to . Moreover, + /// message disabling is set to its default "off" value. + /// + /// + /// The assembly to use to lookup the repository to reset. + public static void ResetConfiguration(Assembly repositoryAssembly) + { + LoggerManager.ResetConfiguration(repositoryAssembly); + } #if !NETSTANDARD1_3 - /// Get the logger repository. - /// - /// Returns the default instance. - /// - /// - /// - /// Gets the for the repository specified - /// by the callers assembly (). - /// - /// - /// The instance for the default repository. - [Obsolete("Use GetRepository instead of GetLoggerRepository")] - public static ILoggerRepository GetLoggerRepository() - { - return GetRepository(Assembly.GetCallingAssembly()); - } + /// Get the logger repository. + /// + /// Returns the default instance. + /// + /// + /// + /// Gets the for the repository specified + /// by the callers assembly (). + /// + /// + /// The instance for the default repository. + [Obsolete("Use GetRepository instead of GetLoggerRepository")] + public static ILoggerRepository GetLoggerRepository() + { + return GetRepository(Assembly.GetCallingAssembly()); + } #endif - /// - /// Returns the default instance. - /// - /// The default instance. - /// - /// - /// Gets the for the repository specified - /// by the argument. - /// - /// - /// The repository to lookup in. - [Obsolete("Use GetRepository instead of GetLoggerRepository")] - public static ILoggerRepository GetLoggerRepository(string repository) - { - return GetRepository(repository); - } - - /// - /// Returns the default instance. - /// - /// The default instance. - /// - /// - /// Gets the for the repository specified - /// by the argument. - /// - /// - /// The assembly to use to lookup the repository. - [Obsolete("Use GetRepository instead of GetLoggerRepository")] - public static ILoggerRepository GetLoggerRepository(Assembly repositoryAssembly) - { - return GetRepository(repositoryAssembly); - } + /// + /// Returns the default instance. + /// + /// The default instance. + /// + /// + /// Gets the for the repository specified + /// by the argument. + /// + /// + /// The repository to lookup in. + [Obsolete("Use GetRepository instead of GetLoggerRepository")] + public static ILoggerRepository GetLoggerRepository(string repository) + { + return GetRepository(repository); + } + + /// + /// Returns the default instance. + /// + /// The default instance. + /// + /// + /// Gets the for the repository specified + /// by the argument. + /// + /// + /// The assembly to use to lookup the repository. + [Obsolete("Use GetRepository instead of GetLoggerRepository")] + public static ILoggerRepository GetLoggerRepository(Assembly repositoryAssembly) + { + return GetRepository(repositoryAssembly); + } #if !NETSTANDARD1_3 - /// Get a logger repository. - /// - /// Returns the default instance. - /// - /// - /// - /// Gets the for the repository specified - /// by the callers assembly (). - /// - /// - /// The instance for the default repository. - public static ILoggerRepository GetRepository() - { - return GetRepository(Assembly.GetCallingAssembly()); - } + /// Get a logger repository. + /// + /// Returns the default instance. + /// + /// + /// + /// Gets the for the repository specified + /// by the callers assembly (). + /// + /// + /// The instance for the default repository. + public static ILoggerRepository GetRepository() + { + return GetRepository(Assembly.GetCallingAssembly()); + } #endif - /// - /// Returns the default instance. - /// - /// The default instance. - /// - /// - /// Gets the for the repository specified - /// by the argument. - /// - /// - /// The repository to lookup in. - public static ILoggerRepository GetRepository(string repository) - { - return LoggerManager.GetRepository(repository); - } - - /// - /// Returns the default instance. - /// - /// The default instance. - /// - /// - /// Gets the for the repository specified - /// by the argument. - /// - /// - /// The assembly to use to lookup the repository. - public static ILoggerRepository GetRepository(Assembly repositoryAssembly) - { - return LoggerManager.GetRepository(repositoryAssembly); - } + /// + /// Returns the default instance. + /// + /// The default instance. + /// + /// + /// Gets the for the repository specified + /// by the argument. + /// + /// + /// The repository to lookup in. + public static ILoggerRepository GetRepository(string repository) + { + return LoggerManager.GetRepository(repository); + } + + /// + /// Returns the default instance. + /// + /// The default instance. + /// + /// + /// Gets the for the repository specified + /// by the argument. + /// + /// + /// The assembly to use to lookup the repository. + public static ILoggerRepository GetRepository(Assembly repositoryAssembly) + { + return LoggerManager.GetRepository(repositoryAssembly); + } #if !NETSTANDARD1_3 - /// Create a domain - /// - /// Creates a repository with the specified repository type. - /// - /// - /// - /// CreateDomain is obsolete. Use CreateRepository instead of CreateDomain. - /// - /// - /// The created will be associated with the repository - /// specified such that a call to will return - /// the same repository instance. - /// - /// - /// A that implements - /// and has a no arg constructor. An instance of this type will be created to act - /// as the for the repository specified. - /// The created for the repository. - [Obsolete("Use CreateRepository instead of CreateDomain")] - public static ILoggerRepository CreateDomain(Type repositoryType) - { - return CreateRepository(Assembly.GetCallingAssembly(), repositoryType); - } - - /// Create a logger repository. - /// - /// Creates a repository with the specified repository type. - /// - /// A that implements - /// and has a no arg constructor. An instance of this type will be created to act - /// as the for the repository specified. - /// The created for the repository. - /// - /// - /// The created will be associated with the repository - /// specified such that a call to will return - /// the same repository instance. - /// - /// - public static ILoggerRepository CreateRepository(Type repositoryType) - { - return CreateRepository(Assembly.GetCallingAssembly(), repositoryType); - } + /// Create a domain + /// + /// Creates a repository with the specified repository type. + /// + /// + /// + /// CreateDomain is obsolete. Use CreateRepository instead of CreateDomain. + /// + /// + /// The created will be associated with the repository + /// specified such that a call to will return + /// the same repository instance. + /// + /// + /// A that implements + /// and has a no arg constructor. An instance of this type will be created to act + /// as the for the repository specified. + /// The created for the repository. + [Obsolete("Use CreateRepository instead of CreateDomain")] + public static ILoggerRepository CreateDomain(Type repositoryType) + { + return CreateRepository(Assembly.GetCallingAssembly(), repositoryType); + } + + /// Create a logger repository. + /// + /// Creates a repository with the specified repository type. + /// + /// A that implements + /// and has a no arg constructor. An instance of this type will be created to act + /// as the for the repository specified. + /// The created for the repository. + /// + /// + /// The created will be associated with the repository + /// specified such that a call to will return + /// the same repository instance. + /// + /// + public static ILoggerRepository CreateRepository(Type repositoryType) + { + return CreateRepository(Assembly.GetCallingAssembly(), repositoryType); + } #endif - /// - /// Creates a repository with the specified name. - /// - /// - /// - /// CreateDomain is obsolete. Use CreateRepository instead of CreateDomain. - /// - /// - /// Creates the default type of which is a - /// object. - /// - /// - /// The name must be unique. Repositories cannot be redefined. - /// An will be thrown if the repository already exists. - /// - /// - /// The name of the repository, this must be unique amongst repositories. - /// The created for the repository. - /// The specified repository already exists. - [Obsolete("Use CreateRepository instead of CreateDomain")] - public static ILoggerRepository CreateDomain(string repository) - { - return LoggerManager.CreateRepository(repository); - } - - /// - /// Creates a repository with the specified name. - /// - /// - /// - /// Creates the default type of which is a - /// object. - /// - /// - /// The name must be unique. Repositories cannot be redefined. - /// An will be thrown if the repository already exists. - /// - /// - /// The name of the repository, this must be unique amongst repositories. - /// The created for the repository. - /// The specified repository already exists. - public static ILoggerRepository CreateRepository(string repository) - { - return LoggerManager.CreateRepository(repository); - } - - /// - /// Creates a repository with the specified name and repository type. - /// - /// - /// - /// CreateDomain is obsolete. Use CreateRepository instead of CreateDomain. - /// - /// - /// The name must be unique. Repositories cannot be redefined. - /// An will be thrown if the repository already exists. - /// - /// - /// The name of the repository, this must be unique to the repository. - /// A that implements - /// and has a no arg constructor. An instance of this type will be created to act - /// as the for the repository specified. - /// The created for the repository. - /// The specified repository already exists. - [Obsolete("Use CreateRepository instead of CreateDomain")] - public static ILoggerRepository CreateDomain(string repository, Type repositoryType) - { - return LoggerManager.CreateRepository(repository, repositoryType); - } - - /// - /// Creates a repository with the specified name and repository type. - /// - /// - /// - /// The name must be unique. Repositories cannot be redefined. - /// An will be thrown if the repository already exists. - /// - /// - /// The name of the repository, this must be unique to the repository. - /// A that implements - /// and has a no arg constructor. An instance of this type will be created to act - /// as the for the repository specified. - /// The created for the repository. - /// The specified repository already exists. - public static ILoggerRepository CreateRepository(string repository, Type repositoryType) - { - return LoggerManager.CreateRepository(repository, repositoryType); - } - - /// - /// Creates a repository for the specified assembly and repository type. - /// - /// - /// - /// CreateDomain is obsolete. Use CreateRepository instead of CreateDomain. - /// - /// - /// The created will be associated with the repository - /// specified such that a call to with the - /// same assembly specified will return the same repository instance. - /// - /// - /// The assembly to use to get the name of the repository. - /// A that implements - /// and has a no arg constructor. An instance of this type will be created to act - /// as the for the repository specified. - /// The created for the repository. - [Obsolete("Use CreateRepository instead of CreateDomain")] - public static ILoggerRepository CreateDomain(Assembly repositoryAssembly, Type repositoryType) - { - return LoggerManager.CreateRepository(repositoryAssembly, repositoryType); - } - - /// - /// Creates a repository for the specified assembly and repository type. - /// - /// - /// - /// The created will be associated with the repository - /// specified such that a call to with the - /// same assembly specified will return the same repository instance. - /// - /// - /// The assembly to use to get the name of the repository. - /// A that implements - /// and has a no arg constructor. An instance of this type will be created to act - /// as the for the repository specified. - /// The created for the repository. - public static ILoggerRepository CreateRepository(Assembly repositoryAssembly, Type repositoryType) - { - return LoggerManager.CreateRepository(repositoryAssembly, repositoryType); - } - - /// - /// Gets the list of currently defined repositories. - /// - /// - /// - /// Get an array of all the objects that have been created. - /// - /// - /// An array of all the known objects. - public static ILoggerRepository[] GetAllRepositories() - { - return LoggerManager.GetAllRepositories(); - } + /// + /// Creates a repository with the specified name. + /// + /// + /// + /// CreateDomain is obsolete. Use CreateRepository instead of CreateDomain. + /// + /// + /// Creates the default type of which is a + /// object. + /// + /// + /// The name must be unique. Repositories cannot be redefined. + /// An will be thrown if the repository already exists. + /// + /// + /// The name of the repository, this must be unique amongst repositories. + /// The created for the repository. + /// The specified repository already exists. + [Obsolete("Use CreateRepository instead of CreateDomain")] + public static ILoggerRepository CreateDomain(string repository) + { + return LoggerManager.CreateRepository(repository); + } + + /// + /// Creates a repository with the specified name. + /// + /// + /// + /// Creates the default type of which is a + /// object. + /// + /// + /// The name must be unique. Repositories cannot be redefined. + /// An will be thrown if the repository already exists. + /// + /// + /// The name of the repository, this must be unique amongst repositories. + /// The created for the repository. + /// The specified repository already exists. + public static ILoggerRepository CreateRepository(string repository) + { + return LoggerManager.CreateRepository(repository); + } + + /// + /// Creates a repository with the specified name and repository type. + /// + /// + /// + /// CreateDomain is obsolete. Use CreateRepository instead of CreateDomain. + /// + /// + /// The name must be unique. Repositories cannot be redefined. + /// An will be thrown if the repository already exists. + /// + /// + /// The name of the repository, this must be unique to the repository. + /// A that implements + /// and has a no arg constructor. An instance of this type will be created to act + /// as the for the repository specified. + /// The created for the repository. + /// The specified repository already exists. + [Obsolete("Use CreateRepository instead of CreateDomain")] + public static ILoggerRepository CreateDomain(string repository, Type repositoryType) + { + return LoggerManager.CreateRepository(repository, repositoryType); + } + + /// + /// Creates a repository with the specified name and repository type. + /// + /// + /// + /// The name must be unique. Repositories cannot be redefined. + /// An will be thrown if the repository already exists. + /// + /// + /// The name of the repository, this must be unique to the repository. + /// A that implements + /// and has a no arg constructor. An instance of this type will be created to act + /// as the for the repository specified. + /// The created for the repository. + /// The specified repository already exists. + public static ILoggerRepository CreateRepository(string repository, Type repositoryType) + { + return LoggerManager.CreateRepository(repository, repositoryType); + } + + /// + /// Creates a repository for the specified assembly and repository type. + /// + /// + /// + /// CreateDomain is obsolete. Use CreateRepository instead of CreateDomain. + /// + /// + /// The created will be associated with the repository + /// specified such that a call to with the + /// same assembly specified will return the same repository instance. + /// + /// + /// The assembly to use to get the name of the repository. + /// A that implements + /// and has a no arg constructor. An instance of this type will be created to act + /// as the for the repository specified. + /// The created for the repository. + [Obsolete("Use CreateRepository instead of CreateDomain")] + public static ILoggerRepository CreateDomain(Assembly repositoryAssembly, Type repositoryType) + { + return LoggerManager.CreateRepository(repositoryAssembly, repositoryType); + } + + /// + /// Creates a repository for the specified assembly and repository type. + /// + /// + /// + /// The created will be associated with the repository + /// specified such that a call to with the + /// same assembly specified will return the same repository instance. + /// + /// + /// The assembly to use to get the name of the repository. + /// A that implements + /// and has a no arg constructor. An instance of this type will be created to act + /// as the for the repository specified. + /// The created for the repository. + public static ILoggerRepository CreateRepository(Assembly repositoryAssembly, Type repositoryType) + { + return LoggerManager.CreateRepository(repositoryAssembly, repositoryType); + } + + /// + /// Gets the list of currently defined repositories. + /// + /// + /// + /// Get an array of all the objects that have been created. + /// + /// + /// An array of all the known objects. + public static ILoggerRepository[] GetAllRepositories() + { + return LoggerManager.GetAllRepositories(); + } /// /// Flushes logging events buffered in all configured appenders in the default repository. @@ -773,55 +773,55 @@ public static bool Flush(int millisecondsTimeout) #endif } - #endregion Domain & Repository Manager Methods - - #region Extension Handlers - - /// - /// Looks up the wrapper object for the logger specified. - /// - /// The logger to get the wrapper for. - /// The wrapper for the logger specified. - private static ILog WrapLogger(ILogger logger) - { - return (ILog)s_wrapperMap.GetWrapper(logger); - } - - /// - /// Looks up the wrapper objects for the loggers specified. - /// - /// The loggers to get the wrappers for. - /// The wrapper objects for the loggers specified. - private static ILog[] WrapLoggers(ILogger[] loggers) - { - ILog[] results = new ILog[loggers.Length]; - for(int i=0; i - /// Create the objects used by - /// this manager. - /// - /// The logger to wrap. - /// The wrapper for the logger specified. - private static ILoggerWrapper WrapperCreationHandler(ILogger logger) - { - return new LogImpl(logger); - } - - #endregion - - #region Private Static Fields - - /// - /// The wrapper map to use to hold the objects. - /// - private static readonly WrapperMap s_wrapperMap = new WrapperMap(new WrapperCreationHandler(WrapperCreationHandler)); - - #endregion Private Static Fields - } + #endregion Domain & Repository Manager Methods + + #region Extension Handlers + + /// + /// Looks up the wrapper object for the logger specified. + /// + /// The logger to get the wrapper for. + /// The wrapper for the logger specified. + private static ILog WrapLogger(ILogger logger) + { + return (ILog)s_wrapperMap.GetWrapper(logger); + } + + /// + /// Looks up the wrapper objects for the loggers specified. + /// + /// The loggers to get the wrappers for. + /// The wrapper objects for the loggers specified. + private static ILog[] WrapLoggers(ILogger[] loggers) + { + ILog[] results = new ILog[loggers.Length]; + for(int i=0; i + /// Create the objects used by + /// this manager. + /// + /// The logger to wrap. + /// The wrapper for the logger specified. + private static ILoggerWrapper WrapperCreationHandler(ILogger logger) + { + return new LogImpl(logger); + } + + #endregion + + #region Private Static Fields + + /// + /// The wrapper map to use to hold the objects. + /// + private static readonly WrapperMap s_wrapperMap = new WrapperMap(new WrapperCreationHandler(WrapperCreationHandler)); + + #endregion Private Static Fields + } } diff --git a/src/log4net/LogicalThreadContext.cs b/src/log4net/LogicalThreadContext.cs index 937f952c..79da8fc0 100644 --- a/src/log4net/LogicalThreadContext.cs +++ b/src/log4net/LogicalThreadContext.cs @@ -24,130 +24,130 @@ namespace log4net { - /// - /// The log4net Logical Thread Context. - /// - /// - /// - /// The LogicalThreadContext provides a location for specific debugging - /// information to be stored. - /// The LogicalThreadContext properties override any or - /// properties with the same name. - /// - /// - /// For .NET Standard 1.3 this class uses - /// System.Threading.AsyncLocal rather than . - /// - /// - /// The Logical Thread Context has a properties map and a stack. - /// The properties and stack can - /// be included in the output of log messages. The - /// supports selecting and outputting these properties. - /// - /// - /// The Logical Thread Context provides a diagnostic context for the current call context. - /// 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. - /// - /// - /// The Logical Thread Context is managed on a per basis. - /// - /// - /// The requires a link time - /// for the - /// . - /// If the calling code does not have this permission then this context will be disabled. - /// It will not store any property values set on it. - /// - /// - /// Example of using the thread context properties to store a username. - /// - /// LogicalThreadContext.Properties["user"] = userName; - /// log.Info("This log message has a LogicalThreadContext Property called 'user'"); - /// - /// - /// Example of how to push a message into the context stack - /// - /// using(LogicalThreadContext.Stacks["LDC"].Push("my context message")) - /// { - /// log.Info("This log message has a LogicalThreadContext Stack message that includes 'my context message'"); - /// - /// } // at the end of the using block the message is automatically popped - /// - /// - /// - /// Nicko Cadell - public sealed class LogicalThreadContext - { - #region Private Instance Constructors + /// + /// The log4net Logical Thread Context. + /// + /// + /// + /// The LogicalThreadContext provides a location for specific debugging + /// information to be stored. + /// The LogicalThreadContext properties override any or + /// properties with the same name. + /// + /// + /// For .NET Standard 1.3 this class uses + /// System.Threading.AsyncLocal rather than . + /// + /// + /// The Logical Thread Context has a properties map and a stack. + /// The properties and stack can + /// be included in the output of log messages. The + /// supports selecting and outputting these properties. + /// + /// + /// The Logical Thread Context provides a diagnostic context for the current call context. + /// 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. + /// + /// + /// The Logical Thread Context is managed on a per basis. + /// + /// + /// The requires a link time + /// for the + /// . + /// If the calling code does not have this permission then this context will be disabled. + /// It will not store any property values set on it. + /// + /// + /// Example of using the thread context properties to store a username. + /// + /// LogicalThreadContext.Properties["user"] = userName; + /// log.Info("This log message has a LogicalThreadContext Property called 'user'"); + /// + /// + /// Example of how to push a message into the context stack + /// + /// using(LogicalThreadContext.Stacks["LDC"].Push("my context message")) + /// { + /// log.Info("This log message has a LogicalThreadContext Stack message that includes 'my context message'"); + /// + /// } // at the end of the using block the message is automatically popped + /// + /// + /// + /// Nicko Cadell + public sealed class LogicalThreadContext + { + #region Private Instance Constructors - /// - /// Private Constructor. - /// - /// - /// - /// Uses a private access modifier to prevent instantiation of this class. - /// - /// - private LogicalThreadContext() - { - } + /// + /// Private Constructor. + /// + /// + /// + /// Uses a private access modifier to prevent instantiation of this class. + /// + /// + private LogicalThreadContext() + { + } - #endregion Private Instance Constructors + #endregion Private Instance Constructors - #region Public Static Properties + #region Public Static Properties - /// - /// The thread properties map - /// - /// - /// The thread properties map - /// - /// - /// - /// The LogicalThreadContext properties override any - /// or properties with the same name. - /// - /// - public static LogicalThreadContextProperties Properties - { - get { return s_properties; } - } + /// + /// The thread properties map + /// + /// + /// The thread properties map + /// + /// + /// + /// The LogicalThreadContext properties override any + /// or properties with the same name. + /// + /// + public static LogicalThreadContextProperties Properties + { + get { return s_properties; } + } - /// - /// The thread stacks - /// - /// - /// stack map - /// - /// - /// - /// The logical thread stacks. - /// - /// - public static LogicalThreadContextStacks Stacks - { - get { return s_stacks; } - } + /// + /// The thread stacks + /// + /// + /// stack map + /// + /// + /// + /// The logical thread stacks. + /// + /// + public static LogicalThreadContextStacks Stacks + { + get { return s_stacks; } + } - #endregion Public Static Properties + #endregion Public Static Properties - #region Private Static Fields + #region Private Static Fields - /// - /// The thread context properties instance - /// - private static readonly LogicalThreadContextProperties s_properties = new LogicalThreadContextProperties(); + /// + /// The thread context properties instance + /// + private static readonly LogicalThreadContextProperties s_properties = new LogicalThreadContextProperties(); - /// - /// The thread context stacks instance - /// - private static readonly LogicalThreadContextStacks s_stacks = new LogicalThreadContextStacks(s_properties); + /// + /// The thread context stacks instance + /// + private static readonly LogicalThreadContextStacks s_stacks = new LogicalThreadContextStacks(s_properties); - #endregion Private Static Fields - } + #endregion Private Static Fields + } } #endif \ No newline at end of file diff --git a/src/log4net/MDC.cs b/src/log4net/MDC.cs index 06e1b1db..f0d25317 100644 --- a/src/log4net/MDC.cs +++ b/src/log4net/MDC.cs @@ -22,148 +22,148 @@ namespace log4net { - /// - /// Implementation of Mapped Diagnostic Contexts. - /// - /// - /// - /// - /// The MDC is deprecated and has been replaced by the . - /// The current MDC implementation forwards to the ThreadContext.Properties. - /// - /// - /// - /// The MDC class is similar to the class except that it is - /// based on a map instead of a stack. It provides mapped - /// diagnostic contexts. A Mapped Diagnostic Context, or - /// MDC in short, is an instrument for distinguishing interleaved log - /// output from different sources. Log output is typically interleaved - /// when a server handles multiple clients near-simultaneously. - /// - /// - /// The MDC is managed on a per thread basis. - /// - /// - /// - /// Nicko Cadell - /// Gert Driesen - /*[Obsolete("MDC has been replaced by ThreadContext.Properties")]*/ - public sealed class MDC - { - #region Private Instance Constructors + /// + /// Implementation of Mapped Diagnostic Contexts. + /// + /// + /// + /// + /// The MDC is deprecated and has been replaced by the . + /// The current MDC implementation forwards to the ThreadContext.Properties. + /// + /// + /// + /// The MDC class is similar to the class except that it is + /// based on a map instead of a stack. It provides mapped + /// diagnostic contexts. A Mapped Diagnostic Context, or + /// MDC in short, is an instrument for distinguishing interleaved log + /// output from different sources. Log output is typically interleaved + /// when a server handles multiple clients near-simultaneously. + /// + /// + /// The MDC is managed on a per thread basis. + /// + /// + /// + /// Nicko Cadell + /// Gert Driesen + /*[Obsolete("MDC has been replaced by ThreadContext.Properties")]*/ + public sealed class MDC + { + #region Private Instance Constructors - /// - /// Initializes a new instance of the class. - /// - /// - /// Uses a private access modifier to prevent instantiation of this class. - /// - private MDC() - { - } + /// + /// Initializes a new instance of the class. + /// + /// + /// Uses a private access modifier to prevent instantiation of this class. + /// + private MDC() + { + } - #endregion Private Instance Constructors + #endregion Private Instance Constructors - #region Public Static Methods + #region Public Static Methods - /// - /// Gets the context value identified by the parameter. - /// - /// The key to lookup in the MDC. - /// The string value held for the key, or a null reference if no corresponding value is found. - /// - /// - /// - /// The MDC is deprecated and has been replaced by the . - /// The current MDC implementation forwards to the ThreadContext.Properties. - /// - /// - /// - /// If the parameter does not look up to a - /// previously defined context then null will be returned. - /// - /// - /*[Obsolete("MDC has been replaced by ThreadContext.Properties")]*/ - public static string Get(string key) - { - object obj = ThreadContext.Properties[key]; - if (obj == null) - { - return null; - } - return obj.ToString(); - } + /// + /// Gets the context value identified by the parameter. + /// + /// The key to lookup in the MDC. + /// The string value held for the key, or a null reference if no corresponding value is found. + /// + /// + /// + /// The MDC is deprecated and has been replaced by the . + /// The current MDC implementation forwards to the ThreadContext.Properties. + /// + /// + /// + /// If the parameter does not look up to a + /// previously defined context then null will be returned. + /// + /// + /*[Obsolete("MDC has been replaced by ThreadContext.Properties")]*/ + public static string Get(string key) + { + object obj = ThreadContext.Properties[key]; + if (obj == null) + { + return null; + } + return obj.ToString(); + } - /// - /// Add an entry to the MDC - /// - /// The key to store the value under. - /// The value to store. - /// - /// - /// - /// The MDC is deprecated and has been replaced by the . - /// The current MDC implementation forwards to the ThreadContext.Properties. - /// - /// - /// - /// Puts a context value (the parameter) as identified - /// with the parameter into the current thread's - /// context map. - /// - /// - /// If a value is already defined for the - /// specified then the value will be replaced. If the - /// is specified as null then the key value mapping will be removed. - /// - /// - /*[Obsolete("MDC has been replaced by ThreadContext.Properties")]*/ - public static void Set(string key, string value) - { - ThreadContext.Properties[key] = value; - } + /// + /// Add an entry to the MDC + /// + /// The key to store the value under. + /// The value to store. + /// + /// + /// + /// The MDC is deprecated and has been replaced by the . + /// The current MDC implementation forwards to the ThreadContext.Properties. + /// + /// + /// + /// Puts a context value (the parameter) as identified + /// with the parameter into the current thread's + /// context map. + /// + /// + /// If a value is already defined for the + /// specified then the value will be replaced. If the + /// is specified as null then the key value mapping will be removed. + /// + /// + /*[Obsolete("MDC has been replaced by ThreadContext.Properties")]*/ + public static void Set(string key, string value) + { + ThreadContext.Properties[key] = value; + } - /// - /// Removes the key value mapping for the key specified. - /// - /// The key to remove. - /// - /// - /// - /// The MDC is deprecated and has been replaced by the . - /// The current MDC implementation forwards to the ThreadContext.Properties. - /// - /// - /// - /// Remove the specified entry from this thread's MDC - /// - /// - /*[Obsolete("MDC has been replaced by ThreadContext.Properties")]*/ - public static void Remove(string key) - { - ThreadContext.Properties.Remove(key); - } + /// + /// Removes the key value mapping for the key specified. + /// + /// The key to remove. + /// + /// + /// + /// The MDC is deprecated and has been replaced by the . + /// The current MDC implementation forwards to the ThreadContext.Properties. + /// + /// + /// + /// Remove the specified entry from this thread's MDC + /// + /// + /*[Obsolete("MDC has been replaced by ThreadContext.Properties")]*/ + public static void Remove(string key) + { + ThreadContext.Properties.Remove(key); + } - /// - /// Clear all entries in the MDC - /// - /// - /// - /// - /// The MDC is deprecated and has been replaced by the . - /// The current MDC implementation forwards to the ThreadContext.Properties. - /// - /// - /// - /// Remove all the entries from this thread's MDC - /// - /// - /*[Obsolete("MDC has been replaced by ThreadContext.Properties")]*/ - public static void Clear() - { - ThreadContext.Properties.Clear(); - } + /// + /// Clear all entries in the MDC + /// + /// + /// + /// + /// The MDC is deprecated and has been replaced by the . + /// The current MDC implementation forwards to the ThreadContext.Properties. + /// + /// + /// + /// Remove all the entries from this thread's MDC + /// + /// + /*[Obsolete("MDC has been replaced by ThreadContext.Properties")]*/ + public static void Clear() + { + ThreadContext.Properties.Clear(); + } - #endregion Public Static Methods - } + #endregion Public Static Methods + } } diff --git a/src/log4net/NDC.cs b/src/log4net/NDC.cs index 6b79619e..1c4c7b1c 100644 --- a/src/log4net/NDC.cs +++ b/src/log4net/NDC.cs @@ -26,324 +26,324 @@ namespace log4net { - /// - /// Implementation of Nested Diagnostic Contexts. - /// - /// - /// - /// - /// The NDC is deprecated and has been replaced by the . - /// The current NDC implementation forwards to the ThreadContext.Stacks["NDC"]. - /// - /// - /// - /// 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 - /// clients near-simultaneously. - /// - /// - /// Interleaved log output can still be meaningful if each log entry - /// from different contexts had a distinctive stamp. This is where NDCs - /// come into play. - /// - /// - /// Note that NDCs are managed on a per thread basis. The NDC class - /// is made up of static methods that operate on the context of the - /// calling thread. - /// - /// - /// How to push a message into the context - /// - /// using(NDC.Push("my context message")) - /// { - /// ... all log calls will have 'my context message' included ... - /// - /// } // at the end of the using block the message is automatically removed - /// - /// - /// - /// Nicko Cadell - /// Gert Driesen - /*[Obsolete("NDC has been replaced by ThreadContext.Stacks")]*/ - public sealed class NDC - { - #region Private Instance Constructors + /// + /// Implementation of Nested Diagnostic Contexts. + /// + /// + /// + /// + /// The NDC is deprecated and has been replaced by the . + /// The current NDC implementation forwards to the ThreadContext.Stacks["NDC"]. + /// + /// + /// + /// 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 + /// clients near-simultaneously. + /// + /// + /// Interleaved log output can still be meaningful if each log entry + /// from different contexts had a distinctive stamp. This is where NDCs + /// come into play. + /// + /// + /// Note that NDCs are managed on a per thread basis. The NDC class + /// is made up of static methods that operate on the context of the + /// calling thread. + /// + /// + /// How to push a message into the context + /// + /// using(NDC.Push("my context message")) + /// { + /// ... all log calls will have 'my context message' included ... + /// + /// } // at the end of the using block the message is automatically removed + /// + /// + /// + /// Nicko Cadell + /// Gert Driesen + /*[Obsolete("NDC has been replaced by ThreadContext.Stacks")]*/ + public sealed class NDC + { + #region Private Instance Constructors - /// - /// Initializes a new instance of the class. - /// - /// - /// Uses a private access modifier to prevent instantiation of this class. - /// - private NDC() - { - } + /// + /// Initializes a new instance of the class. + /// + /// + /// Uses a private access modifier to prevent instantiation of this class. + /// + private NDC() + { + } - #endregion Private Instance Constructors + #endregion Private Instance Constructors - #region Public Static Properties + #region Public Static Properties - /// - /// Gets the current context depth. - /// - /// The current context depth. - /// - /// - /// - /// The NDC is deprecated and has been replaced by the . - /// The current NDC implementation forwards to the ThreadContext.Stacks["NDC"]. - /// - /// - /// - /// The number of context values pushed onto the context stack. - /// - /// - /// Used to record the current depth of the context. This can then - /// be restored using the method. - /// - /// - /// - /*[Obsolete("NDC has been replaced by ThreadContext.Stacks")]*/ - public static int Depth - { - get { return ThreadContext.Stacks["NDC"].Count; } - } + /// + /// Gets the current context depth. + /// + /// The current context depth. + /// + /// + /// + /// The NDC is deprecated and has been replaced by the . + /// The current NDC implementation forwards to the ThreadContext.Stacks["NDC"]. + /// + /// + /// + /// The number of context values pushed onto the context stack. + /// + /// + /// Used to record the current depth of the context. This can then + /// be restored using the method. + /// + /// + /// + /*[Obsolete("NDC has been replaced by ThreadContext.Stacks")]*/ + public static int Depth + { + get { return ThreadContext.Stacks["NDC"].Count; } + } - #endregion Public Static Properties + #endregion Public Static Properties - #region Public Static Methods + #region Public Static Methods - /// - /// Clears all the contextual information held on the current thread. - /// - /// - /// - /// - /// The NDC is deprecated and has been replaced by the . - /// The current NDC implementation forwards to the ThreadContext.Stacks["NDC"]. - /// - /// - /// - /// Clears the stack of NDC data held on the current thread. - /// - /// - /*[Obsolete("NDC has been replaced by ThreadContext.Stacks")]*/ - public static void Clear() - { - ThreadContext.Stacks["NDC"].Clear(); - } + /// + /// Clears all the contextual information held on the current thread. + /// + /// + /// + /// + /// The NDC is deprecated and has been replaced by the . + /// The current NDC implementation forwards to the ThreadContext.Stacks["NDC"]. + /// + /// + /// + /// Clears the stack of NDC data held on the current thread. + /// + /// + /*[Obsolete("NDC has been replaced by ThreadContext.Stacks")]*/ + public static void Clear() + { + ThreadContext.Stacks["NDC"].Clear(); + } - /// - /// Creates a clone of the stack of context information. - /// - /// A clone of the context info for this thread. - /// - /// - /// - /// The NDC is deprecated and has been replaced by the . - /// The current NDC implementation forwards to the ThreadContext.Stacks["NDC"]. - /// - /// - /// - /// The results of this method can be passed to the - /// method to allow child threads to inherit the context of their - /// parent thread. - /// - /// - /*[Obsolete("NDC has been replaced by ThreadContext.Stacks")]*/ - public static Stack CloneStack() - { - return ThreadContext.Stacks["NDC"].InternalStack; - } + /// + /// Creates a clone of the stack of context information. + /// + /// A clone of the context info for this thread. + /// + /// + /// + /// The NDC is deprecated and has been replaced by the . + /// The current NDC implementation forwards to the ThreadContext.Stacks["NDC"]. + /// + /// + /// + /// The results of this method can be passed to the + /// method to allow child threads to inherit the context of their + /// parent thread. + /// + /// + /*[Obsolete("NDC has been replaced by ThreadContext.Stacks")]*/ + public static Stack CloneStack() + { + return ThreadContext.Stacks["NDC"].InternalStack; + } - /// - /// Inherits the contextual information from another thread. - /// - /// The context stack to inherit. - /// - /// - /// - /// The NDC is deprecated and has been replaced by the . - /// The current NDC implementation forwards to the ThreadContext.Stacks["NDC"]. - /// - /// - /// - /// This thread will use the context information from the stack - /// supplied. This can be used to initialize child threads with - /// the same contextual information as their parent threads. These - /// contexts will NOT be shared. Any further contexts that - /// are pushed onto the stack will not be visible to the other. - /// Call to obtain a stack to pass to - /// this method. - /// - /// - /*[Obsolete("NDC has been replaced by ThreadContext.Stacks", true)]*/ - public static void Inherit(Stack stack) - { - ThreadContext.Stacks["NDC"].InternalStack = stack; - } + /// + /// Inherits the contextual information from another thread. + /// + /// The context stack to inherit. + /// + /// + /// + /// The NDC is deprecated and has been replaced by the . + /// The current NDC implementation forwards to the ThreadContext.Stacks["NDC"]. + /// + /// + /// + /// This thread will use the context information from the stack + /// supplied. This can be used to initialize child threads with + /// the same contextual information as their parent threads. These + /// contexts will NOT be shared. Any further contexts that + /// are pushed onto the stack will not be visible to the other. + /// Call to obtain a stack to pass to + /// this method. + /// + /// + /*[Obsolete("NDC has been replaced by ThreadContext.Stacks", true)]*/ + public static void Inherit(Stack stack) + { + ThreadContext.Stacks["NDC"].InternalStack = stack; + } - /// - /// Removes the top context from the stack. - /// - /// - /// The message in the context that was removed from the top - /// of the stack. - /// - /// - /// - /// - /// The NDC is deprecated and has been replaced by the . - /// The current NDC implementation forwards to the ThreadContext.Stacks["NDC"]. - /// - /// - /// - /// Remove the top context from the stack, and return - /// it to the caller. If the stack is empty then an - /// empty string (not null) is returned. - /// - /// - /*[Obsolete("NDC has been replaced by ThreadContext.Stacks")]*/ - public static string Pop() - { - return ThreadContext.Stacks["NDC"].Pop(); - } + /// + /// Removes the top context from the stack. + /// + /// + /// The message in the context that was removed from the top + /// of the stack. + /// + /// + /// + /// + /// The NDC is deprecated and has been replaced by the . + /// The current NDC implementation forwards to the ThreadContext.Stacks["NDC"]. + /// + /// + /// + /// Remove the top context from the stack, and return + /// it to the caller. If the stack is empty then an + /// empty string (not null) is returned. + /// + /// + /*[Obsolete("NDC has been replaced by ThreadContext.Stacks")]*/ + public static string Pop() + { + return ThreadContext.Stacks["NDC"].Pop(); + } - /// - /// Pushes a new context message. - /// - /// The new context message. - /// - /// An that can be used to clean up - /// the context stack. - /// - /// - /// - /// - /// The NDC is deprecated and has been replaced by the . - /// The current NDC implementation forwards to the ThreadContext.Stacks["NDC"]. - /// - /// - /// - /// Pushes a new context onto the context stack. An - /// is returned that can be used to clean up the context stack. This - /// can be easily combined with the using keyword to scope the - /// context. - /// - /// - /// Simple example of using the Push method with the using keyword. - /// - /// using(log4net.NDC.Push("NDC_Message")) - /// { - /// log.Warn("This should have an NDC message"); - /// } - /// - /// - /*[Obsolete("NDC has been replaced by ThreadContext.Stacks")]*/ - public static IDisposable Push(string message) - { - return ThreadContext.Stacks["NDC"].Push(message); - } + /// + /// Pushes a new context message. + /// + /// The new context message. + /// + /// An that can be used to clean up + /// the context stack. + /// + /// + /// + /// + /// The NDC is deprecated and has been replaced by the . + /// The current NDC implementation forwards to the ThreadContext.Stacks["NDC"]. + /// + /// + /// + /// Pushes a new context onto the context stack. An + /// is returned that can be used to clean up the context stack. This + /// can be easily combined with the using keyword to scope the + /// context. + /// + /// + /// Simple example of using the Push method with the using keyword. + /// + /// using(log4net.NDC.Push("NDC_Message")) + /// { + /// log.Warn("This should have an NDC message"); + /// } + /// + /// + /*[Obsolete("NDC has been replaced by ThreadContext.Stacks")]*/ + public static IDisposable Push(string message) + { + return ThreadContext.Stacks["NDC"].Push(message); + } - /// - /// Pushes a new context message. - /// - /// The new context message string format. - /// Arguments to be passed into messageFormat. - /// - /// An that can be used to clean up - /// the context stack. - /// - /// - /// - /// - /// The NDC is deprecated and has been replaced by the . - /// The current NDC implementation forwards to the ThreadContext.Stacks["NDC"]. - /// - /// - /// - /// Pushes a new context onto the context stack. An - /// is returned that can be used to clean up the context stack. This - /// can be easily combined with the using keyword to scope the - /// context. - /// - /// - /// Simple example of using the Push method with the using keyword. - /// - /// var someValue = "ExampleContext" - /// using(log4net.NDC.PushFormat("NDC_Message {0}", someValue)) - /// { - /// log.Warn("This should have an NDC message"); - /// } - /// - /// - /*[Obsolete("NDC has been replaced by ThreadContext.Stacks")]*/ - public static IDisposable PushFormat(string messageFormat, params object[] args) - { - return Push(string.Format(messageFormat, args)); - } + /// + /// Pushes a new context message. + /// + /// The new context message string format. + /// Arguments to be passed into messageFormat. + /// + /// An that can be used to clean up + /// the context stack. + /// + /// + /// + /// + /// The NDC is deprecated and has been replaced by the . + /// The current NDC implementation forwards to the ThreadContext.Stacks["NDC"]. + /// + /// + /// + /// Pushes a new context onto the context stack. An + /// is returned that can be used to clean up the context stack. This + /// can be easily combined with the using keyword to scope the + /// context. + /// + /// + /// Simple example of using the Push method with the using keyword. + /// + /// var someValue = "ExampleContext" + /// using(log4net.NDC.PushFormat("NDC_Message {0}", someValue)) + /// { + /// log.Warn("This should have an NDC message"); + /// } + /// + /// + /*[Obsolete("NDC has been replaced by ThreadContext.Stacks")]*/ + public static IDisposable PushFormat(string messageFormat, params object[] args) + { + return Push(string.Format(messageFormat, args)); + } - /// - /// Removes the context information for this thread. It is - /// not required to call this method. - /// - /// - /// - /// - /// The NDC is deprecated and has been replaced by the . - /// The current NDC implementation forwards to the ThreadContext.Stacks["NDC"]. - /// - /// - /// - /// This method is not implemented. - /// - /// - /*[Obsolete("NDC has been replaced by ThreadContext.Stacks")]*/ - public static void Remove() - { - } + /// + /// Removes the context information for this thread. It is + /// not required to call this method. + /// + /// + /// + /// + /// The NDC is deprecated and has been replaced by the . + /// The current NDC implementation forwards to the ThreadContext.Stacks["NDC"]. + /// + /// + /// + /// This method is not implemented. + /// + /// + /*[Obsolete("NDC has been replaced by ThreadContext.Stacks")]*/ + public static void Remove() + { + } - /// - /// Forces the stack depth to be at most . - /// - /// The maximum depth of the stack - /// - /// - /// - /// The NDC is deprecated and has been replaced by the . - /// The current NDC implementation forwards to the ThreadContext.Stacks["NDC"]. - /// - /// - /// - /// Forces the stack depth to be at most . - /// This may truncate the head of the stack. This only affects the - /// stack in the current thread. Also it does not prevent it from - /// growing, it only sets the maximum depth at the time of the - /// call. This can be used to return to a known context depth. - /// - /// - /*[Obsolete("NDC has been replaced by ThreadContext.Stacks")]*/ - public static void SetMaxDepth(int maxDepth) - { - if (maxDepth >= 0) - { - log4net.Util.ThreadContextStack stack = ThreadContext.Stacks["NDC"]; + /// + /// Forces the stack depth to be at most . + /// + /// The maximum depth of the stack + /// + /// + /// + /// The NDC is deprecated and has been replaced by the . + /// The current NDC implementation forwards to the ThreadContext.Stacks["NDC"]. + /// + /// + /// + /// Forces the stack depth to be at most . + /// This may truncate the head of the stack. This only affects the + /// stack in the current thread. Also it does not prevent it from + /// growing, it only sets the maximum depth at the time of the + /// call. This can be used to return to a known context depth. + /// + /// + /*[Obsolete("NDC has been replaced by ThreadContext.Stacks")]*/ + public static void SetMaxDepth(int maxDepth) + { + if (maxDepth >= 0) + { + log4net.Util.ThreadContextStack stack = ThreadContext.Stacks["NDC"]; - if (maxDepth == 0) - { - stack.Clear(); - } - else - { - while(stack.Count > maxDepth) - { - stack.Pop(); - } - } - } - } + if (maxDepth == 0) + { + stack.Clear(); + } + else + { + while(stack.Count > maxDepth) + { + stack.Pop(); + } + } + } + } - #endregion Public Static Methods - } + #endregion Public Static Methods + } } diff --git a/src/log4net/ObjectRenderer/DefaultRenderer.cs b/src/log4net/ObjectRenderer/DefaultRenderer.cs index 8dc603df..73add46a 100644 --- a/src/log4net/ObjectRenderer/DefaultRenderer.cs +++ b/src/log4net/ObjectRenderer/DefaultRenderer.cs @@ -26,285 +26,285 @@ namespace log4net.ObjectRenderer { - /// - /// The default object Renderer. - /// - /// - /// - /// The default renderer supports rendering objects and collections to strings. - /// - /// - /// See the method for details of the output. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public sealed class DefaultRenderer : IObjectRenderer - { - #region Constructors + /// + /// The default object Renderer. + /// + /// + /// + /// The default renderer supports rendering objects and collections to strings. + /// + /// + /// See the method for details of the output. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public sealed class DefaultRenderer : IObjectRenderer + { + #region Constructors - /// - /// Default constructor - /// - /// - /// - /// Default constructor - /// - /// - public DefaultRenderer() - { - } + /// + /// Default constructor + /// + /// + /// + /// Default constructor + /// + /// + public DefaultRenderer() + { + } - #endregion + #endregion - #region Implementation of IObjectRenderer + #region Implementation of IObjectRenderer - /// - /// Render the object to a string - /// - /// The map used to lookup renderers - /// The object to render - /// The writer to render to - /// - /// - /// Render the object to a string. - /// - /// - /// The parameter is - /// provided to lookup and render other objects. This is - /// very useful where contains - /// nested objects of unknown type. The - /// method can be used to render these objects. - /// - /// - /// The default renderer supports rendering objects to strings as follows: - /// - /// - /// - /// Value - /// Rendered String - /// - /// - /// null - /// - /// "(null)" - /// - /// - /// - /// - /// - /// - /// For a one dimensional array this is the - /// array type name, an open brace, followed by a comma - /// separated list of the elements (using the appropriate - /// renderer), followed by a close brace. - /// - /// - /// For example: int[] {1, 2, 3}. - /// - /// - /// If the array is not one dimensional the - /// Array.ToString() is returned. - /// - /// - /// - /// - /// , & - /// - /// - /// Rendered as an open brace, followed by a comma - /// separated list of the elements (using the appropriate - /// renderer), followed by a close brace. - /// - /// - /// For example: {a, b, c}. - /// - /// - /// All collection classes that implement its subclasses, - /// or generic equivalents all implement the interface. - /// - /// - /// - /// - /// - /// - /// - /// Rendered as the key, an equals sign ('='), and the value (using the appropriate - /// renderer). - /// - /// - /// For example: key=value. - /// - /// - /// - /// - /// other - /// - /// Object.ToString() - /// - /// - /// - /// - public void RenderObject(RendererMap rendererMap, object obj, TextWriter writer) - { - if (rendererMap == null) - { - throw new ArgumentNullException("rendererMap"); - } + /// + /// Render the object to a string + /// + /// The map used to lookup renderers + /// The object to render + /// The writer to render to + /// + /// + /// Render the object to a string. + /// + /// + /// The parameter is + /// provided to lookup and render other objects. This is + /// very useful where contains + /// nested objects of unknown type. The + /// method can be used to render these objects. + /// + /// + /// The default renderer supports rendering objects to strings as follows: + /// + /// + /// + /// Value + /// Rendered String + /// + /// + /// null + /// + /// "(null)" + /// + /// + /// + /// + /// + /// + /// For a one dimensional array this is the + /// array type name, an open brace, followed by a comma + /// separated list of the elements (using the appropriate + /// renderer), followed by a close brace. + /// + /// + /// For example: int[] {1, 2, 3}. + /// + /// + /// If the array is not one dimensional the + /// Array.ToString() is returned. + /// + /// + /// + /// + /// , & + /// + /// + /// Rendered as an open brace, followed by a comma + /// separated list of the elements (using the appropriate + /// renderer), followed by a close brace. + /// + /// + /// For example: {a, b, c}. + /// + /// + /// All collection classes that implement its subclasses, + /// or generic equivalents all implement the interface. + /// + /// + /// + /// + /// + /// + /// + /// Rendered as the key, an equals sign ('='), and the value (using the appropriate + /// renderer). + /// + /// + /// For example: key=value. + /// + /// + /// + /// + /// other + /// + /// Object.ToString() + /// + /// + /// + /// + public void RenderObject(RendererMap rendererMap, object obj, TextWriter writer) + { + if (rendererMap == null) + { + throw new ArgumentNullException("rendererMap"); + } - if (obj == null) - { - writer.Write(SystemInfo.NullText); - return; - } - - Array objArray = obj as Array; - if (objArray != null) - { - RenderArray(rendererMap, objArray, writer); - return; - } + if (obj == null) + { + writer.Write(SystemInfo.NullText); + return; + } + + Array objArray = obj as Array; + if (objArray != null) + { + RenderArray(rendererMap, objArray, writer); + return; + } - // Test if we are dealing with some form of collection object - IEnumerable objEnumerable = obj as IEnumerable; - if (objEnumerable != null) - { - // Get a collection interface if we can as its .Count property may be more - // performant than getting the IEnumerator object and trying to advance it. - ICollection objCollection = obj as ICollection; - if (objCollection != null && objCollection.Count == 0) - { - writer.Write("{}"); - return; - } - - // This is a special check to allow us to get the enumerator from the IDictionary - // interface as this guarantees us DictionaryEntry objects. Note that in .NET 2.0 - // the generic IDictionary<> interface enumerates KeyValuePair objects rather than - // DictionaryEntry ones. However the implementation of the plain IDictionary - // interface on the generic Dictionary<> still returns DictionaryEntry objects. - IDictionary objDictionary = obj as IDictionary; - if (objDictionary != null) - { - RenderEnumerator(rendererMap, objDictionary.GetEnumerator(), writer); - return; - } + // Test if we are dealing with some form of collection object + IEnumerable objEnumerable = obj as IEnumerable; + if (objEnumerable != null) + { + // Get a collection interface if we can as its .Count property may be more + // performant than getting the IEnumerator object and trying to advance it. + ICollection objCollection = obj as ICollection; + if (objCollection != null && objCollection.Count == 0) + { + writer.Write("{}"); + return; + } + + // This is a special check to allow us to get the enumerator from the IDictionary + // interface as this guarantees us DictionaryEntry objects. Note that in .NET 2.0 + // the generic IDictionary<> interface enumerates KeyValuePair objects rather than + // DictionaryEntry ones. However the implementation of the plain IDictionary + // interface on the generic Dictionary<> still returns DictionaryEntry objects. + IDictionary objDictionary = obj as IDictionary; + if (objDictionary != null) + { + RenderEnumerator(rendererMap, objDictionary.GetEnumerator(), writer); + return; + } - RenderEnumerator(rendererMap, objEnumerable.GetEnumerator(), writer); - return; - } + RenderEnumerator(rendererMap, objEnumerable.GetEnumerator(), writer); + return; + } - IEnumerator objEnumerator = obj as IEnumerator; - if (objEnumerator != null) - { - RenderEnumerator(rendererMap, objEnumerator, writer); - return; - } - - if (obj is DictionaryEntry) - { - RenderDictionaryEntry(rendererMap, (DictionaryEntry)obj, writer); - return; - } + IEnumerator objEnumerator = obj as IEnumerator; + if (objEnumerator != null) + { + RenderEnumerator(rendererMap, objEnumerator, writer); + return; + } + + if (obj is DictionaryEntry) + { + RenderDictionaryEntry(rendererMap, (DictionaryEntry)obj, writer); + return; + } - string str = obj.ToString(); - writer.Write( (str==null) ? SystemInfo.NullText : str ); - } + string str = obj.ToString(); + writer.Write( (str==null) ? SystemInfo.NullText : str ); + } - #endregion + #endregion - /// - /// Render the array argument into a string - /// - /// The map used to lookup renderers - /// the array to render - /// The writer to render to - /// - /// - /// For a one dimensional array this is the - /// array type name, an open brace, followed by a comma - /// separated list of the elements (using the appropriate - /// renderer), followed by a close brace. For example: - /// int[] {1, 2, 3}. - /// - /// - /// If the array is not one dimensional the - /// Array.ToString() is returned. - /// - /// - private void RenderArray(RendererMap rendererMap, Array array, TextWriter writer) - { - if (array.Rank != 1) - { - writer.Write(array.ToString()); - } - else - { - writer.Write(array.GetType().Name + " {"); - int len = array.Length; + /// + /// Render the array argument into a string + /// + /// The map used to lookup renderers + /// the array to render + /// The writer to render to + /// + /// + /// For a one dimensional array this is the + /// array type name, an open brace, followed by a comma + /// separated list of the elements (using the appropriate + /// renderer), followed by a close brace. For example: + /// int[] {1, 2, 3}. + /// + /// + /// If the array is not one dimensional the + /// Array.ToString() is returned. + /// + /// + private void RenderArray(RendererMap rendererMap, Array array, TextWriter writer) + { + if (array.Rank != 1) + { + writer.Write(array.ToString()); + } + else + { + writer.Write(array.GetType().Name + " {"); + int len = array.Length; - if (len > 0) - { - rendererMap.FindAndRender(array.GetValue(0), writer); - for(int i=1; i 0) + { + rendererMap.FindAndRender(array.GetValue(0), writer); + for(int i=1; i - /// Render the enumerator argument into a string - ///
- /// The map used to lookup renderers - /// the enumerator to render - /// The writer to render to - /// - /// - /// Rendered as an open brace, followed by a comma - /// separated list of the elements (using the appropriate - /// renderer), followed by a close brace. For example: - /// {a, b, c}. - /// - /// - private void RenderEnumerator(RendererMap rendererMap, IEnumerator enumerator, TextWriter writer) - { - writer.Write("{"); + /// + /// Render the enumerator argument into a string + /// + /// The map used to lookup renderers + /// the enumerator to render + /// The writer to render to + /// + /// + /// Rendered as an open brace, followed by a comma + /// separated list of the elements (using the appropriate + /// renderer), followed by a close brace. For example: + /// {a, b, c}. + /// + /// + private void RenderEnumerator(RendererMap rendererMap, IEnumerator enumerator, TextWriter writer) + { + writer.Write("{"); - if (enumerator != null && enumerator.MoveNext()) - { - rendererMap.FindAndRender(enumerator.Current, writer); + if (enumerator != null && enumerator.MoveNext()) + { + rendererMap.FindAndRender(enumerator.Current, writer); - while (enumerator.MoveNext()) - { - writer.Write(", "); - rendererMap.FindAndRender(enumerator.Current, writer); - } - } + while (enumerator.MoveNext()) + { + writer.Write(", "); + rendererMap.FindAndRender(enumerator.Current, writer); + } + } - writer.Write("}"); - } + writer.Write("}"); + } - /// - /// Render the DictionaryEntry argument into a string - /// - /// The map used to lookup renderers - /// the DictionaryEntry to render - /// The writer to render to - /// - /// - /// Render the key, an equals sign ('='), and the value (using the appropriate - /// renderer). For example: key=value. - /// - /// - private void RenderDictionaryEntry(RendererMap rendererMap, DictionaryEntry entry, TextWriter writer) - { - rendererMap.FindAndRender(entry.Key, writer); - writer.Write("="); - rendererMap.FindAndRender(entry.Value, writer); - } - } + /// + /// Render the DictionaryEntry argument into a string + /// + /// The map used to lookup renderers + /// the DictionaryEntry to render + /// The writer to render to + /// + /// + /// Render the key, an equals sign ('='), and the value (using the appropriate + /// renderer). For example: key=value. + /// + /// + private void RenderDictionaryEntry(RendererMap rendererMap, DictionaryEntry entry, TextWriter writer) + { + rendererMap.FindAndRender(entry.Key, writer); + writer.Write("="); + rendererMap.FindAndRender(entry.Value, writer); + } + } } diff --git a/src/log4net/ObjectRenderer/IObjectRenderer.cs b/src/log4net/ObjectRenderer/IObjectRenderer.cs index 3a79d1e1..b9d673b4 100644 --- a/src/log4net/ObjectRenderer/IObjectRenderer.cs +++ b/src/log4net/ObjectRenderer/IObjectRenderer.cs @@ -22,40 +22,40 @@ namespace log4net.ObjectRenderer { - /// - /// Implement this interface in order to render objects as strings - /// - /// - /// - /// Certain types require special case conversion to - /// string form. This conversion is done by an object renderer. - /// Object renderers implement the - /// interface. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public interface IObjectRenderer - { - /// - /// Render the object to a string - /// - /// The map used to lookup renderers - /// The object to render - /// The writer to render to - /// - /// - /// Render the object to a - /// string. - /// - /// - /// The parameter is - /// provided to lookup and render other objects. This is - /// very useful where contains - /// nested objects of unknown type. The - /// method can be used to render these objects. - /// - /// - void RenderObject(RendererMap rendererMap, object obj, TextWriter writer); - } + /// + /// Implement this interface in order to render objects as strings + /// + /// + /// + /// Certain types require special case conversion to + /// string form. This conversion is done by an object renderer. + /// Object renderers implement the + /// interface. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public interface IObjectRenderer + { + /// + /// Render the object to a string + /// + /// The map used to lookup renderers + /// The object to render + /// The writer to render to + /// + /// + /// Render the object to a + /// string. + /// + /// + /// The parameter is + /// provided to lookup and render other objects. This is + /// very useful where contains + /// nested objects of unknown type. The + /// method can be used to render these objects. + /// + /// + void RenderObject(RendererMap rendererMap, object obj, TextWriter writer); + } } diff --git a/src/log4net/ObjectRenderer/RendererMap.cs b/src/log4net/ObjectRenderer/RendererMap.cs index a20ae198..c3ba5900 100644 --- a/src/log4net/ObjectRenderer/RendererMap.cs +++ b/src/log4net/ObjectRenderer/RendererMap.cs @@ -27,307 +27,307 @@ namespace log4net.ObjectRenderer { - /// - /// Map class objects to an . - /// - /// - /// - /// Maintains a mapping between types that require special - /// rendering and the that - /// is used to render them. - /// - /// - /// The method is used to render an - /// object using the appropriate renderers defined in this map. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public class RendererMap - { - private static readonly Type declaringType = typeof(RendererMap); + /// + /// Map class objects to an . + /// + /// + /// + /// Maintains a mapping between types that require special + /// rendering and the that + /// is used to render them. + /// + /// + /// The method is used to render an + /// object using the appropriate renderers defined in this map. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public class RendererMap + { + private static readonly Type declaringType = typeof(RendererMap); - #region Member Variables + #region Member Variables - private readonly Hashtable m_map = new(); - private readonly Hashtable m_cache = new(); + private readonly Hashtable m_map = new(); + private readonly Hashtable m_cache = new(); - private static IObjectRenderer s_defaultRenderer = new DefaultRenderer(); + private static IObjectRenderer s_defaultRenderer = new DefaultRenderer(); - #endregion + #endregion - /// - /// Render using the appropriate renderer. - /// - /// the object to render to a string - /// the object rendered as a string - /// - /// - /// This is a convenience method used to render an object to a string. - /// The alternative method - /// should be used when streaming output to a . - /// - /// - public string FindAndRender(object obj) - { - // Optimisation for strings - string strData = obj as String; - if (strData != null) - { - return strData; - } + /// + /// Render using the appropriate renderer. + /// + /// the object to render to a string + /// the object rendered as a string + /// + /// + /// This is a convenience method used to render an object to a string. + /// The alternative method + /// should be used when streaming output to a . + /// + /// + public string FindAndRender(object obj) + { + // Optimisation for strings + string strData = obj as String; + if (strData != null) + { + return strData; + } - using StringWriter stringWriter = new StringWriter(System.Globalization.CultureInfo.InvariantCulture); - FindAndRender(obj, stringWriter); - return stringWriter.ToString(); - } + using StringWriter stringWriter = new StringWriter(System.Globalization.CultureInfo.InvariantCulture); + FindAndRender(obj, stringWriter); + return stringWriter.ToString(); + } - /// - /// Render using the appropriate renderer. - /// - /// the object to render to a string - /// The writer to render to - /// - /// - /// Find the appropriate renderer for the type of the - /// parameter. This is accomplished by calling the - /// method. Once a renderer is found, it is - /// applied on the object and the result is returned - /// as a . - /// - /// - public void FindAndRender(object obj, TextWriter writer) - { - if (obj == null) - { - writer.Write(SystemInfo.NullText); - } - else - { - // Optimisation for strings - string str = obj as string; - if (str != null) - { - writer.Write(str); - } - else - { - // Lookup the renderer for the specific type - try - { - Get(obj.GetType()).RenderObject(this, obj, writer); - } - catch(Exception ex) - { - // Exception rendering the object - LogLog.Error(declaringType, "Exception while rendering object of type ["+obj.GetType().FullName+"]", ex); + /// + /// Render using the appropriate renderer. + /// + /// the object to render to a string + /// The writer to render to + /// + /// + /// Find the appropriate renderer for the type of the + /// parameter. This is accomplished by calling the + /// method. Once a renderer is found, it is + /// applied on the object and the result is returned + /// as a . + /// + /// + public void FindAndRender(object obj, TextWriter writer) + { + if (obj == null) + { + writer.Write(SystemInfo.NullText); + } + else + { + // Optimisation for strings + string str = obj as string; + if (str != null) + { + writer.Write(str); + } + else + { + // Lookup the renderer for the specific type + try + { + Get(obj.GetType()).RenderObject(this, obj, writer); + } + catch(Exception ex) + { + // Exception rendering the object + LogLog.Error(declaringType, "Exception while rendering object of type ["+obj.GetType().FullName+"]", ex); - // return default message - string objectTypeName = ""; - if (obj != null && obj.GetType() != null) - { - objectTypeName = obj.GetType().FullName; - } + // return default message + string objectTypeName = ""; + if (obj != null && obj.GetType() != null) + { + objectTypeName = obj.GetType().FullName; + } - writer.Write("Exception rendering object type ["+objectTypeName+"]"); - if (ex != null) - { - string exceptionText = null; + writer.Write("Exception rendering object type ["+objectTypeName+"]"); + if (ex != null) + { + string exceptionText = null; - try - { - exceptionText = ex.ToString(); - } - catch - { - // Ignore exception - } + try + { + exceptionText = ex.ToString(); + } + catch + { + // Ignore exception + } - writer.Write("" + exceptionText + ""); - } - writer.Write(""); - } - } - } - } + writer.Write("" + exceptionText + ""); + } + writer.Write(""); + } + } + } + } - /// - /// Gets the renderer for the specified object type - /// - /// the object to lookup the renderer for - /// the renderer for - /// - /// - /// Gets the renderer for the specified object type. - /// - /// - /// Syntactic sugar method that calls - /// with the type of the object parameter. - /// - /// - public IObjectRenderer Get(Object obj) - { - if (obj == null) - { - return null; - } - else - { - return Get(obj.GetType()); - } - } + /// + /// Gets the renderer for the specified object type + /// + /// the object to lookup the renderer for + /// the renderer for + /// + /// + /// Gets the renderer for the specified object type. + /// + /// + /// Syntactic sugar method that calls + /// with the type of the object parameter. + /// + /// + public IObjectRenderer Get(Object obj) + { + if (obj == null) + { + return null; + } + else + { + return Get(obj.GetType()); + } + } - /// - /// Gets the renderer for the specified type - /// - /// the type to lookup the renderer for - /// the renderer for the specified type - /// - /// - /// Returns the renderer for the specified type. - /// If no specific renderer has been defined the - /// will be returned. - /// - /// - public IObjectRenderer Get(Type type) - { - if (type == null) - { - throw new ArgumentNullException("type"); - } + /// + /// Gets the renderer for the specified type + /// + /// the type to lookup the renderer for + /// the renderer for the specified type + /// + /// + /// Returns the renderer for the specified type. + /// If no specific renderer has been defined the + /// will be returned. + /// + /// + public IObjectRenderer Get(Type type) + { + if (type == null) + { + throw new ArgumentNullException("type"); + } - IObjectRenderer result = null; + IObjectRenderer result = null; - // Check cache - result = (IObjectRenderer)m_cache[type]; + // Check cache + result = (IObjectRenderer)m_cache[type]; - if (result == null) - { + if (result == null) + { #if NETSTANDARD1_3 - for (Type cur = type; cur != null; cur = cur.GetTypeInfo().BaseType) + for (Type cur = type; cur != null; cur = cur.GetTypeInfo().BaseType) #else - for(Type cur = type; cur != null; cur = cur.BaseType) + for(Type cur = type; cur != null; cur = cur.BaseType) #endif - { - // Search the type's interfaces - result = SearchTypeAndInterfaces(cur); - if (result != null) - { - break; - } - } + { + // Search the type's interfaces + result = SearchTypeAndInterfaces(cur); + if (result != null) + { + break; + } + } - // if not set then use the default renderer - if (result == null) - { - result = s_defaultRenderer; - } + // if not set then use the default renderer + if (result == null) + { + result = s_defaultRenderer; + } - // Add to cache - lock (m_cache) - { - m_cache[type] = result; - } - } + // Add to cache + lock (m_cache) + { + m_cache[type] = result; + } + } - return result; - } + return result; + } - /// - /// Internal function to recursively search interfaces - /// - /// the type to lookup the renderer for - /// the renderer for the specified type - private IObjectRenderer SearchTypeAndInterfaces(Type type) - { - IObjectRenderer r = (IObjectRenderer)m_map[type]; - if (r != null) - { - return r; - } - else - { - foreach(Type t in type.GetInterfaces()) - { - r = SearchTypeAndInterfaces(t); - if (r != null) - { - return r; - } - } - } - return null; - } + /// + /// Internal function to recursively search interfaces + /// + /// the type to lookup the renderer for + /// the renderer for the specified type + private IObjectRenderer SearchTypeAndInterfaces(Type type) + { + IObjectRenderer r = (IObjectRenderer)m_map[type]; + if (r != null) + { + return r; + } + else + { + foreach(Type t in type.GetInterfaces()) + { + r = SearchTypeAndInterfaces(t); + if (r != null) + { + return r; + } + } + } + return null; + } - /// - /// Get the default renderer instance - /// - /// the default renderer - /// - /// - /// Get the default renderer - /// - /// - public IObjectRenderer DefaultRenderer - { - get { return s_defaultRenderer; } - } + /// + /// Get the default renderer instance + /// + /// the default renderer + /// + /// + /// Get the default renderer + /// + /// + public IObjectRenderer DefaultRenderer + { + get { return s_defaultRenderer; } + } - /// - /// Clear the map of renderers - /// - /// - /// - /// Clear the custom renderers defined by using - /// . The - /// cannot be removed. - /// - /// - public void Clear() - { - lock (m_map) - { - m_map.Clear(); - } + /// + /// Clear the map of renderers + /// + /// + /// + /// Clear the custom renderers defined by using + /// . The + /// cannot be removed. + /// + /// + public void Clear() + { + lock (m_map) + { + m_map.Clear(); + } - lock (m_cache) - { - m_cache.Clear(); - } - } + lock (m_cache) + { + m_cache.Clear(); + } + } - /// - /// Register an for . - /// - /// the type that will be rendered by - /// the renderer for - /// - /// - /// Register an object renderer for a specific source type. - /// This renderer will be returned from a call to - /// specifying the same as an argument. - /// - /// - public void Put(Type typeToRender, IObjectRenderer renderer) - { - lock (m_cache) - { - m_cache.Clear(); - } + /// + /// Register an for . + /// + /// the type that will be rendered by + /// the renderer for + /// + /// + /// Register an object renderer for a specific source type. + /// This renderer will be returned from a call to + /// specifying the same as an argument. + /// + /// + public void Put(Type typeToRender, IObjectRenderer renderer) + { + lock (m_cache) + { + m_cache.Clear(); + } - if (typeToRender == null) - { - throw new ArgumentNullException("typeToRender"); - } - if (renderer == null) - { - throw new ArgumentNullException("renderer"); - } + if (typeToRender == null) + { + throw new ArgumentNullException("typeToRender"); + } + if (renderer == null) + { + throw new ArgumentNullException("renderer"); + } - lock (m_map) - { - m_map[typeToRender] = renderer; - } - } - } + lock (m_map) + { + m_map[typeToRender] = renderer; + } + } + } } diff --git a/src/log4net/Plugin/IPlugin.cs b/src/log4net/Plugin/IPlugin.cs index 065898e8..da66a9ca 100644 --- a/src/log4net/Plugin/IPlugin.cs +++ b/src/log4net/Plugin/IPlugin.cs @@ -21,65 +21,65 @@ namespace log4net.Plugin { - /// - /// Interface implemented by logger repository plugins. - /// - /// - /// - /// Plugins define additional behavior that can be associated - /// with a . - /// The held by the - /// property is used to store the plugins for a repository. - /// - /// - /// The log4net.Config.PluginAttribute can be used to - /// attach plugins to repositories created using configuration - /// attributes. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public interface IPlugin - { - /// - /// Gets the name of the plugin. - /// - /// - /// The name of the plugin. - /// - /// - /// - /// Plugins are stored in the - /// keyed by name. Each plugin instance attached to a - /// repository must be a unique name. - /// - /// - string Name { get; } + /// + /// Interface implemented by logger repository plugins. + /// + /// + /// + /// Plugins define additional behavior that can be associated + /// with a . + /// The held by the + /// property is used to store the plugins for a repository. + /// + /// + /// The log4net.Config.PluginAttribute can be used to + /// attach plugins to repositories created using configuration + /// attributes. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public interface IPlugin + { + /// + /// Gets the name of the plugin. + /// + /// + /// The name of the plugin. + /// + /// + /// + /// Plugins are stored in the + /// keyed by name. Each plugin instance attached to a + /// repository must be a unique name. + /// + /// + string Name { get; } - /// - /// Attaches the plugin to the specified . - /// - /// The that this plugin should be attached to. - /// - /// - /// A plugin may only be attached to a single repository. - /// - /// - /// This method is called when the plugin is attached to the repository. - /// - /// - void Attach(ILoggerRepository repository); + /// + /// Attaches the plugin to the specified . + /// + /// The that this plugin should be attached to. + /// + /// + /// A plugin may only be attached to a single repository. + /// + /// + /// This method is called when the plugin is attached to the repository. + /// + /// + void Attach(ILoggerRepository repository); - /// - /// Is called when the plugin is to shutdown. - /// - /// - /// - /// This method is called to notify the plugin that - /// it should stop operating and should detach from - /// the repository. - /// - /// - void Shutdown(); - } + /// + /// Is called when the plugin is to shutdown. + /// + /// + /// + /// This method is called to notify the plugin that + /// it should stop operating and should detach from + /// the repository. + /// + /// + void Shutdown(); + } } diff --git a/src/log4net/Plugin/IPluginFactory.cs b/src/log4net/Plugin/IPluginFactory.cs index 460a4d46..ce168a92 100644 --- a/src/log4net/Plugin/IPluginFactory.cs +++ b/src/log4net/Plugin/IPluginFactory.cs @@ -19,27 +19,27 @@ namespace log4net.Plugin { - /// - /// Interface used to create plugins. - /// - /// - /// - /// Interface used to create a plugin. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public interface IPluginFactory - { - /// - /// Creates the plugin object. - /// - /// the new plugin instance - /// - /// - /// Create and return a new plugin instance. - /// - /// - IPlugin CreatePlugin(); - } + /// + /// Interface used to create plugins. + /// + /// + /// + /// Interface used to create a plugin. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public interface IPluginFactory + { + /// + /// Creates the plugin object. + /// + /// the new plugin instance + /// + /// + /// Create and return a new plugin instance. + /// + /// + IPlugin CreatePlugin(); + } } diff --git a/src/log4net/Plugin/PluginCollection.cs b/src/log4net/Plugin/PluginCollection.cs index 7e7d4e24..c3c28e77 100644 --- a/src/log4net/Plugin/PluginCollection.cs +++ b/src/log4net/Plugin/PluginCollection.cs @@ -22,855 +22,855 @@ namespace log4net.Plugin { - /// - /// A strongly-typed collection of objects. - /// - /// Nicko Cadell - public class PluginCollection : ICollection, IList, IEnumerable + /// + /// A strongly-typed collection of objects. + /// + /// Nicko Cadell + public class PluginCollection : ICollection, IList, IEnumerable #if !NETSTANDARD1_3 - , ICloneable + , ICloneable #endif - { - #region Interfaces - - /// - /// Supports type-safe iteration over a . - /// - /// - public interface IPluginCollectionEnumerator - { - /// - /// Gets the current element in the collection. - /// - IPlugin Current { get; } - - /// - /// Advances the enumerator to the next element in the collection. - /// - /// - /// true if the enumerator was successfully advanced to the next element; - /// false if the enumerator has passed the end of the collection. - /// - /// - /// The collection was modified after the enumerator was created. - /// - bool MoveNext(); - - /// - /// Sets the enumerator to its initial position, before the first element in the collection. - /// - void Reset(); - } - - #endregion Interfaces - - private const int DEFAULT_CAPACITY = 16; - - #region Implementation (data) - - private IPlugin[] m_array; - private int m_count = 0; - private int m_version = 0; - - #endregion Implementation (data) - - #region Static Wrappers - - /// - /// Creates a read-only wrapper for a PluginCollection instance. - /// - /// list to create a readonly wrapper arround - /// - /// A PluginCollection wrapper that is read-only. - /// - public static PluginCollection ReadOnly(PluginCollection list) - { - if(list == null) throw new ArgumentNullException("list"); - - return new ReadOnlyPluginCollection(list); - } - - #endregion - - #region Constructors - - /// - /// Initializes a new instance of the PluginCollection class - /// that is empty and has the default initial capacity. - /// - public PluginCollection() - { - m_array = new IPlugin[DEFAULT_CAPACITY]; - } - - /// - /// Initializes a new instance of the PluginCollection class - /// that has the specified initial capacity. - /// - /// - /// The number of elements that the new PluginCollection is initially capable of storing. - /// - public PluginCollection(int capacity) - { - m_array = new IPlugin[capacity]; - } - - /// - /// Initializes a new instance of the PluginCollection class - /// that contains elements copied from the specified PluginCollection. - /// - /// The PluginCollection whose elements are copied to the new collection. - public PluginCollection(PluginCollection c) - { - m_array = new IPlugin[c.Count]; - AddRange(c); - } - - /// - /// Initializes a new instance of the PluginCollection class - /// that contains elements copied from the specified array. - /// - /// The array whose elements are copied to the new list. - public PluginCollection(IPlugin[] a) - { - m_array = new IPlugin[a.Length]; - AddRange(a); - } - - /// - /// Initializes a new instance of the PluginCollection class - /// that contains elements copied from the specified collection. - /// - /// The collection whose elements are copied to the new list. - public PluginCollection(ICollection col) - { - m_array = new IPlugin[col.Count]; - AddRange(col); - } - - /// - /// Type visible only to our subclasses - /// Used to access protected constructor - /// - /// - protected internal enum Tag - { - /// - /// A value - /// - Default - } - - /// - /// Allow subclasses to avoid our default constructors - /// - /// - /// - protected internal PluginCollection(Tag tag) - { - m_array = null; - } - - #endregion - - #region Operations (type-safe ICollection) - - /// - /// Gets the number of elements actually contained in the PluginCollection. - /// - public virtual int Count - { - get { return m_count; } - } - - /// - /// Copies the entire PluginCollection to a one-dimensional - /// array. - /// - /// The one-dimensional array to copy to. - public virtual void CopyTo(IPlugin[] array) - { - this.CopyTo(array, 0); - } - - /// - /// Copies the entire PluginCollection to a one-dimensional - /// array, starting at the specified index of the target array. - /// - /// The one-dimensional array to copy to. - /// The zero-based index in at which copying begins. - public virtual void CopyTo(IPlugin[] array, int start) - { - if (m_count > array.GetUpperBound(0) + 1 - start) - { - throw new System.ArgumentException("Destination array was not long enough."); - } - - Array.Copy(m_array, 0, array, start, m_count); - } - - /// - /// Gets a value indicating whether access to the collection is synchronized (thread-safe). - /// - /// false, because the backing type is an array, which is never thread-safe. - public virtual bool IsSynchronized - { - get { return false; } - } - - /// - /// Gets an object that can be used to synchronize access to the collection. - /// - /// - /// An object that can be used to synchronize access to the collection. - /// - public virtual object SyncRoot - { - get { return m_array; } - } - - #endregion - - #region Operations (type-safe IList) - - /// - /// Gets or sets the at the specified index. - /// - /// - /// The at the specified index. - /// - /// The zero-based index of the element to get or set. - /// - /// is less than zero. - /// -or- - /// is equal to or greater than . - /// - public virtual IPlugin this[int index] - { - get - { - ValidateIndex(index); // throws - return m_array[index]; - } - set - { - ValidateIndex(index); // throws - ++m_version; - m_array[index] = value; - } - } - - /// - /// Adds a to the end of the PluginCollection. - /// - /// The to be added to the end of the PluginCollection. - /// The index at which the value has been added. - public virtual int Add(IPlugin item) - { - if (m_count == m_array.Length) - { - EnsureCapacity(m_count + 1); - } - - m_array[m_count] = item; - m_version++; - - return m_count++; - } - - /// - /// Removes all elements from the PluginCollection. - /// - public virtual void Clear() - { - ++m_version; - m_array = new IPlugin[DEFAULT_CAPACITY]; - m_count = 0; - } - - /// - /// Creates a shallow copy of the . - /// - /// A new with a shallow copy of the collection data. - public virtual object Clone() - { - PluginCollection newCol = new PluginCollection(m_count); - Array.Copy(m_array, 0, newCol.m_array, 0, m_count); - newCol.m_count = m_count; - newCol.m_version = m_version; - - return newCol; - } - - /// - /// Determines whether a given is in the PluginCollection. - /// - /// The to check for. - /// true if is found in the PluginCollection; otherwise, false. - public virtual bool Contains(IPlugin item) - { - for (int i=0; i != m_count; ++i) - { - if (m_array[i].Equals(item)) - { - return true; - } - } - return false; - } - - /// - /// Returns the zero-based index of the first occurrence of a - /// in the PluginCollection. - /// - /// The to locate in the PluginCollection. - /// - /// The zero-based index of the first occurrence of - /// in the entire PluginCollection, if found; otherwise, -1. - /// - public virtual int IndexOf(IPlugin item) - { - for (int i=0; i != m_count; ++i) - { - if (m_array[i].Equals(item)) - { - return i; - } - } - return -1; - } - - /// - /// Inserts an element into the PluginCollection at the specified index. - /// - /// The zero-based index at which should be inserted. - /// The to insert. - /// - /// is less than zero - /// -or- - /// is equal to or greater than . - /// - public virtual void Insert(int index, IPlugin item) - { - ValidateIndex(index, true); // throws - - if (m_count == m_array.Length) - { - EnsureCapacity(m_count + 1); - } - - if (index < m_count) - { - Array.Copy(m_array, index, m_array, index + 1, m_count - index); - } - - m_array[index] = item; - m_count++; - m_version++; - } - - /// - /// Removes the first occurrence of a specific from the PluginCollection. - /// - /// The to remove from the PluginCollection. - /// - /// The specified was not found in the PluginCollection. - /// - public virtual void Remove(IPlugin item) - { - int i = IndexOf(item); - if (i < 0) - { - throw new System.ArgumentException("Cannot remove the specified item because it was not found in the specified Collection."); - } - ++m_version; - RemoveAt(i); - } - - /// - /// Removes the element at the specified index of the PluginCollection. - /// - /// The zero-based index of the element to remove. - /// - /// is less than zero. - /// -or- - /// is equal to or greater than . - /// - public virtual void RemoveAt(int index) - { - ValidateIndex(index); // throws - - m_count--; - - if (index < m_count) - { - Array.Copy(m_array, index + 1, m_array, index, m_count - index); - } - - // We can't set the deleted entry equal to null, because it might be a value type. - // Instead, we'll create an empty single-element array of the right type and copy it - // over the entry we want to erase. - IPlugin[] temp = new IPlugin[1]; - Array.Copy(temp, 0, m_array, m_count, 1); - m_version++; - } - - /// - /// Gets a value indicating whether the collection has a fixed size. - /// - /// true if the collection has a fixed size; otherwise, false. The default is false. - public virtual bool IsFixedSize - { - get { return false; } - } - - /// - /// Gets a value indicating whether the IList is read-only. - /// - /// true if the collection is read-only; otherwise, false. The default is false. - public virtual bool IsReadOnly - { - get { return false; } - } - - #endregion - - #region Operations (type-safe IEnumerable) - - /// - /// Returns an enumerator that can iterate through the PluginCollection. - /// - /// An for the entire PluginCollection. - public virtual IPluginCollectionEnumerator GetEnumerator() - { - return new Enumerator(this); - } - - #endregion - - #region Public helpers (just to mimic some nice features of ArrayList) - - /// - /// Gets or sets the number of elements the PluginCollection can contain. - /// - /// - /// The number of elements the PluginCollection can contain. - /// - public virtual int Capacity - { - get - { - return m_array.Length; - } - set - { - if (value < m_count) - { - value = m_count; - } - - if (value != m_array.Length) - { - if (value > 0) - { - IPlugin[] temp = new IPlugin[value]; - Array.Copy(m_array, 0, temp, 0, m_count); - m_array = temp; - } - else - { - m_array = new IPlugin[DEFAULT_CAPACITY]; - } - } - } - } - - /// - /// Adds the elements of another PluginCollection to the current PluginCollection. - /// - /// The PluginCollection whose elements should be added to the end of the current PluginCollection. - /// The new of the PluginCollection. - public virtual int AddRange(PluginCollection x) - { - if (m_count + x.Count >= m_array.Length) - { - EnsureCapacity(m_count + x.Count); - } - - Array.Copy(x.m_array, 0, m_array, m_count, x.Count); - m_count += x.Count; - m_version++; - - return m_count; - } - - /// - /// Adds the elements of a array to the current PluginCollection. - /// - /// The array whose elements should be added to the end of the PluginCollection. - /// The new of the PluginCollection. - public virtual int AddRange(IPlugin[] x) - { - if (m_count + x.Length >= m_array.Length) - { - EnsureCapacity(m_count + x.Length); - } - - Array.Copy(x, 0, m_array, m_count, x.Length); - m_count += x.Length; - m_version++; - - return m_count; - } - - /// - /// Adds the elements of a collection to the current PluginCollection. - /// - /// The collection whose elements should be added to the end of the PluginCollection. - /// The new of the PluginCollection. - public virtual int AddRange(ICollection col) - { - if (m_count + col.Count >= m_array.Length) - { - EnsureCapacity(m_count + col.Count); - } - - foreach(object item in col) - { - Add((IPlugin)item); - } - - return m_count; - } - - /// - /// Sets the capacity to the actual number of elements. - /// - public virtual void TrimToSize() - { - this.Capacity = m_count; - } - - #endregion - - #region Implementation (helpers) - - /// - /// is less than zero. - /// -or- - /// is equal to or greater than . - /// - private void ValidateIndex(int i) - { - ValidateIndex(i, false); - } - - /// - /// is less than zero. - /// -or- - /// is equal to or greater than . - /// - private void ValidateIndex(int i, bool allowEqualEnd) - { - int max = (allowEqualEnd) ? (m_count) : (m_count-1); - if (i < 0 || i > max) - { - throw log4net.Util.SystemInfo.CreateArgumentOutOfRangeException("i", (object)i, "Index was out of range. Must be non-negative and less than the size of the collection. [" + (object)i + "] Specified argument was out of the range of valid values."); - } - } - - private void EnsureCapacity(int min) - { - int newCapacity = ((m_array.Length == 0) ? DEFAULT_CAPACITY : m_array.Length * 2); - if (newCapacity < min) - { - newCapacity = min; - } - - this.Capacity = newCapacity; - } - - #endregion - - #region Implementation (ICollection) - - void ICollection.CopyTo(Array array, int start) - { - Array.Copy(m_array, 0, array, start, m_count); - } - - #endregion - - #region Implementation (IList) - - object IList.this[int i] - { - get { return (object)this[i]; } - set { this[i] = (IPlugin)value; } - } - - int IList.Add(object x) - { - return this.Add((IPlugin)x); - } - - bool IList.Contains(object x) - { - return this.Contains((IPlugin)x); - } - - int IList.IndexOf(object x) - { - return this.IndexOf((IPlugin)x); - } - - void IList.Insert(int pos, object x) - { - this.Insert(pos, (IPlugin)x); - } - - void IList.Remove(object x) - { - this.Remove((IPlugin)x); - } - - void IList.RemoveAt(int pos) - { - this.RemoveAt(pos); - } - - #endregion - - #region Implementation (IEnumerable) - - IEnumerator IEnumerable.GetEnumerator() - { - return (IEnumerator)(this.GetEnumerator()); - } - - #endregion Implementation (IEnumerable) - - #region Nested enumerator class - - /// - /// Supports simple iteration over a . - /// - /// - private sealed class Enumerator : IEnumerator, IPluginCollectionEnumerator - { - #region Implementation (data) - - private readonly PluginCollection m_collection; - private int m_index; - private int m_version; - - #endregion Implementation (data) - - #region Construction - - /// - /// Initializes a new instance of the Enumerator class. - /// - /// - internal Enumerator(PluginCollection tc) - { - m_collection = tc; - m_index = -1; - m_version = tc.m_version; - } - - #endregion - - #region Operations (type-safe IEnumerator) - - /// - /// Gets the current element in the collection. - /// - /// - /// The current element in the collection. - /// - public IPlugin Current - { - get { return m_collection[m_index]; } - } - - /// - /// Advances the enumerator to the next element in the collection. - /// - /// - /// true if the enumerator was successfully advanced to the next element; - /// false if the enumerator has passed the end of the collection. - /// - /// - /// The collection was modified after the enumerator was created. - /// - public bool MoveNext() - { - if (m_version != m_collection.m_version) - { - throw new System.InvalidOperationException("Collection was modified; enumeration operation may not execute."); - } - - ++m_index; - return (m_index < m_collection.Count); - } - - /// - /// Sets the enumerator to its initial position, before the first element in the collection. - /// - public void Reset() - { - m_index = -1; - } - - #endregion - - #region Implementation (IEnumerator) - - object IEnumerator.Current - { - get { return this.Current; } - } - - #endregion - } - - #endregion - - #region Nested Read Only Wrapper class - - /// - private sealed class ReadOnlyPluginCollection : PluginCollection - { - #region Implementation (data) - - private readonly PluginCollection m_collection; - - #endregion - - #region Construction - - internal ReadOnlyPluginCollection(PluginCollection list) : base(Tag.Default) - { - m_collection = list; - } - - #endregion - - #region Type-safe ICollection - - public override void CopyTo(IPlugin[] array) - { - m_collection.CopyTo(array); - } - - public override void CopyTo(IPlugin[] array, int start) - { - m_collection.CopyTo(array,start); - } - public override int Count - { - get { return m_collection.Count; } - } - - public override bool IsSynchronized - { - get { return m_collection.IsSynchronized; } - } - - public override object SyncRoot - { - get { return this.m_collection.SyncRoot; } - } - - #endregion - - #region Type-safe IList - - public override IPlugin this[int i] - { - get { return m_collection[i]; } - set { throw new NotSupportedException("This is a Read Only Collection and can not be modified"); } - } - - public override int Add(IPlugin x) - { - throw new NotSupportedException("This is a Read Only Collection and can not be modified"); - } + { + #region Interfaces + + /// + /// Supports type-safe iteration over a . + /// + /// + public interface IPluginCollectionEnumerator + { + /// + /// Gets the current element in the collection. + /// + IPlugin Current { get; } + + /// + /// Advances the enumerator to the next element in the collection. + /// + /// + /// true if the enumerator was successfully advanced to the next element; + /// false if the enumerator has passed the end of the collection. + /// + /// + /// The collection was modified after the enumerator was created. + /// + bool MoveNext(); + + /// + /// Sets the enumerator to its initial position, before the first element in the collection. + /// + void Reset(); + } + + #endregion Interfaces + + private const int DEFAULT_CAPACITY = 16; + + #region Implementation (data) + + private IPlugin[] m_array; + private int m_count = 0; + private int m_version = 0; + + #endregion Implementation (data) + + #region Static Wrappers + + /// + /// Creates a read-only wrapper for a PluginCollection instance. + /// + /// list to create a readonly wrapper arround + /// + /// A PluginCollection wrapper that is read-only. + /// + public static PluginCollection ReadOnly(PluginCollection list) + { + if(list == null) throw new ArgumentNullException("list"); + + return new ReadOnlyPluginCollection(list); + } + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the PluginCollection class + /// that is empty and has the default initial capacity. + /// + public PluginCollection() + { + m_array = new IPlugin[DEFAULT_CAPACITY]; + } + + /// + /// Initializes a new instance of the PluginCollection class + /// that has the specified initial capacity. + /// + /// + /// The number of elements that the new PluginCollection is initially capable of storing. + /// + public PluginCollection(int capacity) + { + m_array = new IPlugin[capacity]; + } + + /// + /// Initializes a new instance of the PluginCollection class + /// that contains elements copied from the specified PluginCollection. + /// + /// The PluginCollection whose elements are copied to the new collection. + public PluginCollection(PluginCollection c) + { + m_array = new IPlugin[c.Count]; + AddRange(c); + } + + /// + /// Initializes a new instance of the PluginCollection class + /// that contains elements copied from the specified array. + /// + /// The array whose elements are copied to the new list. + public PluginCollection(IPlugin[] a) + { + m_array = new IPlugin[a.Length]; + AddRange(a); + } + + /// + /// Initializes a new instance of the PluginCollection class + /// that contains elements copied from the specified collection. + /// + /// The collection whose elements are copied to the new list. + public PluginCollection(ICollection col) + { + m_array = new IPlugin[col.Count]; + AddRange(col); + } + + /// + /// Type visible only to our subclasses + /// Used to access protected constructor + /// + /// + protected internal enum Tag + { + /// + /// A value + /// + Default + } + + /// + /// Allow subclasses to avoid our default constructors + /// + /// + /// + protected internal PluginCollection(Tag tag) + { + m_array = null; + } + + #endregion + + #region Operations (type-safe ICollection) + + /// + /// Gets the number of elements actually contained in the PluginCollection. + /// + public virtual int Count + { + get { return m_count; } + } + + /// + /// Copies the entire PluginCollection to a one-dimensional + /// array. + /// + /// The one-dimensional array to copy to. + public virtual void CopyTo(IPlugin[] array) + { + this.CopyTo(array, 0); + } + + /// + /// Copies the entire PluginCollection to a one-dimensional + /// array, starting at the specified index of the target array. + /// + /// The one-dimensional array to copy to. + /// The zero-based index in at which copying begins. + public virtual void CopyTo(IPlugin[] array, int start) + { + if (m_count > array.GetUpperBound(0) + 1 - start) + { + throw new System.ArgumentException("Destination array was not long enough."); + } + + Array.Copy(m_array, 0, array, start, m_count); + } + + /// + /// Gets a value indicating whether access to the collection is synchronized (thread-safe). + /// + /// false, because the backing type is an array, which is never thread-safe. + public virtual bool IsSynchronized + { + get { return false; } + } + + /// + /// Gets an object that can be used to synchronize access to the collection. + /// + /// + /// An object that can be used to synchronize access to the collection. + /// + public virtual object SyncRoot + { + get { return m_array; } + } + + #endregion + + #region Operations (type-safe IList) + + /// + /// Gets or sets the at the specified index. + /// + /// + /// The at the specified index. + /// + /// The zero-based index of the element to get or set. + /// + /// is less than zero. + /// -or- + /// is equal to or greater than . + /// + public virtual IPlugin this[int index] + { + get + { + ValidateIndex(index); // throws + return m_array[index]; + } + set + { + ValidateIndex(index); // throws + ++m_version; + m_array[index] = value; + } + } + + /// + /// Adds a to the end of the PluginCollection. + /// + /// The to be added to the end of the PluginCollection. + /// The index at which the value has been added. + public virtual int Add(IPlugin item) + { + if (m_count == m_array.Length) + { + EnsureCapacity(m_count + 1); + } + + m_array[m_count] = item; + m_version++; + + return m_count++; + } + + /// + /// Removes all elements from the PluginCollection. + /// + public virtual void Clear() + { + ++m_version; + m_array = new IPlugin[DEFAULT_CAPACITY]; + m_count = 0; + } + + /// + /// Creates a shallow copy of the . + /// + /// A new with a shallow copy of the collection data. + public virtual object Clone() + { + PluginCollection newCol = new PluginCollection(m_count); + Array.Copy(m_array, 0, newCol.m_array, 0, m_count); + newCol.m_count = m_count; + newCol.m_version = m_version; + + return newCol; + } + + /// + /// Determines whether a given is in the PluginCollection. + /// + /// The to check for. + /// true if is found in the PluginCollection; otherwise, false. + public virtual bool Contains(IPlugin item) + { + for (int i=0; i != m_count; ++i) + { + if (m_array[i].Equals(item)) + { + return true; + } + } + return false; + } + + /// + /// Returns the zero-based index of the first occurrence of a + /// in the PluginCollection. + /// + /// The to locate in the PluginCollection. + /// + /// The zero-based index of the first occurrence of + /// in the entire PluginCollection, if found; otherwise, -1. + /// + public virtual int IndexOf(IPlugin item) + { + for (int i=0; i != m_count; ++i) + { + if (m_array[i].Equals(item)) + { + return i; + } + } + return -1; + } + + /// + /// Inserts an element into the PluginCollection at the specified index. + /// + /// The zero-based index at which should be inserted. + /// The to insert. + /// + /// is less than zero + /// -or- + /// is equal to or greater than . + /// + public virtual void Insert(int index, IPlugin item) + { + ValidateIndex(index, true); // throws + + if (m_count == m_array.Length) + { + EnsureCapacity(m_count + 1); + } + + if (index < m_count) + { + Array.Copy(m_array, index, m_array, index + 1, m_count - index); + } + + m_array[index] = item; + m_count++; + m_version++; + } + + /// + /// Removes the first occurrence of a specific from the PluginCollection. + /// + /// The to remove from the PluginCollection. + /// + /// The specified was not found in the PluginCollection. + /// + public virtual void Remove(IPlugin item) + { + int i = IndexOf(item); + if (i < 0) + { + throw new System.ArgumentException("Cannot remove the specified item because it was not found in the specified Collection."); + } + ++m_version; + RemoveAt(i); + } + + /// + /// Removes the element at the specified index of the PluginCollection. + /// + /// The zero-based index of the element to remove. + /// + /// is less than zero. + /// -or- + /// is equal to or greater than . + /// + public virtual void RemoveAt(int index) + { + ValidateIndex(index); // throws + + m_count--; + + if (index < m_count) + { + Array.Copy(m_array, index + 1, m_array, index, m_count - index); + } + + // We can't set the deleted entry equal to null, because it might be a value type. + // Instead, we'll create an empty single-element array of the right type and copy it + // over the entry we want to erase. + IPlugin[] temp = new IPlugin[1]; + Array.Copy(temp, 0, m_array, m_count, 1); + m_version++; + } + + /// + /// Gets a value indicating whether the collection has a fixed size. + /// + /// true if the collection has a fixed size; otherwise, false. The default is false. + public virtual bool IsFixedSize + { + get { return false; } + } + + /// + /// Gets a value indicating whether the IList is read-only. + /// + /// true if the collection is read-only; otherwise, false. The default is false. + public virtual bool IsReadOnly + { + get { return false; } + } + + #endregion + + #region Operations (type-safe IEnumerable) + + /// + /// Returns an enumerator that can iterate through the PluginCollection. + /// + /// An for the entire PluginCollection. + public virtual IPluginCollectionEnumerator GetEnumerator() + { + return new Enumerator(this); + } + + #endregion + + #region Public helpers (just to mimic some nice features of ArrayList) + + /// + /// Gets or sets the number of elements the PluginCollection can contain. + /// + /// + /// The number of elements the PluginCollection can contain. + /// + public virtual int Capacity + { + get + { + return m_array.Length; + } + set + { + if (value < m_count) + { + value = m_count; + } + + if (value != m_array.Length) + { + if (value > 0) + { + IPlugin[] temp = new IPlugin[value]; + Array.Copy(m_array, 0, temp, 0, m_count); + m_array = temp; + } + else + { + m_array = new IPlugin[DEFAULT_CAPACITY]; + } + } + } + } + + /// + /// Adds the elements of another PluginCollection to the current PluginCollection. + /// + /// The PluginCollection whose elements should be added to the end of the current PluginCollection. + /// The new of the PluginCollection. + public virtual int AddRange(PluginCollection x) + { + if (m_count + x.Count >= m_array.Length) + { + EnsureCapacity(m_count + x.Count); + } + + Array.Copy(x.m_array, 0, m_array, m_count, x.Count); + m_count += x.Count; + m_version++; + + return m_count; + } + + /// + /// Adds the elements of a array to the current PluginCollection. + /// + /// The array whose elements should be added to the end of the PluginCollection. + /// The new of the PluginCollection. + public virtual int AddRange(IPlugin[] x) + { + if (m_count + x.Length >= m_array.Length) + { + EnsureCapacity(m_count + x.Length); + } + + Array.Copy(x, 0, m_array, m_count, x.Length); + m_count += x.Length; + m_version++; + + return m_count; + } + + /// + /// Adds the elements of a collection to the current PluginCollection. + /// + /// The collection whose elements should be added to the end of the PluginCollection. + /// The new of the PluginCollection. + public virtual int AddRange(ICollection col) + { + if (m_count + col.Count >= m_array.Length) + { + EnsureCapacity(m_count + col.Count); + } + + foreach(object item in col) + { + Add((IPlugin)item); + } + + return m_count; + } + + /// + /// Sets the capacity to the actual number of elements. + /// + public virtual void TrimToSize() + { + this.Capacity = m_count; + } + + #endregion + + #region Implementation (helpers) + + /// + /// is less than zero. + /// -or- + /// is equal to or greater than . + /// + private void ValidateIndex(int i) + { + ValidateIndex(i, false); + } + + /// + /// is less than zero. + /// -or- + /// is equal to or greater than . + /// + private void ValidateIndex(int i, bool allowEqualEnd) + { + int max = (allowEqualEnd) ? (m_count) : (m_count-1); + if (i < 0 || i > max) + { + throw log4net.Util.SystemInfo.CreateArgumentOutOfRangeException("i", (object)i, "Index was out of range. Must be non-negative and less than the size of the collection. [" + (object)i + "] Specified argument was out of the range of valid values."); + } + } + + private void EnsureCapacity(int min) + { + int newCapacity = ((m_array.Length == 0) ? DEFAULT_CAPACITY : m_array.Length * 2); + if (newCapacity < min) + { + newCapacity = min; + } + + this.Capacity = newCapacity; + } + + #endregion + + #region Implementation (ICollection) + + void ICollection.CopyTo(Array array, int start) + { + Array.Copy(m_array, 0, array, start, m_count); + } + + #endregion + + #region Implementation (IList) + + object IList.this[int i] + { + get { return (object)this[i]; } + set { this[i] = (IPlugin)value; } + } + + int IList.Add(object x) + { + return this.Add((IPlugin)x); + } + + bool IList.Contains(object x) + { + return this.Contains((IPlugin)x); + } + + int IList.IndexOf(object x) + { + return this.IndexOf((IPlugin)x); + } + + void IList.Insert(int pos, object x) + { + this.Insert(pos, (IPlugin)x); + } + + void IList.Remove(object x) + { + this.Remove((IPlugin)x); + } + + void IList.RemoveAt(int pos) + { + this.RemoveAt(pos); + } + + #endregion + + #region Implementation (IEnumerable) + + IEnumerator IEnumerable.GetEnumerator() + { + return (IEnumerator)(this.GetEnumerator()); + } + + #endregion Implementation (IEnumerable) + + #region Nested enumerator class + + /// + /// Supports simple iteration over a . + /// + /// + private sealed class Enumerator : IEnumerator, IPluginCollectionEnumerator + { + #region Implementation (data) + + private readonly PluginCollection m_collection; + private int m_index; + private int m_version; + + #endregion Implementation (data) + + #region Construction + + /// + /// Initializes a new instance of the Enumerator class. + /// + /// + internal Enumerator(PluginCollection tc) + { + m_collection = tc; + m_index = -1; + m_version = tc.m_version; + } + + #endregion + + #region Operations (type-safe IEnumerator) + + /// + /// Gets the current element in the collection. + /// + /// + /// The current element in the collection. + /// + public IPlugin Current + { + get { return m_collection[m_index]; } + } + + /// + /// Advances the enumerator to the next element in the collection. + /// + /// + /// true if the enumerator was successfully advanced to the next element; + /// false if the enumerator has passed the end of the collection. + /// + /// + /// The collection was modified after the enumerator was created. + /// + public bool MoveNext() + { + if (m_version != m_collection.m_version) + { + throw new System.InvalidOperationException("Collection was modified; enumeration operation may not execute."); + } + + ++m_index; + return (m_index < m_collection.Count); + } + + /// + /// Sets the enumerator to its initial position, before the first element in the collection. + /// + public void Reset() + { + m_index = -1; + } + + #endregion + + #region Implementation (IEnumerator) + + object IEnumerator.Current + { + get { return this.Current; } + } + + #endregion + } + + #endregion + + #region Nested Read Only Wrapper class + + /// + private sealed class ReadOnlyPluginCollection : PluginCollection + { + #region Implementation (data) + + private readonly PluginCollection m_collection; + + #endregion + + #region Construction + + internal ReadOnlyPluginCollection(PluginCollection list) : base(Tag.Default) + { + m_collection = list; + } + + #endregion + + #region Type-safe ICollection + + public override void CopyTo(IPlugin[] array) + { + m_collection.CopyTo(array); + } + + public override void CopyTo(IPlugin[] array, int start) + { + m_collection.CopyTo(array,start); + } + public override int Count + { + get { return m_collection.Count; } + } + + public override bool IsSynchronized + { + get { return m_collection.IsSynchronized; } + } + + public override object SyncRoot + { + get { return this.m_collection.SyncRoot; } + } + + #endregion + + #region Type-safe IList + + public override IPlugin this[int i] + { + get { return m_collection[i]; } + set { throw new NotSupportedException("This is a Read Only Collection and can not be modified"); } + } + + public override int Add(IPlugin x) + { + throw new NotSupportedException("This is a Read Only Collection and can not be modified"); + } - public override void Clear() - { - throw new NotSupportedException("This is a Read Only Collection and can not be modified"); - } - - public override bool Contains(IPlugin x) - { - return m_collection.Contains(x); - } - - public override int IndexOf(IPlugin x) - { - return m_collection.IndexOf(x); - } - - public override void Insert(int pos, IPlugin x) - { - throw new NotSupportedException("This is a Read Only Collection and can not be modified"); - } - - public override void Remove(IPlugin x) - { - throw new NotSupportedException("This is a Read Only Collection and can not be modified"); - } - - public override void RemoveAt(int pos) - { - throw new NotSupportedException("This is a Read Only Collection and can not be modified"); - } - - public override bool IsFixedSize - { - get { return true; } - } - - public override bool IsReadOnly - { - get { return true; } - } - - #endregion - - #region Type-safe IEnumerable - - public override IPluginCollectionEnumerator GetEnumerator() - { - return m_collection.GetEnumerator(); - } - - #endregion - - #region Public Helpers - - // (just to mimic some nice features of ArrayList) - public override int Capacity - { - get { return m_collection.Capacity; } - set { throw new NotSupportedException("This is a Read Only Collection and can not be modified"); } - } - - public override int AddRange(PluginCollection x) - { - throw new NotSupportedException("This is a Read Only Collection and can not be modified"); - } - - public override int AddRange(IPlugin[] x) - { - throw new NotSupportedException("This is a Read Only Collection and can not be modified"); - } - - #endregion - } - - #endregion - } + public override void Clear() + { + throw new NotSupportedException("This is a Read Only Collection and can not be modified"); + } + + public override bool Contains(IPlugin x) + { + return m_collection.Contains(x); + } + + public override int IndexOf(IPlugin x) + { + return m_collection.IndexOf(x); + } + + public override void Insert(int pos, IPlugin x) + { + throw new NotSupportedException("This is a Read Only Collection and can not be modified"); + } + + public override void Remove(IPlugin x) + { + throw new NotSupportedException("This is a Read Only Collection and can not be modified"); + } + + public override void RemoveAt(int pos) + { + throw new NotSupportedException("This is a Read Only Collection and can not be modified"); + } + + public override bool IsFixedSize + { + get { return true; } + } + + public override bool IsReadOnly + { + get { return true; } + } + + #endregion + + #region Type-safe IEnumerable + + public override IPluginCollectionEnumerator GetEnumerator() + { + return m_collection.GetEnumerator(); + } + + #endregion + + #region Public Helpers + + // (just to mimic some nice features of ArrayList) + public override int Capacity + { + get { return m_collection.Capacity; } + set { throw new NotSupportedException("This is a Read Only Collection and can not be modified"); } + } + + public override int AddRange(PluginCollection x) + { + throw new NotSupportedException("This is a Read Only Collection and can not be modified"); + } + + public override int AddRange(IPlugin[] x) + { + throw new NotSupportedException("This is a Read Only Collection and can not be modified"); + } + + #endregion + } + + #endregion + } } diff --git a/src/log4net/Plugin/PluginMap.cs b/src/log4net/Plugin/PluginMap.cs index d05223f2..5c818d3e 100644 --- a/src/log4net/Plugin/PluginMap.cs +++ b/src/log4net/Plugin/PluginMap.cs @@ -25,165 +25,165 @@ namespace log4net.Plugin { - /// - /// Map of repository plugins. - /// - /// - /// - /// This class is a name keyed map of the plugins that are - /// attached to a repository. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public sealed class PluginMap - { - #region Public Instance Constructors - - /// - /// Constructor - /// - /// The repository that the plugins should be attached to. - /// - /// - /// Initialize a new instance of the class with a - /// repository that the plugins should be attached to. - /// - /// - public PluginMap(ILoggerRepository repository) - { - m_repository = repository; - } - - #endregion Public Instance Constructors - - #region Public Instance Properties - - /// - /// Gets a by name. - /// - /// The name of the to lookup. - /// - /// The from the map with the name specified, or - /// null if no plugin is found. - /// - /// - /// - /// Lookup a plugin by name. If the plugin is not found null - /// will be returned. - /// - /// - public IPlugin this[string name] - { - get - { - if (name == null) - { - throw new ArgumentNullException("name"); - } - - lock(this) - { - return (IPlugin)m_mapName2Plugin[name]; - } - } - } - - /// - /// Gets all possible plugins as a list of objects. - /// - /// All possible plugins as a list of objects. - /// - /// - /// Get a collection of all the plugins defined in this map. - /// - /// - public PluginCollection AllPlugins - { - get - { - lock(this) - { - return new PluginCollection(m_mapName2Plugin.Values); - } - } - } - - #endregion Public Instance Properties - - #region Public Instance Methods - - /// - /// Adds a to the map. - /// - /// The to add to the map. - /// - /// - /// The will be attached to the repository when added. - /// - /// - /// If there already exists a plugin with the same name - /// attached to the repository then the old plugin will - /// be and replaced with - /// the new plugin. - /// - /// - public void Add(IPlugin plugin) - { - if (plugin == null) - { - throw new ArgumentNullException("plugin"); - } - - IPlugin curPlugin = null; - - lock(this) - { - // Get the current plugin if it exists - curPlugin = m_mapName2Plugin[plugin.Name] as IPlugin; - - // Store new plugin - m_mapName2Plugin[plugin.Name] = plugin; - } - - // Shutdown existing plugin with same name - if (curPlugin != null) - { - curPlugin.Shutdown(); - } - - // Attach new plugin to repository - plugin.Attach(m_repository); - } - - /// - /// Removes a from the map. - /// - /// The to remove from the map. - /// - /// - /// Remove a specific plugin from this map. - /// - /// - public void Remove(IPlugin plugin) - { - if (plugin == null) - { - throw new ArgumentNullException("plugin"); - } - lock(this) - { - m_mapName2Plugin.Remove(plugin.Name); - } - } - - #endregion Public Instance Methods - - #region Private Instance Fields - - private readonly Hashtable m_mapName2Plugin = new Hashtable(); - private readonly ILoggerRepository m_repository; - - #endregion Private Instance Fields - } + /// + /// Map of repository plugins. + /// + /// + /// + /// This class is a name keyed map of the plugins that are + /// attached to a repository. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public sealed class PluginMap + { + #region Public Instance Constructors + + /// + /// Constructor + /// + /// The repository that the plugins should be attached to. + /// + /// + /// Initialize a new instance of the class with a + /// repository that the plugins should be attached to. + /// + /// + public PluginMap(ILoggerRepository repository) + { + m_repository = repository; + } + + #endregion Public Instance Constructors + + #region Public Instance Properties + + /// + /// Gets a by name. + /// + /// The name of the to lookup. + /// + /// The from the map with the name specified, or + /// null if no plugin is found. + /// + /// + /// + /// Lookup a plugin by name. If the plugin is not found null + /// will be returned. + /// + /// + public IPlugin this[string name] + { + get + { + if (name == null) + { + throw new ArgumentNullException("name"); + } + + lock(this) + { + return (IPlugin)m_mapName2Plugin[name]; + } + } + } + + /// + /// Gets all possible plugins as a list of objects. + /// + /// All possible plugins as a list of objects. + /// + /// + /// Get a collection of all the plugins defined in this map. + /// + /// + public PluginCollection AllPlugins + { + get + { + lock(this) + { + return new PluginCollection(m_mapName2Plugin.Values); + } + } + } + + #endregion Public Instance Properties + + #region Public Instance Methods + + /// + /// Adds a to the map. + /// + /// The to add to the map. + /// + /// + /// The will be attached to the repository when added. + /// + /// + /// If there already exists a plugin with the same name + /// attached to the repository then the old plugin will + /// be and replaced with + /// the new plugin. + /// + /// + public void Add(IPlugin plugin) + { + if (plugin == null) + { + throw new ArgumentNullException("plugin"); + } + + IPlugin curPlugin = null; + + lock(this) + { + // Get the current plugin if it exists + curPlugin = m_mapName2Plugin[plugin.Name] as IPlugin; + + // Store new plugin + m_mapName2Plugin[plugin.Name] = plugin; + } + + // Shutdown existing plugin with same name + if (curPlugin != null) + { + curPlugin.Shutdown(); + } + + // Attach new plugin to repository + plugin.Attach(m_repository); + } + + /// + /// Removes a from the map. + /// + /// The to remove from the map. + /// + /// + /// Remove a specific plugin from this map. + /// + /// + public void Remove(IPlugin plugin) + { + if (plugin == null) + { + throw new ArgumentNullException("plugin"); + } + lock(this) + { + m_mapName2Plugin.Remove(plugin.Name); + } + } + + #endregion Public Instance Methods + + #region Private Instance Fields + + private readonly Hashtable m_mapName2Plugin = new Hashtable(); + private readonly ILoggerRepository m_repository; + + #endregion Private Instance Fields + } } diff --git a/src/log4net/Plugin/PluginSkeleton.cs b/src/log4net/Plugin/PluginSkeleton.cs index 56ce5c3b..2c3d0f98 100644 --- a/src/log4net/Plugin/PluginSkeleton.cs +++ b/src/log4net/Plugin/PluginSkeleton.cs @@ -21,128 +21,128 @@ namespace log4net.Plugin { - /// - /// Base implementation of - /// - /// - /// - /// Default abstract implementation of the - /// interface. This base class can be used by implementors - /// of the interface. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public abstract class PluginSkeleton : IPlugin - { - #region Protected Instance Constructors - - /// - /// Constructor - /// - /// the name of the plugin - /// - /// Initializes a new Plugin with the specified name. - /// - protected PluginSkeleton(string name) - { - m_name = name; - } - - #endregion Protected Instance Constructors - - #region Implementation of IPlugin - - /// - /// Gets or sets the name of the plugin. - /// - /// - /// The name of the plugin. - /// - /// - /// - /// Plugins are stored in the - /// keyed by name. Each plugin instance attached to a - /// repository must be a unique name. - /// - /// - /// The name of the plugin must not change one the - /// plugin has been attached to a repository. - /// - /// - public virtual string Name - { - get { return m_name; } - set { m_name = value; } - } - - /// - /// Attaches this plugin to a . - /// - /// The that this plugin should be attached to. - /// - /// - /// A plugin may only be attached to a single repository. - /// - /// - /// This method is called when the plugin is attached to the repository. - /// - /// - public virtual void Attach(ILoggerRepository repository) - { - m_repository = repository; - } - - /// - /// Is called when the plugin is to shutdown. - /// - /// - /// - /// This method is called to notify the plugin that - /// it should stop operating and should detach from - /// the repository. - /// - /// - public virtual void Shutdown() - { - } - - #endregion Implementation of IPlugin - - #region Protected Instance Properties - - /// - /// The repository for this plugin - /// - /// - /// The that this plugin is attached to. - /// - /// - /// - /// Gets or sets the that this plugin is - /// attached to. - /// - /// - protected virtual ILoggerRepository LoggerRepository - { - get { return this.m_repository; } - set { this.m_repository = value; } - } - - #endregion Protected Instance Properties - - #region Private Instance Fields - - /// - /// The name of this plugin. - /// - private string m_name; - - /// - /// The repository this plugin is attached to. - /// - private ILoggerRepository m_repository; - - #endregion Private Instance Fields - } + /// + /// Base implementation of + /// + /// + /// + /// Default abstract implementation of the + /// interface. This base class can be used by implementors + /// of the interface. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public abstract class PluginSkeleton : IPlugin + { + #region Protected Instance Constructors + + /// + /// Constructor + /// + /// the name of the plugin + /// + /// Initializes a new Plugin with the specified name. + /// + protected PluginSkeleton(string name) + { + m_name = name; + } + + #endregion Protected Instance Constructors + + #region Implementation of IPlugin + + /// + /// Gets or sets the name of the plugin. + /// + /// + /// The name of the plugin. + /// + /// + /// + /// Plugins are stored in the + /// keyed by name. Each plugin instance attached to a + /// repository must be a unique name. + /// + /// + /// The name of the plugin must not change one the + /// plugin has been attached to a repository. + /// + /// + public virtual string Name + { + get { return m_name; } + set { m_name = value; } + } + + /// + /// Attaches this plugin to a . + /// + /// The that this plugin should be attached to. + /// + /// + /// A plugin may only be attached to a single repository. + /// + /// + /// This method is called when the plugin is attached to the repository. + /// + /// + public virtual void Attach(ILoggerRepository repository) + { + m_repository = repository; + } + + /// + /// Is called when the plugin is to shutdown. + /// + /// + /// + /// This method is called to notify the plugin that + /// it should stop operating and should detach from + /// the repository. + /// + /// + public virtual void Shutdown() + { + } + + #endregion Implementation of IPlugin + + #region Protected Instance Properties + + /// + /// The repository for this plugin + /// + /// + /// The that this plugin is attached to. + /// + /// + /// + /// Gets or sets the that this plugin is + /// attached to. + /// + /// + protected virtual ILoggerRepository LoggerRepository + { + get { return this.m_repository; } + set { this.m_repository = value; } + } + + #endregion Protected Instance Properties + + #region Private Instance Fields + + /// + /// The name of this plugin. + /// + private string m_name; + + /// + /// The repository this plugin is attached to. + /// + private ILoggerRepository m_repository; + + #endregion Private Instance Fields + } } diff --git a/src/log4net/Plugin/RemoteLoggingServerPlugin.cs b/src/log4net/Plugin/RemoteLoggingServerPlugin.cs index ff5824bb..ec059785 100644 --- a/src/log4net/Plugin/RemoteLoggingServerPlugin.cs +++ b/src/log4net/Plugin/RemoteLoggingServerPlugin.cs @@ -31,250 +31,250 @@ namespace log4net.Plugin { - /// - /// Plugin that listens for events from the - /// - /// - /// - /// This plugin publishes an instance of - /// on a specified . This listens for logging events delivered from - /// a remote . - /// - /// - /// When an event is received it is relogged within the attached repository - /// as if it had been raised locally. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public class RemoteLoggingServerPlugin : PluginSkeleton - { - #region Public Instance Constructors - - /// - /// Default constructor - /// - /// - /// - /// Initializes a new instance of the class. - /// - /// - /// The property must be set. - /// - /// - public RemoteLoggingServerPlugin() : base("RemoteLoggingServerPlugin:Unset URI") - { - } - - /// - /// Construct with sink Uri. - /// - /// The name to publish the sink under in the remoting infrastructure. - /// See for more details. - /// - /// - /// Initializes a new instance of the class - /// with specified name. - /// - /// - public RemoteLoggingServerPlugin(string sinkUri) : base("RemoteLoggingServerPlugin:"+sinkUri) - { - m_sinkUri = sinkUri; - } - - #endregion Public Instance Constructors - - #region Public Instance Properties - - /// - /// Gets or sets the URI of this sink. - /// - /// - /// The URI of this sink. - /// - /// - /// - /// This is the name under which the object is marshaled. - /// - /// - /// - public virtual string SinkUri - { - get { return m_sinkUri; } - set { m_sinkUri = value; } - } - - #endregion Public Instance Properties - - #region Override implementation of PluginSkeleton - - /// - /// Attaches this plugin to a . - /// - /// The that this plugin should be attached to. - /// - /// - /// A plugin may only be attached to a single repository. - /// - /// - /// This method is called when the plugin is attached to the repository. - /// - /// + /// + /// Plugin that listens for events from the + /// + /// + /// + /// This plugin publishes an instance of + /// on a specified . This listens for logging events delivered from + /// a remote . + /// + /// + /// When an event is received it is relogged within the attached repository + /// as if it had been raised locally. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public class RemoteLoggingServerPlugin : PluginSkeleton + { + #region Public Instance Constructors + + /// + /// Default constructor + /// + /// + /// + /// Initializes a new instance of the class. + /// + /// + /// The property must be set. + /// + /// + public RemoteLoggingServerPlugin() : base("RemoteLoggingServerPlugin:Unset URI") + { + } + + /// + /// Construct with sink Uri. + /// + /// The name to publish the sink under in the remoting infrastructure. + /// See for more details. + /// + /// + /// Initializes a new instance of the class + /// with specified name. + /// + /// + public RemoteLoggingServerPlugin(string sinkUri) : base("RemoteLoggingServerPlugin:"+sinkUri) + { + m_sinkUri = sinkUri; + } + + #endregion Public Instance Constructors + + #region Public Instance Properties + + /// + /// Gets or sets the URI of this sink. + /// + /// + /// The URI of this sink. + /// + /// + /// + /// This is the name under which the object is marshaled. + /// + /// + /// + public virtual string SinkUri + { + get { return m_sinkUri; } + set { m_sinkUri = value; } + } + + #endregion Public Instance Properties + + #region Override implementation of PluginSkeleton + + /// + /// Attaches this plugin to a . + /// + /// The that this plugin should be attached to. + /// + /// + /// A plugin may only be attached to a single repository. + /// + /// + /// This method is called when the plugin is attached to the repository. + /// + /// #if NET_4_0 || MONO_4_0 - [System.Security.SecuritySafeCritical] + [System.Security.SecuritySafeCritical] #endif - public override void Attach(ILoggerRepository repository) - { - base.Attach(repository); - - // Create the sink and marshal it - m_sink = new RemoteLoggingSinkImpl(repository); - - try - { - RemotingServices.Marshal(m_sink, m_sinkUri, typeof(IRemoteLoggingSink)); - } - catch(Exception ex) - { - LogLog.Error(declaringType, "Failed to Marshal remoting sink", ex); - } - } - - /// - /// Is called when the plugin is to shutdown. - /// - /// - /// - /// When the plugin is shutdown the remote logging - /// sink is disconnected. - /// - /// + public override void Attach(ILoggerRepository repository) + { + base.Attach(repository); + + // Create the sink and marshal it + m_sink = new RemoteLoggingSinkImpl(repository); + + try + { + RemotingServices.Marshal(m_sink, m_sinkUri, typeof(IRemoteLoggingSink)); + } + catch(Exception ex) + { + LogLog.Error(declaringType, "Failed to Marshal remoting sink", ex); + } + } + + /// + /// Is called when the plugin is to shutdown. + /// + /// + /// + /// When the plugin is shutdown the remote logging + /// sink is disconnected. + /// + /// #if NET_4_0 || MONO_4_0 [System.Security.SecuritySafeCritical] #endif public override void Shutdown() - { - // Stops the sink from receiving messages - RemotingServices.Disconnect(m_sink); - m_sink = null; - - base.Shutdown(); - } - - #endregion Override implementation of PluginSkeleton - - #region Private Instance Fields - - private RemoteLoggingSinkImpl m_sink; - private string m_sinkUri; - - #endregion Private Instance Fields - - #region Private Static Fields - - /// - /// The fully qualified type of the RemoteLoggingServerPlugin class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(RemoteLoggingServerPlugin); - - #endregion Private Static Fields - - /// - /// Delivers objects to a remote sink. - /// - /// - /// - /// Internal class used to listen for logging events - /// and deliver them to the local repository. - /// - /// - private class RemoteLoggingSinkImpl : MarshalByRefObject, IRemoteLoggingSink - { - #region Public Instance Constructors - - /// - /// Constructor - /// - /// The repository to log to. - /// - /// - /// Initializes a new instance of the for the - /// specified . - /// - /// - public RemoteLoggingSinkImpl(ILoggerRepository repository) - { - m_repository = repository; - } - - #endregion Public Instance Constructors - - #region Implementation of IRemoteLoggingSink - - /// - /// Logs the events to the repository. - /// - /// The events to log. - /// - /// - /// The events passed are logged to the - /// - /// - public void LogEvents(LoggingEvent[] events) - { - if (events != null) - { - foreach(LoggingEvent logEvent in events) - { - if (logEvent != null) - { - m_repository.Log(logEvent); - } - } - } - } - - #endregion Implementation of IRemoteLoggingSink - - #region Override implementation of MarshalByRefObject - - /// - /// Obtains a lifetime service object to control the lifetime - /// policy for this instance. - /// - /// null to indicate that this instance should live forever. - /// - /// - /// Obtains a lifetime service object to control the lifetime - /// policy for this instance. This object should live forever - /// therefore this implementation returns null. - /// - /// + { + // Stops the sink from receiving messages + RemotingServices.Disconnect(m_sink); + m_sink = null; + + base.Shutdown(); + } + + #endregion Override implementation of PluginSkeleton + + #region Private Instance Fields + + private RemoteLoggingSinkImpl m_sink; + private string m_sinkUri; + + #endregion Private Instance Fields + + #region Private Static Fields + + /// + /// The fully qualified type of the RemoteLoggingServerPlugin class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(RemoteLoggingServerPlugin); + + #endregion Private Static Fields + + /// + /// Delivers objects to a remote sink. + /// + /// + /// + /// Internal class used to listen for logging events + /// and deliver them to the local repository. + /// + /// + private class RemoteLoggingSinkImpl : MarshalByRefObject, IRemoteLoggingSink + { + #region Public Instance Constructors + + /// + /// Constructor + /// + /// The repository to log to. + /// + /// + /// Initializes a new instance of the for the + /// specified . + /// + /// + public RemoteLoggingSinkImpl(ILoggerRepository repository) + { + m_repository = repository; + } + + #endregion Public Instance Constructors + + #region Implementation of IRemoteLoggingSink + + /// + /// Logs the events to the repository. + /// + /// The events to log. + /// + /// + /// The events passed are logged to the + /// + /// + public void LogEvents(LoggingEvent[] events) + { + if (events != null) + { + foreach(LoggingEvent logEvent in events) + { + if (logEvent != null) + { + m_repository.Log(logEvent); + } + } + } + } + + #endregion Implementation of IRemoteLoggingSink + + #region Override implementation of MarshalByRefObject + + /// + /// Obtains a lifetime service object to control the lifetime + /// policy for this instance. + /// + /// null to indicate that this instance should live forever. + /// + /// + /// Obtains a lifetime service object to control the lifetime + /// policy for this instance. This object should live forever + /// therefore this implementation returns null. + /// + /// #if NET_4_0 || MONO_4_0 [System.Security.SecurityCritical] #endif public override object InitializeLifetimeService() - { - return null; - } + { + return null; + } - #endregion Override implementation of MarshalByRefObject + #endregion Override implementation of MarshalByRefObject - #region Private Instance Fields + #region Private Instance Fields - /// - /// The underlying that events should - /// be logged to. - /// - private readonly ILoggerRepository m_repository; + /// + /// The underlying that events should + /// be logged to. + /// + private readonly ILoggerRepository m_repository; - #endregion Private Instance Fields - } - } + #endregion Private Instance Fields + } + } } #endif // NET_2_0 \ No newline at end of file diff --git a/src/log4net/Repository/Hierarchy/DefaultLoggerFactory.cs b/src/log4net/Repository/Hierarchy/DefaultLoggerFactory.cs index 78239c57..9bb079b6 100644 --- a/src/log4net/Repository/Hierarchy/DefaultLoggerFactory.cs +++ b/src/log4net/Repository/Hierarchy/DefaultLoggerFactory.cs @@ -21,94 +21,94 @@ namespace log4net.Repository.Hierarchy { - /// - /// Default implementation of - /// - /// - /// - /// This default implementation of the - /// interface is used to create the default subclass - /// of the object. - /// - /// - /// Nicko Cadell - /// Gert Driesen - internal class DefaultLoggerFactory : ILoggerFactory - { - #region Internal Instance Constructors + /// + /// Default implementation of + /// + /// + /// + /// This default implementation of the + /// interface is used to create the default subclass + /// of the object. + /// + /// + /// Nicko Cadell + /// Gert Driesen + internal class DefaultLoggerFactory : ILoggerFactory + { + #region Internal Instance Constructors - /// - /// Default constructor - /// - /// - /// - /// Initializes a new instance of the class. - /// - /// - internal DefaultLoggerFactory() - { - } + /// + /// Default constructor + /// + /// + /// + /// Initializes a new instance of the class. + /// + /// + internal DefaultLoggerFactory() + { + } - #endregion Internal Instance Constructors + #endregion Internal Instance Constructors - #region Implementation of ILoggerFactory + #region Implementation of ILoggerFactory - /// - /// Create a new instance - /// - /// The that will own the . - /// The name of the . - /// The instance for the specified name. - /// - /// - /// Create a new instance with the - /// specified name. - /// - /// - /// Called by the to create - /// new named instances. - /// - /// - /// If the is null then the root logger - /// must be returned. - /// - /// - public Logger CreateLogger(ILoggerRepository repository, string name) - { - if (name == null) - { - return new RootLogger(repository.LevelMap.LookupWithDefault(Level.Debug)); - } - return new LoggerImpl(name); - } + /// + /// Create a new instance + /// + /// The that will own the . + /// The name of the . + /// The instance for the specified name. + /// + /// + /// Create a new instance with the + /// specified name. + /// + /// + /// Called by the to create + /// new named instances. + /// + /// + /// If the is null then the root logger + /// must be returned. + /// + /// + public Logger CreateLogger(ILoggerRepository repository, string name) + { + if (name == null) + { + return new RootLogger(repository.LevelMap.LookupWithDefault(Level.Debug)); + } + return new LoggerImpl(name); + } - #endregion + #endregion - /// - /// Default internal subclass of - /// - /// - /// - /// This subclass has no additional behavior over the - /// class but does allow instances - /// to be created. - /// - /// - internal sealed class LoggerImpl : Logger - { - /// - /// Construct a new Logger - /// - /// the name of the logger - /// - /// - /// Initializes a new instance of the class - /// with the specified name. - /// - /// - internal LoggerImpl(string name) : base(name) - { - } - } - } + /// + /// Default internal subclass of + /// + /// + /// + /// This subclass has no additional behavior over the + /// class but does allow instances + /// to be created. + /// + /// + internal sealed class LoggerImpl : Logger + { + /// + /// Construct a new Logger + /// + /// the name of the logger + /// + /// + /// Initializes a new instance of the class + /// with the specified name. + /// + /// + internal LoggerImpl(string name) : base(name) + { + } + } + } } diff --git a/src/log4net/Repository/Hierarchy/Hierarchy.cs b/src/log4net/Repository/Hierarchy/Hierarchy.cs index c21d09af..ce215be5 100644 --- a/src/log4net/Repository/Hierarchy/Hierarchy.cs +++ b/src/log4net/Repository/Hierarchy/Hierarchy.cs @@ -26,523 +26,523 @@ namespace log4net.Repository.Hierarchy { - #region LoggerCreationEvent - - /// - /// Delegate used to handle logger creation event notifications. - /// - /// The in which the has been created. - /// The event args that hold the instance that has been created. - /// - /// - /// Delegate used to handle logger creation event notifications. - /// - /// - public delegate void LoggerCreationEventHandler(object sender, LoggerCreationEventArgs e); - - /// - /// Provides data for the event. - /// - /// - /// - /// A event is raised every time a - /// is created. - /// - /// - public class LoggerCreationEventArgs : EventArgs - { - /// - /// The created - /// - private Logger m_log; - - /// - /// Constructor - /// - /// The that has been created. - /// - /// - /// Initializes a new instance of the event argument - /// class,with the specified . - /// - /// - public LoggerCreationEventArgs(Logger log) - { - m_log = log; - } - - /// - /// Gets the that has been created. - /// - /// - /// The that has been created. - /// - /// - /// - /// The that has been created. - /// - /// - public Logger Logger - { - get { return m_log; } - } - } - - #endregion LoggerCreationEvent - - /// - /// Hierarchical organization of loggers - /// - /// - /// - /// The casual user should not have to deal with this class - /// directly. - /// - /// - /// This class is specialized in retrieving loggers by name and - /// also maintaining the logger hierarchy. Implements the - /// interface. - /// - /// - /// The structure of the logger hierarchy is maintained by the - /// method. The hierarchy is such that children - /// link to their parent but parents do not have any references to their - /// children. Moreover, loggers can be instantiated in any order, in - /// particular descendant before ancestor. - /// - /// - /// In case a descendant is created before a particular ancestor, - /// then it creates a provision node for the ancestor and adds itself - /// to the provision node. Other descendants of the same ancestor add - /// themselves to the previously created provision node. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public class Hierarchy : LoggerRepositorySkeleton, IBasicRepositoryConfigurator, IXmlRepositoryConfigurator - { - #region Public Events - - /// - /// Event used to notify that a logger has been created. - /// - /// - /// - /// Event raised when a logger is created. - /// - /// - public event LoggerCreationEventHandler LoggerCreatedEvent - { - add { m_loggerCreatedEvent += value; } - remove { m_loggerCreatedEvent -= value; } - } - - #endregion Public Events - - #region Public Instance Constructors - - /// - /// Default constructor - /// - /// - /// - /// Initializes a new instance of the class. - /// - /// - public Hierarchy() : this(new DefaultLoggerFactory()) - { - } - - /// - /// Construct with properties - /// - /// The properties to pass to this repository. - /// - /// - /// Initializes a new instance of the class. - /// - /// - public Hierarchy(PropertiesDictionary properties) : this(properties, new DefaultLoggerFactory()) - { - } - - /// - /// Construct with a logger factory - /// - /// The factory to use to create new logger instances. - /// - /// - /// Initializes a new instance of the class with - /// the specified . - /// - /// - public Hierarchy(ILoggerFactory loggerFactory) : this(new PropertiesDictionary(), loggerFactory) - { - } - - /// - /// Construct with properties and a logger factory - /// - /// The properties to pass to this repository. - /// The factory to use to create new logger instances. - /// - /// - /// Initializes a new instance of the class with - /// the specified . - /// - /// - public Hierarchy(PropertiesDictionary properties, ILoggerFactory loggerFactory) : base(properties) - { - if (loggerFactory == null) - { - throw new ArgumentNullException("loggerFactory"); - } - - m_defaultFactory = loggerFactory; - - m_ht = System.Collections.Hashtable.Synchronized(new System.Collections.Hashtable()); - } - - #endregion Public Instance Constructors - - #region Public Instance Properties - - /// - /// Has no appender warning been emitted - /// - /// - /// - /// Flag to indicate if we have already issued a warning - /// about not having an appender warning. - /// - /// - public bool EmittedNoAppenderWarning - { - get { return m_emittedNoAppenderWarning; } - set { m_emittedNoAppenderWarning = value; } - } - - /// - /// Get the root of this hierarchy - /// - /// - /// - /// Get the root of this hierarchy. - /// - /// - public Logger Root - { - get - { - if (m_root == null) - { - lock(this) - { - if (m_root == null) - { - // Create the root logger - Logger root = m_defaultFactory.CreateLogger(this, null); - root.Hierarchy = this; - - // Store root - m_root = root; - } - } - } - return m_root; - } - } - - /// - /// Gets or sets the default instance. - /// - /// The default - /// - /// - /// The logger factory is used to create logger instances. - /// - /// - public ILoggerFactory LoggerFactory - { - get { return m_defaultFactory; } - set - { - if (value == null) - { - throw new ArgumentNullException("value"); - } - m_defaultFactory = value; - } - } - - #endregion Public Instance Properties - - #region Override Implementation of LoggerRepositorySkeleton - - /// - /// Test if a logger exists - /// - /// The name of the logger to lookup - /// The Logger object with the name specified - /// - /// - /// Check if the named logger exists in the hierarchy. If so return - /// its reference, otherwise returns null. - /// - /// - public override ILogger Exists(string name) - { - if (name == null) - { - throw new ArgumentNullException("name"); - } - - lock(m_ht) - { - return m_ht[new LoggerKey(name)] as Logger; - } - } - - /// - /// Returns all the currently defined loggers in the hierarchy as an Array - /// - /// All the defined loggers - /// - /// - /// Returns all the currently defined loggers in the hierarchy as an Array. - /// The root logger is not included in the returned - /// enumeration. - /// - /// - public override ILogger[] GetCurrentLoggers() - { - // The accumulation in loggers is necessary because not all elements in - // ht are Logger objects as there might be some ProvisionNodes - // as well. - lock(m_ht) - { - System.Collections.ArrayList loggers = new System.Collections.ArrayList(m_ht.Count); - - // Iterate through m_ht values - foreach(object node in m_ht.Values) - { - if (node is Logger) - { - loggers.Add(node); - } - } - return (Logger[])loggers.ToArray(typeof(Logger)); - } - } - - /// - /// Return a new logger instance named as the first parameter using - /// the default factory. - /// - /// - /// - /// Return a new logger instance named as the first parameter using - /// the default factory. - /// - /// - /// If a logger of that name already exists, then it will be - /// returned. Otherwise, a new logger will be instantiated and - /// then linked with its existing ancestors as well as children. - /// - /// - /// The name of the logger to retrieve - /// The logger object with the name specified - public override ILogger GetLogger(string name) - { - if (name == null) - { - throw new ArgumentNullException("name"); - } - - return GetLogger(name, m_defaultFactory); - } - - /// - /// Shutting down a hierarchy will safely close and remove - /// all appenders in all loggers including the root logger. - /// - /// - /// - /// Shutting down a hierarchy will safely close and remove - /// all appenders in all loggers including the root logger. - /// - /// - /// Some appenders need to be closed before the - /// application exists. Otherwise, pending logging events might be - /// lost. - /// - /// - /// The Shutdown method is careful to close nested - /// appenders before closing regular appenders. This is allows - /// configurations where a regular appender is attached to a logger - /// and again to a nested appender. - /// - /// - public override void Shutdown() - { - LogLog.Debug(declaringType, "Shutdown called on Hierarchy ["+this.Name+"]"); - - // begin by closing nested appenders - Root.CloseNestedAppenders(); - - lock(m_ht) - { - ILogger[] currentLoggers = this.GetCurrentLoggers(); - - foreach(Logger logger in currentLoggers) - { - logger.CloseNestedAppenders(); - } - - // then, remove all appenders - Root.RemoveAllAppenders(); - - foreach(Logger logger in currentLoggers) - { - logger.RemoveAllAppenders(); - } - } - - base.Shutdown(); - } - - /// - /// Reset all values contained in this hierarchy instance to their default. - /// - /// - /// - /// Reset all values contained in this hierarchy instance to their - /// default. This removes all appenders from all loggers, sets - /// the level of all non-root loggers to null, - /// sets their additivity flag to true and sets the level - /// of the root logger to . Moreover, - /// message disabling is set its default "off" value. - /// - /// - /// Existing loggers are not removed. They are just reset. - /// - /// - /// This method should be used sparingly and with care as it will - /// block all logging until it is completed. - /// - /// - public override void ResetConfiguration() - { - Root.Level = LevelMap.LookupWithDefault(Level.Debug); - Threshold = LevelMap.LookupWithDefault(Level.All); - - // the synchronization is needed to prevent hashtable surprises - lock(m_ht) - { - Shutdown(); // nested locks are OK - - foreach(Logger l in this.GetCurrentLoggers()) - { - l.Level = null; - l.Additivity = true; - } - } - - base.ResetConfiguration(); - - // Notify listeners - OnConfigurationChanged(null); - } - - /// - /// Log the logEvent through this hierarchy. - /// - /// the event to log - /// - /// - /// This method should not normally be used to log. - /// The interface should be used - /// for routine logging. This interface can be obtained - /// using the method. - /// - /// - /// The logEvent is delivered to the appropriate logger and - /// that logger is then responsible for logging the event. - /// - /// - public override void Log(LoggingEvent logEvent) - { - if (logEvent == null) - { - throw new ArgumentNullException("logEvent"); - } - - this.GetLogger(logEvent.LoggerName, m_defaultFactory).Log(logEvent); - } - - /// - /// Returns all the Appenders that are currently configured - /// - /// An array containing all the currently configured appenders - /// - /// - /// Returns all the instances that are currently configured. - /// All the loggers are searched for appenders. The appenders may also be containers - /// for appenders and these are also searched for additional loggers. - /// - /// - /// The list returned is unordered but does not contain duplicates. - /// - /// - public override Appender.IAppender[] GetAppenders() - { - System.Collections.ArrayList appenderList = new System.Collections.ArrayList(); - - CollectAppenders(appenderList, Root); - - foreach(Logger logger in GetCurrentLoggers()) - { - CollectAppenders(appenderList, logger); - } - - return (Appender.IAppender[])appenderList.ToArray(typeof(Appender.IAppender)); - } - - #endregion Override Implementation of LoggerRepositorySkeleton + #region LoggerCreationEvent + + /// + /// Delegate used to handle logger creation event notifications. + /// + /// The in which the has been created. + /// The event args that hold the instance that has been created. + /// + /// + /// Delegate used to handle logger creation event notifications. + /// + /// + public delegate void LoggerCreationEventHandler(object sender, LoggerCreationEventArgs e); + + /// + /// Provides data for the event. + /// + /// + /// + /// A event is raised every time a + /// is created. + /// + /// + public class LoggerCreationEventArgs : EventArgs + { + /// + /// The created + /// + private Logger m_log; + + /// + /// Constructor + /// + /// The that has been created. + /// + /// + /// Initializes a new instance of the event argument + /// class,with the specified . + /// + /// + public LoggerCreationEventArgs(Logger log) + { + m_log = log; + } + + /// + /// Gets the that has been created. + /// + /// + /// The that has been created. + /// + /// + /// + /// The that has been created. + /// + /// + public Logger Logger + { + get { return m_log; } + } + } + + #endregion LoggerCreationEvent + + /// + /// Hierarchical organization of loggers + /// + /// + /// + /// The casual user should not have to deal with this class + /// directly. + /// + /// + /// This class is specialized in retrieving loggers by name and + /// also maintaining the logger hierarchy. Implements the + /// interface. + /// + /// + /// The structure of the logger hierarchy is maintained by the + /// method. The hierarchy is such that children + /// link to their parent but parents do not have any references to their + /// children. Moreover, loggers can be instantiated in any order, in + /// particular descendant before ancestor. + /// + /// + /// In case a descendant is created before a particular ancestor, + /// then it creates a provision node for the ancestor and adds itself + /// to the provision node. Other descendants of the same ancestor add + /// themselves to the previously created provision node. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public class Hierarchy : LoggerRepositorySkeleton, IBasicRepositoryConfigurator, IXmlRepositoryConfigurator + { + #region Public Events + + /// + /// Event used to notify that a logger has been created. + /// + /// + /// + /// Event raised when a logger is created. + /// + /// + public event LoggerCreationEventHandler LoggerCreatedEvent + { + add { m_loggerCreatedEvent += value; } + remove { m_loggerCreatedEvent -= value; } + } + + #endregion Public Events + + #region Public Instance Constructors + + /// + /// Default constructor + /// + /// + /// + /// Initializes a new instance of the class. + /// + /// + public Hierarchy() : this(new DefaultLoggerFactory()) + { + } + + /// + /// Construct with properties + /// + /// The properties to pass to this repository. + /// + /// + /// Initializes a new instance of the class. + /// + /// + public Hierarchy(PropertiesDictionary properties) : this(properties, new DefaultLoggerFactory()) + { + } + + /// + /// Construct with a logger factory + /// + /// The factory to use to create new logger instances. + /// + /// + /// Initializes a new instance of the class with + /// the specified . + /// + /// + public Hierarchy(ILoggerFactory loggerFactory) : this(new PropertiesDictionary(), loggerFactory) + { + } + + /// + /// Construct with properties and a logger factory + /// + /// The properties to pass to this repository. + /// The factory to use to create new logger instances. + /// + /// + /// Initializes a new instance of the class with + /// the specified . + /// + /// + public Hierarchy(PropertiesDictionary properties, ILoggerFactory loggerFactory) : base(properties) + { + if (loggerFactory == null) + { + throw new ArgumentNullException("loggerFactory"); + } + + m_defaultFactory = loggerFactory; + + m_ht = System.Collections.Hashtable.Synchronized(new System.Collections.Hashtable()); + } + + #endregion Public Instance Constructors + + #region Public Instance Properties + + /// + /// Has no appender warning been emitted + /// + /// + /// + /// Flag to indicate if we have already issued a warning + /// about not having an appender warning. + /// + /// + public bool EmittedNoAppenderWarning + { + get { return m_emittedNoAppenderWarning; } + set { m_emittedNoAppenderWarning = value; } + } + + /// + /// Get the root of this hierarchy + /// + /// + /// + /// Get the root of this hierarchy. + /// + /// + public Logger Root + { + get + { + if (m_root == null) + { + lock(this) + { + if (m_root == null) + { + // Create the root logger + Logger root = m_defaultFactory.CreateLogger(this, null); + root.Hierarchy = this; + + // Store root + m_root = root; + } + } + } + return m_root; + } + } + + /// + /// Gets or sets the default instance. + /// + /// The default + /// + /// + /// The logger factory is used to create logger instances. + /// + /// + public ILoggerFactory LoggerFactory + { + get { return m_defaultFactory; } + set + { + if (value == null) + { + throw new ArgumentNullException("value"); + } + m_defaultFactory = value; + } + } + + #endregion Public Instance Properties + + #region Override Implementation of LoggerRepositorySkeleton + + /// + /// Test if a logger exists + /// + /// The name of the logger to lookup + /// The Logger object with the name specified + /// + /// + /// Check if the named logger exists in the hierarchy. If so return + /// its reference, otherwise returns null. + /// + /// + public override ILogger Exists(string name) + { + if (name == null) + { + throw new ArgumentNullException("name"); + } + + lock(m_ht) + { + return m_ht[new LoggerKey(name)] as Logger; + } + } + + /// + /// Returns all the currently defined loggers in the hierarchy as an Array + /// + /// All the defined loggers + /// + /// + /// Returns all the currently defined loggers in the hierarchy as an Array. + /// The root logger is not included in the returned + /// enumeration. + /// + /// + public override ILogger[] GetCurrentLoggers() + { + // The accumulation in loggers is necessary because not all elements in + // ht are Logger objects as there might be some ProvisionNodes + // as well. + lock(m_ht) + { + System.Collections.ArrayList loggers = new System.Collections.ArrayList(m_ht.Count); + + // Iterate through m_ht values + foreach(object node in m_ht.Values) + { + if (node is Logger) + { + loggers.Add(node); + } + } + return (Logger[])loggers.ToArray(typeof(Logger)); + } + } + + /// + /// Return a new logger instance named as the first parameter using + /// the default factory. + /// + /// + /// + /// Return a new logger instance named as the first parameter using + /// the default factory. + /// + /// + /// If a logger of that name already exists, then it will be + /// returned. Otherwise, a new logger will be instantiated and + /// then linked with its existing ancestors as well as children. + /// + /// + /// The name of the logger to retrieve + /// The logger object with the name specified + public override ILogger GetLogger(string name) + { + if (name == null) + { + throw new ArgumentNullException("name"); + } + + return GetLogger(name, m_defaultFactory); + } + + /// + /// Shutting down a hierarchy will safely close and remove + /// all appenders in all loggers including the root logger. + /// + /// + /// + /// Shutting down a hierarchy will safely close and remove + /// all appenders in all loggers including the root logger. + /// + /// + /// Some appenders need to be closed before the + /// application exists. Otherwise, pending logging events might be + /// lost. + /// + /// + /// The Shutdown method is careful to close nested + /// appenders before closing regular appenders. This is allows + /// configurations where a regular appender is attached to a logger + /// and again to a nested appender. + /// + /// + public override void Shutdown() + { + LogLog.Debug(declaringType, "Shutdown called on Hierarchy ["+this.Name+"]"); + + // begin by closing nested appenders + Root.CloseNestedAppenders(); + + lock(m_ht) + { + ILogger[] currentLoggers = this.GetCurrentLoggers(); + + foreach(Logger logger in currentLoggers) + { + logger.CloseNestedAppenders(); + } + + // then, remove all appenders + Root.RemoveAllAppenders(); + + foreach(Logger logger in currentLoggers) + { + logger.RemoveAllAppenders(); + } + } + + base.Shutdown(); + } + + /// + /// Reset all values contained in this hierarchy instance to their default. + /// + /// + /// + /// Reset all values contained in this hierarchy instance to their + /// default. This removes all appenders from all loggers, sets + /// the level of all non-root loggers to null, + /// sets their additivity flag to true and sets the level + /// of the root logger to . Moreover, + /// message disabling is set its default "off" value. + /// + /// + /// Existing loggers are not removed. They are just reset. + /// + /// + /// This method should be used sparingly and with care as it will + /// block all logging until it is completed. + /// + /// + public override void ResetConfiguration() + { + Root.Level = LevelMap.LookupWithDefault(Level.Debug); + Threshold = LevelMap.LookupWithDefault(Level.All); + + // the synchronization is needed to prevent hashtable surprises + lock(m_ht) + { + Shutdown(); // nested locks are OK + + foreach(Logger l in this.GetCurrentLoggers()) + { + l.Level = null; + l.Additivity = true; + } + } + + base.ResetConfiguration(); + + // Notify listeners + OnConfigurationChanged(null); + } + + /// + /// Log the logEvent through this hierarchy. + /// + /// the event to log + /// + /// + /// This method should not normally be used to log. + /// The interface should be used + /// for routine logging. This interface can be obtained + /// using the method. + /// + /// + /// The logEvent is delivered to the appropriate logger and + /// that logger is then responsible for logging the event. + /// + /// + public override void Log(LoggingEvent logEvent) + { + if (logEvent == null) + { + throw new ArgumentNullException("logEvent"); + } + + this.GetLogger(logEvent.LoggerName, m_defaultFactory).Log(logEvent); + } + + /// + /// Returns all the Appenders that are currently configured + /// + /// An array containing all the currently configured appenders + /// + /// + /// Returns all the instances that are currently configured. + /// All the loggers are searched for appenders. The appenders may also be containers + /// for appenders and these are also searched for additional loggers. + /// + /// + /// The list returned is unordered but does not contain duplicates. + /// + /// + public override Appender.IAppender[] GetAppenders() + { + System.Collections.ArrayList appenderList = new System.Collections.ArrayList(); + + CollectAppenders(appenderList, Root); + + foreach(Logger logger in GetCurrentLoggers()) + { + CollectAppenders(appenderList, logger); + } + + return (Appender.IAppender[])appenderList.ToArray(typeof(Appender.IAppender)); + } + + #endregion Override Implementation of LoggerRepositorySkeleton #region Private Static Methods /// - /// Collect the appenders from an . - /// The appender may also be a container. - /// - /// - /// - private static void CollectAppender(System.Collections.ArrayList appenderList, Appender.IAppender appender) - { - if (!appenderList.Contains(appender)) - { - appenderList.Add(appender); - - IAppenderAttachable container = appender as IAppenderAttachable; - if (container != null) - { - CollectAppenders(appenderList, container); - } - } - } - - /// - /// Collect the appenders from an container - /// - /// - /// - private static void CollectAppenders(System.Collections.ArrayList appenderList, IAppenderAttachable container) - { - foreach(Appender.IAppender appender in container.Appenders) - { - CollectAppender(appenderList, appender); - } + /// Collect the appenders from an . + /// The appender may also be a container. + ///
+ /// + /// + private static void CollectAppender(System.Collections.ArrayList appenderList, Appender.IAppender appender) + { + if (!appenderList.Contains(appender)) + { + appenderList.Add(appender); + + IAppenderAttachable container = appender as IAppenderAttachable; + if (container != null) + { + CollectAppenders(appenderList, container); + } + } + } + + /// + /// Collect the appenders from an container + /// + /// + /// + private static void CollectAppenders(System.Collections.ArrayList appenderList, IAppenderAttachable container) + { + foreach(Appender.IAppender appender in container.Appenders) + { + CollectAppender(appenderList, appender); + } } #endregion @@ -550,13 +550,13 @@ private static void CollectAppenders(System.Collections.ArrayList appenderList, #region Implementation of IBasicRepositoryConfigurator /// - /// Initialize the log4net system using the specified appender - /// - /// the appender to use to log all logging events - void IBasicRepositoryConfigurator.Configure(IAppender appender) - { - BasicRepositoryConfigure(appender); - } + /// Initialize the log4net system using the specified appender + ///
+ /// the appender to use to log all logging events + void IBasicRepositoryConfigurator.Configure(IAppender appender) + { + BasicRepositoryConfigure(appender); + } /// /// Initialize the log4net system using the specified appenders @@ -567,19 +567,19 @@ void IBasicRepositoryConfigurator.Configure(params IAppender[] appenders) BasicRepositoryConfigure(appenders); } - /// - /// Initialize the log4net system using the specified appenders - /// - /// the appenders to use to log all logging events - /// - /// - /// This method provides the same functionality as the - /// method implemented - /// on this object, but it is protected and therefore can be called by subclasses. - /// - /// - protected void BasicRepositoryConfigure(params IAppender[] appenders) - { + /// + /// Initialize the log4net system using the specified appenders + /// + /// the appenders to use to log all logging events + /// + /// + /// This method provides the same functionality as the + /// method implemented + /// on this object, but it is protected and therefore can be called by subclasses. + /// + /// + protected void BasicRepositoryConfigure(params IAppender[] appenders) + { ArrayList configurationMessages = new ArrayList(); using (new LogLog.LogReceivedAdapter(configurationMessages)) @@ -590,497 +590,497 @@ protected void BasicRepositoryConfigure(params IAppender[] appenders) } } - Configured = true; + Configured = true; ConfigurationMessages = configurationMessages; - // Notify listeners + // Notify listeners OnConfigurationChanged(new ConfigurationChangedEventArgs(configurationMessages)); - } - - #endregion Implementation of IBasicRepositoryConfigurator - - #region Implementation of IXmlRepositoryConfigurator - - /// - /// Initialize the log4net system using the specified config - /// - /// the element containing the root of the config - void IXmlRepositoryConfigurator.Configure(System.Xml.XmlElement element) - { - XmlRepositoryConfigure(element); - } - - /// - /// Initialize the log4net system using the specified config - /// - /// the element containing the root of the config - /// - /// - /// This method provides the same functionality as the - /// method implemented - /// on this object, but it is protected and therefore can be called by subclasses. - /// - /// - protected void XmlRepositoryConfigure(System.Xml.XmlElement element) - { + } + + #endregion Implementation of IBasicRepositoryConfigurator + + #region Implementation of IXmlRepositoryConfigurator + + /// + /// Initialize the log4net system using the specified config + /// + /// the element containing the root of the config + void IXmlRepositoryConfigurator.Configure(System.Xml.XmlElement element) + { + XmlRepositoryConfigure(element); + } + + /// + /// Initialize the log4net system using the specified config + /// + /// the element containing the root of the config + /// + /// + /// This method provides the same functionality as the + /// method implemented + /// on this object, but it is protected and therefore can be called by subclasses. + /// + /// + protected void XmlRepositoryConfigure(System.Xml.XmlElement element) + { ArrayList configurationMessages = new ArrayList(); using (new LogLog.LogReceivedAdapter(configurationMessages)) - { - XmlHierarchyConfigurator config = new XmlHierarchyConfigurator(this); + { + XmlHierarchyConfigurator config = new XmlHierarchyConfigurator(this); config.Configure(element); - } + } - Configured = true; + Configured = true; ConfigurationMessages = configurationMessages; - // Notify listeners + // Notify listeners OnConfigurationChanged(new ConfigurationChangedEventArgs(configurationMessages)); - } - - #endregion Implementation of IXmlRepositoryConfigurator - - #region Public Instance Methods - - /// - /// Test if this hierarchy is disabled for the specified . - /// - /// The level to check against. - /// - /// true if the repository is disabled for the level argument, false otherwise. - /// - /// - /// - /// If this hierarchy has not been configured then this method will - /// always return true. - /// - /// - /// This method will return true if this repository is - /// disabled for level object passed as parameter and - /// false otherwise. - /// - /// - /// See also the property. - /// - /// - public bool IsDisabled(Level level) - { - // Cast level to object for performance - if ((object)level == null) - { - throw new ArgumentNullException("level"); - } - - if (Configured) - { - return Threshold > level; - } - else - { - // If not configured the hierarchy is effectively disabled - return true; - } - } - - /// - /// Clear all logger definitions from the internal hashtable - /// - /// - /// - /// This call will clear all logger definitions from the internal - /// hashtable. Invoking this method will irrevocably mess up the - /// logger hierarchy. - /// - /// - /// You should really know what you are doing before - /// invoking this method. - /// - /// - public void Clear() - { - lock(m_ht) - { - m_ht.Clear(); - } - } - - /// - /// Return a new logger instance named as the first parameter using - /// . - /// - /// The name of the logger to retrieve - /// The factory that will make the new logger instance - /// The logger object with the name specified - /// - /// - /// If a logger of that name already exists, then it will be - /// returned. Otherwise, a new logger will be instantiated by the - /// parameter and linked with its existing - /// ancestors as well as children. - /// - /// - public Logger GetLogger(string name, ILoggerFactory factory) - { - if (name == null) - { - throw new ArgumentNullException("name"); - } - if (factory == null) - { - throw new ArgumentNullException("factory"); - } - - LoggerKey key = new LoggerKey(name); + } + + #endregion Implementation of IXmlRepositoryConfigurator + + #region Public Instance Methods + + /// + /// Test if this hierarchy is disabled for the specified . + /// + /// The level to check against. + /// + /// true if the repository is disabled for the level argument, false otherwise. + /// + /// + /// + /// If this hierarchy has not been configured then this method will + /// always return true. + /// + /// + /// This method will return true if this repository is + /// disabled for level object passed as parameter and + /// false otherwise. + /// + /// + /// See also the property. + /// + /// + public bool IsDisabled(Level level) + { + // Cast level to object for performance + if ((object)level == null) + { + throw new ArgumentNullException("level"); + } + + if (Configured) + { + return Threshold > level; + } + else + { + // If not configured the hierarchy is effectively disabled + return true; + } + } + + /// + /// Clear all logger definitions from the internal hashtable + /// + /// + /// + /// This call will clear all logger definitions from the internal + /// hashtable. Invoking this method will irrevocably mess up the + /// logger hierarchy. + /// + /// + /// You should really know what you are doing before + /// invoking this method. + /// + /// + public void Clear() + { + lock(m_ht) + { + m_ht.Clear(); + } + } + + /// + /// Return a new logger instance named as the first parameter using + /// . + /// + /// The name of the logger to retrieve + /// The factory that will make the new logger instance + /// The logger object with the name specified + /// + /// + /// If a logger of that name already exists, then it will be + /// returned. Otherwise, a new logger will be instantiated by the + /// parameter and linked with its existing + /// ancestors as well as children. + /// + /// + public Logger GetLogger(string name, ILoggerFactory factory) + { + if (name == null) + { + throw new ArgumentNullException("name"); + } + if (factory == null) + { + throw new ArgumentNullException("factory"); + } + + LoggerKey key = new LoggerKey(name); - // Synchronize to prevent write conflicts. Read conflicts (in - // GetEffectiveLevel() method) are possible only if variable - // assignments are non-atomic. - - lock(m_ht) - { - Logger logger = null; - - Object node = m_ht[key]; - if (node == null) - { - logger = factory.CreateLogger(this, name); - logger.Hierarchy = this; - m_ht[key] = logger; - UpdateParents(logger); - OnLoggerCreationEvent(logger); - return logger; - } - - Logger nodeLogger = node as Logger; - if (nodeLogger != null) - { - return nodeLogger; - } - - ProvisionNode nodeProvisionNode = node as ProvisionNode; - if (nodeProvisionNode != null) - { - logger = factory.CreateLogger(this, name); - logger.Hierarchy = this; - m_ht[key] = logger; - UpdateChildren(nodeProvisionNode, logger); - UpdateParents(logger); - OnLoggerCreationEvent(logger); - return logger; - } - - // It should be impossible to arrive here but let's keep the compiler happy. - return null; - } - } - - #endregion Public Instance Methods - - #region Protected Instance Methods - - /// - /// Sends a logger creation event to all registered listeners - /// - /// The newly created logger - /// - /// Raises the logger creation event. - /// - protected virtual void OnLoggerCreationEvent(Logger logger) - { - LoggerCreationEventHandler handler = m_loggerCreatedEvent; - if (handler != null) - { - handler(this, new LoggerCreationEventArgs(logger)); - } - } - - #endregion Protected Instance Methods - - #region Private Instance Methods - - /// - /// Updates all the parents of the specified logger - /// - /// The logger to update the parents for - /// - /// - /// This method loops through all the potential parents of - /// . There 3 possible cases: - /// - /// - /// - /// No entry for the potential parent of exists - /// - /// We create a ProvisionNode for this potential - /// parent and insert in that provision node. - /// - /// - /// - /// The entry is of type Logger for the potential parent. - /// - /// The entry is 's nearest existing parent. We - /// update 's parent field with this entry. We also break from - /// he loop because updating our parent's parent is our parent's - /// responsibility. - /// - /// - /// - /// The entry is of type ProvisionNode for this potential parent. - /// - /// We add to the list of children for this - /// potential parent. - /// - /// - /// - /// - private void UpdateParents(Logger log) - { - string name = log.Name; - int length = name.Length; - bool parentFound = false; - - // if name = "w.x.y.z", loop through "w.x.y", "w.x" and "w", but not "w.x.y.z" - for(int i = name.LastIndexOf('.', length-1); i >= 0; i = name.LastIndexOf('.', i-1)) - { - string substr = name.Substring(0, i); - - LoggerKey key = new LoggerKey(substr); // simple constructor - Object node = m_ht[key]; - // Create a provision node for a future parent. - if (node == null) - { - ProvisionNode pn = new ProvisionNode(log); - m_ht[key] = pn; - } - else - { - Logger nodeLogger = node as Logger; - if (nodeLogger != null) - { - parentFound = true; - log.Parent = nodeLogger; - break; // no need to update the ancestors of the closest ancestor - } - else - { - ProvisionNode nodeProvisionNode = node as ProvisionNode; - if (nodeProvisionNode != null) - { - nodeProvisionNode.Add(log); - } - else - { - LogLog.Error(declaringType, "Unexpected object type ["+node.GetType()+"] in ht.", new LogException()); - } - } - } - if (i == 0) { - // logger name starts with a dot - // and we've hit the start - break; - } - } - - // If we could not find any existing parents, then link with root. - if (!parentFound) - { - log.Parent = this.Root; - } - } - - /// - /// Replace a with a in the hierarchy. - /// - /// - /// - /// - /// - /// We update the links for all the children that placed themselves - /// in the provision node 'pn'. The second argument 'log' is a - /// reference for the newly created Logger, parent of all the - /// children in 'pn'. - /// - /// - /// We loop on all the children 'c' in 'pn'. - /// - /// - /// If the child 'c' has been already linked to a child of - /// 'log' then there is no need to update 'c'. - /// - /// - /// Otherwise, we set log's parent field to c's parent and set - /// c's parent field to log. - /// - /// - private static void UpdateChildren(ProvisionNode pn, Logger log) - { - for(int i = 0; i < pn.Count; i++) - { - Logger childLogger = (Logger)pn[i]; - - // Unless this child already points to a correct (lower) parent, - // make log.Parent point to childLogger.Parent and childLogger.Parent to log. - if (!childLogger.Parent.Name.StartsWith(log.Name)) - { - log.Parent = childLogger.Parent; - childLogger.Parent = log; - } - } - } - - /// - /// Define or redefine a Level using the values in the argument - /// - /// the level values - /// - /// - /// Define or redefine a Level using the values in the argument - /// - /// - /// Supports setting levels via the configuration file. - /// - /// - internal void AddLevel(LevelEntry levelEntry) - { - if (levelEntry == null) throw new ArgumentNullException("levelEntry"); - if (levelEntry.Name == null) throw new ArgumentNullException("levelEntry.Name"); - - // Lookup replacement value - if (levelEntry.Value == -1) - { - Level previousLevel = LevelMap[levelEntry.Name]; - if (previousLevel == null) - { - throw new InvalidOperationException("Cannot redefine level ["+levelEntry.Name+"] because it is not defined in the LevelMap. To define the level supply the level value."); - } - - levelEntry.Value = previousLevel.Value; - } - - LevelMap.Add(levelEntry.Name, levelEntry.Value, levelEntry.DisplayName); - } - - /// - /// A class to hold the value, name and display name for a level - /// - /// - /// - /// A class to hold the value, name and display name for a level - /// - /// - internal class LevelEntry - { - private int m_levelValue = -1; - private string m_levelName = null; - private string m_levelDisplayName = null; - - /// - /// Value of the level - /// - /// - /// - /// If the value is not set (defaults to -1) the value will be looked - /// up for the current level with the same name. - /// - /// - public int Value - { - get { return m_levelValue; } - set { m_levelValue = value; } - } - - /// - /// Name of the level - /// - /// - /// The name of the level - /// - /// - /// - /// The name of the level. - /// - /// - public string Name - { - get { return m_levelName; } - set { m_levelName = value; } - } - - /// - /// Display name for the level - /// - /// - /// The display name of the level - /// - /// - /// - /// The display name of the level. - /// - /// - public string DisplayName - { - get { return m_levelDisplayName; } - set { m_levelDisplayName = value; } - } - - /// - /// Override Object.ToString to return sensible debug info - /// - /// string info about this object - public override string ToString() - { - return "LevelEntry(Value="+m_levelValue+", Name="+m_levelName+", DisplayName="+m_levelDisplayName+")"; - } - } - - /// - /// Set a Property using the values in the argument - /// - /// the property value - /// - /// - /// Set a Property using the values in the argument. - /// - /// - /// Supports setting property values via the configuration file. - /// - /// - internal void AddProperty(PropertyEntry propertyEntry) - { - if (propertyEntry == null) throw new ArgumentNullException("propertyEntry"); - if (propertyEntry.Key == null) throw new ArgumentNullException("propertyEntry.Key"); - - Properties[propertyEntry.Key] = propertyEntry.Value; - } - - #endregion Private Instance Methods - - #region Private Instance Fields - - private ILoggerFactory m_defaultFactory; - - private System.Collections.Hashtable m_ht; - private Logger m_root; + // Synchronize to prevent write conflicts. Read conflicts (in + // GetEffectiveLevel() method) are possible only if variable + // assignments are non-atomic. + + lock(m_ht) + { + Logger logger = null; + + Object node = m_ht[key]; + if (node == null) + { + logger = factory.CreateLogger(this, name); + logger.Hierarchy = this; + m_ht[key] = logger; + UpdateParents(logger); + OnLoggerCreationEvent(logger); + return logger; + } + + Logger nodeLogger = node as Logger; + if (nodeLogger != null) + { + return nodeLogger; + } + + ProvisionNode nodeProvisionNode = node as ProvisionNode; + if (nodeProvisionNode != null) + { + logger = factory.CreateLogger(this, name); + logger.Hierarchy = this; + m_ht[key] = logger; + UpdateChildren(nodeProvisionNode, logger); + UpdateParents(logger); + OnLoggerCreationEvent(logger); + return logger; + } + + // It should be impossible to arrive here but let's keep the compiler happy. + return null; + } + } + + #endregion Public Instance Methods + + #region Protected Instance Methods + + /// + /// Sends a logger creation event to all registered listeners + /// + /// The newly created logger + /// + /// Raises the logger creation event. + /// + protected virtual void OnLoggerCreationEvent(Logger logger) + { + LoggerCreationEventHandler handler = m_loggerCreatedEvent; + if (handler != null) + { + handler(this, new LoggerCreationEventArgs(logger)); + } + } + + #endregion Protected Instance Methods + + #region Private Instance Methods + + /// + /// Updates all the parents of the specified logger + /// + /// The logger to update the parents for + /// + /// + /// This method loops through all the potential parents of + /// . There 3 possible cases: + /// + /// + /// + /// No entry for the potential parent of exists + /// + /// We create a ProvisionNode for this potential + /// parent and insert in that provision node. + /// + /// + /// + /// The entry is of type Logger for the potential parent. + /// + /// The entry is 's nearest existing parent. We + /// update 's parent field with this entry. We also break from + /// he loop because updating our parent's parent is our parent's + /// responsibility. + /// + /// + /// + /// The entry is of type ProvisionNode for this potential parent. + /// + /// We add to the list of children for this + /// potential parent. + /// + /// + /// + /// + private void UpdateParents(Logger log) + { + string name = log.Name; + int length = name.Length; + bool parentFound = false; + + // if name = "w.x.y.z", loop through "w.x.y", "w.x" and "w", but not "w.x.y.z" + for(int i = name.LastIndexOf('.', length-1); i >= 0; i = name.LastIndexOf('.', i-1)) + { + string substr = name.Substring(0, i); + + LoggerKey key = new LoggerKey(substr); // simple constructor + Object node = m_ht[key]; + // Create a provision node for a future parent. + if (node == null) + { + ProvisionNode pn = new ProvisionNode(log); + m_ht[key] = pn; + } + else + { + Logger nodeLogger = node as Logger; + if (nodeLogger != null) + { + parentFound = true; + log.Parent = nodeLogger; + break; // no need to update the ancestors of the closest ancestor + } + else + { + ProvisionNode nodeProvisionNode = node as ProvisionNode; + if (nodeProvisionNode != null) + { + nodeProvisionNode.Add(log); + } + else + { + LogLog.Error(declaringType, "Unexpected object type ["+node.GetType()+"] in ht.", new LogException()); + } + } + } + if (i == 0) { + // logger name starts with a dot + // and we've hit the start + break; + } + } + + // If we could not find any existing parents, then link with root. + if (!parentFound) + { + log.Parent = this.Root; + } + } + + /// + /// Replace a with a in the hierarchy. + /// + /// + /// + /// + /// + /// We update the links for all the children that placed themselves + /// in the provision node 'pn'. The second argument 'log' is a + /// reference for the newly created Logger, parent of all the + /// children in 'pn'. + /// + /// + /// We loop on all the children 'c' in 'pn'. + /// + /// + /// If the child 'c' has been already linked to a child of + /// 'log' then there is no need to update 'c'. + /// + /// + /// Otherwise, we set log's parent field to c's parent and set + /// c's parent field to log. + /// + /// + private static void UpdateChildren(ProvisionNode pn, Logger log) + { + for(int i = 0; i < pn.Count; i++) + { + Logger childLogger = (Logger)pn[i]; + + // Unless this child already points to a correct (lower) parent, + // make log.Parent point to childLogger.Parent and childLogger.Parent to log. + if (!childLogger.Parent.Name.StartsWith(log.Name)) + { + log.Parent = childLogger.Parent; + childLogger.Parent = log; + } + } + } + + /// + /// Define or redefine a Level using the values in the argument + /// + /// the level values + /// + /// + /// Define or redefine a Level using the values in the argument + /// + /// + /// Supports setting levels via the configuration file. + /// + /// + internal void AddLevel(LevelEntry levelEntry) + { + if (levelEntry == null) throw new ArgumentNullException("levelEntry"); + if (levelEntry.Name == null) throw new ArgumentNullException("levelEntry.Name"); + + // Lookup replacement value + if (levelEntry.Value == -1) + { + Level previousLevel = LevelMap[levelEntry.Name]; + if (previousLevel == null) + { + throw new InvalidOperationException("Cannot redefine level ["+levelEntry.Name+"] because it is not defined in the LevelMap. To define the level supply the level value."); + } + + levelEntry.Value = previousLevel.Value; + } + + LevelMap.Add(levelEntry.Name, levelEntry.Value, levelEntry.DisplayName); + } + + /// + /// A class to hold the value, name and display name for a level + /// + /// + /// + /// A class to hold the value, name and display name for a level + /// + /// + internal class LevelEntry + { + private int m_levelValue = -1; + private string m_levelName = null; + private string m_levelDisplayName = null; + + /// + /// Value of the level + /// + /// + /// + /// If the value is not set (defaults to -1) the value will be looked + /// up for the current level with the same name. + /// + /// + public int Value + { + get { return m_levelValue; } + set { m_levelValue = value; } + } + + /// + /// Name of the level + /// + /// + /// The name of the level + /// + /// + /// + /// The name of the level. + /// + /// + public string Name + { + get { return m_levelName; } + set { m_levelName = value; } + } + + /// + /// Display name for the level + /// + /// + /// The display name of the level + /// + /// + /// + /// The display name of the level. + /// + /// + public string DisplayName + { + get { return m_levelDisplayName; } + set { m_levelDisplayName = value; } + } + + /// + /// Override Object.ToString to return sensible debug info + /// + /// string info about this object + public override string ToString() + { + return "LevelEntry(Value="+m_levelValue+", Name="+m_levelName+", DisplayName="+m_levelDisplayName+")"; + } + } + + /// + /// Set a Property using the values in the argument + /// + /// the property value + /// + /// + /// Set a Property using the values in the argument. + /// + /// + /// Supports setting property values via the configuration file. + /// + /// + internal void AddProperty(PropertyEntry propertyEntry) + { + if (propertyEntry == null) throw new ArgumentNullException("propertyEntry"); + if (propertyEntry.Key == null) throw new ArgumentNullException("propertyEntry.Key"); + + Properties[propertyEntry.Key] = propertyEntry.Value; + } + + #endregion Private Instance Methods + + #region Private Instance Fields + + private ILoggerFactory m_defaultFactory; + + private System.Collections.Hashtable m_ht; + private Logger m_root; - private bool m_emittedNoAppenderWarning = false; + private bool m_emittedNoAppenderWarning = false; - private event LoggerCreationEventHandler m_loggerCreatedEvent; + private event LoggerCreationEventHandler m_loggerCreatedEvent; - #endregion Private Instance Fields + #endregion Private Instance Fields - #region Private Static Fields + #region Private Static Fields - /// - /// The fully qualified type of the Hierarchy class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(Hierarchy); + /// + /// The fully qualified type of the Hierarchy class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(Hierarchy); - #endregion Private Static Fields - } + #endregion Private Static Fields + } } diff --git a/src/log4net/Repository/Hierarchy/ILoggerFactory.cs b/src/log4net/Repository/Hierarchy/ILoggerFactory.cs index 52966f4e..9826a97c 100644 --- a/src/log4net/Repository/Hierarchy/ILoggerFactory.cs +++ b/src/log4net/Repository/Hierarchy/ILoggerFactory.cs @@ -19,46 +19,46 @@ namespace log4net.Repository.Hierarchy { - /// - /// Interface abstracts creation of instances - /// - /// - /// - /// This interface is used by the to - /// create new objects. - /// - /// - /// The method is called - /// to create a named . - /// - /// - /// Implement this interface to create new subclasses of . - /// - /// - /// Nicko Cadell - /// Gert Driesen - public interface ILoggerFactory - { - /// - /// Create a new instance - /// - /// The that will own the . - /// The name of the . - /// The instance for the specified name. - /// - /// - /// Create a new instance with the - /// specified name. - /// - /// - /// Called by the to create - /// new named instances. - /// - /// - /// If the is null then the root logger - /// must be returned. - /// - /// - Logger CreateLogger(ILoggerRepository repository, string name); - } + /// + /// Interface abstracts creation of instances + /// + /// + /// + /// This interface is used by the to + /// create new objects. + /// + /// + /// The method is called + /// to create a named . + /// + /// + /// Implement this interface to create new subclasses of . + /// + /// + /// Nicko Cadell + /// Gert Driesen + public interface ILoggerFactory + { + /// + /// Create a new instance + /// + /// The that will own the . + /// The name of the . + /// The instance for the specified name. + /// + /// + /// Create a new instance with the + /// specified name. + /// + /// + /// Called by the to create + /// new named instances. + /// + /// + /// If the is null then the root logger + /// must be returned. + /// + /// + Logger CreateLogger(ILoggerRepository repository, string name); + } } diff --git a/src/log4net/Repository/Hierarchy/Logger.cs b/src/log4net/Repository/Hierarchy/Logger.cs index 839e688d..dbeab32e 100644 --- a/src/log4net/Repository/Hierarchy/Logger.cs +++ b/src/log4net/Repository/Hierarchy/Logger.cs @@ -25,764 +25,764 @@ namespace log4net.Repository.Hierarchy { - /// - /// Implementation of used by - /// - /// - /// - /// Internal class used to provide implementation of - /// interface. Applications should use to get - /// logger instances. - /// - /// - /// This is one of the central classes in the log4net implementation. One of the - /// distinctive features of log4net are hierarchical loggers and their - /// evaluation. The organizes the - /// instances into a rooted tree hierarchy. - /// - /// - /// The class is abstract. Only concrete subclasses of - /// can be created. The - /// is used to create instances of this type for the . - /// - /// - /// Nicko Cadell - /// Gert Driesen - /// Aspi Havewala - /// Douglas de la Torre - public abstract class Logger : IAppenderAttachable, ILogger - { - #region Protected Instance Constructors - - /// - /// This constructor created a new instance and - /// sets its name. - /// - /// The name of the . - /// - /// - /// This constructor is protected and designed to be used by - /// a subclass that is not abstract. - /// - /// - /// Loggers are constructed by - /// objects. See for the default - /// logger creator. - /// - /// - protected Logger(string name) - { + /// + /// Implementation of used by + /// + /// + /// + /// Internal class used to provide implementation of + /// interface. Applications should use to get + /// logger instances. + /// + /// + /// This is one of the central classes in the log4net implementation. One of the + /// distinctive features of log4net are hierarchical loggers and their + /// evaluation. The organizes the + /// instances into a rooted tree hierarchy. + /// + /// + /// The class is abstract. Only concrete subclasses of + /// can be created. The + /// is used to create instances of this type for the . + /// + /// + /// Nicko Cadell + /// Gert Driesen + /// Aspi Havewala + /// Douglas de la Torre + public abstract class Logger : IAppenderAttachable, ILogger + { + #region Protected Instance Constructors + + /// + /// This constructor created a new instance and + /// sets its name. + /// + /// The name of the . + /// + /// + /// This constructor is protected and designed to be used by + /// a subclass that is not abstract. + /// + /// + /// Loggers are constructed by + /// objects. See for the default + /// logger creator. + /// + /// + protected Logger(string name) + { #if NETCF || NETSTANDARD1_3 - // NETCF: String.Intern causes Native Exception - m_name = name; + // NETCF: String.Intern causes Native Exception + m_name = name; #else - m_name = string.Intern(name); + m_name = string.Intern(name); #endif - } - - #endregion Protected Instance Constructors - - #region Public Instance Properties - - /// - /// Gets or sets the parent logger in the hierarchy. - /// - /// - /// The parent logger in the hierarchy. - /// - /// - /// - /// Part of the Composite pattern that makes the hierarchy. - /// The hierarchy is parent linked rather than child linked. - /// - /// - public virtual Logger Parent - { - get { return m_parent; } - set { m_parent = value; } - } - - /// - /// Gets or sets a value indicating if child loggers inherit their parent's appenders. - /// - /// - /// true if child loggers inherit their parent's appenders. - /// - /// - /// - /// Additivity is set to true by default, that is children inherit - /// the appenders of their ancestors by default. If this variable is - /// set to false then the appenders found in the - /// ancestors of this logger are not used. However, the children - /// of this logger will inherit its appenders, unless the children - /// have their additivity flag set to false too. See - /// the user manual for more details. - /// - /// - public virtual bool Additivity - { - get { return m_additive; } - set { m_additive = value; } - } - - /// - /// Gets the effective level for this logger. - /// - /// The nearest level in the logger hierarchy. - /// - /// - /// Starting from this logger, searches the logger hierarchy for a - /// non-null level and returns it. Otherwise, returns the level of the - /// root logger. - /// - /// The Logger class is designed so that this method executes as - /// quickly as possible. - /// - public virtual Level EffectiveLevel - { - get - { - for(Logger c = this; c != null; c = c.m_parent) - { - Level level = c.m_level; - - // Casting level to Object for performance, otherwise the overloaded operator is called - if ((object)level != null) - { - return level; - } - } - return null; // If reached will cause an NullPointerException. - } - } - - /// - /// Gets or sets the where this - /// Logger instance is attached to. - /// - /// The hierarchy that this logger belongs to. - /// - /// - /// This logger must be attached to a single . - /// - /// - public virtual Hierarchy Hierarchy - { - get { return m_hierarchy; } - set { m_hierarchy = value; } - } - - /// - /// Gets or sets the assigned , if any, for this Logger. - /// - /// - /// The of this logger. - /// - /// - /// - /// The assigned can be null. - /// - /// - public virtual Level Level - { - get { return m_level; } - set { m_level = value; } - } - - #endregion Public Instance Properties - - #region Implementation of IAppenderAttachable - - /// - /// Add to the list of appenders of this - /// Logger instance. - /// - /// An appender to add to this logger - /// - /// - /// Add to the list of appenders of this - /// Logger instance. - /// - /// - /// If is already in the list of - /// appenders, then it won't be added again. - /// - /// - public virtual void AddAppender(IAppender newAppender) - { - if (newAppender == null) - { - throw new ArgumentNullException("newAppender"); - } - - m_appenderLock.AcquireWriterLock(); - try - { - if (m_appenderAttachedImpl == null) - { - m_appenderAttachedImpl = new log4net.Util.AppenderAttachedImpl(); - } - m_appenderAttachedImpl.AddAppender(newAppender); - } - finally - { - m_appenderLock.ReleaseWriterLock(); - } - } - - /// - /// Get the appenders contained in this logger as an - /// . - /// - /// A collection of the appenders in this logger - /// - /// - /// Get the appenders contained in this logger as an - /// . If no appenders - /// can be found, then a is returned. - /// - /// - public virtual AppenderCollection Appenders - { - get - { - m_appenderLock.AcquireReaderLock(); - try - { - if (m_appenderAttachedImpl == null) - { - return AppenderCollection.EmptyCollection; - } - else - { - return m_appenderAttachedImpl.Appenders; - } - } - finally - { - m_appenderLock.ReleaseReaderLock(); - } - } - } - - /// - /// Look for the appender named as name - /// - /// The name of the appender to lookup - /// The appender with the name specified, or null. - /// - /// - /// Returns the named appender, or null if the appender is not found. - /// - /// - public virtual IAppender GetAppender(string name) - { - m_appenderLock.AcquireReaderLock(); - try - { - if (m_appenderAttachedImpl == null || name == null) - { - return null; - } - - return m_appenderAttachedImpl.GetAppender(name); - } - finally - { - m_appenderLock.ReleaseReaderLock(); - } - } - - /// - /// Remove all previously added appenders from this Logger instance. - /// - /// - /// - /// Remove all previously added appenders from this Logger instance. - /// - /// - /// This is useful when re-reading configuration information. - /// - /// - public virtual void RemoveAllAppenders() - { - m_appenderLock.AcquireWriterLock(); - try - { - if (m_appenderAttachedImpl != null) - { - m_appenderAttachedImpl.RemoveAllAppenders(); - m_appenderAttachedImpl = null; - } - } - finally - { - m_appenderLock.ReleaseWriterLock(); - } - } - - /// - /// Remove the appender passed as parameter form the list of appenders. - /// - /// The appender to remove - /// The appender removed from the list - /// - /// - /// Remove the appender passed as parameter form the list of appenders. - /// The appender removed is not closed. - /// If you are discarding the appender you must call - /// on the appender removed. - /// - /// - public virtual IAppender RemoveAppender(IAppender appender) - { - m_appenderLock.AcquireWriterLock(); - try - { - if (appender != null && m_appenderAttachedImpl != null) - { - return m_appenderAttachedImpl.RemoveAppender(appender); - } - } - finally - { - m_appenderLock.ReleaseWriterLock(); - } - return null; - } - - /// - /// Remove the appender passed as parameter form the list of appenders. - /// - /// The name of the appender to remove - /// The appender removed from the list - /// - /// - /// Remove the named appender passed as parameter form the list of appenders. - /// The appender removed is not closed. - /// If you are discarding the appender you must call - /// on the appender removed. - /// - /// - public virtual IAppender RemoveAppender(string name) - { - m_appenderLock.AcquireWriterLock(); - try - { - if (name != null && m_appenderAttachedImpl != null) - { - return m_appenderAttachedImpl.RemoveAppender(name); - } - } - finally - { - m_appenderLock.ReleaseWriterLock(); - } - return null; - } + } + + #endregion Protected Instance Constructors + + #region Public Instance Properties + + /// + /// Gets or sets the parent logger in the hierarchy. + /// + /// + /// The parent logger in the hierarchy. + /// + /// + /// + /// Part of the Composite pattern that makes the hierarchy. + /// The hierarchy is parent linked rather than child linked. + /// + /// + public virtual Logger Parent + { + get { return m_parent; } + set { m_parent = value; } + } + + /// + /// Gets or sets a value indicating if child loggers inherit their parent's appenders. + /// + /// + /// true if child loggers inherit their parent's appenders. + /// + /// + /// + /// Additivity is set to true by default, that is children inherit + /// the appenders of their ancestors by default. If this variable is + /// set to false then the appenders found in the + /// ancestors of this logger are not used. However, the children + /// of this logger will inherit its appenders, unless the children + /// have their additivity flag set to false too. See + /// the user manual for more details. + /// + /// + public virtual bool Additivity + { + get { return m_additive; } + set { m_additive = value; } + } + + /// + /// Gets the effective level for this logger. + /// + /// The nearest level in the logger hierarchy. + /// + /// + /// Starting from this logger, searches the logger hierarchy for a + /// non-null level and returns it. Otherwise, returns the level of the + /// root logger. + /// + /// The Logger class is designed so that this method executes as + /// quickly as possible. + /// + public virtual Level EffectiveLevel + { + get + { + for(Logger c = this; c != null; c = c.m_parent) + { + Level level = c.m_level; + + // Casting level to Object for performance, otherwise the overloaded operator is called + if ((object)level != null) + { + return level; + } + } + return null; // If reached will cause an NullPointerException. + } + } + + /// + /// Gets or sets the where this + /// Logger instance is attached to. + /// + /// The hierarchy that this logger belongs to. + /// + /// + /// This logger must be attached to a single . + /// + /// + public virtual Hierarchy Hierarchy + { + get { return m_hierarchy; } + set { m_hierarchy = value; } + } + + /// + /// Gets or sets the assigned , if any, for this Logger. + /// + /// + /// The of this logger. + /// + /// + /// + /// The assigned can be null. + /// + /// + public virtual Level Level + { + get { return m_level; } + set { m_level = value; } + } + + #endregion Public Instance Properties + + #region Implementation of IAppenderAttachable + + /// + /// Add to the list of appenders of this + /// Logger instance. + /// + /// An appender to add to this logger + /// + /// + /// Add to the list of appenders of this + /// Logger instance. + /// + /// + /// If is already in the list of + /// appenders, then it won't be added again. + /// + /// + public virtual void AddAppender(IAppender newAppender) + { + if (newAppender == null) + { + throw new ArgumentNullException("newAppender"); + } + + m_appenderLock.AcquireWriterLock(); + try + { + if (m_appenderAttachedImpl == null) + { + m_appenderAttachedImpl = new log4net.Util.AppenderAttachedImpl(); + } + m_appenderAttachedImpl.AddAppender(newAppender); + } + finally + { + m_appenderLock.ReleaseWriterLock(); + } + } + + /// + /// Get the appenders contained in this logger as an + /// . + /// + /// A collection of the appenders in this logger + /// + /// + /// Get the appenders contained in this logger as an + /// . If no appenders + /// can be found, then a is returned. + /// + /// + public virtual AppenderCollection Appenders + { + get + { + m_appenderLock.AcquireReaderLock(); + try + { + if (m_appenderAttachedImpl == null) + { + return AppenderCollection.EmptyCollection; + } + else + { + return m_appenderAttachedImpl.Appenders; + } + } + finally + { + m_appenderLock.ReleaseReaderLock(); + } + } + } + + /// + /// Look for the appender named as name + /// + /// The name of the appender to lookup + /// The appender with the name specified, or null. + /// + /// + /// Returns the named appender, or null if the appender is not found. + /// + /// + public virtual IAppender GetAppender(string name) + { + m_appenderLock.AcquireReaderLock(); + try + { + if (m_appenderAttachedImpl == null || name == null) + { + return null; + } + + return m_appenderAttachedImpl.GetAppender(name); + } + finally + { + m_appenderLock.ReleaseReaderLock(); + } + } + + /// + /// Remove all previously added appenders from this Logger instance. + /// + /// + /// + /// Remove all previously added appenders from this Logger instance. + /// + /// + /// This is useful when re-reading configuration information. + /// + /// + public virtual void RemoveAllAppenders() + { + m_appenderLock.AcquireWriterLock(); + try + { + if (m_appenderAttachedImpl != null) + { + m_appenderAttachedImpl.RemoveAllAppenders(); + m_appenderAttachedImpl = null; + } + } + finally + { + m_appenderLock.ReleaseWriterLock(); + } + } + + /// + /// Remove the appender passed as parameter form the list of appenders. + /// + /// The appender to remove + /// The appender removed from the list + /// + /// + /// Remove the appender passed as parameter form the list of appenders. + /// The appender removed is not closed. + /// If you are discarding the appender you must call + /// on the appender removed. + /// + /// + public virtual IAppender RemoveAppender(IAppender appender) + { + m_appenderLock.AcquireWriterLock(); + try + { + if (appender != null && m_appenderAttachedImpl != null) + { + return m_appenderAttachedImpl.RemoveAppender(appender); + } + } + finally + { + m_appenderLock.ReleaseWriterLock(); + } + return null; + } + + /// + /// Remove the appender passed as parameter form the list of appenders. + /// + /// The name of the appender to remove + /// The appender removed from the list + /// + /// + /// Remove the named appender passed as parameter form the list of appenders. + /// The appender removed is not closed. + /// If you are discarding the appender you must call + /// on the appender removed. + /// + /// + public virtual IAppender RemoveAppender(string name) + { + m_appenderLock.AcquireWriterLock(); + try + { + if (name != null && m_appenderAttachedImpl != null) + { + return m_appenderAttachedImpl.RemoveAppender(name); + } + } + finally + { + m_appenderLock.ReleaseWriterLock(); + } + return null; + } - #endregion - - #region Implementation of ILogger - - /// - /// Gets the logger name. - /// - /// - /// The name of the logger. - /// - /// - /// - /// The name of this logger - /// - /// - public virtual string Name - { - get { return m_name; } - } - - /// - /// This generic form is intended to be used by wrappers. - /// - /// The declaring type of the method that is - /// the stack boundary into the logging system for this call. - /// The level of the message to be logged. - /// The message object to log. - /// The exception to log, including its stack trace. - /// - /// - /// Generate a logging event for the specified using - /// the and . - /// - /// - /// This method must not throw any exception to the caller. - /// - /// - public virtual void Log(Type callerStackBoundaryDeclaringType, Level level, object message, Exception exception) - { - try - { - if (IsEnabledFor(level)) - { + #endregion + + #region Implementation of ILogger + + /// + /// Gets the logger name. + /// + /// + /// The name of the logger. + /// + /// + /// + /// The name of this logger + /// + /// + public virtual string Name + { + get { return m_name; } + } + + /// + /// This generic form is intended to be used by wrappers. + /// + /// The declaring type of the method that is + /// the stack boundary into the logging system for this call. + /// The level of the message to be logged. + /// The message object to log. + /// The exception to log, including its stack trace. + /// + /// + /// Generate a logging event for the specified using + /// the and . + /// + /// + /// This method must not throw any exception to the caller. + /// + /// + public virtual void Log(Type callerStackBoundaryDeclaringType, Level level, object message, Exception exception) + { + try + { + if (IsEnabledFor(level)) + { ForcedLog((callerStackBoundaryDeclaringType != null) ? callerStackBoundaryDeclaringType : declaringType, level, message, exception); - } - } - catch (Exception ex) - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); - } + } + } + catch (Exception ex) + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); + } #if !NET_2_0 && !MONO_2_0 && !MONO_3_5 && !MONO_4_0 && !NETSTANDARD - catch - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging"); - } + catch + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging"); + } #endif - } - - /// - /// This is the most generic printing method that is intended to be used - /// by wrappers. - /// - /// The event being logged. - /// - /// - /// Logs the specified logging event through this logger. - /// - /// - /// This method must not throw any exception to the caller. - /// - /// - public virtual void Log(LoggingEvent logEvent) - { - try - { - if (logEvent != null) - { - if (IsEnabledFor(logEvent.Level)) - { - ForcedLog(logEvent); - } - } - } - catch (Exception ex) - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); - } + } + + /// + /// This is the most generic printing method that is intended to be used + /// by wrappers. + /// + /// The event being logged. + /// + /// + /// Logs the specified logging event through this logger. + /// + /// + /// This method must not throw any exception to the caller. + /// + /// + public virtual void Log(LoggingEvent logEvent) + { + try + { + if (logEvent != null) + { + if (IsEnabledFor(logEvent.Level)) + { + ForcedLog(logEvent); + } + } + } + catch (Exception ex) + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); + } #if !NET_2_0 && !MONO_2_0 && !MONO_3_5 && !MONO_4_0 && !NETSTANDARD - catch - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging"); - } + catch + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging"); + } #endif - } - - /// - /// Checks if this logger is enabled for a given passed as parameter. - /// - /// The level to check. - /// - /// true if this logger is enabled for level, otherwise false. - /// - /// - /// - /// Test if this logger is going to log events of the specified . - /// - /// - /// This method must not throw any exception to the caller. - /// - /// - public virtual bool IsEnabledFor(Level level) - { - try - { - if (level != null) - { - if (m_hierarchy.IsDisabled(level)) - { - return false; - } - return level >= this.EffectiveLevel; - } - } - catch (Exception ex) - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); - } + } + + /// + /// Checks if this logger is enabled for a given passed as parameter. + /// + /// The level to check. + /// + /// true if this logger is enabled for level, otherwise false. + /// + /// + /// + /// Test if this logger is going to log events of the specified . + /// + /// + /// This method must not throw any exception to the caller. + /// + /// + public virtual bool IsEnabledFor(Level level) + { + try + { + if (level != null) + { + if (m_hierarchy.IsDisabled(level)) + { + return false; + } + return level >= this.EffectiveLevel; + } + } + catch (Exception ex) + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); + } #if !NET_2_0 && !MONO_2_0 && !MONO_3_5 && !MONO_4_0 && !NETSTANDARD - catch - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging"); - } + catch + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging"); + } #endif - return false; - } - - /// - /// Gets the where this - /// Logger instance is attached to. - /// - /// - /// The that this logger belongs to. - /// - /// - /// - /// Gets the where this - /// Logger instance is attached to. - /// - /// - public ILoggerRepository Repository - { - get { return m_hierarchy; } - } - - #endregion Implementation of ILogger - - /// - /// Deliver the to the attached appenders. - /// - /// The event to log. - /// - /// - /// Call the appenders in the hierarchy starting at - /// this. If no appenders could be found, emit a - /// warning. - /// - /// - /// This method calls all the appenders inherited from the - /// hierarchy circumventing any evaluation of whether to log or not - /// to log the particular log request. - /// - /// - protected virtual void CallAppenders(LoggingEvent loggingEvent) - { - if (loggingEvent == null) - { - throw new ArgumentNullException("loggingEvent"); - } - - int writes = 0; - - for(Logger c=this; c != null; c=c.m_parent) - { - if (c.m_appenderAttachedImpl != null) - { - // Protected against simultaneous call to addAppender, removeAppender,... - c.m_appenderLock.AcquireReaderLock(); - try - { - if (c.m_appenderAttachedImpl != null) - { - writes += c.m_appenderAttachedImpl.AppendLoopOnAppenders(loggingEvent); - } - } - finally - { - c.m_appenderLock.ReleaseReaderLock(); - } - } - - if (!c.m_additive) - { - break; - } - } - - // No appenders in hierarchy, warn user only once. - // - // Note that by including the AppDomain values for the currently running - // thread, it becomes much easier to see which application the warning - // is from, which is especially helpful in a multi-AppDomain environment - // (like IIS with multiple VDIRS). Without this, it can be difficult - // or impossible to determine which .config file is missing appender - // definitions. - // - if (!m_hierarchy.EmittedNoAppenderWarning && writes == 0) - { - m_hierarchy.EmittedNoAppenderWarning = true; - LogLog.Debug(declaringType, "No appenders could be found for logger [" + Name + "] repository [" + Repository.Name + "]"); - LogLog.Debug(declaringType, "Please initialize the log4net system properly."); - try - { - LogLog.Debug(declaringType, " Current AppDomain context information: "); - LogLog.Debug(declaringType, " BaseDirectory : " + SystemInfo.ApplicationBaseDirectory); + return false; + } + + /// + /// Gets the where this + /// Logger instance is attached to. + /// + /// + /// The that this logger belongs to. + /// + /// + /// + /// Gets the where this + /// Logger instance is attached to. + /// + /// + public ILoggerRepository Repository + { + get { return m_hierarchy; } + } + + #endregion Implementation of ILogger + + /// + /// Deliver the to the attached appenders. + /// + /// The event to log. + /// + /// + /// Call the appenders in the hierarchy starting at + /// this. If no appenders could be found, emit a + /// warning. + /// + /// + /// This method calls all the appenders inherited from the + /// hierarchy circumventing any evaluation of whether to log or not + /// to log the particular log request. + /// + /// + protected virtual void CallAppenders(LoggingEvent loggingEvent) + { + if (loggingEvent == null) + { + throw new ArgumentNullException("loggingEvent"); + } + + int writes = 0; + + for(Logger c=this; c != null; c=c.m_parent) + { + if (c.m_appenderAttachedImpl != null) + { + // Protected against simultaneous call to addAppender, removeAppender,... + c.m_appenderLock.AcquireReaderLock(); + try + { + if (c.m_appenderAttachedImpl != null) + { + writes += c.m_appenderAttachedImpl.AppendLoopOnAppenders(loggingEvent); + } + } + finally + { + c.m_appenderLock.ReleaseReaderLock(); + } + } + + if (!c.m_additive) + { + break; + } + } + + // No appenders in hierarchy, warn user only once. + // + // Note that by including the AppDomain values for the currently running + // thread, it becomes much easier to see which application the warning + // is from, which is especially helpful in a multi-AppDomain environment + // (like IIS with multiple VDIRS). Without this, it can be difficult + // or impossible to determine which .config file is missing appender + // definitions. + // + if (!m_hierarchy.EmittedNoAppenderWarning && writes == 0) + { + m_hierarchy.EmittedNoAppenderWarning = true; + LogLog.Debug(declaringType, "No appenders could be found for logger [" + Name + "] repository [" + Repository.Name + "]"); + LogLog.Debug(declaringType, "Please initialize the log4net system properly."); + try + { + LogLog.Debug(declaringType, " Current AppDomain context information: "); + LogLog.Debug(declaringType, " BaseDirectory : " + SystemInfo.ApplicationBaseDirectory); #if !NETCF && !NETSTANDARD1_3 - LogLog.Debug(declaringType, " FriendlyName : " + AppDomain.CurrentDomain.FriendlyName); - LogLog.Debug(declaringType, " DynamicDirectory: " + AppDomain.CurrentDomain.DynamicDirectory); + LogLog.Debug(declaringType, " FriendlyName : " + AppDomain.CurrentDomain.FriendlyName); + LogLog.Debug(declaringType, " DynamicDirectory: " + AppDomain.CurrentDomain.DynamicDirectory); #endif - } - catch(System.Security.SecurityException) - { - // Insufficient permissions to display info from the AppDomain - } - } - } - - /// - /// Closes all attached appenders implementing the interface. - /// - /// - /// - /// Used to ensure that the appenders are correctly shutdown. - /// - /// - public virtual void CloseNestedAppenders() - { - m_appenderLock.AcquireWriterLock(); - try - { - if (m_appenderAttachedImpl != null) - { - AppenderCollection appenders = m_appenderAttachedImpl.Appenders; - foreach(IAppender appender in appenders) - { - if (appender is IAppenderAttachable) - { - appender.Close(); - } - } - } - } - finally - { - m_appenderLock.ReleaseWriterLock(); - } - } - - /// - /// This is the most generic printing method. This generic form is intended to be used by wrappers - /// - /// The level of the message to be logged. - /// The message object to log. - /// The exception to log, including its stack trace. - /// - /// - /// Generate a logging event for the specified using - /// the . - /// - /// - public virtual void Log(Level level, object message, Exception exception) - { - if (IsEnabledFor(level)) - { + } + catch(System.Security.SecurityException) + { + // Insufficient permissions to display info from the AppDomain + } + } + } + + /// + /// Closes all attached appenders implementing the interface. + /// + /// + /// + /// Used to ensure that the appenders are correctly shutdown. + /// + /// + public virtual void CloseNestedAppenders() + { + m_appenderLock.AcquireWriterLock(); + try + { + if (m_appenderAttachedImpl != null) + { + AppenderCollection appenders = m_appenderAttachedImpl.Appenders; + foreach(IAppender appender in appenders) + { + if (appender is IAppenderAttachable) + { + appender.Close(); + } + } + } + } + finally + { + m_appenderLock.ReleaseWriterLock(); + } + } + + /// + /// This is the most generic printing method. This generic form is intended to be used by wrappers + /// + /// The level of the message to be logged. + /// The message object to log. + /// The exception to log, including its stack trace. + /// + /// + /// Generate a logging event for the specified using + /// the . + /// + /// + public virtual void Log(Level level, object message, Exception exception) + { + if (IsEnabledFor(level)) + { ForcedLog(declaringType, level, message, exception); - } - } - - /// - /// Creates a new logging event and logs the event without further checks. - /// - /// The declaring type of the method that is - /// the stack boundary into the logging system for this call. - /// The level of the message to be logged. - /// The message object to log. - /// The exception to log, including its stack trace. - /// - /// - /// Generates a logging event and delivers it to the attached - /// appenders. - /// - /// - protected virtual void ForcedLog(Type callerStackBoundaryDeclaringType, Level level, object message, Exception exception) - { - CallAppenders(new LoggingEvent(callerStackBoundaryDeclaringType, this.Hierarchy, this.Name, level, message, exception)); - } - - /// - /// Creates a new logging event and logs the event without further checks. - /// - /// The event being logged. - /// - /// - /// Delivers the logging event to the attached appenders. - /// - /// - protected virtual void ForcedLog(LoggingEvent logEvent) - { - // The logging event may not have been created by this logger - // the Repository may not be correctly set on the event. This - // is required for the appenders to correctly lookup renderers etc... - logEvent.EnsureRepository(this.Hierarchy); - - CallAppenders(logEvent); - } - - #region Private Static Fields + } + } + + /// + /// Creates a new logging event and logs the event without further checks. + /// + /// The declaring type of the method that is + /// the stack boundary into the logging system for this call. + /// The level of the message to be logged. + /// The message object to log. + /// The exception to log, including its stack trace. + /// + /// + /// Generates a logging event and delivers it to the attached + /// appenders. + /// + /// + protected virtual void ForcedLog(Type callerStackBoundaryDeclaringType, Level level, object message, Exception exception) + { + CallAppenders(new LoggingEvent(callerStackBoundaryDeclaringType, this.Hierarchy, this.Name, level, message, exception)); + } + + /// + /// Creates a new logging event and logs the event without further checks. + /// + /// The event being logged. + /// + /// + /// Delivers the logging event to the attached appenders. + /// + /// + protected virtual void ForcedLog(LoggingEvent logEvent) + { + // The logging event may not have been created by this logger + // the Repository may not be correctly set on the event. This + // is required for the appenders to correctly lookup renderers etc... + logEvent.EnsureRepository(this.Hierarchy); + + CallAppenders(logEvent); + } + + #region Private Static Fields /// /// The fully qualified type of the Logger class. /// private static readonly Type declaringType = typeof(Logger); - #endregion Private Static Fields - - #region Private Instance Fields - - /// - /// The name of this logger. - /// - private readonly string m_name; - - /// - /// The assigned level of this logger. - /// - /// - /// - /// The level variable need not be - /// assigned a value in which case it is inherited - /// form the hierarchy. - /// - /// - private Level m_level; - - /// - /// The parent of this logger. - /// - /// - /// - /// The parent of this logger. - /// All loggers have at least one ancestor which is the root logger. - /// - /// - private Logger m_parent; - - /// - /// Loggers need to know what Hierarchy they are in. - /// - /// - /// - /// Loggers need to know what Hierarchy they are in. - /// The hierarchy that this logger is a member of is stored - /// here. - /// - /// - private Hierarchy m_hierarchy; - - /// - /// Helper implementation of the interface - /// - private log4net.Util.AppenderAttachedImpl m_appenderAttachedImpl; - - /// - /// Flag indicating if child loggers inherit their parents appenders - /// - /// - /// - /// Additivity is set to true by default, that is children inherit - /// the appenders of their ancestors by default. If this variable is - /// set to false then the appenders found in the - /// ancestors of this logger are not used. However, the children - /// of this logger will inherit its appenders, unless the children - /// have their additivity flag set to false too. See - /// the user manual for more details. - /// - /// - private bool m_additive = true; - - /// - /// Lock to protect AppenderAttachedImpl variable m_appenderAttachedImpl - /// - private readonly ReaderWriterLock m_appenderLock = new ReaderWriterLock(); + #endregion Private Static Fields + + #region Private Instance Fields + + /// + /// The name of this logger. + /// + private readonly string m_name; + + /// + /// The assigned level of this logger. + /// + /// + /// + /// The level variable need not be + /// assigned a value in which case it is inherited + /// form the hierarchy. + /// + /// + private Level m_level; + + /// + /// The parent of this logger. + /// + /// + /// + /// The parent of this logger. + /// All loggers have at least one ancestor which is the root logger. + /// + /// + private Logger m_parent; + + /// + /// Loggers need to know what Hierarchy they are in. + /// + /// + /// + /// Loggers need to know what Hierarchy they are in. + /// The hierarchy that this logger is a member of is stored + /// here. + /// + /// + private Hierarchy m_hierarchy; + + /// + /// Helper implementation of the interface + /// + private log4net.Util.AppenderAttachedImpl m_appenderAttachedImpl; + + /// + /// Flag indicating if child loggers inherit their parents appenders + /// + /// + /// + /// Additivity is set to true by default, that is children inherit + /// the appenders of their ancestors by default. If this variable is + /// set to false then the appenders found in the + /// ancestors of this logger are not used. However, the children + /// of this logger will inherit its appenders, unless the children + /// have their additivity flag set to false too. See + /// the user manual for more details. + /// + /// + private bool m_additive = true; + + /// + /// Lock to protect AppenderAttachedImpl variable m_appenderAttachedImpl + /// + private readonly ReaderWriterLock m_appenderLock = new ReaderWriterLock(); - #endregion - } + #endregion + } } diff --git a/src/log4net/Repository/Hierarchy/LoggerKey.cs b/src/log4net/Repository/Hierarchy/LoggerKey.cs index 14854172..00671520 100644 --- a/src/log4net/Repository/Hierarchy/LoggerKey.cs +++ b/src/log4net/Repository/Hierarchy/LoggerKey.cs @@ -21,118 +21,118 @@ namespace log4net.Repository.Hierarchy { - /// - /// Used internally to accelerate hash table searches. - /// - /// - /// - /// Internal class used to improve performance of - /// string keyed hashtables. - /// - /// - /// The hashcode of the string is cached for reuse. - /// The string is stored as an interned value. - /// When comparing two objects for equality - /// the reference equality of the interned strings is compared. - /// - /// - /// Nicko Cadell - /// Gert Driesen - internal sealed class LoggerKey - { - #region Internal Instance Constructors + /// + /// Used internally to accelerate hash table searches. + /// + /// + /// + /// Internal class used to improve performance of + /// string keyed hashtables. + /// + /// + /// The hashcode of the string is cached for reuse. + /// The string is stored as an interned value. + /// When comparing two objects for equality + /// the reference equality of the interned strings is compared. + /// + /// + /// Nicko Cadell + /// Gert Driesen + internal sealed class LoggerKey + { + #region Internal Instance Constructors - /// - /// Construct key with string name - /// - /// - /// - /// Initializes a new instance of the class - /// with the specified name. - /// - /// - /// Stores the hashcode of the string and interns - /// the string key to optimize comparisons. - /// - /// - /// The Compact Framework 1.0 the - /// method does not work. On the Compact Framework - /// the string keys are not interned nor are they - /// compared by reference. - /// - /// - /// The name of the logger. - internal LoggerKey(string name) - { + /// + /// Construct key with string name + /// + /// + /// + /// Initializes a new instance of the class + /// with the specified name. + /// + /// + /// Stores the hashcode of the string and interns + /// the string key to optimize comparisons. + /// + /// + /// The Compact Framework 1.0 the + /// method does not work. On the Compact Framework + /// the string keys are not interned nor are they + /// compared by reference. + /// + /// + /// The name of the logger. + internal LoggerKey(string name) + { #if NETCF || NETSTANDARD1_3 - // NETCF: String.Intern causes Native Exception - m_name = name; + // NETCF: String.Intern causes Native Exception + m_name = name; #else - m_name = string.Intern(name); + m_name = string.Intern(name); #endif - m_hashCache = name.GetHashCode(); - } + m_hashCache = name.GetHashCode(); + } - #endregion Internal Instance Constructors + #endregion Internal Instance Constructors - #region Override implementation of Object + #region Override implementation of Object - /// - /// Returns a hash code for the current instance. - /// - /// A hash code for the current instance. - /// - /// - /// Returns the cached hashcode. - /// - /// - public override int GetHashCode() - { - return m_hashCache; - } + /// + /// Returns a hash code for the current instance. + /// + /// A hash code for the current instance. + /// + /// + /// Returns the cached hashcode. + /// + /// + public override int GetHashCode() + { + return m_hashCache; + } - /// - /// Determines whether two instances - /// are equal. - /// - /// The to compare with the current . - /// - /// true if the specified is equal to the current ; otherwise, false. - /// - /// - /// - /// Compares the references of the interned strings. - /// - /// - public override bool Equals(object obj) - { - // Compare reference type of this against argument - if (((object)this) == obj) - { - return true; - } - - LoggerKey objKey = obj as LoggerKey; - if (objKey != null) - { + /// + /// Determines whether two instances + /// are equal. + /// + /// The to compare with the current . + /// + /// true if the specified is equal to the current ; otherwise, false. + /// + /// + /// + /// Compares the references of the interned strings. + /// + /// + public override bool Equals(object obj) + { + // Compare reference type of this against argument + if (((object)this) == obj) + { + return true; + } + + LoggerKey objKey = obj as LoggerKey; + if (objKey != null) + { #if NETCF || NETSTANDARD1_3 - return ( m_name == objKey.m_name ); + return ( m_name == objKey.m_name ); #else - // Compare reference types rather than string's overloaded == - return ( ((object)m_name) == ((object)objKey.m_name) ); + // Compare reference types rather than string's overloaded == + return ( ((object)m_name) == ((object)objKey.m_name) ); #endif - } - return false; - } + } + return false; + } - #endregion + #endregion - #region Private Instance Fields + #region Private Instance Fields - private readonly string m_name; - private readonly int m_hashCache; + private readonly string m_name; + private readonly int m_hashCache; - #endregion Private Instance Fields - } + #endregion Private Instance Fields + } } diff --git a/src/log4net/Repository/Hierarchy/ProvisionNode.cs b/src/log4net/Repository/Hierarchy/ProvisionNode.cs index 50f4e168..9262a474 100644 --- a/src/log4net/Repository/Hierarchy/ProvisionNode.cs +++ b/src/log4net/Repository/Hierarchy/ProvisionNode.cs @@ -22,37 +22,37 @@ namespace log4net.Repository.Hierarchy { - /// - /// Provision nodes are used where no logger instance has been specified - /// - /// - /// - /// instances are used in the - /// when there is no specified - /// for that node. - /// - /// - /// A provision node holds a list of child loggers on behalf of - /// a logger that does not exist. - /// - /// - /// Nicko Cadell - /// Gert Driesen - internal sealed class ProvisionNode : ArrayList - { - /// - /// Create a new provision node with child node - /// - /// A child logger to add to this node. - /// - /// - /// Initializes a new instance of the class - /// with the specified child logger. - /// - /// - internal ProvisionNode(Logger log) : base() - { - this.Add(log); - } - } + /// + /// Provision nodes are used where no logger instance has been specified + /// + /// + /// + /// instances are used in the + /// when there is no specified + /// for that node. + /// + /// + /// A provision node holds a list of child loggers on behalf of + /// a logger that does not exist. + /// + /// + /// Nicko Cadell + /// Gert Driesen + internal sealed class ProvisionNode : ArrayList + { + /// + /// Create a new provision node with child node + /// + /// A child logger to add to this node. + /// + /// + /// Initializes a new instance of the class + /// with the specified child logger. + /// + /// + internal ProvisionNode(Logger log) : base() + { + this.Add(log); + } + } } diff --git a/src/log4net/Repository/Hierarchy/RootLogger.cs b/src/log4net/Repository/Hierarchy/RootLogger.cs index 8184e3f0..dae8aa9c 100644 --- a/src/log4net/Repository/Hierarchy/RootLogger.cs +++ b/src/log4net/Repository/Hierarchy/RootLogger.cs @@ -24,110 +24,110 @@ namespace log4net.Repository.Hierarchy { - /// - /// The sits at the root of the logger hierarchy tree. - /// - /// - /// - /// The is a regular except - /// that it provides several guarantees. - /// - /// - /// First, it cannot be assigned a null - /// level. Second, since the root logger cannot have a parent, the - /// property always returns the value of the - /// level field without walking the hierarchy. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public class RootLogger : Logger - { - #region Public Instance Constructors + /// + /// The sits at the root of the logger hierarchy tree. + /// + /// + /// + /// The is a regular except + /// that it provides several guarantees. + /// + /// + /// First, it cannot be assigned a null + /// level. Second, since the root logger cannot have a parent, the + /// property always returns the value of the + /// level field without walking the hierarchy. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public class RootLogger : Logger + { + #region Public Instance Constructors - /// - /// Construct a - /// - /// The level to assign to the root logger. - /// - /// - /// Initializes a new instance of the class with - /// the specified logging level. - /// - /// - /// The root logger names itself as "root". However, the root - /// logger cannot be retrieved by name. - /// - /// - public RootLogger(Level level) : base("root") - { - this.Level = level; - } + /// + /// Construct a + /// + /// The level to assign to the root logger. + /// + /// + /// Initializes a new instance of the class with + /// the specified logging level. + /// + /// + /// The root logger names itself as "root". However, the root + /// logger cannot be retrieved by name. + /// + /// + public RootLogger(Level level) : base("root") + { + this.Level = level; + } - #endregion Public Instance Constructors + #endregion Public Instance Constructors - #region Override implementation of Logger + #region Override implementation of Logger - /// - /// Gets the assigned level value without walking the logger hierarchy. - /// - /// The assigned level value without walking the logger hierarchy. - /// - /// - /// Because the root logger cannot have a parent and its level - /// must not be null this property just returns the - /// value of . - /// - /// - public override Level EffectiveLevel - { - get - { - return base.Level; - } - } + /// + /// Gets the assigned level value without walking the logger hierarchy. + /// + /// The assigned level value without walking the logger hierarchy. + /// + /// + /// Because the root logger cannot have a parent and its level + /// must not be null this property just returns the + /// value of . + /// + /// + public override Level EffectiveLevel + { + get + { + return base.Level; + } + } - /// - /// Gets or sets the assigned for the root logger. - /// - /// - /// The of the root logger. - /// - /// - /// - /// Setting the level of the root logger to a null reference - /// may have catastrophic results. We prevent this here. - /// - /// - public override Level Level - { - get { return base.Level; } - set - { - if (value == null) - { - LogLog.Error(declaringType, "You have tried to set a null level to root.", new LogException()); - } - else - { - base.Level = value; - } - } - } + /// + /// Gets or sets the assigned for the root logger. + /// + /// + /// The of the root logger. + /// + /// + /// + /// Setting the level of the root logger to a null reference + /// may have catastrophic results. We prevent this here. + /// + /// + public override Level Level + { + get { return base.Level; } + set + { + if (value == null) + { + LogLog.Error(declaringType, "You have tried to set a null level to root.", new LogException()); + } + else + { + base.Level = value; + } + } + } - #endregion Override implementation of Logger + #endregion Override implementation of Logger - #region Private Static Fields + #region Private Static Fields - /// - /// The fully qualified type of the RootLogger class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(RootLogger); + /// + /// The fully qualified type of the RootLogger class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(RootLogger); - #endregion Private Static Fields - } + #endregion Private Static Fields + } } diff --git a/src/log4net/Repository/Hierarchy/XmlHierarchyConfigurator.cs b/src/log4net/Repository/Hierarchy/XmlHierarchyConfigurator.cs index bc2561d5..b7bb6053 100644 --- a/src/log4net/Repository/Hierarchy/XmlHierarchyConfigurator.cs +++ b/src/log4net/Repository/Hierarchy/XmlHierarchyConfigurator.cs @@ -30,69 +30,69 @@ namespace log4net.Repository.Hierarchy { - /// - /// Initializes the log4net environment using an XML DOM. - /// - /// - /// - /// Configures a using an XML DOM. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public class XmlHierarchyConfigurator - { - private enum ConfigUpdateMode - { - Merge, - Overwrite - } - - #region Public Instance Constructors - - /// - /// Construct the configurator for a hierarchy - /// - /// The hierarchy to build. - /// - /// - /// Initializes a new instance of the class - /// with the specified . - /// - /// - public XmlHierarchyConfigurator(Hierarchy hierarchy) - { - m_hierarchy = hierarchy; - m_appenderBag = new Hashtable(); - } - - #endregion Public Instance Constructors - - #region Public Instance Methods - - /// - /// Configure the hierarchy by parsing a DOM tree of XML elements. - /// - /// The root element to parse. - /// - /// - /// Configure the hierarchy by parsing a DOM tree of XML elements. - /// - /// - public void Configure(XmlElement element) - { - if (element == null || m_hierarchy == null) - { + /// + /// Initializes the log4net environment using an XML DOM. + /// + /// + /// + /// Configures a using an XML DOM. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public class XmlHierarchyConfigurator + { + private enum ConfigUpdateMode + { + Merge, + Overwrite + } + + #region Public Instance Constructors + + /// + /// Construct the configurator for a hierarchy + /// + /// The hierarchy to build. + /// + /// + /// Initializes a new instance of the class + /// with the specified . + /// + /// + public XmlHierarchyConfigurator(Hierarchy hierarchy) + { + m_hierarchy = hierarchy; + m_appenderBag = new Hashtable(); + } + + #endregion Public Instance Constructors + + #region Public Instance Methods + + /// + /// Configure the hierarchy by parsing a DOM tree of XML elements. + /// + /// The root element to parse. + /// + /// + /// Configure the hierarchy by parsing a DOM tree of XML elements. + /// + /// + public void Configure(XmlElement element) + { + if (element == null || m_hierarchy == null) + { return; - } + } - string rootElementName = element.LocalName; + string rootElementName = element.LocalName; - if (rootElementName != CONFIGURATION_TAG) - { - LogLog.Error(declaringType, "Xml element is - not a <" + CONFIGURATION_TAG + "> element."); + if (rootElementName != CONFIGURATION_TAG) + { + LogLog.Error(declaringType, "Xml element is - not a <" + CONFIGURATION_TAG + "> element."); return; - } + } if (!LogLog.EmitInternalMessages) { @@ -110,1054 +110,1054 @@ public void Configure(XmlElement element) } } - if (!LogLog.InternalDebugging) - { - // Look for a debug attribute to enable internal debug - string debugAttribute = element.GetAttribute(INTERNAL_DEBUG_ATTR); - LogLog.Debug(declaringType, INTERNAL_DEBUG_ATTR+" attribute [" + debugAttribute + "]."); - - if (debugAttribute.Length>0 && debugAttribute != "null") - { - LogLog.InternalDebugging = OptionConverter.ToBoolean(debugAttribute, true); - } - else - { - LogLog.Debug(declaringType, "Ignoring " + INTERNAL_DEBUG_ATTR + " attribute."); - } - - string confDebug = element.GetAttribute(CONFIG_DEBUG_ATTR); - if (confDebug.Length>0 && confDebug != "null") - { - LogLog.Warn(declaringType, "The \"" + CONFIG_DEBUG_ATTR + "\" attribute is deprecated."); - LogLog.Warn(declaringType, "Use the \"" + INTERNAL_DEBUG_ATTR + "\" attribute instead."); - LogLog.InternalDebugging = OptionConverter.ToBoolean(confDebug, true); - } - } - - // Default mode is merge - ConfigUpdateMode configUpdateMode = ConfigUpdateMode.Merge; - - // Look for the config update attribute - string configUpdateModeAttribute = element.GetAttribute(CONFIG_UPDATE_MODE_ATTR); - if (configUpdateModeAttribute != null && configUpdateModeAttribute.Length > 0) - { - // Parse the attribute - try - { - configUpdateMode = (ConfigUpdateMode)OptionConverter.ConvertStringTo(typeof(ConfigUpdateMode), configUpdateModeAttribute); - } - catch - { - LogLog.Error(declaringType, "Invalid " + CONFIG_UPDATE_MODE_ATTR + " attribute value [" + configUpdateModeAttribute + "]"); - } - } - - // IMPL: The IFormatProvider argument to Enum.ToString() is deprecated in .NET 2.0 - LogLog.Debug(declaringType, "Configuration update mode [" + configUpdateMode.ToString() + "]."); - - // Only reset configuration if overwrite flag specified - if (configUpdateMode == ConfigUpdateMode.Overwrite) - { - // Reset to original unset configuration - m_hierarchy.ResetConfiguration(); - LogLog.Debug(declaringType, "Configuration reset before reading config."); - } - - /* Building Appender objects, placing them in a local namespace - for future reference */ - - /* Process all the top level elements */ - - foreach (XmlNode currentNode in element.ChildNodes) - { - if (currentNode.NodeType == XmlNodeType.Element) - { - XmlElement currentElement = (XmlElement)currentNode; - - if (currentElement.LocalName == LOGGER_TAG) - { - ParseLogger(currentElement); - } - else if (currentElement.LocalName == CATEGORY_TAG) - { - // TODO: deprecated use of category - ParseLogger(currentElement); - } - else if (currentElement.LocalName == ROOT_TAG) - { - ParseRoot(currentElement); - } - else if (currentElement.LocalName == RENDERER_TAG) - { - ParseRenderer(currentElement); - } - else if (currentElement.LocalName == APPENDER_TAG) - { - // We ignore appenders in this pass. They will - // be found and loaded if they are referenced. - } - else - { - // Read the param tags and set properties on the hierarchy - SetParameter(currentElement, m_hierarchy); - } - } - } - - // Lastly set the hierarchy threshold - string thresholdStr = element.GetAttribute(THRESHOLD_ATTR); - LogLog.Debug(declaringType, "Hierarchy Threshold [" + thresholdStr + "]"); - if (thresholdStr.Length > 0 && thresholdStr != "null") - { - Level thresholdLevel = (Level) ConvertStringTo(typeof(Level), thresholdStr); - if (thresholdLevel != null) - { - m_hierarchy.Threshold = thresholdLevel; - } - else - { - LogLog.Warn(declaringType, "Unable to set hierarchy threshold using value [" + thresholdStr + "] (with acceptable conversion types)"); - } - } - - // Done reading config - } - - #endregion Public Instance Methods - - #region Protected Instance Methods - - /// - /// Parse appenders by IDREF. - /// - /// The appender ref element. - /// The instance of the appender that the ref refers to. - /// - /// - /// Parse an XML element that represents an appender and return - /// the appender. - /// - /// - protected IAppender FindAppenderByReference(XmlElement appenderRef) - { - string appenderName = appenderRef.GetAttribute(REF_ATTR); - - IAppender appender = (IAppender)m_appenderBag[appenderName]; - if (appender != null) - { - return appender; - } - else - { - // Find the element with that id - XmlElement element = null; - - if (appenderName != null && appenderName.Length > 0) - { - foreach (XmlElement curAppenderElement in appenderRef.OwnerDocument.GetElementsByTagName(APPENDER_TAG)) - { - if (curAppenderElement.GetAttribute("name") == appenderName) - { - element = curAppenderElement; - break; - } - } - } - - if (element == null) - { - LogLog.Error(declaringType, "XmlHierarchyConfigurator: No appender named [" + appenderName + "] could be found."); - return null; - } - else - { - appender = ParseAppender(element); - if (appender != null) - { - m_appenderBag[appenderName] = appender; - } - return appender; - } - } - } - - /// - /// Parses an appender element. - /// - /// The appender element. - /// The appender instance or null when parsing failed. - /// - /// - /// Parse an XML element that represents an appender and return - /// the appender instance. - /// - /// - protected IAppender ParseAppender(XmlElement appenderElement) - { - string appenderName = appenderElement.GetAttribute(NAME_ATTR); - string typeName = appenderElement.GetAttribute(TYPE_ATTR); - - LogLog.Debug(declaringType, "Loading Appender [" + appenderName + "] type: [" + typeName + "]"); - try - { + if (!LogLog.InternalDebugging) + { + // Look for a debug attribute to enable internal debug + string debugAttribute = element.GetAttribute(INTERNAL_DEBUG_ATTR); + LogLog.Debug(declaringType, INTERNAL_DEBUG_ATTR+" attribute [" + debugAttribute + "]."); + + if (debugAttribute.Length>0 && debugAttribute != "null") + { + LogLog.InternalDebugging = OptionConverter.ToBoolean(debugAttribute, true); + } + else + { + LogLog.Debug(declaringType, "Ignoring " + INTERNAL_DEBUG_ATTR + " attribute."); + } + + string confDebug = element.GetAttribute(CONFIG_DEBUG_ATTR); + if (confDebug.Length>0 && confDebug != "null") + { + LogLog.Warn(declaringType, "The \"" + CONFIG_DEBUG_ATTR + "\" attribute is deprecated."); + LogLog.Warn(declaringType, "Use the \"" + INTERNAL_DEBUG_ATTR + "\" attribute instead."); + LogLog.InternalDebugging = OptionConverter.ToBoolean(confDebug, true); + } + } + + // Default mode is merge + ConfigUpdateMode configUpdateMode = ConfigUpdateMode.Merge; + + // Look for the config update attribute + string configUpdateModeAttribute = element.GetAttribute(CONFIG_UPDATE_MODE_ATTR); + if (configUpdateModeAttribute != null && configUpdateModeAttribute.Length > 0) + { + // Parse the attribute + try + { + configUpdateMode = (ConfigUpdateMode)OptionConverter.ConvertStringTo(typeof(ConfigUpdateMode), configUpdateModeAttribute); + } + catch + { + LogLog.Error(declaringType, "Invalid " + CONFIG_UPDATE_MODE_ATTR + " attribute value [" + configUpdateModeAttribute + "]"); + } + } + + // IMPL: The IFormatProvider argument to Enum.ToString() is deprecated in .NET 2.0 + LogLog.Debug(declaringType, "Configuration update mode [" + configUpdateMode.ToString() + "]."); + + // Only reset configuration if overwrite flag specified + if (configUpdateMode == ConfigUpdateMode.Overwrite) + { + // Reset to original unset configuration + m_hierarchy.ResetConfiguration(); + LogLog.Debug(declaringType, "Configuration reset before reading config."); + } + + /* Building Appender objects, placing them in a local namespace + for future reference */ + + /* Process all the top level elements */ + + foreach (XmlNode currentNode in element.ChildNodes) + { + if (currentNode.NodeType == XmlNodeType.Element) + { + XmlElement currentElement = (XmlElement)currentNode; + + if (currentElement.LocalName == LOGGER_TAG) + { + ParseLogger(currentElement); + } + else if (currentElement.LocalName == CATEGORY_TAG) + { + // TODO: deprecated use of category + ParseLogger(currentElement); + } + else if (currentElement.LocalName == ROOT_TAG) + { + ParseRoot(currentElement); + } + else if (currentElement.LocalName == RENDERER_TAG) + { + ParseRenderer(currentElement); + } + else if (currentElement.LocalName == APPENDER_TAG) + { + // We ignore appenders in this pass. They will + // be found and loaded if they are referenced. + } + else + { + // Read the param tags and set properties on the hierarchy + SetParameter(currentElement, m_hierarchy); + } + } + } + + // Lastly set the hierarchy threshold + string thresholdStr = element.GetAttribute(THRESHOLD_ATTR); + LogLog.Debug(declaringType, "Hierarchy Threshold [" + thresholdStr + "]"); + if (thresholdStr.Length > 0 && thresholdStr != "null") + { + Level thresholdLevel = (Level) ConvertStringTo(typeof(Level), thresholdStr); + if (thresholdLevel != null) + { + m_hierarchy.Threshold = thresholdLevel; + } + else + { + LogLog.Warn(declaringType, "Unable to set hierarchy threshold using value [" + thresholdStr + "] (with acceptable conversion types)"); + } + } + + // Done reading config + } + + #endregion Public Instance Methods + + #region Protected Instance Methods + + /// + /// Parse appenders by IDREF. + /// + /// The appender ref element. + /// The instance of the appender that the ref refers to. + /// + /// + /// Parse an XML element that represents an appender and return + /// the appender. + /// + /// + protected IAppender FindAppenderByReference(XmlElement appenderRef) + { + string appenderName = appenderRef.GetAttribute(REF_ATTR); + + IAppender appender = (IAppender)m_appenderBag[appenderName]; + if (appender != null) + { + return appender; + } + else + { + // Find the element with that id + XmlElement element = null; + + if (appenderName != null && appenderName.Length > 0) + { + foreach (XmlElement curAppenderElement in appenderRef.OwnerDocument.GetElementsByTagName(APPENDER_TAG)) + { + if (curAppenderElement.GetAttribute("name") == appenderName) + { + element = curAppenderElement; + break; + } + } + } + + if (element == null) + { + LogLog.Error(declaringType, "XmlHierarchyConfigurator: No appender named [" + appenderName + "] could be found."); + return null; + } + else + { + appender = ParseAppender(element); + if (appender != null) + { + m_appenderBag[appenderName] = appender; + } + return appender; + } + } + } + + /// + /// Parses an appender element. + /// + /// The appender element. + /// The appender instance or null when parsing failed. + /// + /// + /// Parse an XML element that represents an appender and return + /// the appender instance. + /// + /// + protected IAppender ParseAppender(XmlElement appenderElement) + { + string appenderName = appenderElement.GetAttribute(NAME_ATTR); + string typeName = appenderElement.GetAttribute(TYPE_ATTR); + + LogLog.Debug(declaringType, "Loading Appender [" + appenderName + "] type: [" + typeName + "]"); + try + { #if NETSTANDARD1_3 - IAppender appender = (IAppender)Activator.CreateInstance(SystemInfo.GetTypeFromString(this.GetType().GetTypeInfo().Assembly, typeName, true, true)); + IAppender appender = (IAppender)Activator.CreateInstance(SystemInfo.GetTypeFromString(this.GetType().GetTypeInfo().Assembly, typeName, true, true)); #else - IAppender appender = (IAppender)Activator.CreateInstance(SystemInfo.GetTypeFromString(typeName, true, true)); + IAppender appender = (IAppender)Activator.CreateInstance(SystemInfo.GetTypeFromString(typeName, true, true)); #endif - appender.Name = appenderName; - - foreach (XmlNode currentNode in appenderElement.ChildNodes) - { - /* We're only interested in Elements */ - if (currentNode.NodeType == XmlNodeType.Element) - { - XmlElement currentElement = (XmlElement)currentNode; - - // Look for the appender ref tag - if (currentElement.LocalName == APPENDER_REF_TAG) - { - string refName = currentElement.GetAttribute(REF_ATTR); - - IAppenderAttachable appenderContainer = appender as IAppenderAttachable; - if (appenderContainer != null) - { - LogLog.Debug(declaringType, "Attaching appender named [" + refName + "] to appender named [" + appender.Name + "]."); - - IAppender referencedAppender = FindAppenderByReference(currentElement); - if (referencedAppender != null) - { - appenderContainer.AddAppender(referencedAppender); - } - } - else - { - LogLog.Error(declaringType, "Requesting attachment of appender named ["+refName+ "] to appender named [" + appender.Name + "] which does not implement log4net.Core.IAppenderAttachable."); - } - } - else - { - // For all other tags we use standard set param method - SetParameter(currentElement, appender); - } - } - } - - IOptionHandler optionHandler = appender as IOptionHandler; - if (optionHandler != null) - { - optionHandler.ActivateOptions(); - } - - LogLog.Debug(declaringType, "Created Appender [" + appenderName + "]"); - return appender; - } - catch (Exception ex) - { - // Yes, it's ugly. But all exceptions point to the same problem: we can't create an Appender - - LogLog.Error(declaringType, "Could not create Appender [" + appenderName + "] of type [" + typeName + "]. Reported error follows.", ex); - return null; - } - } - - /// - /// Parses a logger element. - /// - /// The logger element. - /// - /// - /// Parse an XML element that represents a logger. - /// - /// - protected void ParseLogger(XmlElement loggerElement) - { - // Create a new log4net.Logger object from the element. - string loggerName = loggerElement.GetAttribute(NAME_ATTR); - - LogLog.Debug(declaringType, "Retrieving an instance of log4net.Repository.Logger for logger [" + loggerName + "]."); - Logger log = m_hierarchy.GetLogger(loggerName) as Logger; - - // Setting up a logger needs to be an atomic operation, in order - // to protect potential log operations while logger - // configuration is in progress. - lock(log) - { - bool additivity = OptionConverter.ToBoolean(loggerElement.GetAttribute(ADDITIVITY_ATTR), true); - - LogLog.Debug(declaringType, "Setting [" + log.Name + "] additivity to [" + additivity + "]."); - log.Additivity = additivity; - ParseChildrenOfLoggerElement(loggerElement, log, false); - } - } - - /// - /// Parses the root logger element. - /// - /// The root element. - /// - /// - /// Parse an XML element that represents the root logger. - /// - /// - protected void ParseRoot(XmlElement rootElement) - { - Logger root = m_hierarchy.Root; - // logger configuration needs to be atomic - lock(root) - { - ParseChildrenOfLoggerElement(rootElement, root, true); - } - } - - /// - /// Parses the children of a logger element. - /// - /// The category element. - /// The logger instance. - /// Flag to indicate if the logger is the root logger. - /// - /// - /// Parse the child elements of a <logger> element. - /// - /// - protected void ParseChildrenOfLoggerElement(XmlElement catElement, Logger log, bool isRoot) - { - // Remove all existing appenders from log. They will be - // reconstructed if need be. - log.RemoveAllAppenders(); - - foreach (XmlNode currentNode in catElement.ChildNodes) - { - if (currentNode.NodeType == XmlNodeType.Element) - { - XmlElement currentElement = (XmlElement) currentNode; - - if (currentElement.LocalName == APPENDER_REF_TAG) - { - IAppender appender = FindAppenderByReference(currentElement); - string refName = currentElement.GetAttribute(REF_ATTR); - if (appender != null) - { - LogLog.Debug(declaringType, "Adding appender named [" + refName + "] to logger [" + log.Name + "]."); - log.AddAppender(appender); - } - else - { - LogLog.Error(declaringType, "Appender named [" + refName + "] not found."); - } - } - else if (currentElement.LocalName == LEVEL_TAG || currentElement.LocalName == PRIORITY_TAG) - { - ParseLevel(currentElement, log, isRoot); - } - else - { - SetParameter(currentElement, log); - } - } - } - - IOptionHandler optionHandler = log as IOptionHandler; - if (optionHandler != null) - { - optionHandler.ActivateOptions(); - } - } - - /// - /// Parses an object renderer. - /// - /// The renderer element. - /// - /// - /// Parse an XML element that represents a renderer. - /// - /// - protected void ParseRenderer(XmlElement element) - { - string renderingClassName = element.GetAttribute(RENDERING_TYPE_ATTR); - string renderedClassName = element.GetAttribute(RENDERED_TYPE_ATTR); - - LogLog.Debug(declaringType, "Rendering class [" + renderingClassName + "], Rendered class [" + renderedClassName + "]."); - IObjectRenderer renderer = (IObjectRenderer)OptionConverter.InstantiateByClassName(renderingClassName, typeof(IObjectRenderer), null); - if (renderer == null) - { - LogLog.Error(declaringType, "Could not instantiate renderer [" + renderingClassName + "]."); - return; - } - else - { - try - { + appender.Name = appenderName; + + foreach (XmlNode currentNode in appenderElement.ChildNodes) + { + /* We're only interested in Elements */ + if (currentNode.NodeType == XmlNodeType.Element) + { + XmlElement currentElement = (XmlElement)currentNode; + + // Look for the appender ref tag + if (currentElement.LocalName == APPENDER_REF_TAG) + { + string refName = currentElement.GetAttribute(REF_ATTR); + + IAppenderAttachable appenderContainer = appender as IAppenderAttachable; + if (appenderContainer != null) + { + LogLog.Debug(declaringType, "Attaching appender named [" + refName + "] to appender named [" + appender.Name + "]."); + + IAppender referencedAppender = FindAppenderByReference(currentElement); + if (referencedAppender != null) + { + appenderContainer.AddAppender(referencedAppender); + } + } + else + { + LogLog.Error(declaringType, "Requesting attachment of appender named ["+refName+ "] to appender named [" + appender.Name + "] which does not implement log4net.Core.IAppenderAttachable."); + } + } + else + { + // For all other tags we use standard set param method + SetParameter(currentElement, appender); + } + } + } + + IOptionHandler optionHandler = appender as IOptionHandler; + if (optionHandler != null) + { + optionHandler.ActivateOptions(); + } + + LogLog.Debug(declaringType, "Created Appender [" + appenderName + "]"); + return appender; + } + catch (Exception ex) + { + // Yes, it's ugly. But all exceptions point to the same problem: we can't create an Appender + + LogLog.Error(declaringType, "Could not create Appender [" + appenderName + "] of type [" + typeName + "]. Reported error follows.", ex); + return null; + } + } + + /// + /// Parses a logger element. + /// + /// The logger element. + /// + /// + /// Parse an XML element that represents a logger. + /// + /// + protected void ParseLogger(XmlElement loggerElement) + { + // Create a new log4net.Logger object from the element. + string loggerName = loggerElement.GetAttribute(NAME_ATTR); + + LogLog.Debug(declaringType, "Retrieving an instance of log4net.Repository.Logger for logger [" + loggerName + "]."); + Logger log = m_hierarchy.GetLogger(loggerName) as Logger; + + // Setting up a logger needs to be an atomic operation, in order + // to protect potential log operations while logger + // configuration is in progress. + lock(log) + { + bool additivity = OptionConverter.ToBoolean(loggerElement.GetAttribute(ADDITIVITY_ATTR), true); + + LogLog.Debug(declaringType, "Setting [" + log.Name + "] additivity to [" + additivity + "]."); + log.Additivity = additivity; + ParseChildrenOfLoggerElement(loggerElement, log, false); + } + } + + /// + /// Parses the root logger element. + /// + /// The root element. + /// + /// + /// Parse an XML element that represents the root logger. + /// + /// + protected void ParseRoot(XmlElement rootElement) + { + Logger root = m_hierarchy.Root; + // logger configuration needs to be atomic + lock(root) + { + ParseChildrenOfLoggerElement(rootElement, root, true); + } + } + + /// + /// Parses the children of a logger element. + /// + /// The category element. + /// The logger instance. + /// Flag to indicate if the logger is the root logger. + /// + /// + /// Parse the child elements of a <logger> element. + /// + /// + protected void ParseChildrenOfLoggerElement(XmlElement catElement, Logger log, bool isRoot) + { + // Remove all existing appenders from log. They will be + // reconstructed if need be. + log.RemoveAllAppenders(); + + foreach (XmlNode currentNode in catElement.ChildNodes) + { + if (currentNode.NodeType == XmlNodeType.Element) + { + XmlElement currentElement = (XmlElement) currentNode; + + if (currentElement.LocalName == APPENDER_REF_TAG) + { + IAppender appender = FindAppenderByReference(currentElement); + string refName = currentElement.GetAttribute(REF_ATTR); + if (appender != null) + { + LogLog.Debug(declaringType, "Adding appender named [" + refName + "] to logger [" + log.Name + "]."); + log.AddAppender(appender); + } + else + { + LogLog.Error(declaringType, "Appender named [" + refName + "] not found."); + } + } + else if (currentElement.LocalName == LEVEL_TAG || currentElement.LocalName == PRIORITY_TAG) + { + ParseLevel(currentElement, log, isRoot); + } + else + { + SetParameter(currentElement, log); + } + } + } + + IOptionHandler optionHandler = log as IOptionHandler; + if (optionHandler != null) + { + optionHandler.ActivateOptions(); + } + } + + /// + /// Parses an object renderer. + /// + /// The renderer element. + /// + /// + /// Parse an XML element that represents a renderer. + /// + /// + protected void ParseRenderer(XmlElement element) + { + string renderingClassName = element.GetAttribute(RENDERING_TYPE_ATTR); + string renderedClassName = element.GetAttribute(RENDERED_TYPE_ATTR); + + LogLog.Debug(declaringType, "Rendering class [" + renderingClassName + "], Rendered class [" + renderedClassName + "]."); + IObjectRenderer renderer = (IObjectRenderer)OptionConverter.InstantiateByClassName(renderingClassName, typeof(IObjectRenderer), null); + if (renderer == null) + { + LogLog.Error(declaringType, "Could not instantiate renderer [" + renderingClassName + "]."); + return; + } + else + { + try + { #if NETSTANDARD1_3 - m_hierarchy.RendererMap.Put(SystemInfo.GetTypeFromString(this.GetType().GetTypeInfo().Assembly, renderedClassName, true, true), renderer); + m_hierarchy.RendererMap.Put(SystemInfo.GetTypeFromString(this.GetType().GetTypeInfo().Assembly, renderedClassName, true, true), renderer); #else - m_hierarchy.RendererMap.Put(SystemInfo.GetTypeFromString(renderedClassName, true, true), renderer); + m_hierarchy.RendererMap.Put(SystemInfo.GetTypeFromString(renderedClassName, true, true), renderer); #endif - } - catch(Exception e) - { - LogLog.Error(declaringType, "Could not find class [" + renderedClassName + "].", e); - } - } - } - - /// - /// Parses a level element. - /// - /// The level element. - /// The logger object to set the level on. - /// Flag to indicate if the logger is the root logger. - /// - /// - /// Parse an XML element that represents a level. - /// - /// - protected void ParseLevel(XmlElement element, Logger log, bool isRoot) - { - string loggerName = log.Name; - if (isRoot) - { - loggerName = "root"; - } - - string levelStr = element.GetAttribute(VALUE_ATTR); - LogLog.Debug(declaringType, "Logger [" + loggerName + "] Level string is [" + levelStr + "]."); - - if (INHERITED == levelStr) - { - if (isRoot) - { - LogLog.Error(declaringType, "Root level cannot be inherited. Ignoring directive."); - } - else - { - LogLog.Debug(declaringType, "Logger [" + loggerName + "] level set to inherit from parent."); - log.Level = null; - } - } - else - { - log.Level = log.Hierarchy.LevelMap[levelStr]; - if (log.Level == null) - { - LogLog.Error(declaringType, "Undefined level [" + levelStr + "] on Logger [" + loggerName + "]."); - } - else - { - LogLog.Debug(declaringType, "Logger [" + loggerName + "] level set to [name=\"" + log.Level.Name + "\",value=" + log.Level.Value + "]."); - } - } - } - - /// - /// Sets a parameter on an object. - /// - /// The parameter element. - /// The object to set the parameter on. - /// - /// The parameter name must correspond to a writable property - /// on the object. The value of the parameter is a string, - /// therefore this function will attempt to set a string - /// property first. If unable to set a string property it - /// will inspect the property and its argument type. It will - /// attempt to call a static method called Parse on the - /// type of the property. This method will take a single - /// string argument and return a value that can be used to - /// set the property. - /// - protected void SetParameter(XmlElement element, object target) - { - // Get the property name - string name = element.GetAttribute(NAME_ATTR); - - // If the name attribute does not exist then use the name of the element - if (element.LocalName != PARAM_TAG || name == null || name.Length == 0) - { - name = element.LocalName; - } - - // Look for the property on the target object - Type targetType = target.GetType(); - Type propertyType = null; - - PropertyInfo propInfo = null; - MethodInfo methInfo = null; - - // Try to find a writable property - propInfo = targetType.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.IgnoreCase); - if (propInfo != null && propInfo.CanWrite) - { - // found a property - propertyType = propInfo.PropertyType; - } - else - { - propInfo = null; - - // look for a method with the signature Add(type) - methInfo = FindMethodInfo(targetType, name); - - if (methInfo != null) - { - propertyType = methInfo.GetParameters()[0].ParameterType; - } - } - - if (propertyType == null) - { - LogLog.Error(declaringType, "XmlHierarchyConfigurator: Cannot find Property [" + name + "] to set object on [" + target.ToString() + "]"); - } - else - { - string propertyValue = null; - - if (element.GetAttributeNode(VALUE_ATTR) != null) - { - propertyValue = element.GetAttribute(VALUE_ATTR); - } - else if (element.HasChildNodes) - { - // Concatenate the CDATA and Text nodes together - foreach(XmlNode childNode in element.ChildNodes) - { - if (childNode.NodeType == XmlNodeType.CDATA || childNode.NodeType == XmlNodeType.Text) - { - if (propertyValue == null) - { - propertyValue = childNode.InnerText; - } - else - { - propertyValue += childNode.InnerText; - } - } - } - } - - if(propertyValue != null) - { + } + catch(Exception e) + { + LogLog.Error(declaringType, "Could not find class [" + renderedClassName + "].", e); + } + } + } + + /// + /// Parses a level element. + /// + /// The level element. + /// The logger object to set the level on. + /// Flag to indicate if the logger is the root logger. + /// + /// + /// Parse an XML element that represents a level. + /// + /// + protected void ParseLevel(XmlElement element, Logger log, bool isRoot) + { + string loggerName = log.Name; + if (isRoot) + { + loggerName = "root"; + } + + string levelStr = element.GetAttribute(VALUE_ATTR); + LogLog.Debug(declaringType, "Logger [" + loggerName + "] Level string is [" + levelStr + "]."); + + if (INHERITED == levelStr) + { + if (isRoot) + { + LogLog.Error(declaringType, "Root level cannot be inherited. Ignoring directive."); + } + else + { + LogLog.Debug(declaringType, "Logger [" + loggerName + "] level set to inherit from parent."); + log.Level = null; + } + } + else + { + log.Level = log.Hierarchy.LevelMap[levelStr]; + if (log.Level == null) + { + LogLog.Error(declaringType, "Undefined level [" + levelStr + "] on Logger [" + loggerName + "]."); + } + else + { + LogLog.Debug(declaringType, "Logger [" + loggerName + "] level set to [name=\"" + log.Level.Name + "\",value=" + log.Level.Value + "]."); + } + } + } + + /// + /// Sets a parameter on an object. + /// + /// The parameter element. + /// The object to set the parameter on. + /// + /// The parameter name must correspond to a writable property + /// on the object. The value of the parameter is a string, + /// therefore this function will attempt to set a string + /// property first. If unable to set a string property it + /// will inspect the property and its argument type. It will + /// attempt to call a static method called Parse on the + /// type of the property. This method will take a single + /// string argument and return a value that can be used to + /// set the property. + /// + protected void SetParameter(XmlElement element, object target) + { + // Get the property name + string name = element.GetAttribute(NAME_ATTR); + + // If the name attribute does not exist then use the name of the element + if (element.LocalName != PARAM_TAG || name == null || name.Length == 0) + { + name = element.LocalName; + } + + // Look for the property on the target object + Type targetType = target.GetType(); + Type propertyType = null; + + PropertyInfo propInfo = null; + MethodInfo methInfo = null; + + // Try to find a writable property + propInfo = targetType.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.IgnoreCase); + if (propInfo != null && propInfo.CanWrite) + { + // found a property + propertyType = propInfo.PropertyType; + } + else + { + propInfo = null; + + // look for a method with the signature Add(type) + methInfo = FindMethodInfo(targetType, name); + + if (methInfo != null) + { + propertyType = methInfo.GetParameters()[0].ParameterType; + } + } + + if (propertyType == null) + { + LogLog.Error(declaringType, "XmlHierarchyConfigurator: Cannot find Property [" + name + "] to set object on [" + target.ToString() + "]"); + } + else + { + string propertyValue = null; + + if (element.GetAttributeNode(VALUE_ATTR) != null) + { + propertyValue = element.GetAttribute(VALUE_ATTR); + } + else if (element.HasChildNodes) + { + // Concatenate the CDATA and Text nodes together + foreach(XmlNode childNode in element.ChildNodes) + { + if (childNode.NodeType == XmlNodeType.CDATA || childNode.NodeType == XmlNodeType.Text) + { + if (propertyValue == null) + { + propertyValue = childNode.InnerText; + } + else + { + propertyValue += childNode.InnerText; + } + } + } + } + + if(propertyValue != null) + { #if !NETCF && !NETSTANDARD1_3 // NETSTANDARD1_3: System.Runtime.InteropServices.RuntimeInformation not available on desktop 4.6 - try - { - // Expand environment variables in the string. - IDictionary environmentVariables = Environment.GetEnvironmentVariables(); - if (HasCaseInsensitiveEnvironment) { - environmentVariables = CreateCaseInsensitiveWrapper(environmentVariables); - } - propertyValue = OptionConverter.SubstituteVariables(propertyValue, environmentVariables); - } - catch(System.Security.SecurityException) - { - // This security exception will occur if the caller does not have - // unrestricted environment permission. If this occurs the expansion - // will be skipped with the following warning message. - LogLog.Debug(declaringType, "Security exception while trying to expand environment variables. Error Ignored. No Expansion."); - } + try + { + // Expand environment variables in the string. + IDictionary environmentVariables = Environment.GetEnvironmentVariables(); + if (HasCaseInsensitiveEnvironment) { + environmentVariables = CreateCaseInsensitiveWrapper(environmentVariables); + } + propertyValue = OptionConverter.SubstituteVariables(propertyValue, environmentVariables); + } + catch(System.Security.SecurityException) + { + // This security exception will occur if the caller does not have + // unrestricted environment permission. If this occurs the expansion + // will be skipped with the following warning message. + LogLog.Debug(declaringType, "Security exception while trying to expand environment variables. Error Ignored. No Expansion."); + } #endif - Type parsedObjectConversionTargetType = null; + Type parsedObjectConversionTargetType = null; - // Check if a specific subtype is specified on the element using the 'type' attribute - string subTypeString = element.GetAttribute(TYPE_ATTR); - if (subTypeString != null && subTypeString.Length > 0) - { - // Read the explicit subtype - try - { + // Check if a specific subtype is specified on the element using the 'type' attribute + string subTypeString = element.GetAttribute(TYPE_ATTR); + if (subTypeString != null && subTypeString.Length > 0) + { + // Read the explicit subtype + try + { #if NETSTANDARD1_3 - Type subType = SystemInfo.GetTypeFromString(this.GetType().GetTypeInfo().Assembly, subTypeString, true, true); + Type subType = SystemInfo.GetTypeFromString(this.GetType().GetTypeInfo().Assembly, subTypeString, true, true); #else - Type subType = SystemInfo.GetTypeFromString(subTypeString, true, true); + Type subType = SystemInfo.GetTypeFromString(subTypeString, true, true); #endif - LogLog.Debug(declaringType, "Parameter ["+name+"] specified subtype ["+subType.FullName+"]"); - - if (!propertyType.IsAssignableFrom(subType)) - { - // Check if there is an appropriate type converter - if (OptionConverter.CanConvertTypeTo(subType, propertyType)) - { - // Must re-convert to the real property type - parsedObjectConversionTargetType = propertyType; - - // Use sub type as intermediary type - propertyType = subType; - } - else - { - LogLog.Error(declaringType, "subtype ["+subType.FullName+"] set on ["+name+"] is not a subclass of property type ["+propertyType.FullName+"] and there are no acceptable type conversions."); - } - } - else - { - // The subtype specified is found and is actually a subtype of the property - // type, therefore we can switch to using this type. - propertyType = subType; - } - } - catch(Exception ex) - { - LogLog.Error(declaringType, "Failed to find type ["+subTypeString+"] set on ["+name+"]", ex); - } - } - - // Now try to convert the string value to an acceptable type - // to pass to this property. - - object convertedValue = ConvertStringTo(propertyType, propertyValue); - - // Check if we need to do an additional conversion - if (convertedValue != null && parsedObjectConversionTargetType != null) - { - LogLog.Debug(declaringType, "Performing additional conversion of value from [" + convertedValue.GetType().Name + "] to [" + parsedObjectConversionTargetType.Name + "]"); - convertedValue = OptionConverter.ConvertTypeTo(convertedValue, parsedObjectConversionTargetType); - } - - if (convertedValue != null) - { - if (propInfo != null) - { - // Got a converted result - LogLog.Debug(declaringType, "Setting Property [" + propInfo.Name + "] to " + convertedValue.GetType().Name + " value [" + convertedValue.ToString() + "]"); - - try - { - // Pass to the property + LogLog.Debug(declaringType, "Parameter ["+name+"] specified subtype ["+subType.FullName+"]"); + + if (!propertyType.IsAssignableFrom(subType)) + { + // Check if there is an appropriate type converter + if (OptionConverter.CanConvertTypeTo(subType, propertyType)) + { + // Must re-convert to the real property type + parsedObjectConversionTargetType = propertyType; + + // Use sub type as intermediary type + propertyType = subType; + } + else + { + LogLog.Error(declaringType, "subtype ["+subType.FullName+"] set on ["+name+"] is not a subclass of property type ["+propertyType.FullName+"] and there are no acceptable type conversions."); + } + } + else + { + // The subtype specified is found and is actually a subtype of the property + // type, therefore we can switch to using this type. + propertyType = subType; + } + } + catch(Exception ex) + { + LogLog.Error(declaringType, "Failed to find type ["+subTypeString+"] set on ["+name+"]", ex); + } + } + + // Now try to convert the string value to an acceptable type + // to pass to this property. + + object convertedValue = ConvertStringTo(propertyType, propertyValue); + + // Check if we need to do an additional conversion + if (convertedValue != null && parsedObjectConversionTargetType != null) + { + LogLog.Debug(declaringType, "Performing additional conversion of value from [" + convertedValue.GetType().Name + "] to [" + parsedObjectConversionTargetType.Name + "]"); + convertedValue = OptionConverter.ConvertTypeTo(convertedValue, parsedObjectConversionTargetType); + } + + if (convertedValue != null) + { + if (propInfo != null) + { + // Got a converted result + LogLog.Debug(declaringType, "Setting Property [" + propInfo.Name + "] to " + convertedValue.GetType().Name + " value [" + convertedValue.ToString() + "]"); + + try + { + // Pass to the property #if NETSTANDARD1_3 // TODO BindingFlags is available for netstandard1.5 - propInfo.SetValue(target, convertedValue, null); + propInfo.SetValue(target, convertedValue, null); #else - propInfo.SetValue(target, convertedValue, BindingFlags.SetProperty, null, null, CultureInfo.InvariantCulture); + propInfo.SetValue(target, convertedValue, BindingFlags.SetProperty, null, null, CultureInfo.InvariantCulture); #endif - } - catch(TargetInvocationException targetInvocationEx) - { - LogLog.Error(declaringType, "Failed to set parameter [" + propInfo.Name + "] on object [" + target + "] using value [" + convertedValue + "]", targetInvocationEx.InnerException); - } - } - else if (methInfo != null) - { - // Got a converted result - LogLog.Debug(declaringType, "Setting Collection Property [" + methInfo.Name + "] to " + convertedValue.GetType().Name + " value [" + convertedValue.ToString() + "]"); - - try - { - // Pass to the property + } + catch(TargetInvocationException targetInvocationEx) + { + LogLog.Error(declaringType, "Failed to set parameter [" + propInfo.Name + "] on object [" + target + "] using value [" + convertedValue + "]", targetInvocationEx.InnerException); + } + } + else if (methInfo != null) + { + // Got a converted result + LogLog.Debug(declaringType, "Setting Collection Property [" + methInfo.Name + "] to " + convertedValue.GetType().Name + " value [" + convertedValue.ToString() + "]"); + + try + { + // Pass to the property #if NETSTANDARD1_3 // TODO BindingFlags is available for netstandard1.5 - methInfo.Invoke(target, new[] { convertedValue }); + methInfo.Invoke(target, new[] { convertedValue }); #else - methInfo.Invoke(target, BindingFlags.InvokeMethod, null, new object[] {convertedValue}, CultureInfo.InvariantCulture); + methInfo.Invoke(target, BindingFlags.InvokeMethod, null, new object[] {convertedValue}, CultureInfo.InvariantCulture); #endif - } - catch(TargetInvocationException targetInvocationEx) - { - LogLog.Error(declaringType, "Failed to set parameter [" + name + "] on object [" + target + "] using value [" + convertedValue + "]", targetInvocationEx.InnerException); - } - } - } - else - { - LogLog.Warn(declaringType, "Unable to set property [" + name + "] on object [" + target + "] using value [" + propertyValue + "] (with acceptable conversion types)"); - } - } - else - { - object createdObject = null; - - if (propertyType == typeof(string) && !HasAttributesOrElements(element)) - { - // If the property is a string and the element is empty (no attributes - // or child elements) then we special case the object value to an empty string. - // This is necessary because while the String is a class it does not have - // a default constructor that creates an empty string, which is the behavior - // we are trying to simulate and would be expected from CreateObjectFromXml - createdObject = ""; - } - else - { - // No value specified - Type defaultObjectType = null; - if (IsTypeConstructible(propertyType)) - { - defaultObjectType = propertyType; - } - - createdObject = CreateObjectFromXml(element, defaultObjectType, propertyType); - } - - if (createdObject == null) - { - LogLog.Error(declaringType, "Failed to create object to set param: "+name); - } - else - { - if (propInfo != null) - { - // Got a converted result - LogLog.Debug(declaringType, "Setting Property ["+ propInfo.Name +"] to object ["+ createdObject +"]"); - - try - { - // Pass to the property + } + catch(TargetInvocationException targetInvocationEx) + { + LogLog.Error(declaringType, "Failed to set parameter [" + name + "] on object [" + target + "] using value [" + convertedValue + "]", targetInvocationEx.InnerException); + } + } + } + else + { + LogLog.Warn(declaringType, "Unable to set property [" + name + "] on object [" + target + "] using value [" + propertyValue + "] (with acceptable conversion types)"); + } + } + else + { + object createdObject = null; + + if (propertyType == typeof(string) && !HasAttributesOrElements(element)) + { + // If the property is a string and the element is empty (no attributes + // or child elements) then we special case the object value to an empty string. + // This is necessary because while the String is a class it does not have + // a default constructor that creates an empty string, which is the behavior + // we are trying to simulate and would be expected from CreateObjectFromXml + createdObject = ""; + } + else + { + // No value specified + Type defaultObjectType = null; + if (IsTypeConstructible(propertyType)) + { + defaultObjectType = propertyType; + } + + createdObject = CreateObjectFromXml(element, defaultObjectType, propertyType); + } + + if (createdObject == null) + { + LogLog.Error(declaringType, "Failed to create object to set param: "+name); + } + else + { + if (propInfo != null) + { + // Got a converted result + LogLog.Debug(declaringType, "Setting Property ["+ propInfo.Name +"] to object ["+ createdObject +"]"); + + try + { + // Pass to the property #if NETSTANDARD1_3 // TODO BindingFlags is available for netstandard1.5 - propInfo.SetValue(target, createdObject, null); + propInfo.SetValue(target, createdObject, null); #else - propInfo.SetValue(target, createdObject, BindingFlags.SetProperty, null, null, CultureInfo.InvariantCulture); + propInfo.SetValue(target, createdObject, BindingFlags.SetProperty, null, null, CultureInfo.InvariantCulture); #endif - } - catch(TargetInvocationException targetInvocationEx) - { - LogLog.Error(declaringType, "Failed to set parameter [" + propInfo.Name + "] on object [" + target + "] using value [" + createdObject + "]", targetInvocationEx.InnerException); - } - } - else if (methInfo != null) - { - // Got a converted result - LogLog.Debug(declaringType, "Setting Collection Property ["+ methInfo.Name +"] to object ["+ createdObject +"]"); - - try - { - // Pass to the property + } + catch(TargetInvocationException targetInvocationEx) + { + LogLog.Error(declaringType, "Failed to set parameter [" + propInfo.Name + "] on object [" + target + "] using value [" + createdObject + "]", targetInvocationEx.InnerException); + } + } + else if (methInfo != null) + { + // Got a converted result + LogLog.Debug(declaringType, "Setting Collection Property ["+ methInfo.Name +"] to object ["+ createdObject +"]"); + + try + { + // Pass to the property #if NETSTANDARD1_3 // TODO BindingFlags is available for netstandard1.5 - methInfo.Invoke(target, new[] { createdObject }); + methInfo.Invoke(target, new[] { createdObject }); #else - methInfo.Invoke(target, BindingFlags.InvokeMethod, null, new object[] {createdObject}, CultureInfo.InvariantCulture); + methInfo.Invoke(target, BindingFlags.InvokeMethod, null, new object[] {createdObject}, CultureInfo.InvariantCulture); #endif - } - catch(TargetInvocationException targetInvocationEx) - { - LogLog.Error(declaringType, "Failed to set parameter [" + methInfo.Name + "] on object [" + target + "] using value [" + createdObject + "]", targetInvocationEx.InnerException); - } - } - } - } - } - } - - /// - /// Test if an element has no attributes or child elements - /// - /// the element to inspect - /// true if the element has any attributes or child elements, false otherwise - private bool HasAttributesOrElements(XmlElement element) - { - foreach(XmlNode node in element.ChildNodes) - { - if (node.NodeType == XmlNodeType.Attribute || node.NodeType == XmlNodeType.Element) - { - return true; - } - } - return false; - } - - /// - /// Test if a is constructible with Activator.CreateInstance. - /// - /// the type to inspect - /// true if the type is creatable using a default constructor, false otherwise - private static bool IsTypeConstructible(Type type) - { + } + catch(TargetInvocationException targetInvocationEx) + { + LogLog.Error(declaringType, "Failed to set parameter [" + methInfo.Name + "] on object [" + target + "] using value [" + createdObject + "]", targetInvocationEx.InnerException); + } + } + } + } + } + } + + /// + /// Test if an element has no attributes or child elements + /// + /// the element to inspect + /// true if the element has any attributes or child elements, false otherwise + private bool HasAttributesOrElements(XmlElement element) + { + foreach(XmlNode node in element.ChildNodes) + { + if (node.NodeType == XmlNodeType.Attribute || node.NodeType == XmlNodeType.Element) + { + return true; + } + } + return false; + } + + /// + /// Test if a is constructible with Activator.CreateInstance. + /// + /// the type to inspect + /// true if the type is creatable using a default constructor, false otherwise + private static bool IsTypeConstructible(Type type) + { #if NETSTANDARD1_3 - TypeInfo typeInfo = type.GetTypeInfo(); - if (typeInfo.IsClass && !typeInfo.IsAbstract) + TypeInfo typeInfo = type.GetTypeInfo(); + if (typeInfo.IsClass && !typeInfo.IsAbstract) #else - if (type.IsClass && !type.IsAbstract) + if (type.IsClass && !type.IsAbstract) #endif - { - ConstructorInfo defaultConstructor = type.GetConstructor(new Type[0]); - if (defaultConstructor != null && !defaultConstructor.IsAbstract && !defaultConstructor.IsPrivate) - { - return true; - } - } - return false; - } - - /// - /// Look for a method on the that matches the supplied - /// - /// the type that has the method - /// the name of the method - /// the method info found - /// - /// - /// The method must be a public instance method on the . - /// The method must be named or "Add" followed by . - /// The method must take a single parameter. - /// - /// - private MethodInfo FindMethodInfo(Type targetType, string name) - { - string requiredMethodNameA = name; - string requiredMethodNameB = "Add" + name; - - MethodInfo[] methods = targetType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); - - foreach(MethodInfo methInfo in methods) - { - if (!methInfo.IsStatic) - { - string methodInfoName = methInfo.Name; - - if (SystemInfo.EqualsIgnoringCase(methodInfoName, requiredMethodNameA) || - SystemInfo.EqualsIgnoringCase(methodInfoName, requiredMethodNameB)) - { - // Found matching method name - - // Look for version with one arg only - System.Reflection.ParameterInfo[] methParams = methInfo.GetParameters(); - if (methParams.Length == 1) - { - return methInfo; - } - } - } - } - return null; - } - - /// - /// Converts a string value to a target type. - /// - /// The type of object to convert the string to. - /// The string value to use as the value of the object. - /// - /// - /// An object of type with value or - /// null when the conversion could not be performed. - /// - /// - protected object ConvertStringTo(Type type, string value) - { - // Hack to allow use of Level in property - if (typeof(Level) == type) - { - // Property wants a level - Level levelValue = m_hierarchy.LevelMap[value]; - - if (levelValue == null) - { - LogLog.Error(declaringType, "XmlHierarchyConfigurator: Unknown Level Specified ["+ value +"]"); - } - - return levelValue; - } - return OptionConverter.ConvertStringTo(type, value); - } - - /// - /// Creates an object as specified in XML. - /// - /// The XML element that contains the definition of the object. - /// The object type to use if not explicitly specified. - /// The type that the returned object must be or must inherit from. - /// The object or null - /// - /// - /// Parse an XML element and create an object instance based on the configuration - /// data. - /// - /// - /// The type of the instance may be specified in the XML. If not - /// specified then the is used - /// as the type. However the type is specified it must support the - /// type. - /// - /// - protected object CreateObjectFromXml(XmlElement element, Type defaultTargetType, Type typeConstraint) - { - Type objectType = null; - - // Get the object type - string objectTypeString = element.GetAttribute(TYPE_ATTR); - if (objectTypeString == null || objectTypeString.Length == 0) - { - if (defaultTargetType == null) - { - LogLog.Error(declaringType, "Object type not specified. Cannot create object of type ["+typeConstraint.FullName+"]. Missing Value or Type."); - return null; - } - else - { - // Use the default object type - objectType = defaultTargetType; - } - } - else - { - // Read the explicit object type - try - { + { + ConstructorInfo defaultConstructor = type.GetConstructor(new Type[0]); + if (defaultConstructor != null && !defaultConstructor.IsAbstract && !defaultConstructor.IsPrivate) + { + return true; + } + } + return false; + } + + /// + /// Look for a method on the that matches the supplied + /// + /// the type that has the method + /// the name of the method + /// the method info found + /// + /// + /// The method must be a public instance method on the . + /// The method must be named or "Add" followed by . + /// The method must take a single parameter. + /// + /// + private MethodInfo FindMethodInfo(Type targetType, string name) + { + string requiredMethodNameA = name; + string requiredMethodNameB = "Add" + name; + + MethodInfo[] methods = targetType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); + + foreach(MethodInfo methInfo in methods) + { + if (!methInfo.IsStatic) + { + string methodInfoName = methInfo.Name; + + if (SystemInfo.EqualsIgnoringCase(methodInfoName, requiredMethodNameA) || + SystemInfo.EqualsIgnoringCase(methodInfoName, requiredMethodNameB)) + { + // Found matching method name + + // Look for version with one arg only + System.Reflection.ParameterInfo[] methParams = methInfo.GetParameters(); + if (methParams.Length == 1) + { + return methInfo; + } + } + } + } + return null; + } + + /// + /// Converts a string value to a target type. + /// + /// The type of object to convert the string to. + /// The string value to use as the value of the object. + /// + /// + /// An object of type with value or + /// null when the conversion could not be performed. + /// + /// + protected object ConvertStringTo(Type type, string value) + { + // Hack to allow use of Level in property + if (typeof(Level) == type) + { + // Property wants a level + Level levelValue = m_hierarchy.LevelMap[value]; + + if (levelValue == null) + { + LogLog.Error(declaringType, "XmlHierarchyConfigurator: Unknown Level Specified ["+ value +"]"); + } + + return levelValue; + } + return OptionConverter.ConvertStringTo(type, value); + } + + /// + /// Creates an object as specified in XML. + /// + /// The XML element that contains the definition of the object. + /// The object type to use if not explicitly specified. + /// The type that the returned object must be or must inherit from. + /// The object or null + /// + /// + /// Parse an XML element and create an object instance based on the configuration + /// data. + /// + /// + /// The type of the instance may be specified in the XML. If not + /// specified then the is used + /// as the type. However the type is specified it must support the + /// type. + /// + /// + protected object CreateObjectFromXml(XmlElement element, Type defaultTargetType, Type typeConstraint) + { + Type objectType = null; + + // Get the object type + string objectTypeString = element.GetAttribute(TYPE_ATTR); + if (objectTypeString == null || objectTypeString.Length == 0) + { + if (defaultTargetType == null) + { + LogLog.Error(declaringType, "Object type not specified. Cannot create object of type ["+typeConstraint.FullName+"]. Missing Value or Type."); + return null; + } + else + { + // Use the default object type + objectType = defaultTargetType; + } + } + else + { + // Read the explicit object type + try + { #if NETSTANDARD1_3 - objectType = SystemInfo.GetTypeFromString(this.GetType().GetTypeInfo().Assembly, objectTypeString, true, true); + objectType = SystemInfo.GetTypeFromString(this.GetType().GetTypeInfo().Assembly, objectTypeString, true, true); #else - objectType = SystemInfo.GetTypeFromString(objectTypeString, true, true); + objectType = SystemInfo.GetTypeFromString(objectTypeString, true, true); #endif - } - catch(Exception ex) - { - LogLog.Error(declaringType, "Failed to find type ["+objectTypeString+"]", ex); - return null; - } - } - - bool requiresConversion = false; - - // Got the object type. Check that it meets the typeConstraint - if (typeConstraint != null) - { - if (!typeConstraint.IsAssignableFrom(objectType)) - { - // Check if there is an appropriate type converter - if (OptionConverter.CanConvertTypeTo(objectType, typeConstraint)) - { - requiresConversion = true; - } - else - { - LogLog.Error(declaringType, "Object type ["+objectType.FullName+"] is not assignable to type ["+typeConstraint.FullName+"]. There are no acceptable type conversions."); - return null; - } - } - } - - // Create using the default constructor - object createdObject = null; - try - { - createdObject = Activator.CreateInstance(objectType); - } - catch(Exception createInstanceEx) - { - LogLog.Error(declaringType, "XmlHierarchyConfigurator: Failed to construct object of type [" + objectType.FullName + "] Exception: "+createInstanceEx.ToString()); - } - - // Set any params on object - foreach (XmlNode currentNode in element.ChildNodes) - { - if (currentNode.NodeType == XmlNodeType.Element) - { - SetParameter((XmlElement)currentNode, createdObject); - } - } - - // Check if we need to call ActivateOptions - IOptionHandler optionHandler = createdObject as IOptionHandler; - if (optionHandler != null) - { - optionHandler.ActivateOptions(); - } - - // Ok object should be initialized - - if (requiresConversion) - { - // Convert the object type - return OptionConverter.ConvertTypeTo(createdObject, typeConstraint); - } - else - { - // The object is of the correct type - return createdObject; - } - } - - #endregion Protected Instance Methods + } + catch(Exception ex) + { + LogLog.Error(declaringType, "Failed to find type ["+objectTypeString+"]", ex); + return null; + } + } + + bool requiresConversion = false; + + // Got the object type. Check that it meets the typeConstraint + if (typeConstraint != null) + { + if (!typeConstraint.IsAssignableFrom(objectType)) + { + // Check if there is an appropriate type converter + if (OptionConverter.CanConvertTypeTo(objectType, typeConstraint)) + { + requiresConversion = true; + } + else + { + LogLog.Error(declaringType, "Object type ["+objectType.FullName+"] is not assignable to type ["+typeConstraint.FullName+"]. There are no acceptable type conversions."); + return null; + } + } + } + + // Create using the default constructor + object createdObject = null; + try + { + createdObject = Activator.CreateInstance(objectType); + } + catch(Exception createInstanceEx) + { + LogLog.Error(declaringType, "XmlHierarchyConfigurator: Failed to construct object of type [" + objectType.FullName + "] Exception: "+createInstanceEx.ToString()); + } + + // Set any params on object + foreach (XmlNode currentNode in element.ChildNodes) + { + if (currentNode.NodeType == XmlNodeType.Element) + { + SetParameter((XmlElement)currentNode, createdObject); + } + } + + // Check if we need to call ActivateOptions + IOptionHandler optionHandler = createdObject as IOptionHandler; + if (optionHandler != null) + { + optionHandler.ActivateOptions(); + } + + // Ok object should be initialized + + if (requiresConversion) + { + // Convert the object type + return OptionConverter.ConvertTypeTo(createdObject, typeConstraint); + } + else + { + // The object is of the correct type + return createdObject; + } + } + + #endregion Protected Instance Methods #if !NETCF && !NETSTANDARD1_3 // NETSTANDARD1_3: System.Runtime.InteropServices.RuntimeInformation not available on desktop 4.6 - private bool HasCaseInsensitiveEnvironment - { - get - { + private bool HasCaseInsensitiveEnvironment + { + get + { #if NET_1_0 || NET_1_1 || CLI_1_0 - // actually there is no guarantee, but we don't know better - return true; + // actually there is no guarantee, but we don't know better + return true; #elif MONO_1_0 - // see above - return false; + // see above + return false; #else - PlatformID platform = Environment.OSVersion.Platform; - return platform != PlatformID.Unix && platform != PlatformID.MacOSX; + PlatformID platform = Environment.OSVersion.Platform; + return platform != PlatformID.Unix && platform != PlatformID.MacOSX; #endif - } - } - - private IDictionary CreateCaseInsensitiveWrapper(IDictionary dict) - { - if (dict == null) - { - return dict; - } - Hashtable hash = SystemInfo.CreateCaseInsensitiveHashtable(); - foreach (DictionaryEntry entry in dict) { - hash[entry.Key] = entry.Value; - } - return hash; - } + } + } + + private IDictionary CreateCaseInsensitiveWrapper(IDictionary dict) + { + if (dict == null) + { + return dict; + } + Hashtable hash = SystemInfo.CreateCaseInsensitiveHashtable(); + foreach (DictionaryEntry entry in dict) { + hash[entry.Key] = entry.Value; + } + return hash; + } #endif - #region Private Constants - - // String constants used while parsing the XML data - private const string CONFIGURATION_TAG = "log4net"; - private const string RENDERER_TAG = "renderer"; - private const string APPENDER_TAG = "appender"; - private const string APPENDER_REF_TAG = "appender-ref"; - private const string PARAM_TAG = "param"; - - // TODO: Deprecate use of category tags - private const string CATEGORY_TAG = "category"; - // TODO: Deprecate use of priority tag - private const string PRIORITY_TAG = "priority"; - - private const string LOGGER_TAG = "logger"; - private const string NAME_ATTR = "name"; - private const string TYPE_ATTR = "type"; - private const string VALUE_ATTR = "value"; - private const string ROOT_TAG = "root"; - private const string LEVEL_TAG = "level"; - private const string REF_ATTR = "ref"; - private const string ADDITIVITY_ATTR = "additivity"; - private const string THRESHOLD_ATTR = "threshold"; - private const string CONFIG_DEBUG_ATTR = "configDebug"; - private const string INTERNAL_DEBUG_ATTR = "debug"; - private const string EMIT_INTERNAL_DEBUG_ATTR = "emitDebug"; - private const string CONFIG_UPDATE_MODE_ATTR = "update"; - private const string RENDERING_TYPE_ATTR = "renderingClass"; - private const string RENDERED_TYPE_ATTR = "renderedClass"; - - // flag used on the level element - private const string INHERITED = "inherited"; - - #endregion Private Constants - - #region Private Instance Fields - - /// - /// key: appenderName, value: appender. - /// - private Hashtable m_appenderBag; - - /// - /// The Hierarchy being configured. - /// - private readonly Hierarchy m_hierarchy; - - #endregion Private Instance Fields - - #region Private Static Fields - - /// - /// The fully qualified type of the XmlHierarchyConfigurator class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(XmlHierarchyConfigurator); - - #endregion Private Static Fields - } + #region Private Constants + + // String constants used while parsing the XML data + private const string CONFIGURATION_TAG = "log4net"; + private const string RENDERER_TAG = "renderer"; + private const string APPENDER_TAG = "appender"; + private const string APPENDER_REF_TAG = "appender-ref"; + private const string PARAM_TAG = "param"; + + // TODO: Deprecate use of category tags + private const string CATEGORY_TAG = "category"; + // TODO: Deprecate use of priority tag + private const string PRIORITY_TAG = "priority"; + + private const string LOGGER_TAG = "logger"; + private const string NAME_ATTR = "name"; + private const string TYPE_ATTR = "type"; + private const string VALUE_ATTR = "value"; + private const string ROOT_TAG = "root"; + private const string LEVEL_TAG = "level"; + private const string REF_ATTR = "ref"; + private const string ADDITIVITY_ATTR = "additivity"; + private const string THRESHOLD_ATTR = "threshold"; + private const string CONFIG_DEBUG_ATTR = "configDebug"; + private const string INTERNAL_DEBUG_ATTR = "debug"; + private const string EMIT_INTERNAL_DEBUG_ATTR = "emitDebug"; + private const string CONFIG_UPDATE_MODE_ATTR = "update"; + private const string RENDERING_TYPE_ATTR = "renderingClass"; + private const string RENDERED_TYPE_ATTR = "renderedClass"; + + // flag used on the level element + private const string INHERITED = "inherited"; + + #endregion Private Constants + + #region Private Instance Fields + + /// + /// key: appenderName, value: appender. + /// + private Hashtable m_appenderBag; + + /// + /// The Hierarchy being configured. + /// + private readonly Hierarchy m_hierarchy; + + #endregion Private Instance Fields + + #region Private Static Fields + + /// + /// The fully qualified type of the XmlHierarchyConfigurator class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(XmlHierarchyConfigurator); + + #endregion Private Static Fields + } } diff --git a/src/log4net/Repository/IBasicRepositoryConfigurator.cs b/src/log4net/Repository/IBasicRepositoryConfigurator.cs index 7fdbb70c..b6196f7b 100644 --- a/src/log4net/Repository/IBasicRepositoryConfigurator.cs +++ b/src/log4net/Repository/IBasicRepositoryConfigurator.cs @@ -19,33 +19,33 @@ namespace log4net.Repository { - /// - /// Basic Configurator interface for repositories - /// - /// - /// - /// Interface used by basic configurator to configure a - /// with a default . - /// - /// - /// A should implement this interface to support - /// configuration by the . - /// - /// - /// Nicko Cadell - /// Gert Driesen - public interface IBasicRepositoryConfigurator - { - /// - /// Initialize the repository using the specified appender - /// - /// the appender to use to log all logging events - /// - /// - /// Configure the repository to route all logging events to the - /// specified appender. - /// - /// + /// + /// Basic Configurator interface for repositories + /// + /// + /// + /// Interface used by basic configurator to configure a + /// with a default . + /// + /// + /// A should implement this interface to support + /// configuration by the . + /// + /// + /// Nicko Cadell + /// Gert Driesen + public interface IBasicRepositoryConfigurator + { + /// + /// Initialize the repository using the specified appender + /// + /// the appender to use to log all logging events + /// + /// + /// Configure the repository to route all logging events to the + /// specified appender. + /// + /// void Configure(Appender.IAppender appender); /// @@ -59,5 +59,5 @@ public interface IBasicRepositoryConfigurator /// /// void Configure(params Appender.IAppender[] appenders); - } + } } diff --git a/src/log4net/Repository/ILoggerRepository.cs b/src/log4net/Repository/ILoggerRepository.cs index 30ef5b33..9ea0fd4e 100644 --- a/src/log4net/Repository/ILoggerRepository.cs +++ b/src/log4net/Repository/ILoggerRepository.cs @@ -28,253 +28,253 @@ namespace log4net.Repository { - #region LoggerRepositoryShutdownEvent + #region LoggerRepositoryShutdownEvent - /// - /// Delegate used to handle logger repository shutdown event notifications - /// - /// The that is shutting down. - /// Empty event args - /// - /// - /// Delegate used to handle logger repository shutdown event notifications. - /// - /// - public delegate void LoggerRepositoryShutdownEventHandler(object sender, EventArgs e); + /// + /// Delegate used to handle logger repository shutdown event notifications + /// + /// The that is shutting down. + /// Empty event args + /// + /// + /// Delegate used to handle logger repository shutdown event notifications. + /// + /// + public delegate void LoggerRepositoryShutdownEventHandler(object sender, EventArgs e); - #endregion + #endregion - #region LoggerRepositoryConfigurationResetEventHandler + #region LoggerRepositoryConfigurationResetEventHandler - /// - /// Delegate used to handle logger repository configuration reset event notifications - /// - /// The that has had its configuration reset. - /// Empty event args - /// - /// - /// Delegate used to handle logger repository configuration reset event notifications. - /// - /// - public delegate void LoggerRepositoryConfigurationResetEventHandler(object sender, EventArgs e); + /// + /// Delegate used to handle logger repository configuration reset event notifications + /// + /// The that has had its configuration reset. + /// Empty event args + /// + /// + /// Delegate used to handle logger repository configuration reset event notifications. + /// + /// + public delegate void LoggerRepositoryConfigurationResetEventHandler(object sender, EventArgs e); - #endregion + #endregion - #region LoggerRepositoryConfigurationChangedEventHandler + #region LoggerRepositoryConfigurationChangedEventHandler - /// - /// Delegate used to handle event notifications for logger repository configuration changes. - /// - /// The that has had its configuration changed. - /// Empty event arguments. - /// - /// - /// Delegate used to handle event notifications for logger repository configuration changes. - /// - /// - public delegate void LoggerRepositoryConfigurationChangedEventHandler(object sender, EventArgs e); + /// + /// Delegate used to handle event notifications for logger repository configuration changes. + /// + /// The that has had its configuration changed. + /// Empty event arguments. + /// + /// + /// Delegate used to handle event notifications for logger repository configuration changes. + /// + /// + public delegate void LoggerRepositoryConfigurationChangedEventHandler(object sender, EventArgs e); #endregion - - /// - /// Interface implemented by logger repositories. - /// - /// - /// - /// This interface is implemented by logger repositories. e.g. - /// . - /// - /// - /// This interface is used by the - /// to obtain interfaces. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public interface ILoggerRepository - { - /// - /// The name of the repository - /// - /// - /// The name of the repository - /// - /// - /// - /// The name of the repository. - /// - /// - string Name { get; set; } + + /// + /// Interface implemented by logger repositories. + /// + /// + /// + /// This interface is implemented by logger repositories. e.g. + /// . + /// + /// + /// This interface is used by the + /// to obtain interfaces. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public interface ILoggerRepository + { + /// + /// The name of the repository + /// + /// + /// The name of the repository + /// + /// + /// + /// The name of the repository. + /// + /// + string Name { get; set; } - /// - /// RendererMap accesses the object renderer map for this repository. - /// - /// - /// RendererMap accesses the object renderer map for this repository. - /// - /// - /// - /// RendererMap accesses the object renderer map for this repository. - /// - /// - /// The RendererMap holds a mapping between types and - /// objects. - /// - /// - RendererMap RendererMap { get; } + /// + /// RendererMap accesses the object renderer map for this repository. + /// + /// + /// RendererMap accesses the object renderer map for this repository. + /// + /// + /// + /// RendererMap accesses the object renderer map for this repository. + /// + /// + /// The RendererMap holds a mapping between types and + /// objects. + /// + /// + RendererMap RendererMap { get; } - /// - /// The plugin map for this repository. - /// - /// - /// The plugin map for this repository. - /// - /// - /// - /// The plugin map holds the instances - /// that have been attached to this repository. - /// - /// - PluginMap PluginMap { get; } + /// + /// The plugin map for this repository. + /// + /// + /// The plugin map for this repository. + /// + /// + /// + /// The plugin map holds the instances + /// that have been attached to this repository. + /// + /// + PluginMap PluginMap { get; } - /// - /// Get the level map for the Repository. - /// - /// - /// - /// Get the level map for the Repository. - /// - /// - /// The level map defines the mappings between - /// level names and objects in - /// this repository. - /// - /// - LevelMap LevelMap { get; } + /// + /// Get the level map for the Repository. + /// + /// + /// + /// Get the level map for the Repository. + /// + /// + /// The level map defines the mappings between + /// level names and objects in + /// this repository. + /// + /// + LevelMap LevelMap { get; } - /// - /// The threshold for all events in this repository - /// - /// - /// The threshold for all events in this repository - /// - /// - /// - /// The threshold for all events in this repository. - /// - /// - Level Threshold { get; set; } + /// + /// The threshold for all events in this repository + /// + /// + /// The threshold for all events in this repository + /// + /// + /// + /// The threshold for all events in this repository. + /// + /// + Level Threshold { get; set; } - /// - /// Check if the named logger exists in the repository. If so return - /// its reference, otherwise returns null. - /// - /// The name of the logger to lookup - /// The Logger object with the name specified - /// - /// - /// If the names logger exists it is returned, otherwise - /// null is returned. - /// - /// - ILogger Exists(string name); + /// + /// Check if the named logger exists in the repository. If so return + /// its reference, otherwise returns null. + /// + /// The name of the logger to lookup + /// The Logger object with the name specified + /// + /// + /// If the names logger exists it is returned, otherwise + /// null is returned. + /// + /// + ILogger Exists(string name); - /// - /// Returns all the currently defined loggers as an Array. - /// - /// All the defined loggers - /// - /// - /// Returns all the currently defined loggers as an Array. - /// - /// - ILogger[] GetCurrentLoggers(); + /// + /// Returns all the currently defined loggers as an Array. + /// + /// All the defined loggers + /// + /// + /// Returns all the currently defined loggers as an Array. + /// + /// + ILogger[] GetCurrentLoggers(); - /// - /// Returns a named logger instance - /// - /// The name of the logger to retrieve - /// The logger object with the name specified - /// - /// - /// Returns a named logger instance. - /// - /// - /// If a logger of that name already exists, then it will be - /// returned. Otherwise, a new logger will be instantiated and - /// then linked with its existing ancestors as well as children. - /// - /// - ILogger GetLogger(string name); + /// + /// Returns a named logger instance + /// + /// The name of the logger to retrieve + /// The logger object with the name specified + /// + /// + /// Returns a named logger instance. + /// + /// + /// If a logger of that name already exists, then it will be + /// returned. Otherwise, a new logger will be instantiated and + /// then linked with its existing ancestors as well as children. + /// + /// + ILogger GetLogger(string name); - /// Shutdown the repository - /// - /// - /// Shutting down a repository will safely close and remove - /// all appenders in all loggers including the root logger. - /// - /// - /// Some appenders need to be closed before the - /// application exists. Otherwise, pending logging events might be - /// lost. - /// - /// - /// The method is careful to close nested - /// appenders before closing regular appenders. This is allows - /// configurations where a regular appender is attached to a logger - /// and again to a nested appender. - /// - /// - void Shutdown(); + /// Shutdown the repository + /// + /// + /// Shutting down a repository will safely close and remove + /// all appenders in all loggers including the root logger. + /// + /// + /// Some appenders need to be closed before the + /// application exists. Otherwise, pending logging events might be + /// lost. + /// + /// + /// The method is careful to close nested + /// appenders before closing regular appenders. This is allows + /// configurations where a regular appender is attached to a logger + /// and again to a nested appender. + /// + /// + void Shutdown(); - /// - /// Reset the repositories configuration to a default state - /// - /// - /// - /// Reset all values contained in this instance to their - /// default state. - /// - /// - /// Existing loggers are not removed. They are just reset. - /// - /// - /// This method should be used sparingly and with care as it will - /// block all logging until it is completed. - /// - /// - void ResetConfiguration(); + /// + /// Reset the repositories configuration to a default state + /// + /// + /// + /// Reset all values contained in this instance to their + /// default state. + /// + /// + /// Existing loggers are not removed. They are just reset. + /// + /// + /// This method should be used sparingly and with care as it will + /// block all logging until it is completed. + /// + /// + void ResetConfiguration(); - /// - /// Log the through this repository. - /// - /// the event to log - /// - /// - /// This method should not normally be used to log. - /// The interface should be used - /// for routine logging. This interface can be obtained - /// using the method. - /// - /// - /// The logEvent is delivered to the appropriate logger and - /// that logger is then responsible for logging the event. - /// - /// - void Log(LoggingEvent logEvent); + /// + /// Log the through this repository. + /// + /// the event to log + /// + /// + /// This method should not normally be used to log. + /// The interface should be used + /// for routine logging. This interface can be obtained + /// using the method. + /// + /// + /// The logEvent is delivered to the appropriate logger and + /// that logger is then responsible for logging the event. + /// + /// + void Log(LoggingEvent logEvent); - /// - /// Flag indicates if this repository has been configured. - /// - /// - /// Flag indicates if this repository has been configured. - /// - /// - /// - /// Flag indicates if this repository has been configured. - /// - /// - bool Configured { get; set; } + /// + /// Flag indicates if this repository has been configured. + /// + /// + /// Flag indicates if this repository has been configured. + /// + /// + /// + /// Flag indicates if this repository has been configured. + /// + /// + bool Configured { get; set; } /// /// Collection of internal messages captured during the most @@ -282,68 +282,68 @@ public interface ILoggerRepository /// ICollection ConfigurationMessages { get; set; } - /// - /// Event to notify that the repository has been shutdown. - /// - /// - /// Event to notify that the repository has been shutdown. - /// - /// - /// - /// Event raised when the repository has been shutdown. - /// - /// - event LoggerRepositoryShutdownEventHandler ShutdownEvent; + /// + /// Event to notify that the repository has been shutdown. + /// + /// + /// Event to notify that the repository has been shutdown. + /// + /// + /// + /// Event raised when the repository has been shutdown. + /// + /// + event LoggerRepositoryShutdownEventHandler ShutdownEvent; - /// - /// Event to notify that the repository has had its configuration reset. - /// - /// - /// Event to notify that the repository has had its configuration reset. - /// - /// - /// - /// Event raised when the repository's configuration has been - /// reset to default. - /// - /// - event LoggerRepositoryConfigurationResetEventHandler ConfigurationReset; + /// + /// Event to notify that the repository has had its configuration reset. + /// + /// + /// Event to notify that the repository has had its configuration reset. + /// + /// + /// + /// Event raised when the repository's configuration has been + /// reset to default. + /// + /// + event LoggerRepositoryConfigurationResetEventHandler ConfigurationReset; - /// - /// Event to notify that the repository has had its configuration changed. - /// - /// - /// Event to notify that the repository has had its configuration changed. - /// - /// - /// - /// Event raised when the repository's configuration has been changed. - /// - /// - event LoggerRepositoryConfigurationChangedEventHandler ConfigurationChanged; + /// + /// Event to notify that the repository has had its configuration changed. + /// + /// + /// Event to notify that the repository has had its configuration changed. + /// + /// + /// + /// Event raised when the repository's configuration has been changed. + /// + /// + event LoggerRepositoryConfigurationChangedEventHandler ConfigurationChanged; - /// - /// Repository specific properties - /// - /// - /// Repository specific properties - /// - /// - /// - /// These properties can be specified on a repository specific basis. - /// - /// - PropertiesDictionary Properties { get; } + /// + /// Repository specific properties + /// + /// + /// Repository specific properties + /// + /// + /// + /// These properties can be specified on a repository specific basis. + /// + /// + PropertiesDictionary Properties { get; } - /// - /// Returns all the Appenders that are configured as an Array. - /// - /// All the Appenders - /// - /// - /// Returns all the Appenders that are configured as an Array. - /// - /// - log4net.Appender.IAppender[] GetAppenders(); - } + /// + /// Returns all the Appenders that are configured as an Array. + /// + /// All the Appenders + /// + /// + /// Returns all the Appenders that are configured as an Array. + /// + /// + log4net.Appender.IAppender[] GetAppenders(); + } } diff --git a/src/log4net/Repository/IXmlRepositoryConfigurator.cs b/src/log4net/Repository/IXmlRepositoryConfigurator.cs index 6fd657c0..ad16471f 100644 --- a/src/log4net/Repository/IXmlRepositoryConfigurator.cs +++ b/src/log4net/Repository/IXmlRepositoryConfigurator.cs @@ -23,32 +23,32 @@ namespace log4net.Repository { - /// - /// Configure repository using XML - /// - /// - /// - /// Interface used by Xml configurator to configure a . - /// - /// - /// A should implement this interface to support - /// configuration by the . - /// - /// - /// Nicko Cadell - /// Gert Driesen - public interface IXmlRepositoryConfigurator - { - /// - /// Initialize the repository using the specified config - /// - /// the element containing the root of the config - /// - /// - /// The schema for the XML configuration data is defined by - /// the implementation. - /// - /// - void Configure(System.Xml.XmlElement element); - } + /// + /// Configure repository using XML + /// + /// + /// + /// Interface used by Xml configurator to configure a . + /// + /// + /// A should implement this interface to support + /// configuration by the . + /// + /// + /// Nicko Cadell + /// Gert Driesen + public interface IXmlRepositoryConfigurator + { + /// + /// Initialize the repository using the specified config + /// + /// the element containing the root of the config + /// + /// + /// The schema for the XML configuration data is defined by + /// the implementation. + /// + /// + void Configure(System.Xml.XmlElement element); + } } diff --git a/src/log4net/Repository/LoggerRepositorySkeleton.cs b/src/log4net/Repository/LoggerRepositorySkeleton.cs index 9a2a69c1..7a69a247 100644 --- a/src/log4net/Repository/LoggerRepositorySkeleton.cs +++ b/src/log4net/Repository/LoggerRepositorySkeleton.cs @@ -27,553 +27,553 @@ namespace log4net.Repository { - /// - /// Base implementation of - /// - /// - /// - /// Default abstract implementation of the interface. - /// - /// - /// Skeleton implementation of the interface. - /// All types can extend this type. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public abstract class LoggerRepositorySkeleton : ILoggerRepository, Appender.IFlushable - { - #region Member Variables - - private string m_name; - private RendererMap m_rendererMap; - private PluginMap m_pluginMap; - private LevelMap m_levelMap; - private Level m_threshold; - private bool m_configured; + /// + /// Base implementation of + /// + /// + /// + /// Default abstract implementation of the interface. + /// + /// + /// Skeleton implementation of the interface. + /// All types can extend this type. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public abstract class LoggerRepositorySkeleton : ILoggerRepository, Appender.IFlushable + { + #region Member Variables + + private string m_name; + private RendererMap m_rendererMap; + private PluginMap m_pluginMap; + private LevelMap m_levelMap; + private Level m_threshold; + private bool m_configured; private ICollection m_configurationMessages; - private event LoggerRepositoryShutdownEventHandler m_shutdownEvent; - private event LoggerRepositoryConfigurationResetEventHandler m_configurationResetEvent; - private event LoggerRepositoryConfigurationChangedEventHandler m_configurationChangedEvent; - private PropertiesDictionary m_properties; - - #endregion - - #region Constructors - - /// - /// Default Constructor - /// - /// - /// - /// Initializes the repository with default (empty) properties. - /// - /// - protected LoggerRepositorySkeleton() : this(new PropertiesDictionary()) - { - } - - /// - /// Construct the repository using specific properties - /// - /// the properties to set for this repository - /// - /// - /// Initializes the repository with specified properties. - /// - /// - protected LoggerRepositorySkeleton(PropertiesDictionary properties) - { - m_properties = properties; - m_rendererMap = new RendererMap(); - m_pluginMap = new PluginMap(this); - m_levelMap = new LevelMap(); + private event LoggerRepositoryShutdownEventHandler m_shutdownEvent; + private event LoggerRepositoryConfigurationResetEventHandler m_configurationResetEvent; + private event LoggerRepositoryConfigurationChangedEventHandler m_configurationChangedEvent; + private PropertiesDictionary m_properties; + + #endregion + + #region Constructors + + /// + /// Default Constructor + /// + /// + /// + /// Initializes the repository with default (empty) properties. + /// + /// + protected LoggerRepositorySkeleton() : this(new PropertiesDictionary()) + { + } + + /// + /// Construct the repository using specific properties + /// + /// the properties to set for this repository + /// + /// + /// Initializes the repository with specified properties. + /// + /// + protected LoggerRepositorySkeleton(PropertiesDictionary properties) + { + m_properties = properties; + m_rendererMap = new RendererMap(); + m_pluginMap = new PluginMap(this); + m_levelMap = new LevelMap(); m_configurationMessages = EmptyCollection.Instance; - m_configured = false; - - AddBuiltinLevels(); - - // Don't disable any levels by default. - m_threshold = Level.All; - } - - #endregion - - #region Implementation of ILoggerRepository - - /// - /// The name of the repository - /// - /// - /// The string name of the repository - /// - /// - /// - /// The name of this repository. The name is - /// used to store and lookup the repositories - /// stored by the . - /// - /// - public virtual string Name - { - get { return m_name; } - set { m_name = value; } - } - - /// - /// The threshold for all events in this repository - /// - /// - /// The threshold for all events in this repository - /// - /// - /// - /// The threshold for all events in this repository - /// - /// - public virtual Level Threshold - { - get { return m_threshold; } - set - { - if (value != null) - { - m_threshold = value; - } - else - { - // Must not set threshold to null - LogLog.Warn(declaringType, "LoggerRepositorySkeleton: Threshold cannot be set to null. Setting to ALL"); - m_threshold = Level.All; - } - } - } - - /// - /// RendererMap accesses the object renderer map for this repository. - /// - /// - /// RendererMap accesses the object renderer map for this repository. - /// - /// - /// - /// RendererMap accesses the object renderer map for this repository. - /// - /// - /// The RendererMap holds a mapping between types and - /// objects. - /// - /// - public virtual RendererMap RendererMap - { - get { return m_rendererMap; } - } - - /// - /// The plugin map for this repository. - /// - /// - /// The plugin map for this repository. - /// - /// - /// - /// The plugin map holds the instances - /// that have been attached to this repository. - /// - /// - public virtual PluginMap PluginMap - { - get { return m_pluginMap; } - } - - /// - /// Get the level map for the Repository. - /// - /// - /// - /// Get the level map for the Repository. - /// - /// - /// The level map defines the mappings between - /// level names and objects in - /// this repository. - /// - /// - public virtual LevelMap LevelMap - { - get { return m_levelMap; } - } - - /// - /// Test if logger exists - /// - /// The name of the logger to lookup - /// The Logger object with the name specified - /// - /// - /// Check if the named logger exists in the repository. If so return - /// its reference, otherwise returns null. - /// - /// - public abstract ILogger Exists(string name); - - /// - /// Returns all the currently defined loggers in the repository - /// - /// All the defined loggers - /// - /// - /// Returns all the currently defined loggers in the repository as an Array. - /// - /// - public abstract ILogger[] GetCurrentLoggers(); - - /// - /// Return a new logger instance - /// - /// The name of the logger to retrieve - /// The logger object with the name specified - /// - /// - /// Return a new logger instance. - /// - /// - /// If a logger of that name already exists, then it will be - /// returned. Otherwise, a new logger will be instantiated and - /// then linked with its existing ancestors as well as children. - /// - /// - public abstract ILogger GetLogger(string name); - - /// - /// Shutdown the repository - /// - /// - /// - /// Shutdown the repository. Can be overridden in a subclass. - /// This base class implementation notifies the - /// listeners and all attached plugins of the shutdown event. - /// - /// - public virtual void Shutdown() - { - // Shutdown attached plugins - foreach(IPlugin plugin in PluginMap.AllPlugins) - { - plugin.Shutdown(); - } - - // Notify listeners - OnShutdown(null); - } - - /// - /// Reset the repositories configuration to a default state - /// - /// - /// - /// Reset all values contained in this instance to their - /// default state. - /// - /// - /// Existing loggers are not removed. They are just reset. - /// - /// - /// This method should be used sparingly and with care as it will - /// block all logging until it is completed. - /// - /// - public virtual void ResetConfiguration() - { - // Clear internal data structures - m_rendererMap.Clear(); - m_levelMap.Clear(); + m_configured = false; + + AddBuiltinLevels(); + + // Don't disable any levels by default. + m_threshold = Level.All; + } + + #endregion + + #region Implementation of ILoggerRepository + + /// + /// The name of the repository + /// + /// + /// The string name of the repository + /// + /// + /// + /// The name of this repository. The name is + /// used to store and lookup the repositories + /// stored by the . + /// + /// + public virtual string Name + { + get { return m_name; } + set { m_name = value; } + } + + /// + /// The threshold for all events in this repository + /// + /// + /// The threshold for all events in this repository + /// + /// + /// + /// The threshold for all events in this repository + /// + /// + public virtual Level Threshold + { + get { return m_threshold; } + set + { + if (value != null) + { + m_threshold = value; + } + else + { + // Must not set threshold to null + LogLog.Warn(declaringType, "LoggerRepositorySkeleton: Threshold cannot be set to null. Setting to ALL"); + m_threshold = Level.All; + } + } + } + + /// + /// RendererMap accesses the object renderer map for this repository. + /// + /// + /// RendererMap accesses the object renderer map for this repository. + /// + /// + /// + /// RendererMap accesses the object renderer map for this repository. + /// + /// + /// The RendererMap holds a mapping between types and + /// objects. + /// + /// + public virtual RendererMap RendererMap + { + get { return m_rendererMap; } + } + + /// + /// The plugin map for this repository. + /// + /// + /// The plugin map for this repository. + /// + /// + /// + /// The plugin map holds the instances + /// that have been attached to this repository. + /// + /// + public virtual PluginMap PluginMap + { + get { return m_pluginMap; } + } + + /// + /// Get the level map for the Repository. + /// + /// + /// + /// Get the level map for the Repository. + /// + /// + /// The level map defines the mappings between + /// level names and objects in + /// this repository. + /// + /// + public virtual LevelMap LevelMap + { + get { return m_levelMap; } + } + + /// + /// Test if logger exists + /// + /// The name of the logger to lookup + /// The Logger object with the name specified + /// + /// + /// Check if the named logger exists in the repository. If so return + /// its reference, otherwise returns null. + /// + /// + public abstract ILogger Exists(string name); + + /// + /// Returns all the currently defined loggers in the repository + /// + /// All the defined loggers + /// + /// + /// Returns all the currently defined loggers in the repository as an Array. + /// + /// + public abstract ILogger[] GetCurrentLoggers(); + + /// + /// Return a new logger instance + /// + /// The name of the logger to retrieve + /// The logger object with the name specified + /// + /// + /// Return a new logger instance. + /// + /// + /// If a logger of that name already exists, then it will be + /// returned. Otherwise, a new logger will be instantiated and + /// then linked with its existing ancestors as well as children. + /// + /// + public abstract ILogger GetLogger(string name); + + /// + /// Shutdown the repository + /// + /// + /// + /// Shutdown the repository. Can be overridden in a subclass. + /// This base class implementation notifies the + /// listeners and all attached plugins of the shutdown event. + /// + /// + public virtual void Shutdown() + { + // Shutdown attached plugins + foreach(IPlugin plugin in PluginMap.AllPlugins) + { + plugin.Shutdown(); + } + + // Notify listeners + OnShutdown(null); + } + + /// + /// Reset the repositories configuration to a default state + /// + /// + /// + /// Reset all values contained in this instance to their + /// default state. + /// + /// + /// Existing loggers are not removed. They are just reset. + /// + /// + /// This method should be used sparingly and with care as it will + /// block all logging until it is completed. + /// + /// + public virtual void ResetConfiguration() + { + // Clear internal data structures + m_rendererMap.Clear(); + m_levelMap.Clear(); m_configurationMessages = EmptyCollection.Instance; - // Add the predefined levels to the map - AddBuiltinLevels(); - - Configured = false; - - // Notify listeners - OnConfigurationReset(null); - } - - /// - /// Log the logEvent through this repository. - /// - /// the event to log - /// - /// - /// This method should not normally be used to log. - /// The interface should be used - /// for routine logging. This interface can be obtained - /// using the method. - /// - /// - /// The logEvent is delivered to the appropriate logger and - /// that logger is then responsible for logging the event. - /// - /// - public abstract void Log(LoggingEvent logEvent); - - /// - /// Flag indicates if this repository has been configured. - /// - /// - /// Flag indicates if this repository has been configured. - /// - /// - /// - /// Flag indicates if this repository has been configured. - /// - /// - public virtual bool Configured - { - get { return m_configured; } - set { m_configured = value; } - } + // Add the predefined levels to the map + AddBuiltinLevels(); + + Configured = false; + + // Notify listeners + OnConfigurationReset(null); + } + + /// + /// Log the logEvent through this repository. + /// + /// the event to log + /// + /// + /// This method should not normally be used to log. + /// The interface should be used + /// for routine logging. This interface can be obtained + /// using the method. + /// + /// + /// The logEvent is delivered to the appropriate logger and + /// that logger is then responsible for logging the event. + /// + /// + public abstract void Log(LoggingEvent logEvent); + + /// + /// Flag indicates if this repository has been configured. + /// + /// + /// Flag indicates if this repository has been configured. + /// + /// + /// + /// Flag indicates if this repository has been configured. + /// + /// + public virtual bool Configured + { + get { return m_configured; } + set { m_configured = value; } + } /// /// Contains a list of internal messages captures during the /// last configuration. /// - public virtual ICollection ConfigurationMessages - { + public virtual ICollection ConfigurationMessages + { get { return m_configurationMessages; } set { m_configurationMessages = value; } - } - - /// - /// Event to notify that the repository has been shutdown. - /// - /// - /// Event to notify that the repository has been shutdown. - /// - /// - /// - /// Event raised when the repository has been shutdown. - /// - /// - public event LoggerRepositoryShutdownEventHandler ShutdownEvent - { - add { m_shutdownEvent += value; } - remove { m_shutdownEvent -= value; } - } - - /// - /// Event to notify that the repository has had its configuration reset. - /// - /// - /// Event to notify that the repository has had its configuration reset. - /// - /// - /// - /// Event raised when the repository's configuration has been - /// reset to default. - /// - /// - public event LoggerRepositoryConfigurationResetEventHandler ConfigurationReset - { - add { m_configurationResetEvent += value; } - remove { m_configurationResetEvent -= value; } - } - - /// - /// Event to notify that the repository has had its configuration changed. - /// - /// - /// Event to notify that the repository has had its configuration changed. - /// - /// - /// - /// Event raised when the repository's configuration has been changed. - /// - /// - public event LoggerRepositoryConfigurationChangedEventHandler ConfigurationChanged - { - add { m_configurationChangedEvent += value; } - remove { m_configurationChangedEvent -= value; } - } - - /// - /// Repository specific properties - /// - /// - /// Repository specific properties - /// - /// - /// These properties can be specified on a repository specific basis - /// - public PropertiesDictionary Properties - { - get { return m_properties; } - } - - /// - /// Returns all the Appenders that are configured as an Array. - /// - /// All the Appenders - /// - /// - /// Returns all the Appenders that are configured as an Array. - /// - /// - public abstract log4net.Appender.IAppender[] GetAppenders(); - - #endregion - - #region Private Static Fields - - /// - /// The fully qualified type of the LoggerRepositorySkeleton class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(LoggerRepositorySkeleton); - - #endregion Private Static Fields - - private void AddBuiltinLevels() - { - // Add the predefined levels to the map - m_levelMap.Add(Level.Off); - - // Unrecoverable errors - m_levelMap.Add(Level.Emergency); - m_levelMap.Add(Level.Fatal); - m_levelMap.Add(Level.Alert); - - // Recoverable errors - m_levelMap.Add(Level.Critical); - m_levelMap.Add(Level.Severe); - m_levelMap.Add(Level.Error); - m_levelMap.Add(Level.Warn); - - // Information - m_levelMap.Add(Level.Notice); - m_levelMap.Add(Level.Info); - - // Debug - m_levelMap.Add(Level.Debug); - m_levelMap.Add(Level.Fine); - m_levelMap.Add(Level.Trace); - m_levelMap.Add(Level.Finer); - m_levelMap.Add(Level.Verbose); - m_levelMap.Add(Level.Finest); - - m_levelMap.Add(Level.All); - } - - /// - /// Adds an object renderer for a specific class. - /// - /// The type that will be rendered by the renderer supplied. - /// The object renderer used to render the object. - /// - /// - /// Adds an object renderer for a specific class. - /// - /// - public virtual void AddRenderer(Type typeToRender, IObjectRenderer rendererInstance) - { - if (typeToRender == null) - { - throw new ArgumentNullException("typeToRender"); - } - if (rendererInstance == null) - { - throw new ArgumentNullException("rendererInstance"); - } - - m_rendererMap.Put(typeToRender, rendererInstance); - } - - /// - /// Notify the registered listeners that the repository is shutting down - /// - /// Empty EventArgs - /// - /// - /// Notify any listeners that this repository is shutting down. - /// - /// - protected virtual void OnShutdown(EventArgs e) - { - if (e == null) - { - e = EventArgs.Empty; - } - - LoggerRepositoryShutdownEventHandler handler = m_shutdownEvent; - if (handler != null) - { - handler(this, e); - } - } - - /// - /// Notify the registered listeners that the repository has had its configuration reset - /// - /// Empty EventArgs - /// - /// - /// Notify any listeners that this repository's configuration has been reset. - /// - /// - protected virtual void OnConfigurationReset(EventArgs e) - { - if (e == null) - { - e = EventArgs.Empty; - } - - LoggerRepositoryConfigurationResetEventHandler handler = m_configurationResetEvent; - if (handler != null) - { - handler(this, e); - } - } - - /// - /// Notify the registered listeners that the repository has had its configuration changed - /// - /// Empty EventArgs - /// - /// - /// Notify any listeners that this repository's configuration has changed. - /// - /// - protected virtual void OnConfigurationChanged(EventArgs e) - { - if (e == null) - { - e = EventArgs.Empty; - } - - LoggerRepositoryConfigurationChangedEventHandler handler = m_configurationChangedEvent; - if (handler != null) - { - handler(this, e); - } - } - - /// - /// Raise a configuration changed event on this repository - /// - /// EventArgs.Empty - /// - /// - /// Applications that programmatically change the configuration of the repository should - /// raise this event notification to notify listeners. - /// - /// - public void RaiseConfigurationChanged(EventArgs e) - { - OnConfigurationChanged(e); - } + } + + /// + /// Event to notify that the repository has been shutdown. + /// + /// + /// Event to notify that the repository has been shutdown. + /// + /// + /// + /// Event raised when the repository has been shutdown. + /// + /// + public event LoggerRepositoryShutdownEventHandler ShutdownEvent + { + add { m_shutdownEvent += value; } + remove { m_shutdownEvent -= value; } + } + + /// + /// Event to notify that the repository has had its configuration reset. + /// + /// + /// Event to notify that the repository has had its configuration reset. + /// + /// + /// + /// Event raised when the repository's configuration has been + /// reset to default. + /// + /// + public event LoggerRepositoryConfigurationResetEventHandler ConfigurationReset + { + add { m_configurationResetEvent += value; } + remove { m_configurationResetEvent -= value; } + } + + /// + /// Event to notify that the repository has had its configuration changed. + /// + /// + /// Event to notify that the repository has had its configuration changed. + /// + /// + /// + /// Event raised when the repository's configuration has been changed. + /// + /// + public event LoggerRepositoryConfigurationChangedEventHandler ConfigurationChanged + { + add { m_configurationChangedEvent += value; } + remove { m_configurationChangedEvent -= value; } + } + + /// + /// Repository specific properties + /// + /// + /// Repository specific properties + /// + /// + /// These properties can be specified on a repository specific basis + /// + public PropertiesDictionary Properties + { + get { return m_properties; } + } + + /// + /// Returns all the Appenders that are configured as an Array. + /// + /// All the Appenders + /// + /// + /// Returns all the Appenders that are configured as an Array. + /// + /// + public abstract log4net.Appender.IAppender[] GetAppenders(); + + #endregion + + #region Private Static Fields + + /// + /// The fully qualified type of the LoggerRepositorySkeleton class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(LoggerRepositorySkeleton); + + #endregion Private Static Fields + + private void AddBuiltinLevels() + { + // Add the predefined levels to the map + m_levelMap.Add(Level.Off); + + // Unrecoverable errors + m_levelMap.Add(Level.Emergency); + m_levelMap.Add(Level.Fatal); + m_levelMap.Add(Level.Alert); + + // Recoverable errors + m_levelMap.Add(Level.Critical); + m_levelMap.Add(Level.Severe); + m_levelMap.Add(Level.Error); + m_levelMap.Add(Level.Warn); + + // Information + m_levelMap.Add(Level.Notice); + m_levelMap.Add(Level.Info); + + // Debug + m_levelMap.Add(Level.Debug); + m_levelMap.Add(Level.Fine); + m_levelMap.Add(Level.Trace); + m_levelMap.Add(Level.Finer); + m_levelMap.Add(Level.Verbose); + m_levelMap.Add(Level.Finest); + + m_levelMap.Add(Level.All); + } + + /// + /// Adds an object renderer for a specific class. + /// + /// The type that will be rendered by the renderer supplied. + /// The object renderer used to render the object. + /// + /// + /// Adds an object renderer for a specific class. + /// + /// + public virtual void AddRenderer(Type typeToRender, IObjectRenderer rendererInstance) + { + if (typeToRender == null) + { + throw new ArgumentNullException("typeToRender"); + } + if (rendererInstance == null) + { + throw new ArgumentNullException("rendererInstance"); + } + + m_rendererMap.Put(typeToRender, rendererInstance); + } + + /// + /// Notify the registered listeners that the repository is shutting down + /// + /// Empty EventArgs + /// + /// + /// Notify any listeners that this repository is shutting down. + /// + /// + protected virtual void OnShutdown(EventArgs e) + { + if (e == null) + { + e = EventArgs.Empty; + } + + LoggerRepositoryShutdownEventHandler handler = m_shutdownEvent; + if (handler != null) + { + handler(this, e); + } + } + + /// + /// Notify the registered listeners that the repository has had its configuration reset + /// + /// Empty EventArgs + /// + /// + /// Notify any listeners that this repository's configuration has been reset. + /// + /// + protected virtual void OnConfigurationReset(EventArgs e) + { + if (e == null) + { + e = EventArgs.Empty; + } + + LoggerRepositoryConfigurationResetEventHandler handler = m_configurationResetEvent; + if (handler != null) + { + handler(this, e); + } + } + + /// + /// Notify the registered listeners that the repository has had its configuration changed + /// + /// Empty EventArgs + /// + /// + /// Notify any listeners that this repository's configuration has changed. + /// + /// + protected virtual void OnConfigurationChanged(EventArgs e) + { + if (e == null) + { + e = EventArgs.Empty; + } + + LoggerRepositoryConfigurationChangedEventHandler handler = m_configurationChangedEvent; + if (handler != null) + { + handler(this, e); + } + } + + /// + /// Raise a configuration changed event on this repository + /// + /// EventArgs.Empty + /// + /// + /// Applications that programmatically change the configuration of the repository should + /// raise this event notification to notify listeners. + /// + /// + public void RaiseConfigurationChanged(EventArgs e) + { + OnConfigurationChanged(e); + } private static int GetWaitTime(DateTime startTimeUtc, int millisecondsTimeout) { @@ -628,5 +628,5 @@ public bool Flush(int millisecondsTimeout) return result; } - } + } } diff --git a/src/log4net/ThreadContext.cs b/src/log4net/ThreadContext.cs index 4da972ca..e84dba53 100644 --- a/src/log4net/ThreadContext.cs +++ b/src/log4net/ThreadContext.cs @@ -24,116 +24,116 @@ namespace log4net { - /// - /// The log4net Thread Context. - /// - /// - /// - /// The ThreadContext provides a location for thread specific debugging - /// information to be stored. - /// The ThreadContext properties override any - /// properties with the same name. - /// - /// - /// The thread context has a properties map and a stack. - /// The properties and stack can - /// be included in the output of log messages. The - /// supports selecting and outputting these properties. - /// - /// - /// 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. - /// - /// - /// The Thread Context is managed on a per thread basis. - /// - /// - /// Example of using the thread context properties to store a username. - /// - /// ThreadContext.Properties["user"] = userName; - /// log.Info("This log message has a ThreadContext Property called 'user'"); - /// - /// - /// Example of how to push a message into the context stack - /// - /// using(ThreadContext.Stacks["NDC"].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 - /// - /// - /// - /// Nicko Cadell - public sealed class ThreadContext - { - #region Private Instance Constructors + /// + /// The log4net Thread Context. + /// + /// + /// + /// The ThreadContext provides a location for thread specific debugging + /// information to be stored. + /// The ThreadContext properties override any + /// properties with the same name. + /// + /// + /// The thread context has a properties map and a stack. + /// The properties and stack can + /// be included in the output of log messages. The + /// supports selecting and outputting these properties. + /// + /// + /// 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. + /// + /// + /// The Thread Context is managed on a per thread basis. + /// + /// + /// Example of using the thread context properties to store a username. + /// + /// ThreadContext.Properties["user"] = userName; + /// log.Info("This log message has a ThreadContext Property called 'user'"); + /// + /// + /// Example of how to push a message into the context stack + /// + /// using(ThreadContext.Stacks["NDC"].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 + /// + /// + /// + /// Nicko Cadell + public sealed class ThreadContext + { + #region Private Instance Constructors - /// - /// Private Constructor. - /// - /// - /// - /// Uses a private access modifier to prevent instantiation of this class. - /// - /// - private ThreadContext() - { - } + /// + /// Private Constructor. + /// + /// + /// + /// Uses a private access modifier to prevent instantiation of this class. + /// + /// + private ThreadContext() + { + } - #endregion Private Instance Constructors + #endregion Private Instance Constructors - #region Public Static Properties + #region Public Static Properties - /// - /// The thread properties map - /// - /// - /// The thread properties map - /// - /// - /// - /// The ThreadContext properties override any - /// properties with the same name. - /// - /// - public static ThreadContextProperties Properties - { - get { return s_properties; } - } + /// + /// The thread properties map + /// + /// + /// The thread properties map + /// + /// + /// + /// The ThreadContext properties override any + /// properties with the same name. + /// + /// + public static ThreadContextProperties Properties + { + get { return s_properties; } + } - /// - /// The thread stacks - /// - /// - /// stack map - /// - /// - /// - /// The thread local stacks. - /// - /// - public static ThreadContextStacks Stacks - { - get { return s_stacks; } - } + /// + /// The thread stacks + /// + /// + /// stack map + /// + /// + /// + /// The thread local stacks. + /// + /// + public static ThreadContextStacks Stacks + { + get { return s_stacks; } + } - #endregion Public Static Properties + #endregion Public Static Properties - #region Private Static Fields + #region Private Static Fields - /// - /// The thread context properties instance - /// - private static readonly ThreadContextProperties s_properties = new ThreadContextProperties(); + /// + /// The thread context properties instance + /// + private static readonly ThreadContextProperties s_properties = new ThreadContextProperties(); - /// - /// The thread context stacks instance - /// - private static readonly ThreadContextStacks s_stacks = new ThreadContextStacks(s_properties); + /// + /// The thread context stacks instance + /// + private static readonly ThreadContextStacks s_stacks = new ThreadContextStacks(s_properties); - #endregion Private Static Fields - } + #endregion Private Static Fields + } } diff --git a/src/log4net/Util/AppenderAttachedImpl.cs b/src/log4net/Util/AppenderAttachedImpl.cs index 35080487..b6fc0fd7 100644 --- a/src/log4net/Util/AppenderAttachedImpl.cs +++ b/src/log4net/Util/AppenderAttachedImpl.cs @@ -24,165 +24,165 @@ namespace log4net.Util { - /// - /// A straightforward implementation of the interface. - /// - /// - /// - /// This is the default implementation of the - /// interface. Implementors of the interface - /// should aggregate an instance of this type. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public class AppenderAttachedImpl : IAppenderAttachable - { - #region Public Instance Constructors - - /// - /// Constructor - /// - /// - /// - /// Initializes a new instance of the class. - /// - /// - public AppenderAttachedImpl() - { - } - - #endregion Public Instance Constructors - - #region Public Instance Methods - - /// - /// Append on on all attached appenders. - /// - /// The event being logged. - /// The number of appenders called. - /// - /// - /// Calls the method on all - /// attached appenders. - /// - /// - public int AppendLoopOnAppenders(LoggingEvent loggingEvent) - { - if (loggingEvent == null) - { - throw new ArgumentNullException("loggingEvent"); - } - - // m_appenderList is null when empty - if (m_appenderList == null) - { - return 0; - } - - if (m_appenderArray == null) - { - m_appenderArray = m_appenderList.ToArray(); - } - - foreach(IAppender appender in m_appenderArray) - { - try - { - appender.DoAppend(loggingEvent); - } - catch(Exception ex) - { - LogLog.Error(declaringType, "Failed to append to appender [" + appender.Name + "]", ex); - } - } - return m_appenderList.Count; - } - - /// - /// Append on on all attached appenders. - /// - /// The array of events being logged. - /// The number of appenders called. - /// - /// - /// Calls the method on all - /// attached appenders. - /// - /// - public int AppendLoopOnAppenders(LoggingEvent[] loggingEvents) - { - if (loggingEvents == null) - { - throw new ArgumentNullException("loggingEvents"); - } - if (loggingEvents.Length == 0) - { - throw new ArgumentException("loggingEvents array must not be empty", "loggingEvents"); - } - if (loggingEvents.Length == 1) - { - // Fall back to single event path - return AppendLoopOnAppenders(loggingEvents[0]); - } - - // m_appenderList is null when empty - if (m_appenderList == null) - { - return 0; - } - - if (m_appenderArray == null) - { - m_appenderArray = m_appenderList.ToArray(); - } - - foreach(IAppender appender in m_appenderArray) - { - try - { - CallAppend(appender, loggingEvents); - } - catch(Exception ex) - { - LogLog.Error(declaringType, "Failed to append to appender [" + appender.Name + "]", ex); - } - } - return m_appenderList.Count; - } - - #endregion Public Instance Methods + /// + /// A straightforward implementation of the interface. + /// + /// + /// + /// This is the default implementation of the + /// interface. Implementors of the interface + /// should aggregate an instance of this type. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public class AppenderAttachedImpl : IAppenderAttachable + { + #region Public Instance Constructors + + /// + /// Constructor + /// + /// + /// + /// Initializes a new instance of the class. + /// + /// + public AppenderAttachedImpl() + { + } + + #endregion Public Instance Constructors + + #region Public Instance Methods + + /// + /// Append on on all attached appenders. + /// + /// The event being logged. + /// The number of appenders called. + /// + /// + /// Calls the method on all + /// attached appenders. + /// + /// + public int AppendLoopOnAppenders(LoggingEvent loggingEvent) + { + if (loggingEvent == null) + { + throw new ArgumentNullException("loggingEvent"); + } + + // m_appenderList is null when empty + if (m_appenderList == null) + { + return 0; + } + + if (m_appenderArray == null) + { + m_appenderArray = m_appenderList.ToArray(); + } + + foreach(IAppender appender in m_appenderArray) + { + try + { + appender.DoAppend(loggingEvent); + } + catch(Exception ex) + { + LogLog.Error(declaringType, "Failed to append to appender [" + appender.Name + "]", ex); + } + } + return m_appenderList.Count; + } + + /// + /// Append on on all attached appenders. + /// + /// The array of events being logged. + /// The number of appenders called. + /// + /// + /// Calls the method on all + /// attached appenders. + /// + /// + public int AppendLoopOnAppenders(LoggingEvent[] loggingEvents) + { + if (loggingEvents == null) + { + throw new ArgumentNullException("loggingEvents"); + } + if (loggingEvents.Length == 0) + { + throw new ArgumentException("loggingEvents array must not be empty", "loggingEvents"); + } + if (loggingEvents.Length == 1) + { + // Fall back to single event path + return AppendLoopOnAppenders(loggingEvents[0]); + } + + // m_appenderList is null when empty + if (m_appenderList == null) + { + return 0; + } + + if (m_appenderArray == null) + { + m_appenderArray = m_appenderList.ToArray(); + } + + foreach(IAppender appender in m_appenderArray) + { + try + { + CallAppend(appender, loggingEvents); + } + catch(Exception ex) + { + LogLog.Error(declaringType, "Failed to append to appender [" + appender.Name + "]", ex); + } + } + return m_appenderList.Count; + } + + #endregion Public Instance Methods #region Private Static Methods /// - /// Calls the DoAppende method on the with - /// the objects supplied. - /// - /// The appender - /// The events - /// - /// - /// If the supports the - /// interface then the will be passed - /// through using that interface. Otherwise the - /// objects in the array will be passed one at a time. - /// - /// - private static void CallAppend(IAppender appender, LoggingEvent[] loggingEvents) - { - IBulkAppender bulkAppender = appender as IBulkAppender; - if (bulkAppender != null) - { - bulkAppender.DoAppend(loggingEvents); - } - else - { - foreach(LoggingEvent loggingEvent in loggingEvents) - { - appender.DoAppend(loggingEvent); - } - } + /// Calls the DoAppende method on the with + /// the objects supplied. + /// + /// The appender + /// The events + /// + /// + /// If the supports the + /// interface then the will be passed + /// through using that interface. Otherwise the + /// objects in the array will be passed one at a time. + /// + /// + private static void CallAppend(IAppender appender, LoggingEvent[] loggingEvents) + { + IBulkAppender bulkAppender = appender as IBulkAppender; + if (bulkAppender != null) + { + bulkAppender.DoAppend(loggingEvents); + } + else + { + foreach(LoggingEvent loggingEvent in loggingEvents) + { + appender.DoAppend(loggingEvent); + } + } } #endregion @@ -190,187 +190,187 @@ private static void CallAppend(IAppender appender, LoggingEvent[] loggingEvents) #region Implementation of IAppenderAttachable /// - /// Attaches an appender. - /// - /// The appender to add. - /// - /// - /// If the appender is already in the list it won't be added again. - /// - /// - public void AddAppender(IAppender newAppender) - { - // Null values for newAppender parameter are strictly forbidden. - if (newAppender == null) - { - throw new ArgumentNullException("newAppender"); - } - - m_appenderArray = null; - if (m_appenderList == null) - { - m_appenderList = new AppenderCollection(1); - } - if (!m_appenderList.Contains(newAppender)) - { - m_appenderList.Add(newAppender); - } - } - - /// - /// Gets all attached appenders. - /// - /// - /// A collection of attached appenders, or null if there - /// are no attached appenders. - /// - /// - /// - /// The read only collection of all currently attached appenders. - /// - /// - public AppenderCollection Appenders - { - get - { - if (m_appenderList == null) - { - // We must always return a valid collection - return AppenderCollection.EmptyCollection; - } - else - { - return AppenderCollection.ReadOnly(m_appenderList); - } - } - } - - /// - /// Gets an attached appender with the specified name. - /// - /// The name of the appender to get. - /// - /// The appender with the name specified, or null if no appender with the - /// specified name is found. - /// - /// - /// - /// Lookup an attached appender by name. - /// - /// - public IAppender GetAppender(string name) - { - if (m_appenderList != null && name != null) - { - foreach(IAppender appender in m_appenderList) - { - if (name == appender.Name) - { - return appender; - } - } - } - return null; - } - - /// - /// Removes all attached appenders. - /// - /// - /// - /// Removes and closes all attached appenders - /// - /// - public void RemoveAllAppenders() - { - if (m_appenderList != null) - { - foreach(IAppender appender in m_appenderList) - { - try - { - appender.Close(); - } - catch(Exception ex) - { - LogLog.Error(declaringType, "Failed to Close appender ["+appender.Name+"]", ex); - } - } - m_appenderList = null; - m_appenderArray = null; - } - } - - /// - /// Removes the specified appender from the list of attached appenders. - /// - /// The appender to remove. - /// The appender removed from the list - /// - /// - /// The appender removed is not closed. - /// If you are discarding the appender you must call - /// on the appender removed. - /// - /// - public IAppender RemoveAppender(IAppender appender) - { - if (appender != null && m_appenderList != null) - { - m_appenderList.Remove(appender); - if (m_appenderList.Count == 0) - { - m_appenderList = null; - } - m_appenderArray = null; - } - return appender; - } - - /// - /// Removes the appender with the specified name from the list of appenders. - /// - /// The name of the appender to remove. - /// The appender removed from the list - /// - /// - /// The appender removed is not closed. - /// If you are discarding the appender you must call - /// on the appender removed. - /// - /// - public IAppender RemoveAppender(string name) - { - return RemoveAppender(GetAppender(name)); - } - - #endregion - - #region Private Instance Fields - - /// - /// List of appenders - /// - private AppenderCollection m_appenderList; - - /// - /// Array of appenders, used to cache the m_appenderList - /// - private IAppender[] m_appenderArray; - - #endregion Private Instance Fields - - #region Private Static Fields - - /// - /// The fully qualified type of the AppenderAttachedImpl class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(AppenderAttachedImpl); - - #endregion Private Static Fields - } + /// Attaches an appender. + /// + /// The appender to add. + /// + /// + /// If the appender is already in the list it won't be added again. + /// + /// + public void AddAppender(IAppender newAppender) + { + // Null values for newAppender parameter are strictly forbidden. + if (newAppender == null) + { + throw new ArgumentNullException("newAppender"); + } + + m_appenderArray = null; + if (m_appenderList == null) + { + m_appenderList = new AppenderCollection(1); + } + if (!m_appenderList.Contains(newAppender)) + { + m_appenderList.Add(newAppender); + } + } + + /// + /// Gets all attached appenders. + /// + /// + /// A collection of attached appenders, or null if there + /// are no attached appenders. + /// + /// + /// + /// The read only collection of all currently attached appenders. + /// + /// + public AppenderCollection Appenders + { + get + { + if (m_appenderList == null) + { + // We must always return a valid collection + return AppenderCollection.EmptyCollection; + } + else + { + return AppenderCollection.ReadOnly(m_appenderList); + } + } + } + + /// + /// Gets an attached appender with the specified name. + /// + /// The name of the appender to get. + /// + /// The appender with the name specified, or null if no appender with the + /// specified name is found. + /// + /// + /// + /// Lookup an attached appender by name. + /// + /// + public IAppender GetAppender(string name) + { + if (m_appenderList != null && name != null) + { + foreach(IAppender appender in m_appenderList) + { + if (name == appender.Name) + { + return appender; + } + } + } + return null; + } + + /// + /// Removes all attached appenders. + /// + /// + /// + /// Removes and closes all attached appenders + /// + /// + public void RemoveAllAppenders() + { + if (m_appenderList != null) + { + foreach(IAppender appender in m_appenderList) + { + try + { + appender.Close(); + } + catch(Exception ex) + { + LogLog.Error(declaringType, "Failed to Close appender ["+appender.Name+"]", ex); + } + } + m_appenderList = null; + m_appenderArray = null; + } + } + + /// + /// Removes the specified appender from the list of attached appenders. + /// + /// The appender to remove. + /// The appender removed from the list + /// + /// + /// The appender removed is not closed. + /// If you are discarding the appender you must call + /// on the appender removed. + /// + /// + public IAppender RemoveAppender(IAppender appender) + { + if (appender != null && m_appenderList != null) + { + m_appenderList.Remove(appender); + if (m_appenderList.Count == 0) + { + m_appenderList = null; + } + m_appenderArray = null; + } + return appender; + } + + /// + /// Removes the appender with the specified name from the list of appenders. + /// + /// The name of the appender to remove. + /// The appender removed from the list + /// + /// + /// The appender removed is not closed. + /// If you are discarding the appender you must call + /// on the appender removed. + /// + /// + public IAppender RemoveAppender(string name) + { + return RemoveAppender(GetAppender(name)); + } + + #endregion + + #region Private Instance Fields + + /// + /// List of appenders + /// + private AppenderCollection m_appenderList; + + /// + /// Array of appenders, used to cache the m_appenderList + /// + private IAppender[] m_appenderArray; + + #endregion Private Instance Fields + + #region Private Static Fields + + /// + /// The fully qualified type of the AppenderAttachedImpl class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(AppenderAttachedImpl); + + #endregion Private Static Fields + } } diff --git a/src/log4net/Util/CompositeProperties.cs b/src/log4net/Util/CompositeProperties.cs index b4911970..987661c6 100644 --- a/src/log4net/Util/CompositeProperties.cs +++ b/src/log4net/Util/CompositeProperties.cs @@ -22,134 +22,134 @@ namespace log4net.Util { - /// - /// This class aggregates several PropertiesDictionary collections together. - /// - /// - /// - /// Provides a dictionary style lookup over an ordered list of - /// collections. - /// - /// - /// Nicko Cadell - 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 - - /// - /// Constructor - /// - /// - /// - /// Initializes a new instance of the class. - /// - /// - internal CompositeProperties() - { - } - - #endregion Public Instance Constructors - - #region Public Instance Properties - - /// - /// Gets the value of a property - /// - /// - /// The value for the property with the specified key - /// - /// - /// - /// Looks up the value for the specified. - /// The collections are searched - /// in the order in which they were added to this collection. The value - /// returned is the value held by the first collection that contains - /// the specified key. - /// - /// - /// If none of the collections contain the specified key then - /// null is returned. - /// - /// - 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 - - /// - /// Add a Properties Dictionary to this composite collection - /// - /// the properties to add - /// - /// - /// Properties dictionaries added first take precedence over dictionaries added - /// later. - /// - /// - public void Add(ReadOnlyPropertiesDictionary properties) - { - m_flattened = null; - m_nestedProperties.Add(properties); - } - - /// - /// Flatten this composite collection into a single properties dictionary - /// - /// the flattened dictionary - /// - /// - /// Reduces the collection of ordered dictionaries to a single dictionary - /// containing the resultant values for the keys. - /// - /// - 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 - } + /// + /// This class aggregates several PropertiesDictionary collections together. + /// + /// + /// + /// Provides a dictionary style lookup over an ordered list of + /// collections. + /// + /// + /// Nicko Cadell + 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 + + /// + /// Constructor + /// + /// + /// + /// Initializes a new instance of the class. + /// + /// + internal CompositeProperties() + { + } + + #endregion Public Instance Constructors + + #region Public Instance Properties + + /// + /// Gets the value of a property + /// + /// + /// The value for the property with the specified key + /// + /// + /// + /// Looks up the value for the specified. + /// The collections are searched + /// in the order in which they were added to this collection. The value + /// returned is the value held by the first collection that contains + /// the specified key. + /// + /// + /// If none of the collections contain the specified key then + /// null is returned. + /// + /// + 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 + + /// + /// Add a Properties Dictionary to this composite collection + /// + /// the properties to add + /// + /// + /// Properties dictionaries added first take precedence over dictionaries added + /// later. + /// + /// + public void Add(ReadOnlyPropertiesDictionary properties) + { + m_flattened = null; + m_nestedProperties.Add(properties); + } + + /// + /// Flatten this composite collection into a single properties dictionary + /// + /// the flattened dictionary + /// + /// + /// Reduces the collection of ordered dictionaries to a single dictionary + /// containing the resultant values for the keys. + /// + /// + 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 + } } diff --git a/src/log4net/Util/ContextPropertiesBase.cs b/src/log4net/Util/ContextPropertiesBase.cs index 9d79fee2..47274615 100644 --- a/src/log4net/Util/ContextPropertiesBase.cs +++ b/src/log4net/Util/ContextPropertiesBase.cs @@ -22,29 +22,29 @@ namespace log4net.Util { - /// - /// Base class for Context Properties implementations - /// - /// - /// - /// This class defines a basic property get set accessor - /// - /// - /// Nicko Cadell - public abstract class ContextPropertiesBase - { - /// - /// Gets or sets the value of a property - /// - /// - /// The value for the property with the specified key - /// - /// - /// - /// Gets or sets the value of a property - /// - /// - public abstract object this[string key] { get; set; } - } + /// + /// Base class for Context Properties implementations + /// + /// + /// + /// This class defines a basic property get set accessor + /// + /// + /// Nicko Cadell + public abstract class ContextPropertiesBase + { + /// + /// Gets or sets the value of a property + /// + /// + /// The value for the property with the specified key + /// + /// + /// + /// Gets or sets the value of a property + /// + /// + public abstract object this[string key] { get; set; } + } } diff --git a/src/log4net/Util/CountingQuietTextWriter.cs b/src/log4net/Util/CountingQuietTextWriter.cs index e0c2925b..505163a3 100644 --- a/src/log4net/Util/CountingQuietTextWriter.cs +++ b/src/log4net/Util/CountingQuietTextWriter.cs @@ -24,157 +24,157 @@ namespace log4net.Util { - /// - /// Subclass of that maintains a count of - /// the number of bytes written. - /// - /// - /// - /// This writer counts the number of bytes written. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public class CountingQuietTextWriter : QuietTextWriter - { - #region Public Instance Constructors + /// + /// Subclass of that maintains a count of + /// the number of bytes written. + /// + /// + /// + /// This writer counts the number of bytes written. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public class CountingQuietTextWriter : QuietTextWriter + { + #region Public Instance Constructors - /// - /// Constructor - /// - /// The to actually write to. - /// The to report errors to. - /// - /// - /// Creates a new instance of the class - /// with the specified and . - /// - /// - public CountingQuietTextWriter(TextWriter writer, IErrorHandler errorHandler) : base(writer, errorHandler) - { - m_countBytes = 0; - } + /// + /// Constructor + /// + /// The to actually write to. + /// The to report errors to. + /// + /// + /// Creates a new instance of the class + /// with the specified and . + /// + /// + public CountingQuietTextWriter(TextWriter writer, IErrorHandler errorHandler) : base(writer, errorHandler) + { + m_countBytes = 0; + } - #endregion Public Instance Constructors + #endregion Public Instance Constructors - #region Override implementation of QuietTextWriter + #region Override implementation of QuietTextWriter - /// - /// Writes a character to the underlying writer and counts the number of bytes written. - /// - /// the char to write - /// - /// - /// Overrides implementation of . Counts - /// the number of bytes written. - /// - /// - public override void Write(char value) - { - try - { - base.Write(value); + /// + /// Writes a character to the underlying writer and counts the number of bytes written. + /// + /// the char to write + /// + /// + /// Overrides implementation of . Counts + /// the number of bytes written. + /// + /// + public override void Write(char value) + { + try + { + base.Write(value); - // get the number of bytes needed to represent the - // char using the supplied encoding. - m_countBytes += this.Encoding.GetByteCount(new char[] { value }); - } - catch(Exception e) - { - this.ErrorHandler.Error("Failed to write [" + value + "].", e, ErrorCode.WriteFailure); - } - } + // get the number of bytes needed to represent the + // char using the supplied encoding. + m_countBytes += this.Encoding.GetByteCount(new char[] { value }); + } + catch(Exception e) + { + this.ErrorHandler.Error("Failed to write [" + value + "].", e, ErrorCode.WriteFailure); + } + } - /// - /// Writes a buffer to the underlying writer and counts the number of bytes written. - /// - /// the buffer to write - /// the start index to write from - /// the number of characters to write - /// - /// - /// Overrides implementation of . Counts - /// the number of bytes written. - /// - /// - public override void Write(char[] buffer, int index, int count) - { - if (count > 0) - { - try - { - base.Write(buffer, index, count); + /// + /// Writes a buffer to the underlying writer and counts the number of bytes written. + /// + /// the buffer to write + /// the start index to write from + /// the number of characters to write + /// + /// + /// Overrides implementation of . Counts + /// the number of bytes written. + /// + /// + public override void Write(char[] buffer, int index, int count) + { + if (count > 0) + { + try + { + base.Write(buffer, index, count); - // get the number of bytes needed to represent the - // char array using the supplied encoding. - m_countBytes += this.Encoding.GetByteCount(buffer, index, count); - } - catch(Exception e) - { - this.ErrorHandler.Error("Failed to write buffer.", e, ErrorCode.WriteFailure); - } - } - } + // get the number of bytes needed to represent the + // char array using the supplied encoding. + m_countBytes += this.Encoding.GetByteCount(buffer, index, count); + } + catch(Exception e) + { + this.ErrorHandler.Error("Failed to write buffer.", e, ErrorCode.WriteFailure); + } + } + } - /// - /// Writes a string to the output and counts the number of bytes written. - /// - /// The string data to write to the output. - /// - /// - /// Overrides implementation of . Counts - /// the number of bytes written. - /// - /// - public override void Write(string str) - { - if (str != null && str.Length > 0) - { - try - { - base.Write(str); + /// + /// Writes a string to the output and counts the number of bytes written. + /// + /// The string data to write to the output. + /// + /// + /// Overrides implementation of . Counts + /// the number of bytes written. + /// + /// + public override void Write(string str) + { + if (str != null && str.Length > 0) + { + try + { + base.Write(str); - // get the number of bytes needed to represent the - // string using the supplied encoding. - m_countBytes += this.Encoding.GetByteCount(str); - } - catch(Exception e) - { - this.ErrorHandler.Error("Failed to write [" + str + "].", e, ErrorCode.WriteFailure); - } - } - } - - #endregion Override implementation of QuietTextWriter + // get the number of bytes needed to represent the + // string using the supplied encoding. + m_countBytes += this.Encoding.GetByteCount(str); + } + catch(Exception e) + { + this.ErrorHandler.Error("Failed to write [" + str + "].", e, ErrorCode.WriteFailure); + } + } + } + + #endregion Override implementation of QuietTextWriter - #region Public Instance Properties + #region Public Instance Properties - /// - /// Gets or sets the total number of bytes written. - /// - /// - /// The total number of bytes written. - /// - /// - /// - /// Gets or sets the total number of bytes written. - /// - /// - public long Count - { - get { return m_countBytes; } - set { m_countBytes = value; } - } + /// + /// Gets or sets the total number of bytes written. + /// + /// + /// The total number of bytes written. + /// + /// + /// + /// Gets or sets the total number of bytes written. + /// + /// + public long Count + { + get { return m_countBytes; } + set { m_countBytes = value; } + } - #endregion Public Instance Properties + #endregion Public Instance Properties - #region Private Instance Fields + #region Private Instance Fields - /// - /// Total number of bytes written. - /// - private long m_countBytes; + /// + /// Total number of bytes written. + /// + private long m_countBytes; - #endregion Private Instance Fields - } + #endregion Private Instance Fields + } } diff --git a/src/log4net/Util/CyclicBuffer.cs b/src/log4net/Util/CyclicBuffer.cs index bc8c9024..ca5ca70d 100644 --- a/src/log4net/Util/CyclicBuffer.cs +++ b/src/log4net/Util/CyclicBuffer.cs @@ -23,333 +23,333 @@ namespace log4net.Util { - /// - /// A fixed size rolling buffer of logging events. - /// - /// - /// - /// An array backed fixed size leaky bucket. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public class CyclicBuffer - { - #region Public Instance Constructors - - /// - /// Constructor - /// - /// The maximum number of logging events in the buffer. - /// - /// - /// Initializes a new instance of the class with - /// the specified maximum number of buffered logging events. - /// - /// - /// The argument is not a positive integer. - public CyclicBuffer(int maxSize) - { - if (maxSize < 1) - { - throw SystemInfo.CreateArgumentOutOfRangeException("maxSize", (object)maxSize, "Parameter: maxSize, Value: [" + maxSize + "] out of range. Non zero positive integer required"); - } - - m_maxSize = maxSize; - m_events = new LoggingEvent[maxSize]; - m_first = 0; - m_last = 0; - m_numElems = 0; - } - - #endregion Public Instance Constructors - - #region Public Instance Methods - - /// - /// Appends a to the buffer. - /// - /// The event to append to the buffer. - /// The event discarded from the buffer, if the buffer is full, otherwise null. - /// - /// - /// Append an event to the buffer. If the buffer still contains free space then - /// null is returned. If the buffer is full then an event will be dropped - /// to make space for the new event, the event dropped is returned. - /// - /// - public LoggingEvent Append(LoggingEvent loggingEvent) - { - if (loggingEvent == null) - { - throw new ArgumentNullException("loggingEvent"); - } - - lock(this) - { - // save the discarded event - LoggingEvent discardedLoggingEvent = m_events[m_last]; - - // overwrite the last event position - m_events[m_last] = loggingEvent; - if (++m_last == m_maxSize) - { - m_last = 0; - } - - if (m_numElems < m_maxSize) - { - m_numElems++; - } - else if (++m_first == m_maxSize) - { - m_first = 0; - } - - if (m_numElems < m_maxSize) - { - // Space remaining - return null; - } - else - { - // Buffer is full and discarding an event - return discardedLoggingEvent; - } - } - } - - /// - /// Get and remove the oldest event in the buffer. - /// - /// The oldest logging event in the buffer - /// - /// - /// Gets the oldest (first) logging event in the buffer and removes it - /// from the buffer. - /// - /// - public LoggingEvent PopOldest() - { - lock(this) - { - LoggingEvent ret = null; - if (m_numElems > 0) - { - m_numElems--; - ret = m_events[m_first]; - m_events[m_first] = null; - if (++m_first == m_maxSize) - { - m_first = 0; - } - } - return ret; - } - } - - /// - /// Pops all the logging events from the buffer into an array. - /// - /// An array of all the logging events in the buffer. - /// - /// - /// Get all the events in the buffer and clear the buffer. - /// - /// - public LoggingEvent[] PopAll() - { - lock(this) - { - LoggingEvent[] ret = new LoggingEvent[m_numElems]; - - if (m_numElems > 0) - { - if (m_first < m_last) - { - Array.Copy(m_events, m_first, ret, 0, m_numElems); - } - else - { - Array.Copy(m_events, m_first, ret, 0, m_maxSize - m_first); - Array.Copy(m_events, 0, ret, m_maxSize - m_first, m_last); - } - } - - Clear(); - - return ret; - } - } - - /// - /// Clear the buffer - /// - /// - /// - /// Clear the buffer of all events. The events in the buffer are lost. - /// - /// - public void Clear() - { - lock(this) - { - // Set all the elements to null - Array.Clear(m_events, 0, m_events.Length); - - m_first = 0; - m_last = 0; - m_numElems = 0; - } - } + /// + /// A fixed size rolling buffer of logging events. + /// + /// + /// + /// An array backed fixed size leaky bucket. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public class CyclicBuffer + { + #region Public Instance Constructors + + /// + /// Constructor + /// + /// The maximum number of logging events in the buffer. + /// + /// + /// Initializes a new instance of the class with + /// the specified maximum number of buffered logging events. + /// + /// + /// The argument is not a positive integer. + public CyclicBuffer(int maxSize) + { + if (maxSize < 1) + { + throw SystemInfo.CreateArgumentOutOfRangeException("maxSize", (object)maxSize, "Parameter: maxSize, Value: [" + maxSize + "] out of range. Non zero positive integer required"); + } + + m_maxSize = maxSize; + m_events = new LoggingEvent[maxSize]; + m_first = 0; + m_last = 0; + m_numElems = 0; + } + + #endregion Public Instance Constructors + + #region Public Instance Methods + + /// + /// Appends a to the buffer. + /// + /// The event to append to the buffer. + /// The event discarded from the buffer, if the buffer is full, otherwise null. + /// + /// + /// Append an event to the buffer. If the buffer still contains free space then + /// null is returned. If the buffer is full then an event will be dropped + /// to make space for the new event, the event dropped is returned. + /// + /// + public LoggingEvent Append(LoggingEvent loggingEvent) + { + if (loggingEvent == null) + { + throw new ArgumentNullException("loggingEvent"); + } + + lock(this) + { + // save the discarded event + LoggingEvent discardedLoggingEvent = m_events[m_last]; + + // overwrite the last event position + m_events[m_last] = loggingEvent; + if (++m_last == m_maxSize) + { + m_last = 0; + } + + if (m_numElems < m_maxSize) + { + m_numElems++; + } + else if (++m_first == m_maxSize) + { + m_first = 0; + } + + if (m_numElems < m_maxSize) + { + // Space remaining + return null; + } + else + { + // Buffer is full and discarding an event + return discardedLoggingEvent; + } + } + } + + /// + /// Get and remove the oldest event in the buffer. + /// + /// The oldest logging event in the buffer + /// + /// + /// Gets the oldest (first) logging event in the buffer and removes it + /// from the buffer. + /// + /// + public LoggingEvent PopOldest() + { + lock(this) + { + LoggingEvent ret = null; + if (m_numElems > 0) + { + m_numElems--; + ret = m_events[m_first]; + m_events[m_first] = null; + if (++m_first == m_maxSize) + { + m_first = 0; + } + } + return ret; + } + } + + /// + /// Pops all the logging events from the buffer into an array. + /// + /// An array of all the logging events in the buffer. + /// + /// + /// Get all the events in the buffer and clear the buffer. + /// + /// + public LoggingEvent[] PopAll() + { + lock(this) + { + LoggingEvent[] ret = new LoggingEvent[m_numElems]; + + if (m_numElems > 0) + { + if (m_first < m_last) + { + Array.Copy(m_events, m_first, ret, 0, m_numElems); + } + else + { + Array.Copy(m_events, m_first, ret, 0, m_maxSize - m_first); + Array.Copy(m_events, 0, ret, m_maxSize - m_first, m_last); + } + } + + Clear(); + + return ret; + } + } + + /// + /// Clear the buffer + /// + /// + /// + /// Clear the buffer of all events. The events in the buffer are lost. + /// + /// + public void Clear() + { + lock(this) + { + // Set all the elements to null + Array.Clear(m_events, 0, m_events.Length); + + m_first = 0; + m_last = 0; + m_numElems = 0; + } + } #if RESIZABLE_CYCLIC_BUFFER - /// - /// Resizes the cyclic buffer to . - /// - /// The new size of the buffer. - /// - /// - /// Resize the cyclic buffer. Events in the buffer are copied into - /// the newly sized buffer. If the buffer is shrunk and there are - /// more events currently in the buffer than the new size of the - /// buffer then the newest events will be dropped from the buffer. - /// - /// - /// The argument is not a positive integer. - public void Resize(int newSize) - { - lock(this) - { - if (newSize < 0) - { - throw log4net.Util.SystemInfo.CreateArgumentOutOfRangeException("newSize", (object)newSize, "Parameter: newSize, Value: [" + newSize + "] out of range. Non zero positive integer required"); - } - if (newSize == m_numElems) - { - return; // nothing to do - } - - LoggingEvent[] temp = new LoggingEvent[newSize]; - - int loopLen = (newSize < m_numElems) ? newSize : m_numElems; - - for(int i = 0; i < loopLen; i++) - { - temp[i] = m_events[m_first]; - m_events[m_first] = null; - - if (++m_first == m_numElems) - { - m_first = 0; - } - } - - m_events = temp; - m_first = 0; - m_numElems = loopLen; - m_maxSize = newSize; - - if (loopLen == newSize) - { - m_last = 0; - } - else - { - m_last = loopLen; - } - } - } + /// + /// Resizes the cyclic buffer to . + /// + /// The new size of the buffer. + /// + /// + /// Resize the cyclic buffer. Events in the buffer are copied into + /// the newly sized buffer. If the buffer is shrunk and there are + /// more events currently in the buffer than the new size of the + /// buffer then the newest events will be dropped from the buffer. + /// + /// + /// The argument is not a positive integer. + public void Resize(int newSize) + { + lock(this) + { + if (newSize < 0) + { + throw log4net.Util.SystemInfo.CreateArgumentOutOfRangeException("newSize", (object)newSize, "Parameter: newSize, Value: [" + newSize + "] out of range. Non zero positive integer required"); + } + if (newSize == m_numElems) + { + return; // nothing to do + } + + LoggingEvent[] temp = new LoggingEvent[newSize]; + + int loopLen = (newSize < m_numElems) ? newSize : m_numElems; + + for(int i = 0; i < loopLen; i++) + { + temp[i] = m_events[m_first]; + m_events[m_first] = null; + + if (++m_first == m_numElems) + { + m_first = 0; + } + } + + m_events = temp; + m_first = 0; + m_numElems = loopLen; + m_maxSize = newSize; + + if (loopLen == newSize) + { + m_last = 0; + } + else + { + m_last = loopLen; + } + } + } #endif - #endregion Public Instance Methods - - #region Public Instance Properties - - /// - /// Gets the th oldest event currently in the buffer. - /// - /// The th oldest event currently in the buffer. - /// - /// - /// If is outside the range 0 to the number of events - /// currently in the buffer, then null is returned. - /// - /// - public LoggingEvent this[int i] - { - get - { - lock(this) - { - if (i < 0 || i >= m_numElems) - { - return null; - } - - return m_events[(m_first + i) % m_maxSize]; - } - } - } - - /// - /// Gets the maximum size of the buffer. - /// - /// The maximum size of the buffer. - /// - /// - /// Gets the maximum size of the buffer - /// - /// - public int MaxSize - { - get - { - lock(this) - { - return m_maxSize; - } - } + #endregion Public Instance Methods + + #region Public Instance Properties + + /// + /// Gets the th oldest event currently in the buffer. + /// + /// The th oldest event currently in the buffer. + /// + /// + /// If is outside the range 0 to the number of events + /// currently in the buffer, then null is returned. + /// + /// + public LoggingEvent this[int i] + { + get + { + lock(this) + { + if (i < 0 || i >= m_numElems) + { + return null; + } + + return m_events[(m_first + i) % m_maxSize]; + } + } + } + + /// + /// Gets the maximum size of the buffer. + /// + /// The maximum size of the buffer. + /// + /// + /// Gets the maximum size of the buffer + /// + /// + public int MaxSize + { + get + { + lock(this) + { + return m_maxSize; + } + } #if RESIZABLE_CYCLIC_BUFFER - set - { - /// Setting the MaxSize will cause the buffer to resize. - Resize(value); - } + set + { + /// Setting the MaxSize will cause the buffer to resize. + Resize(value); + } #endif - } - - /// - /// Gets the number of logging events in the buffer. - /// - /// The number of logging events in the buffer. - /// - /// - /// This number is guaranteed to be in the range 0 to - /// (inclusive). - /// - /// - public int Length - { - get - { - lock(this) - { - return m_numElems; - } - } - } - - #endregion Public Instance Properties - - #region Private Instance Fields - - private LoggingEvent[] m_events; - private int m_first; - private int m_last; - private int m_numElems; - private int m_maxSize; - - #endregion Private Instance Fields - } + } + + /// + /// Gets the number of logging events in the buffer. + /// + /// The number of logging events in the buffer. + /// + /// + /// This number is guaranteed to be in the range 0 to + /// (inclusive). + /// + /// + public int Length + { + get + { + lock(this) + { + return m_numElems; + } + } + } + + #endregion Public Instance Properties + + #region Private Instance Fields + + private LoggingEvent[] m_events; + private int m_first; + private int m_last; + private int m_numElems; + private int m_maxSize; + + #endregion Private Instance Fields + } } diff --git a/src/log4net/Util/EmptyCollection.cs b/src/log4net/Util/EmptyCollection.cs index 12225877..2f019dd8 100644 --- a/src/log4net/Util/EmptyCollection.cs +++ b/src/log4net/Util/EmptyCollection.cs @@ -22,157 +22,157 @@ namespace log4net.Util { - /// - /// An always empty . - /// - /// - /// - /// A singleton implementation of the - /// interface that always represents an empty collection. - /// - /// - /// Nicko Cadell - /// Gert Driesen + /// + /// An always empty . + /// + /// + /// + /// A singleton implementation of the + /// interface that always represents an empty collection. + /// + /// + /// Nicko Cadell + /// Gert Driesen #if !NETCF - [Serializable] + [Serializable] #endif - public sealed class EmptyCollection : ICollection - { - #region Private Instance Constructors - - /// - /// Initializes a new instance of the class. - /// - /// - /// - /// Uses a private access modifier to enforce the singleton pattern. - /// - /// - private EmptyCollection() - { - } - - #endregion Private Instance Constructors + public sealed class EmptyCollection : ICollection + { + #region Private Instance Constructors + + /// + /// Initializes a new instance of the class. + /// + /// + /// + /// Uses a private access modifier to enforce the singleton pattern. + /// + /// + private EmptyCollection() + { + } + + #endregion Private Instance Constructors - #region Public Static Properties - - /// - /// Gets the singleton instance of the empty collection. - /// - /// The singleton instance of the empty collection. - /// - /// - /// Gets the singleton instance of the empty collection. - /// - /// - public static EmptyCollection Instance - { - get { return s_instance; } - } - - #endregion Public Static Properties - - #region Implementation of ICollection - - /// - /// Copies the elements of the to an - /// , starting at a particular Array index. - /// - /// The one-dimensional - /// that is the destination of the elements copied from - /// . The Array must have zero-based - /// indexing. - /// The zero-based index in array at which - /// copying begins. - /// - /// - /// As the collection is empty no values are copied into the array. - /// - /// - public void CopyTo(System.Array array, int index) - { - // copy nothing - } - - /// - /// Gets a value indicating if access to the is synchronized (thread-safe). - /// - /// - /// true if access to the is synchronized (thread-safe); otherwise, false. - /// - /// - /// - /// For the this property is always true. - /// - /// - public bool IsSynchronized - { - get { return true; } - } - - /// - /// Gets the number of elements contained in the . - /// - /// - /// The number of elements contained in the . - /// - /// - /// - /// As the collection is empty the is always 0. - /// - /// - public int Count - { - get { return 0; } - } - - /// - /// Gets an object that can be used to synchronize access to the . - /// - /// - /// An object that can be used to synchronize access to the . - /// - /// - /// - /// As the collection is empty and thread safe and synchronized this instance is also - /// the object. - /// - /// - public object SyncRoot - { - get { return this; } - } - - #endregion Implementation of ICollection - - #region Implementation of IEnumerable - - /// - /// Returns an enumerator that can iterate through a collection. - /// - /// - /// An that can be used to - /// iterate through the collection. - /// - /// - /// - /// As the collection is empty a is returned. - /// - /// - public IEnumerator GetEnumerator() - { - return NullEnumerator.Instance; - } - - #endregion Implementation of IEnumerable - - #region Private Static Fields - - /// - /// The singleton instance of the empty collection. - /// - private static readonly EmptyCollection s_instance = new EmptyCollection(); + #region Public Static Properties + + /// + /// Gets the singleton instance of the empty collection. + /// + /// The singleton instance of the empty collection. + /// + /// + /// Gets the singleton instance of the empty collection. + /// + /// + public static EmptyCollection Instance + { + get { return s_instance; } + } + + #endregion Public Static Properties + + #region Implementation of ICollection + + /// + /// Copies the elements of the to an + /// , starting at a particular Array index. + /// + /// The one-dimensional + /// that is the destination of the elements copied from + /// . The Array must have zero-based + /// indexing. + /// The zero-based index in array at which + /// copying begins. + /// + /// + /// As the collection is empty no values are copied into the array. + /// + /// + public void CopyTo(System.Array array, int index) + { + // copy nothing + } + + /// + /// Gets a value indicating if access to the is synchronized (thread-safe). + /// + /// + /// true if access to the is synchronized (thread-safe); otherwise, false. + /// + /// + /// + /// For the this property is always true. + /// + /// + public bool IsSynchronized + { + get { return true; } + } + + /// + /// Gets the number of elements contained in the . + /// + /// + /// The number of elements contained in the . + /// + /// + /// + /// As the collection is empty the is always 0. + /// + /// + public int Count + { + get { return 0; } + } + + /// + /// Gets an object that can be used to synchronize access to the . + /// + /// + /// An object that can be used to synchronize access to the . + /// + /// + /// + /// As the collection is empty and thread safe and synchronized this instance is also + /// the object. + /// + /// + public object SyncRoot + { + get { return this; } + } + + #endregion Implementation of ICollection + + #region Implementation of IEnumerable + + /// + /// Returns an enumerator that can iterate through a collection. + /// + /// + /// An that can be used to + /// iterate through the collection. + /// + /// + /// + /// As the collection is empty a is returned. + /// + /// + public IEnumerator GetEnumerator() + { + return NullEnumerator.Instance; + } + + #endregion Implementation of IEnumerable + + #region Private Static Fields + + /// + /// The singleton instance of the empty collection. + /// + private static readonly EmptyCollection s_instance = new EmptyCollection(); - #endregion Private Static Fields - } + #endregion Private Static Fields + } } diff --git a/src/log4net/Util/EmptyDictionary.cs b/src/log4net/Util/EmptyDictionary.cs index 792a781c..1ccb67e2 100644 --- a/src/log4net/Util/EmptyDictionary.cs +++ b/src/log4net/Util/EmptyDictionary.cs @@ -22,318 +22,318 @@ namespace log4net.Util { - /// - /// An always empty . - /// - /// - /// - /// A singleton implementation of the - /// interface that always represents an empty collection. - /// - /// - /// Nicko Cadell - /// Gert Driesen + /// + /// An always empty . + /// + /// + /// + /// A singleton implementation of the + /// interface that always represents an empty collection. + /// + /// + /// Nicko Cadell + /// Gert Driesen #if !NETCF - [Serializable] + [Serializable] #endif - public sealed class EmptyDictionary : IDictionary - { - #region Private Instance Constructors + public sealed class EmptyDictionary : IDictionary + { + #region Private Instance Constructors - /// - /// Initializes a new instance of the class. - /// - /// - /// - /// Uses a private access modifier to enforce the singleton pattern. - /// - /// - private EmptyDictionary() - { - } + /// + /// Initializes a new instance of the class. + /// + /// + /// + /// Uses a private access modifier to enforce the singleton pattern. + /// + /// + private EmptyDictionary() + { + } - #endregion Private Instance Constructors + #endregion Private Instance Constructors - #region Public Static Properties + #region Public Static Properties - /// - /// Gets the singleton instance of the . - /// - /// The singleton instance of the . - /// - /// - /// Gets the singleton instance of the . - /// - /// - public static EmptyDictionary Instance - { - get { return s_instance; } - } + /// + /// Gets the singleton instance of the . + /// + /// The singleton instance of the . + /// + /// + /// Gets the singleton instance of the . + /// + /// + public static EmptyDictionary Instance + { + get { return s_instance; } + } - #endregion Public Static Properties + #endregion Public Static Properties - #region Implementation of ICollection + #region Implementation of ICollection - /// - /// Copies the elements of the to an - /// , starting at a particular Array index. - /// - /// The one-dimensional - /// that is the destination of the elements copied from - /// . The Array must have zero-based - /// indexing. - /// The zero-based index in array at which - /// copying begins. - /// - /// - /// As the collection is empty no values are copied into the array. - /// - /// - public void CopyTo(System.Array array, int index) - { - // copy nothing - } + /// + /// Copies the elements of the to an + /// , starting at a particular Array index. + /// + /// The one-dimensional + /// that is the destination of the elements copied from + /// . The Array must have zero-based + /// indexing. + /// The zero-based index in array at which + /// copying begins. + /// + /// + /// As the collection is empty no values are copied into the array. + /// + /// + public void CopyTo(System.Array array, int index) + { + // copy nothing + } - /// - /// Gets a value indicating if access to the is synchronized (thread-safe). - /// - /// - /// true if access to the is synchronized (thread-safe); otherwise, false. - /// - /// - /// - /// For the this property is always true. - /// - /// - public bool IsSynchronized - { - get { return true; } - } + /// + /// Gets a value indicating if access to the is synchronized (thread-safe). + /// + /// + /// true if access to the is synchronized (thread-safe); otherwise, false. + /// + /// + /// + /// For the this property is always true. + /// + /// + public bool IsSynchronized + { + get { return true; } + } - /// - /// Gets the number of elements contained in the - /// - /// - /// The number of elements contained in the . - /// - /// - /// - /// As the collection is empty the is always 0. - /// - /// - public int Count - { - get { return 0; } - } + /// + /// Gets the number of elements contained in the + /// + /// + /// The number of elements contained in the . + /// + /// + /// + /// As the collection is empty the is always 0. + /// + /// + public int Count + { + get { return 0; } + } - /// - /// Gets an object that can be used to synchronize access to the . - /// - /// - /// An object that can be used to synchronize access to the . - /// - /// - /// - /// As the collection is empty and thread safe and synchronized this instance is also - /// the object. - /// - /// - public object SyncRoot - { - get { return this; } - } + /// + /// Gets an object that can be used to synchronize access to the . + /// + /// + /// An object that can be used to synchronize access to the . + /// + /// + /// + /// As the collection is empty and thread safe and synchronized this instance is also + /// the object. + /// + /// + public object SyncRoot + { + get { return this; } + } - #endregion Implementation of ICollection + #endregion Implementation of ICollection - #region Implementation of IEnumerable + #region Implementation of IEnumerable - /// - /// Returns an enumerator that can iterate through a collection. - /// - /// - /// An that can be used to - /// iterate through the collection. - /// - /// - /// - /// As the collection is empty a is returned. - /// - /// - IEnumerator IEnumerable.GetEnumerator() - { - return NullEnumerator.Instance; - } + /// + /// Returns an enumerator that can iterate through a collection. + /// + /// + /// An that can be used to + /// iterate through the collection. + /// + /// + /// + /// As the collection is empty a is returned. + /// + /// + IEnumerator IEnumerable.GetEnumerator() + { + return NullEnumerator.Instance; + } - #endregion Implementation of IEnumerable + #endregion Implementation of IEnumerable - #region Implementation of IDictionary + #region Implementation of IDictionary - /// - /// Adds an element with the provided key and value to the - /// . - /// - /// The to use as the key of the element to add. - /// The to use as the value of the element to add. - /// - /// - /// As the collection is empty no new values can be added. A - /// is thrown if this method is called. - /// - /// - /// This dictionary is always empty and cannot be modified. - public void Add(object key, object value) - { - throw new InvalidOperationException(); - } + /// + /// Adds an element with the provided key and value to the + /// . + /// + /// The to use as the key of the element to add. + /// The to use as the value of the element to add. + /// + /// + /// As the collection is empty no new values can be added. A + /// is thrown if this method is called. + /// + /// + /// This dictionary is always empty and cannot be modified. + public void Add(object key, object value) + { + throw new InvalidOperationException(); + } - /// - /// Removes all elements from the . - /// - /// - /// - /// As the collection is empty no values can be removed. A - /// is thrown if this method is called. - /// - /// - /// This dictionary is always empty and cannot be modified. - public void Clear() - { - throw new InvalidOperationException(); - } + /// + /// Removes all elements from the . + /// + /// + /// + /// As the collection is empty no values can be removed. A + /// is thrown if this method is called. + /// + /// + /// This dictionary is always empty and cannot be modified. + public void Clear() + { + throw new InvalidOperationException(); + } - /// - /// Determines whether the contains an element - /// with the specified key. - /// - /// The key to locate in the . - /// false - /// - /// - /// As the collection is empty the method always returns false. - /// - /// - public bool Contains(object key) - { - return false; - } + /// + /// Determines whether the contains an element + /// with the specified key. + /// + /// The key to locate in the . + /// false + /// + /// + /// As the collection is empty the method always returns false. + /// + /// + public bool Contains(object key) + { + return false; + } - /// - /// Returns an enumerator that can iterate through a collection. - /// - /// - /// An that can be used to - /// iterate through the collection. - /// - /// - /// - /// As the collection is empty a is returned. - /// - /// - public IDictionaryEnumerator GetEnumerator() - { - return NullDictionaryEnumerator.Instance; - } + /// + /// Returns an enumerator that can iterate through a collection. + /// + /// + /// An that can be used to + /// iterate through the collection. + /// + /// + /// + /// As the collection is empty a is returned. + /// + /// + public IDictionaryEnumerator GetEnumerator() + { + return NullDictionaryEnumerator.Instance; + } - /// - /// Removes the element with the specified key from the . - /// - /// The key of the element to remove. - /// - /// - /// As the collection is empty no values can be removed. A - /// is thrown if this method is called. - /// - /// - /// This dictionary is always empty and cannot be modified. - public void Remove(object key) - { - throw new InvalidOperationException(); - } + /// + /// Removes the element with the specified key from the . + /// + /// The key of the element to remove. + /// + /// + /// As the collection is empty no values can be removed. A + /// is thrown if this method is called. + /// + /// + /// This dictionary is always empty and cannot be modified. + public void Remove(object key) + { + throw new InvalidOperationException(); + } - /// - /// Gets a value indicating whether the has a fixed size. - /// - /// true - /// - /// - /// As the collection is empty always returns true. - /// - /// - public bool IsFixedSize - { - get { return true; } - } + /// + /// Gets a value indicating whether the has a fixed size. + /// + /// true + /// + /// + /// As the collection is empty always returns true. + /// + /// + public bool IsFixedSize + { + get { return true; } + } - /// - /// Gets a value indicating whether the is read-only. - /// - /// true - /// - /// - /// As the collection is empty always returns true. - /// - /// - public bool IsReadOnly - { - get { return true; } - } + /// + /// Gets a value indicating whether the is read-only. + /// + /// true + /// + /// + /// As the collection is empty always returns true. + /// + /// + public bool IsReadOnly + { + get { return true; } + } - /// - /// Gets an containing the keys of the . - /// - /// An containing the keys of the . - /// - /// - /// As the collection is empty a is returned. - /// - /// - public System.Collections.ICollection Keys - { - get { return EmptyCollection.Instance; } - } + /// + /// Gets an containing the keys of the . + /// + /// An containing the keys of the . + /// + /// + /// As the collection is empty a is returned. + /// + /// + public System.Collections.ICollection Keys + { + get { return EmptyCollection.Instance; } + } - /// - /// Gets an containing the values of the . - /// - /// An containing the values of the . - /// - /// - /// As the collection is empty a is returned. - /// - /// - public System.Collections.ICollection Values - { - get { return EmptyCollection.Instance; } - } + /// + /// Gets an containing the values of the . + /// + /// An containing the values of the . + /// + /// + /// As the collection is empty a is returned. + /// + /// + public System.Collections.ICollection Values + { + get { return EmptyCollection.Instance; } + } - /// - /// Gets or sets the element with the specified key. - /// - /// The key of the element to get or set. - /// null - /// - /// - /// As the collection is empty no values can be looked up or stored. - /// If the index getter is called then null is returned. - /// A is thrown if the setter is called. - /// - /// - /// This dictionary is always empty and cannot be modified. - public object this[object key] - { - get { return null; } - set { throw new InvalidOperationException(); } - } + /// + /// Gets or sets the element with the specified key. + /// + /// The key of the element to get or set. + /// null + /// + /// + /// As the collection is empty no values can be looked up or stored. + /// If the index getter is called then null is returned. + /// A is thrown if the setter is called. + /// + /// + /// This dictionary is always empty and cannot be modified. + public object this[object key] + { + get { return null; } + set { throw new InvalidOperationException(); } + } - #endregion Implementation of IDictionary + #endregion Implementation of IDictionary - #region Private Static Fields + #region Private Static Fields - /// - /// The singleton instance of the empty dictionary. - /// - private static readonly EmptyDictionary s_instance = new EmptyDictionary(); + /// + /// The singleton instance of the empty dictionary. + /// + private static readonly EmptyDictionary s_instance = new EmptyDictionary(); - #endregion Private Static Fields - } + #endregion Private Static Fields + } } diff --git a/src/log4net/Util/FormattingInfo.cs b/src/log4net/Util/FormattingInfo.cs index 4a6c9bb9..6e8ed637 100644 --- a/src/log4net/Util/FormattingInfo.cs +++ b/src/log4net/Util/FormattingInfo.cs @@ -22,115 +22,115 @@ namespace log4net.Util { - /// - /// Contain the information obtained when parsing formatting modifiers - /// in conversion modifiers. - /// - /// - /// - /// Holds the formatting information extracted from the format string by - /// the . This is used by the - /// objects when rendering the output. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public class FormattingInfo - { - #region Public Instance Constructors + /// + /// Contain the information obtained when parsing formatting modifiers + /// in conversion modifiers. + /// + /// + /// + /// Holds the formatting information extracted from the format string by + /// the . This is used by the + /// objects when rendering the output. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public class FormattingInfo + { + #region Public Instance Constructors - /// - /// Defaut Constructor - /// - /// - /// - /// Initializes a new instance of the class. - /// - /// - public FormattingInfo() - { - } + /// + /// Defaut Constructor + /// + /// + /// + /// Initializes a new instance of the class. + /// + /// + public FormattingInfo() + { + } - /// - /// Constructor - /// - /// - /// - /// Initializes a new instance of the class - /// with the specified parameters. - /// - /// - public FormattingInfo(int min, int max, bool leftAlign) - { - m_min = min; - m_max = max; - m_leftAlign = leftAlign; - } + /// + /// Constructor + /// + /// + /// + /// Initializes a new instance of the class + /// with the specified parameters. + /// + /// + public FormattingInfo(int min, int max, bool leftAlign) + { + m_min = min; + m_max = max; + m_leftAlign = leftAlign; + } - #endregion Public Instance Constructors + #endregion Public Instance Constructors - #region Public Instance Properties + #region Public Instance Properties - /// - /// Gets or sets the minimum value. - /// - /// - /// The minimum value. - /// - /// - /// - /// Gets or sets the minimum value. - /// - /// - public int Min - { - get { return m_min; } - set { m_min = value; } - } + /// + /// Gets or sets the minimum value. + /// + /// + /// The minimum value. + /// + /// + /// + /// Gets or sets the minimum value. + /// + /// + public int Min + { + get { return m_min; } + set { m_min = value; } + } - /// - /// Gets or sets the maximum value. - /// - /// - /// The maximum value. - /// - /// - /// - /// Gets or sets the maximum value. - /// - /// - public int Max - { - get { return m_max; } - set { m_max = value; } - } + /// + /// Gets or sets the maximum value. + /// + /// + /// The maximum value. + /// + /// + /// + /// Gets or sets the maximum value. + /// + /// + public int Max + { + get { return m_max; } + set { m_max = value; } + } - /// - /// Gets or sets a flag indicating whether left align is enabled - /// or not. - /// - /// - /// A flag indicating whether left align is enabled or not. - /// - /// - /// - /// Gets or sets a flag indicating whether left align is enabled or not. - /// - /// - public bool LeftAlign - { - get { return m_leftAlign; } - set { m_leftAlign = value; } - } + /// + /// Gets or sets a flag indicating whether left align is enabled + /// or not. + /// + /// + /// A flag indicating whether left align is enabled or not. + /// + /// + /// + /// Gets or sets a flag indicating whether left align is enabled or not. + /// + /// + public bool LeftAlign + { + get { return m_leftAlign; } + set { m_leftAlign = value; } + } - #endregion Public Instance Properties + #endregion Public Instance Properties - #region Private Instance Fields + #region Private Instance Fields - private int m_min = -1; - private int m_max = int.MaxValue; - private bool m_leftAlign = false; + private int m_min = -1; + private int m_max = int.MaxValue; + private bool m_leftAlign = false; - #endregion Private Instance Fields - } + #endregion Private Instance Fields + } } diff --git a/src/log4net/Util/GlobalContextProperties.cs b/src/log4net/Util/GlobalContextProperties.cs index 0c199959..c7c504ff 100644 --- a/src/log4net/Util/GlobalContextProperties.cs +++ b/src/log4net/Util/GlobalContextProperties.cs @@ -22,156 +22,156 @@ namespace log4net.Util { - /// - /// Implementation of Properties collection for the - /// - /// - /// - /// This class implements a properties collection that is thread safe and supports both - /// storing properties and capturing a read only copy of the current propertied. - /// - /// - /// This class is optimized to the scenario where the properties are read frequently - /// and are modified infrequently. - /// - /// - /// Nicko Cadell - public sealed class GlobalContextProperties : ContextPropertiesBase - { - #region Private Instance Fields - - /// - /// The read only copy of the properties. - /// - /// - /// - /// This variable is declared volatile to prevent the compiler and JIT from - /// reordering reads and writes of this thread performed on different threads. - /// - /// + /// + /// Implementation of Properties collection for the + /// + /// + /// + /// This class implements a properties collection that is thread safe and supports both + /// storing properties and capturing a read only copy of the current propertied. + /// + /// + /// This class is optimized to the scenario where the properties are read frequently + /// and are modified infrequently. + /// + /// + /// Nicko Cadell + public sealed class GlobalContextProperties : ContextPropertiesBase + { + #region Private Instance Fields + + /// + /// The read only copy of the properties. + /// + /// + /// + /// This variable is declared volatile to prevent the compiler and JIT from + /// reordering reads and writes of this thread performed on different threads. + /// + /// #if NETCF - private ReadOnlyPropertiesDictionary m_readOnlyProperties = new ReadOnlyPropertiesDictionary(); + private ReadOnlyPropertiesDictionary m_readOnlyProperties = new ReadOnlyPropertiesDictionary(); #else - private volatile ReadOnlyPropertiesDictionary m_readOnlyProperties = new ReadOnlyPropertiesDictionary(); + private volatile ReadOnlyPropertiesDictionary m_readOnlyProperties = new ReadOnlyPropertiesDictionary(); #endif - /// - /// Lock object used to synchronize updates within this instance - /// - private readonly object m_syncRoot = new object(); - - #endregion Private Instance Fields - - #region Public Instance Constructors - - /// - /// Constructor - /// - /// - /// - /// Initializes a new instance of the class. - /// - /// - internal GlobalContextProperties() - { - } - - #endregion Public Instance Constructors - - #region Public Instance Properties - - /// - /// Gets or sets the value of a property - /// - /// - /// The value for the property with the specified key - /// - /// - /// - /// Reading the value for a key is faster than setting the value. - /// When the value is written a new read only copy of - /// the properties is created. - /// - /// - public override object this[string key] - { - get - { - return m_readOnlyProperties[key]; - } - set - { - lock(m_syncRoot) - { - PropertiesDictionary mutableProps = new PropertiesDictionary(m_readOnlyProperties); - - mutableProps[key] = value; - - m_readOnlyProperties = new ReadOnlyPropertiesDictionary(mutableProps); - } - } - } - - #endregion Public Instance Properties - - #region Public Instance Methods - - /// - /// Remove a property from the global context - /// - /// the key for the entry to remove - /// - /// - /// Removing an entry from the global context properties is relatively expensive compared - /// with reading a value. - /// - /// - public void Remove(string key) - { - lock(m_syncRoot) - { - if (m_readOnlyProperties.Contains(key)) - { - PropertiesDictionary mutableProps = new PropertiesDictionary(m_readOnlyProperties); - - mutableProps.Remove(key); - - m_readOnlyProperties = new ReadOnlyPropertiesDictionary(mutableProps); - } - } - } - - /// - /// Clear the global context properties - /// - public void Clear() - { - lock(m_syncRoot) - { - m_readOnlyProperties = new ReadOnlyPropertiesDictionary(); - } - } - - #endregion Public Instance Methods - - #region Internal Instance Methods - - /// - /// Get a readonly immutable copy of the properties - /// - /// the current global context properties - /// - /// - /// This implementation is fast because the GlobalContextProperties class - /// stores a readonly copy of the properties. - /// - /// - internal ReadOnlyPropertiesDictionary GetReadOnlyProperties() - { - return m_readOnlyProperties; - } - - #endregion Internal Instance Methods - } + /// + /// Lock object used to synchronize updates within this instance + /// + private readonly object m_syncRoot = new object(); + + #endregion Private Instance Fields + + #region Public Instance Constructors + + /// + /// Constructor + /// + /// + /// + /// Initializes a new instance of the class. + /// + /// + internal GlobalContextProperties() + { + } + + #endregion Public Instance Constructors + + #region Public Instance Properties + + /// + /// Gets or sets the value of a property + /// + /// + /// The value for the property with the specified key + /// + /// + /// + /// Reading the value for a key is faster than setting the value. + /// When the value is written a new read only copy of + /// the properties is created. + /// + /// + public override object this[string key] + { + get + { + return m_readOnlyProperties[key]; + } + set + { + lock(m_syncRoot) + { + PropertiesDictionary mutableProps = new PropertiesDictionary(m_readOnlyProperties); + + mutableProps[key] = value; + + m_readOnlyProperties = new ReadOnlyPropertiesDictionary(mutableProps); + } + } + } + + #endregion Public Instance Properties + + #region Public Instance Methods + + /// + /// Remove a property from the global context + /// + /// the key for the entry to remove + /// + /// + /// Removing an entry from the global context properties is relatively expensive compared + /// with reading a value. + /// + /// + public void Remove(string key) + { + lock(m_syncRoot) + { + if (m_readOnlyProperties.Contains(key)) + { + PropertiesDictionary mutableProps = new PropertiesDictionary(m_readOnlyProperties); + + mutableProps.Remove(key); + + m_readOnlyProperties = new ReadOnlyPropertiesDictionary(mutableProps); + } + } + } + + /// + /// Clear the global context properties + /// + public void Clear() + { + lock(m_syncRoot) + { + m_readOnlyProperties = new ReadOnlyPropertiesDictionary(); + } + } + + #endregion Public Instance Methods + + #region Internal Instance Methods + + /// + /// Get a readonly immutable copy of the properties + /// + /// the current global context properties + /// + /// + /// This implementation is fast because the GlobalContextProperties class + /// stores a readonly copy of the properties. + /// + /// + internal ReadOnlyPropertiesDictionary GetReadOnlyProperties() + { + return m_readOnlyProperties; + } + + #endregion Internal Instance Methods + } } diff --git a/src/log4net/Util/ILogExtensions.cs b/src/log4net/Util/ILogExtensions.cs index fa52c28e..0d13e040 100644 --- a/src/log4net/Util/ILogExtensions.cs +++ b/src/log4net/Util/ILogExtensions.cs @@ -25,1717 +25,1717 @@ namespace log4net.Util { - /// - /// The static class ILogExtensions contains a set of widely used - /// methods that ease the interaction with the ILog interface implementations. - /// - /// - /// - /// This class contains methods for logging at different levels and checks the - /// properties for determining if those logging levels are enabled in the current - /// configuration. - /// - /// - /// Simple example of logging messages - /// - /// using log4net.Util; - /// - /// ILog log = LogManager.GetLogger("application-log"); - /// - /// log.InfoExt("Application Start"); - /// log.DebugExt("This is a debug message"); - /// - /// - public static class ILogExtensions - { - #region Private Static Fields - - /// - /// The fully qualified type of the Logger class. - /// - private static readonly Type declaringType = typeof(ILogExtensions); - - #endregion //Private Static Fields - - #region debug extensions - - #region debug extensions that uses log message lambda expression - - /// - /// Log a message object with the level. - /// - /// The logger on which the message is logged. - /// The lambda expression that gets the object to log. - /// - /// - /// This method first checks if this logger is INFO - /// enabled by reading the value property. - /// This check happens always and does not depend on the - /// implementation. If this logger is INFO enabled, then it converts - /// the message object (retrieved by invocation of the provided callback) to a - /// string by invoking the appropriate . - /// It then proceeds to call all the registered appenders in this logger - /// and also higher in the hierarchy depending on the value of - /// the additivity flag. - /// - /// WARNING Note that passing an - /// to this method will print the name of the - /// but no stack trace. To print a stack trace use the - /// form instead. - /// - /// - /// - /// - public static void DebugExt(this ILog logger, Func callback) - { - try - { - if (!logger.IsDebugEnabled) - return; - - logger.Debug(callback()); - } - catch (Exception ex) - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); - } - } - - /// - /// Log a message object with the level including - /// the stack trace of the passed - /// as a parameter. - /// - /// The logger on which the message is logged. - /// The lambda expression that gets the object to log. - /// The exception to log, including its stack trace. - /// - /// - /// See the form for more detailed information. - /// - /// - /// - /// - public static void DebugExt(this ILog logger, Func callback, Exception exception) - { - try - { - if (!logger.IsDebugEnabled) - return; - - logger.Debug(callback(), exception); - } - catch (Exception ex) - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); - } - } - - #endregion - - #region debug extension that use the formatter - - /// Log a message object with the level. //TODO - /// - /// Log a message object with the level. - /// - /// The logger on which the message is logged. - /// The message object to log. - /// - /// - /// This method first checks if this logger is INFO - /// enabled by reading the value property. - /// This check happens always and does not depend on the - /// implementation. If this logger is INFO enabled, then it converts - /// the message object (passed as parameter) to a string by invoking the appropriate - /// . It then - /// proceeds to call all the registered appenders in this logger - /// and also higher in the hierarchy depending on the value of - /// the additivity flag. - /// - /// WARNING Note that passing an - /// to this method will print the name of the - /// but no stack trace. To print a stack trace use the - /// form instead. - /// - /// - /// - /// - public static void DebugExt(this ILog logger, object message) - { - try - { - if (!logger.IsDebugEnabled) - return; - - logger.Debug(message); - } - catch (Exception ex) - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); - } - } - - /// - /// Log a message object with the level including - /// the stack trace of the passed - /// as a parameter. - /// - /// The logger on which the message is logged. - /// The message object to log. - /// The exception to log, including its stack trace. - /// - /// - /// See the form for more detailed information. - /// - /// - /// - /// - public static void DebugExt(this ILog logger, object message, Exception exception) - { - try - { - if (!logger.IsDebugEnabled) - return; - - logger.Debug(message, exception); - } - catch (Exception ex) - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); - } - } - - #endregion - - #region debug extension that use string format - - /// - /// Logs a formatted message string with the level. - /// - /// The logger on which the message is logged. - /// A String containing zero or more format items - /// An Object to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - public static void DebugFormatExt(this ILog logger, string format, object arg0) - { - try - { - if (!logger.IsDebugEnabled) - return; - - logger.DebugFormat(format, arg0); - } - catch (Exception ex) - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); - } - } - - /// - /// Logs a formatted message string with the level. - /// - /// The logger on which the message is logged. - /// A String containing zero or more format items - /// An Object array containing zero or more objects to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - public static void DebugFormatExt(this ILog logger, string format, params object[] args) - { - try - { - if (!logger.IsDebugEnabled) - return; - - logger.DebugFormat(format, args); - } - catch (Exception ex) - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); - } - } - - /// - /// Logs a formatted message string with the level. - /// - /// An that supplies culture-specific formatting information - /// The logger on which the message is logged. - /// A String containing zero or more format items - /// An Object array containing zero or more objects to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - public static void DebugFormatExt(this ILog logger, IFormatProvider provider, string format, params object[] args) - { - try - { - if (!logger.IsDebugEnabled) - return; - - logger.DebugFormat(provider, format, args); - } - catch (Exception ex) - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); - } - } - - /// - /// Logs a formatted message string with the level. - /// - /// The logger on which the message is logged. - /// A String containing zero or more format items - /// An Object to format - /// An Object to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - public static void DebugFormatExt(this ILog logger, string format, object arg0, object arg1) - { - try - { - if (!logger.IsDebugEnabled) - return; - - logger.DebugFormat(format, arg0, arg1); - } - catch (Exception ex) - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); - } - } - - /// - /// Logs a formatted message string with the level. - /// - /// The logger on which the message is logged. - /// A String containing zero or more format items - /// An Object to format - /// An Object to format - /// An Object to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - public static void DebugFormatExt(this ILog logger, string format, object arg0, object arg1, object arg2) - { - try - { - if (!logger.IsDebugEnabled) - return; - - logger.DebugFormat(format, arg0, arg1, arg2); - } - catch (Exception ex) - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); - } - } - - #endregion - - #endregion - - #region info extensions - - #region info extensions that uses log message lambda expression - - /// - /// Log a message object with the level. - /// - /// The logger on which the message is logged. - /// The lambda expression that gets the object to log. - /// - /// - /// This method first checks if this logger is INFO - /// enabled by reading the value property. - /// This check happens always and does not depend on the - /// implementation. If this logger is INFO enabled, then it converts - /// the message object (retrieved by invocation of the provided callback) to a - /// string by invoking the appropriate . - /// It then proceeds to call all the registered appenders in this logger - /// and also higher in the hierarchy depending on the value of - /// the additivity flag. - /// - /// WARNING Note that passing an - /// to this method will print the name of the - /// but no stack trace. To print a stack trace use the - /// form instead. - /// - /// - /// - /// - public static void InfoExt(this ILog logger, Func callback) - { - try - { - if (!logger.IsInfoEnabled) - return; - - logger.Info(callback()); - } - catch (Exception ex) - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); - } - } - - /// - /// Log a message object with the level including - /// the stack trace of the passed - /// as a parameter. - /// - /// The logger on which the message is logged. - /// The lambda expression that gets the object to log. - /// The exception to log, including its stack trace. - /// - /// - /// See the form for more detailed information. - /// - /// - /// - /// - public static void InfoExt(this ILog logger, Func callback, Exception exception) - { - try - { - if (!logger.IsInfoEnabled) - return; - - logger.Info(callback(), exception); - } - catch (Exception ex) - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); - } - } - - #endregion - - #region info extension that use the formatter - - /// Log a message object with the level. //TODO - /// - /// Log a message object with the level. - /// - /// The logger on which the message is logged. - /// The message object to log. - /// - /// - /// This method first checks if this logger is INFO - /// enabled by reading the value property. - /// This check happens always and does not depend on the - /// implementation. If this logger is INFO enabled, then it converts - /// the message object (passed as parameter) to a string by invoking the appropriate - /// . It then - /// proceeds to call all the registered appenders in this logger - /// and also higher in the hierarchy depending on the value of - /// the additivity flag. - /// - /// WARNING Note that passing an - /// to this method will print the name of the - /// but no stack trace. To print a stack trace use the - /// form instead. - /// - /// - /// - /// - public static void InfoExt(this ILog logger, object message) - { - try - { - if (!logger.IsInfoEnabled) - return; - - logger.Info(message); - } - catch (Exception ex) - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); - } - } - - /// - /// Log a message object with the level including - /// the stack trace of the passed - /// as a parameter. - /// - /// The logger on which the message is logged. - /// The message object to log. - /// The exception to log, including its stack trace. - /// - /// - /// See the form for more detailed information. - /// - /// - /// - /// - public static void InfoExt(this ILog logger, object message, Exception exception) - { - try - { - if (!logger.IsInfoEnabled) - return; - - logger.Info(message, exception); - } - catch (Exception ex) - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); - } - } - - #endregion - - #region info extension that use string format - - /// - /// Logs a formatted message string with the level. - /// - /// The logger on which the message is logged. - /// A String containing zero or more format items - /// An Object to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - public static void InfoFormatExt(this ILog logger, string format, object arg0) - { - try - { - if (!logger.IsInfoEnabled) - return; - - logger.InfoFormat(format, arg0); - } - catch (Exception ex) - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); - } - } - - /// - /// Logs a formatted message string with the level. - /// - /// The logger on which the message is logged. - /// A String containing zero or more format items - /// An Object array containing zero or more objects to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - public static void InfoFormatExt(this ILog logger, string format, params object[] args) - { - try - { - if (!logger.IsInfoEnabled) - return; - - logger.InfoFormat(format, args); - } - catch (Exception ex) - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); - } - } - - /// - /// Logs a formatted message string with the level. - /// - /// An that supplies culture-specific formatting information - /// The logger on which the message is logged. - /// A String containing zero or more format items - /// An Object array containing zero or more objects to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - public static void InfoFormatExt(this ILog logger, IFormatProvider provider, string format, params object[] args) - { - try - { - if (!logger.IsInfoEnabled) - return; - - logger.InfoFormat(provider, format, args); - } - catch (Exception ex) - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); - } - } - - /// - /// Logs a formatted message string with the level. - /// - /// The logger on which the message is logged. - /// A String containing zero or more format items - /// An Object to format - /// An Object to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - public static void InfoFormatExt(this ILog logger, string format, object arg0, object arg1) - { - try - { - if (!logger.IsInfoEnabled) - return; - - logger.InfoFormat(format, arg0, arg1); - } - catch (Exception ex) - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); - } - } - - /// - /// Logs a formatted message string with the level. - /// - /// The logger on which the message is logged. - /// A String containing zero or more format items - /// An Object to format - /// An Object to format - /// An Object to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - public static void InfoFormatExt(this ILog logger, string format, object arg0, object arg1, object arg2) - { - try - { - if (!logger.IsInfoEnabled) - return; - - logger.InfoFormat(format, arg0, arg1, arg2); - } - catch (Exception ex) - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); - } - } - - #endregion - - #endregion - - #region warn extensions - - #region warn extensions that uses log message lambda expression - - /// - /// Log a message object with the level. - /// - /// The logger on which the message is logged. - /// The lambda expression that gets the object to log. - /// - /// - /// This method first checks if this logger is WARN - /// enabled by reading the value property. - /// This check happens always and does not depend on the - /// implementation. If this logger is WARN enabled, then it converts - /// the message object (retrieved by invocation of the provided callback) to a - /// string by invoking the appropriate . - /// It then proceeds to call all the registered appenders in this logger - /// and also higher in the hierarchy depending on the value of - /// the additivity flag. - /// - /// WARNING Note that passing an - /// to this method will print the name of the - /// but no stack trace. To print a stack trace use the - /// form instead. - /// - /// - /// - /// - public static void WarnExt(this ILog logger, Func callback) - { - try - { - if (!logger.IsWarnEnabled) - return; - - logger.Warn(callback()); - } - catch (Exception ex) - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); - } - } - - /// - /// Log a message object with the level including - /// the stack trace of the passed - /// as a parameter. - /// - /// The logger on which the message is logged. - /// The lambda expression that gets the object to log. - /// The exception to log, including its stack trace. - /// - /// - /// See the form for more detailed information. - /// - /// - /// - /// - public static void WarnExt(this ILog logger, Func callback, Exception exception) - { - try - { - if (!logger.IsWarnEnabled) - return; - - logger.Warn(callback(), exception); - } - catch (Exception ex) - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); - } - } - - #endregion - - #region warn extension that use the formatter - - /// Log a message object with the level. //TODO - /// - /// Log a message object with the level. - /// - /// The logger on which the message is logged. - /// The message object to log. - /// - /// - /// This method first checks if this logger is WARN - /// enabled by reading the value property. - /// This check happens always and does not depend on the - /// implementation. If this logger is WARN enabled, then it converts - /// the message object (passed as parameter) to a string by invoking the appropriate - /// . It then - /// proceeds to call all the registered appenders in this logger - /// and also higher in the hierarchy depending on the value of - /// the additivity flag. - /// - /// WARNING Note that passing an - /// to this method will print the name of the - /// but no stack trace. To print a stack trace use the - /// form instead. - /// - /// - /// - /// - public static void WarnExt(this ILog logger, object message) - { - try - { - if (!logger.IsWarnEnabled) - return; - - logger.Warn(message); - } - catch (Exception ex) - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); - } - } - - /// - /// Log a message object with the level including - /// the stack trace of the passed - /// as a parameter. - /// - /// The logger on which the message is logged. - /// The message object to log. - /// The exception to log, including its stack trace. - /// - /// - /// See the form for more detailed information. - /// - /// - /// - /// - public static void WarnExt(this ILog logger, object message, Exception exception) - { - try - { - if (!logger.IsWarnEnabled) - return; - - logger.Warn(message, exception); - } - catch (Exception ex) - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); - } - } - - #endregion - - #region warn extension that use string format - - /// - /// Logs a formatted message string with the level. - /// - /// The logger on which the message is logged. - /// A String containing zero or more format items - /// An Object to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - public static void WarnFormatExt(this ILog logger, string format, object arg0) - { - try - { - if (!logger.IsWarnEnabled) - return; - - logger.WarnFormat(format, arg0); - } - catch (Exception ex) - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); - } - } - - /// - /// Logs a formatted message string with the level. - /// - /// The logger on which the message is logged. - /// A String containing zero or more format items - /// An Object array containing zero or more objects to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - public static void WarnFormatExt(this ILog logger, string format, params object[] args) - { - try - { - if (!logger.IsWarnEnabled) - return; - - logger.WarnFormat(format, args); - } - catch (Exception ex) - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); - } - } - - /// - /// Logs a formatted message string with the level. - /// - /// An that supplies culture-specific formatting information - /// The logger on which the message is logged. - /// A String containing zero or more format items - /// An Object array containing zero or more objects to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - public static void WarnFormatExt(this ILog logger, IFormatProvider provider, string format, params object[] args) - { - try - { - if (!logger.IsWarnEnabled) - return; - - logger.WarnFormat(provider, format, args); - } - catch (Exception ex) - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); - } - } - - /// - /// Logs a formatted message string with the level. - /// - /// The logger on which the message is logged. - /// A String containing zero or more format items - /// An Object to format - /// An Object to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - public static void WarnFormatExt(this ILog logger, string format, object arg0, object arg1) - { - try - { - if (!logger.IsWarnEnabled) - return; - - logger.WarnFormat(format, arg0, arg1); - } - catch (Exception ex) - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); - } - } - - /// - /// Logs a formatted message string with the level. - /// - /// The logger on which the message is logged. - /// A String containing zero or more format items - /// An Object to format - /// An Object to format - /// An Object to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - public static void WarnFormatExt(this ILog logger, string format, object arg0, object arg1, object arg2) - { - try - { - if (!logger.IsWarnEnabled) - return; - - logger.WarnFormat(format, arg0, arg1, arg2); - } - catch (Exception ex) - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); - } - } - - #endregion - - #endregion - - #region error extensions - - #region error extensions that uses log message lambda expression - - /// - /// Log a message object with the level. - /// - /// The logger on which the message is logged. - /// The lambda expression that gets the object to log. - /// - /// - /// This method first checks if this logger is ERROR - /// enabled by reading the value property. - /// This check happens always and does not depend on the - /// implementation. If this logger is ERROR enabled, then it converts - /// the message object (retrieved by invocation of the provided callback) to a - /// string by invoking the appropriate . - /// It then proceeds to call all the registered appenders in this logger - /// and also higher in the hierarchy depending on the value of - /// the additivity flag. - /// - /// WARNING Note that passing an - /// to this method will print the name of the - /// but no stack trace. To print a stack trace use the - /// form instead. - /// - /// - /// - /// - public static void ErrorExt(this ILog logger, Func callback) - { - try - { - if (!logger.IsErrorEnabled) - return; - - logger.Error(callback()); - } - catch (Exception ex) - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); - } - } - - /// - /// Log a message object with the level including - /// the stack trace of the passed - /// as a parameter. - /// - /// The logger on which the message is logged. - /// The lambda expression that gets the object to log. - /// The exception to log, including its stack trace. - /// - /// - /// See the form for more detailed information. - /// - /// - /// - /// - public static void ErrorExt(this ILog logger, Func callback, Exception exception) - { - try - { - if (!logger.IsErrorEnabled) - return; - - logger.Error(callback(), exception); - } - catch (Exception ex) - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); - } - } - - #endregion - - #region error extension that use the formatter - - /// Log a message object with the level. //TODO - /// - /// Log a message object with the level. - /// - /// The logger on which the message is logged. - /// The message object to log. - /// - /// - /// This method first checks if this logger is ERROR - /// enabled by reading the value property. - /// This check happens always and does not depend on the - /// implementation. If this logger is ERROR enabled, then it converts - /// the message object (passed as parameter) to a string by invoking the appropriate - /// . It then - /// proceeds to call all the registered appenders in this logger - /// and also higher in the hierarchy depending on the value of - /// the additivity flag. - /// - /// WARNING Note that passing an - /// to this method will print the name of the - /// but no stack trace. To print a stack trace use the - /// form instead. - /// - /// - /// - /// - public static void ErrorExt(this ILog logger, object message) - { - try - { - if (!logger.IsErrorEnabled) - return; - - logger.Error(message); - } - catch (Exception ex) - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); - } - } - - /// - /// Log a message object with the level including - /// the stack trace of the passed - /// as a parameter. - /// - /// The logger on which the message is logged. - /// The message object to log. - /// The exception to log, including its stack trace. - /// - /// - /// See the form for more detailed information. - /// - /// - /// - /// - public static void ErrorExt(this ILog logger, object message, Exception exception) - { - try - { - if (!logger.IsErrorEnabled) - return; - - logger.Error(message, exception); - } - catch (Exception ex) - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); - } - } - - #endregion - - #region error extension that use string format - - /// - /// Logs a formatted message string with the level. - /// - /// The logger on which the message is logged. - /// A String containing zero or more format items - /// An Object to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - public static void ErrorFormatExt(this ILog logger, string format, object arg0) - { - try - { - if (!logger.IsErrorEnabled) - return; - - logger.ErrorFormat(format, arg0); - } - catch (Exception ex) - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); - } - } - - /// - /// Logs a formatted message string with the level. - /// - /// The logger on which the message is logged. - /// A String containing zero or more format items - /// An Object array containing zero or more objects to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - public static void ErrorFormatExt(this ILog logger, string format, params object[] args) - { - try - { - if (!logger.IsErrorEnabled) - return; - - logger.ErrorFormat(format, args); - } - catch (Exception ex) - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); - } - } - - /// - /// Logs a formatted message string with the level. - /// - /// An that supplies culture-specific formatting information - /// The logger on which the message is logged. - /// A String containing zero or more format items - /// An Object array containing zero or more objects to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - public static void ErrorFormatExt(this ILog logger, IFormatProvider provider, string format, params object[] args) - { - try - { - if (!logger.IsErrorEnabled) - return; - - logger.ErrorFormat(provider, format, args); - } - catch (Exception ex) - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); - } - } - - /// - /// Logs a formatted message string with the level. - /// - /// The logger on which the message is logged. - /// A String containing zero or more format items - /// An Object to format - /// An Object to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - public static void ErrorFormatExt(this ILog logger, string format, object arg0, object arg1) - { - try - { - if (!logger.IsErrorEnabled) - return; - - logger.ErrorFormat(format, arg0, arg1); - } - catch (Exception ex) - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); - } - } - - /// - /// Logs a formatted message string with the level. - /// - /// The logger on which the message is logged. - /// A String containing zero or more format items - /// An Object to format - /// An Object to format - /// An Object to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - public static void ErrorFormatExt(this ILog logger, string format, object arg0, object arg1, object arg2) - { - try - { - if (!logger.IsErrorEnabled) - return; - - logger.ErrorFormat(format, arg0, arg1, arg2); - } - catch (Exception ex) - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); - } - } - - #endregion - - #endregion - - #region fatal extensions - - #region fatal extensions that uses log message lambda expression - - /// - /// Log a message object with the level. - /// - /// The logger on which the message is logged. - /// The lambda expression that gets the object to log. - /// - /// - /// This method first checks if this logger is FATAL - /// enabled by reading the value property. - /// This check happens always and does not depend on the - /// implementation. If this logger is FATAL enabled, then it converts - /// the message object (retrieved by invocation of the provided callback) to a - /// string by invoking the appropriate . - /// It then proceeds to call all the registered appenders in this logger - /// and also higher in the hierarchy depending on the value of - /// the additivity flag. - /// - /// WARNING Note that passing an - /// to this method will print the name of the - /// but no stack trace. To print a stack trace use the - /// form instead. - /// - /// - /// - /// - public static void FatalExt(this ILog logger, Func callback) - { - try - { - if (!logger.IsFatalEnabled) - return; - - logger.Fatal(callback()); - } - catch (Exception ex) - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); - } - } - - /// - /// Log a message object with the level including - /// the stack trace of the passed - /// as a parameter. - /// - /// The logger on which the message is logged. - /// The lambda expression that gets the object to log. - /// The exception to log, including its stack trace. - /// - /// - /// See the form for more detailed information. - /// - /// - /// - /// - public static void FatalExt(this ILog logger, Func callback, Exception exception) - { - try - { - if (!logger.IsFatalEnabled) - return; - - logger.Fatal(callback(), exception); - } - catch (Exception ex) - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); - } - } - - #endregion - - #region fatal extension that use the formatter - - /// Log a message object with the level. //TODO - /// - /// Log a message object with the level. - /// - /// The logger on which the message is logged. - /// The message object to log. - /// - /// - /// This method first checks if this logger is FATAL - /// enabled by reading the value property. - /// This check happens always and does not depend on the - /// implementation. If this logger is FATAL enabled, then it converts - /// the message object (passed as parameter) to a string by invoking the appropriate - /// . It then - /// proceeds to call all the registered appenders in this logger - /// and also higher in the hierarchy depending on the value of - /// the additivity flag. - /// - /// WARNING Note that passing an - /// to this method will print the name of the - /// but no stack trace. To print a stack trace use the - /// form instead. - /// - /// - /// - /// - public static void FatalExt(this ILog logger, object message) - { - try - { - if (!logger.IsFatalEnabled) - return; - - logger.Fatal(message); - } - catch (Exception ex) - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); - } - } - - /// - /// Log a message object with the level including - /// the stack trace of the passed - /// as a parameter. - /// - /// The logger on which the message is logged. - /// The message object to log. - /// The exception to log, including its stack trace. - /// - /// - /// See the form for more detailed information. - /// - /// - /// - /// - public static void FatalExt(this ILog logger, object message, Exception exception) - { - try - { - if (!logger.IsFatalEnabled) - return; - - logger.Fatal(message, exception); - } - catch (Exception ex) - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); - } - } - - #endregion - - #region fatal extension that use string format - - /// - /// Logs a formatted message string with the level. - /// - /// The logger on which the message is logged. - /// A String containing zero or more format items - /// An Object to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - public static void FatalFormatExt(this ILog logger, string format, object arg0) - { - try - { - if (!logger.IsFatalEnabled) - return; - - logger.FatalFormat(format, arg0); - } - catch (Exception ex) - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); - } - } - - /// - /// Logs a formatted message string with the level. - /// - /// The logger on which the message is logged. - /// A String containing zero or more format items - /// An Object array containing zero or more objects to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - public static void FatalFormatExt(this ILog logger, string format, params object[] args) - { - try - { - if (!logger.IsFatalEnabled) - return; - - logger.FatalFormat(format, args); - } - catch (Exception ex) - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); - } - } - - /// - /// Logs a formatted message string with the level. - /// - /// An that supplies culture-specific formatting information - /// The logger on which the message is logged. - /// A String containing zero or more format items - /// An Object array containing zero or more objects to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - public static void FatalFormatExt(this ILog logger, IFormatProvider provider, string format, params object[] args) - { - try - { - if (!logger.IsFatalEnabled) - return; - - logger.FatalFormat(provider, format, args); - } - catch (Exception ex) - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); - } - } - - /// - /// Logs a formatted message string with the level. - /// - /// The logger on which the message is logged. - /// A String containing zero or more format items - /// An Object to format - /// An Object to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - public static void FatalFormatExt(this ILog logger, string format, object arg0, object arg1) - { - try - { - if (!logger.IsFatalEnabled) - return; - - logger.FatalFormat(format, arg0, arg1); - } - catch (Exception ex) - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); - } - } - - /// - /// Logs a formatted message string with the level. - /// - /// The logger on which the message is logged. - /// A String containing zero or more format items - /// An Object to format - /// An Object to format - /// An Object to format - /// - /// - /// The message is formatted using the String.Format method. See - /// for details of the syntax of the format string and the behavior - /// of the formatting. - /// - /// - /// This method does not take an object to include in the - /// log event. To pass an use one of the - /// methods instead. - /// - /// - /// - /// - public static void FatalFormatExt(this ILog logger, string format, object arg0, object arg1, object arg2) - { - try - { - if (!logger.IsFatalEnabled) - return; - - logger.FatalFormat(format, arg0, arg1, arg2); - } - catch (Exception ex) - { - log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); - } - } - - #endregion - - #endregion - } + /// + /// The static class ILogExtensions contains a set of widely used + /// methods that ease the interaction with the ILog interface implementations. + /// + /// + /// + /// This class contains methods for logging at different levels and checks the + /// properties for determining if those logging levels are enabled in the current + /// configuration. + /// + /// + /// Simple example of logging messages + /// + /// using log4net.Util; + /// + /// ILog log = LogManager.GetLogger("application-log"); + /// + /// log.InfoExt("Application Start"); + /// log.DebugExt("This is a debug message"); + /// + /// + public static class ILogExtensions + { + #region Private Static Fields + + /// + /// The fully qualified type of the Logger class. + /// + private static readonly Type declaringType = typeof(ILogExtensions); + + #endregion //Private Static Fields + + #region debug extensions + + #region debug extensions that uses log message lambda expression + + /// + /// Log a message object with the level. + /// + /// The logger on which the message is logged. + /// The lambda expression that gets the object to log. + /// + /// + /// This method first checks if this logger is INFO + /// enabled by reading the value property. + /// This check happens always and does not depend on the + /// implementation. If this logger is INFO enabled, then it converts + /// the message object (retrieved by invocation of the provided callback) to a + /// string by invoking the appropriate . + /// It then proceeds to call all the registered appenders in this logger + /// and also higher in the hierarchy depending on the value of + /// the additivity flag. + /// + /// WARNING Note that passing an + /// to this method will print the name of the + /// but no stack trace. To print a stack trace use the + /// form instead. + /// + /// + /// + /// + public static void DebugExt(this ILog logger, Func callback) + { + try + { + if (!logger.IsDebugEnabled) + return; + + logger.Debug(callback()); + } + catch (Exception ex) + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); + } + } + + /// + /// Log a message object with the level including + /// the stack trace of the passed + /// as a parameter. + /// + /// The logger on which the message is logged. + /// The lambda expression that gets the object to log. + /// The exception to log, including its stack trace. + /// + /// + /// See the form for more detailed information. + /// + /// + /// + /// + public static void DebugExt(this ILog logger, Func callback, Exception exception) + { + try + { + if (!logger.IsDebugEnabled) + return; + + logger.Debug(callback(), exception); + } + catch (Exception ex) + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); + } + } + + #endregion + + #region debug extension that use the formatter + + /// Log a message object with the level. //TODO + /// + /// Log a message object with the level. + /// + /// The logger on which the message is logged. + /// The message object to log. + /// + /// + /// This method first checks if this logger is INFO + /// enabled by reading the value property. + /// This check happens always and does not depend on the + /// implementation. If this logger is INFO enabled, then it converts + /// the message object (passed as parameter) to a string by invoking the appropriate + /// . It then + /// proceeds to call all the registered appenders in this logger + /// and also higher in the hierarchy depending on the value of + /// the additivity flag. + /// + /// WARNING Note that passing an + /// to this method will print the name of the + /// but no stack trace. To print a stack trace use the + /// form instead. + /// + /// + /// + /// + public static void DebugExt(this ILog logger, object message) + { + try + { + if (!logger.IsDebugEnabled) + return; + + logger.Debug(message); + } + catch (Exception ex) + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); + } + } + + /// + /// Log a message object with the level including + /// the stack trace of the passed + /// as a parameter. + /// + /// The logger on which the message is logged. + /// The message object to log. + /// The exception to log, including its stack trace. + /// + /// + /// See the form for more detailed information. + /// + /// + /// + /// + public static void DebugExt(this ILog logger, object message, Exception exception) + { + try + { + if (!logger.IsDebugEnabled) + return; + + logger.Debug(message, exception); + } + catch (Exception ex) + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); + } + } + + #endregion + + #region debug extension that use string format + + /// + /// Logs a formatted message string with the level. + /// + /// The logger on which the message is logged. + /// A String containing zero or more format items + /// An Object to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + public static void DebugFormatExt(this ILog logger, string format, object arg0) + { + try + { + if (!logger.IsDebugEnabled) + return; + + logger.DebugFormat(format, arg0); + } + catch (Exception ex) + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); + } + } + + /// + /// Logs a formatted message string with the level. + /// + /// The logger on which the message is logged. + /// A String containing zero or more format items + /// An Object array containing zero or more objects to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + public static void DebugFormatExt(this ILog logger, string format, params object[] args) + { + try + { + if (!logger.IsDebugEnabled) + return; + + logger.DebugFormat(format, args); + } + catch (Exception ex) + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); + } + } + + /// + /// Logs a formatted message string with the level. + /// + /// An that supplies culture-specific formatting information + /// The logger on which the message is logged. + /// A String containing zero or more format items + /// An Object array containing zero or more objects to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + public static void DebugFormatExt(this ILog logger, IFormatProvider provider, string format, params object[] args) + { + try + { + if (!logger.IsDebugEnabled) + return; + + logger.DebugFormat(provider, format, args); + } + catch (Exception ex) + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); + } + } + + /// + /// Logs a formatted message string with the level. + /// + /// The logger on which the message is logged. + /// A String containing zero or more format items + /// An Object to format + /// An Object to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + public static void DebugFormatExt(this ILog logger, string format, object arg0, object arg1) + { + try + { + if (!logger.IsDebugEnabled) + return; + + logger.DebugFormat(format, arg0, arg1); + } + catch (Exception ex) + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); + } + } + + /// + /// Logs a formatted message string with the level. + /// + /// The logger on which the message is logged. + /// A String containing zero or more format items + /// An Object to format + /// An Object to format + /// An Object to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + public static void DebugFormatExt(this ILog logger, string format, object arg0, object arg1, object arg2) + { + try + { + if (!logger.IsDebugEnabled) + return; + + logger.DebugFormat(format, arg0, arg1, arg2); + } + catch (Exception ex) + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); + } + } + + #endregion + + #endregion + + #region info extensions + + #region info extensions that uses log message lambda expression + + /// + /// Log a message object with the level. + /// + /// The logger on which the message is logged. + /// The lambda expression that gets the object to log. + /// + /// + /// This method first checks if this logger is INFO + /// enabled by reading the value property. + /// This check happens always and does not depend on the + /// implementation. If this logger is INFO enabled, then it converts + /// the message object (retrieved by invocation of the provided callback) to a + /// string by invoking the appropriate . + /// It then proceeds to call all the registered appenders in this logger + /// and also higher in the hierarchy depending on the value of + /// the additivity flag. + /// + /// WARNING Note that passing an + /// to this method will print the name of the + /// but no stack trace. To print a stack trace use the + /// form instead. + /// + /// + /// + /// + public static void InfoExt(this ILog logger, Func callback) + { + try + { + if (!logger.IsInfoEnabled) + return; + + logger.Info(callback()); + } + catch (Exception ex) + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); + } + } + + /// + /// Log a message object with the level including + /// the stack trace of the passed + /// as a parameter. + /// + /// The logger on which the message is logged. + /// The lambda expression that gets the object to log. + /// The exception to log, including its stack trace. + /// + /// + /// See the form for more detailed information. + /// + /// + /// + /// + public static void InfoExt(this ILog logger, Func callback, Exception exception) + { + try + { + if (!logger.IsInfoEnabled) + return; + + logger.Info(callback(), exception); + } + catch (Exception ex) + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); + } + } + + #endregion + + #region info extension that use the formatter + + /// Log a message object with the level. //TODO + /// + /// Log a message object with the level. + /// + /// The logger on which the message is logged. + /// The message object to log. + /// + /// + /// This method first checks if this logger is INFO + /// enabled by reading the value property. + /// This check happens always and does not depend on the + /// implementation. If this logger is INFO enabled, then it converts + /// the message object (passed as parameter) to a string by invoking the appropriate + /// . It then + /// proceeds to call all the registered appenders in this logger + /// and also higher in the hierarchy depending on the value of + /// the additivity flag. + /// + /// WARNING Note that passing an + /// to this method will print the name of the + /// but no stack trace. To print a stack trace use the + /// form instead. + /// + /// + /// + /// + public static void InfoExt(this ILog logger, object message) + { + try + { + if (!logger.IsInfoEnabled) + return; + + logger.Info(message); + } + catch (Exception ex) + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); + } + } + + /// + /// Log a message object with the level including + /// the stack trace of the passed + /// as a parameter. + /// + /// The logger on which the message is logged. + /// The message object to log. + /// The exception to log, including its stack trace. + /// + /// + /// See the form for more detailed information. + /// + /// + /// + /// + public static void InfoExt(this ILog logger, object message, Exception exception) + { + try + { + if (!logger.IsInfoEnabled) + return; + + logger.Info(message, exception); + } + catch (Exception ex) + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); + } + } + + #endregion + + #region info extension that use string format + + /// + /// Logs a formatted message string with the level. + /// + /// The logger on which the message is logged. + /// A String containing zero or more format items + /// An Object to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + public static void InfoFormatExt(this ILog logger, string format, object arg0) + { + try + { + if (!logger.IsInfoEnabled) + return; + + logger.InfoFormat(format, arg0); + } + catch (Exception ex) + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); + } + } + + /// + /// Logs a formatted message string with the level. + /// + /// The logger on which the message is logged. + /// A String containing zero or more format items + /// An Object array containing zero or more objects to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + public static void InfoFormatExt(this ILog logger, string format, params object[] args) + { + try + { + if (!logger.IsInfoEnabled) + return; + + logger.InfoFormat(format, args); + } + catch (Exception ex) + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); + } + } + + /// + /// Logs a formatted message string with the level. + /// + /// An that supplies culture-specific formatting information + /// The logger on which the message is logged. + /// A String containing zero or more format items + /// An Object array containing zero or more objects to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + public static void InfoFormatExt(this ILog logger, IFormatProvider provider, string format, params object[] args) + { + try + { + if (!logger.IsInfoEnabled) + return; + + logger.InfoFormat(provider, format, args); + } + catch (Exception ex) + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); + } + } + + /// + /// Logs a formatted message string with the level. + /// + /// The logger on which the message is logged. + /// A String containing zero or more format items + /// An Object to format + /// An Object to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + public static void InfoFormatExt(this ILog logger, string format, object arg0, object arg1) + { + try + { + if (!logger.IsInfoEnabled) + return; + + logger.InfoFormat(format, arg0, arg1); + } + catch (Exception ex) + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); + } + } + + /// + /// Logs a formatted message string with the level. + /// + /// The logger on which the message is logged. + /// A String containing zero or more format items + /// An Object to format + /// An Object to format + /// An Object to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + public static void InfoFormatExt(this ILog logger, string format, object arg0, object arg1, object arg2) + { + try + { + if (!logger.IsInfoEnabled) + return; + + logger.InfoFormat(format, arg0, arg1, arg2); + } + catch (Exception ex) + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); + } + } + + #endregion + + #endregion + + #region warn extensions + + #region warn extensions that uses log message lambda expression + + /// + /// Log a message object with the level. + /// + /// The logger on which the message is logged. + /// The lambda expression that gets the object to log. + /// + /// + /// This method first checks if this logger is WARN + /// enabled by reading the value property. + /// This check happens always and does not depend on the + /// implementation. If this logger is WARN enabled, then it converts + /// the message object (retrieved by invocation of the provided callback) to a + /// string by invoking the appropriate . + /// It then proceeds to call all the registered appenders in this logger + /// and also higher in the hierarchy depending on the value of + /// the additivity flag. + /// + /// WARNING Note that passing an + /// to this method will print the name of the + /// but no stack trace. To print a stack trace use the + /// form instead. + /// + /// + /// + /// + public static void WarnExt(this ILog logger, Func callback) + { + try + { + if (!logger.IsWarnEnabled) + return; + + logger.Warn(callback()); + } + catch (Exception ex) + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); + } + } + + /// + /// Log a message object with the level including + /// the stack trace of the passed + /// as a parameter. + /// + /// The logger on which the message is logged. + /// The lambda expression that gets the object to log. + /// The exception to log, including its stack trace. + /// + /// + /// See the form for more detailed information. + /// + /// + /// + /// + public static void WarnExt(this ILog logger, Func callback, Exception exception) + { + try + { + if (!logger.IsWarnEnabled) + return; + + logger.Warn(callback(), exception); + } + catch (Exception ex) + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); + } + } + + #endregion + + #region warn extension that use the formatter + + /// Log a message object with the level. //TODO + /// + /// Log a message object with the level. + /// + /// The logger on which the message is logged. + /// The message object to log. + /// + /// + /// This method first checks if this logger is WARN + /// enabled by reading the value property. + /// This check happens always and does not depend on the + /// implementation. If this logger is WARN enabled, then it converts + /// the message object (passed as parameter) to a string by invoking the appropriate + /// . It then + /// proceeds to call all the registered appenders in this logger + /// and also higher in the hierarchy depending on the value of + /// the additivity flag. + /// + /// WARNING Note that passing an + /// to this method will print the name of the + /// but no stack trace. To print a stack trace use the + /// form instead. + /// + /// + /// + /// + public static void WarnExt(this ILog logger, object message) + { + try + { + if (!logger.IsWarnEnabled) + return; + + logger.Warn(message); + } + catch (Exception ex) + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); + } + } + + /// + /// Log a message object with the level including + /// the stack trace of the passed + /// as a parameter. + /// + /// The logger on which the message is logged. + /// The message object to log. + /// The exception to log, including its stack trace. + /// + /// + /// See the form for more detailed information. + /// + /// + /// + /// + public static void WarnExt(this ILog logger, object message, Exception exception) + { + try + { + if (!logger.IsWarnEnabled) + return; + + logger.Warn(message, exception); + } + catch (Exception ex) + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); + } + } + + #endregion + + #region warn extension that use string format + + /// + /// Logs a formatted message string with the level. + /// + /// The logger on which the message is logged. + /// A String containing zero or more format items + /// An Object to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + public static void WarnFormatExt(this ILog logger, string format, object arg0) + { + try + { + if (!logger.IsWarnEnabled) + return; + + logger.WarnFormat(format, arg0); + } + catch (Exception ex) + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); + } + } + + /// + /// Logs a formatted message string with the level. + /// + /// The logger on which the message is logged. + /// A String containing zero or more format items + /// An Object array containing zero or more objects to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + public static void WarnFormatExt(this ILog logger, string format, params object[] args) + { + try + { + if (!logger.IsWarnEnabled) + return; + + logger.WarnFormat(format, args); + } + catch (Exception ex) + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); + } + } + + /// + /// Logs a formatted message string with the level. + /// + /// An that supplies culture-specific formatting information + /// The logger on which the message is logged. + /// A String containing zero or more format items + /// An Object array containing zero or more objects to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + public static void WarnFormatExt(this ILog logger, IFormatProvider provider, string format, params object[] args) + { + try + { + if (!logger.IsWarnEnabled) + return; + + logger.WarnFormat(provider, format, args); + } + catch (Exception ex) + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); + } + } + + /// + /// Logs a formatted message string with the level. + /// + /// The logger on which the message is logged. + /// A String containing zero or more format items + /// An Object to format + /// An Object to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + public static void WarnFormatExt(this ILog logger, string format, object arg0, object arg1) + { + try + { + if (!logger.IsWarnEnabled) + return; + + logger.WarnFormat(format, arg0, arg1); + } + catch (Exception ex) + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); + } + } + + /// + /// Logs a formatted message string with the level. + /// + /// The logger on which the message is logged. + /// A String containing zero or more format items + /// An Object to format + /// An Object to format + /// An Object to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + public static void WarnFormatExt(this ILog logger, string format, object arg0, object arg1, object arg2) + { + try + { + if (!logger.IsWarnEnabled) + return; + + logger.WarnFormat(format, arg0, arg1, arg2); + } + catch (Exception ex) + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); + } + } + + #endregion + + #endregion + + #region error extensions + + #region error extensions that uses log message lambda expression + + /// + /// Log a message object with the level. + /// + /// The logger on which the message is logged. + /// The lambda expression that gets the object to log. + /// + /// + /// This method first checks if this logger is ERROR + /// enabled by reading the value property. + /// This check happens always and does not depend on the + /// implementation. If this logger is ERROR enabled, then it converts + /// the message object (retrieved by invocation of the provided callback) to a + /// string by invoking the appropriate . + /// It then proceeds to call all the registered appenders in this logger + /// and also higher in the hierarchy depending on the value of + /// the additivity flag. + /// + /// WARNING Note that passing an + /// to this method will print the name of the + /// but no stack trace. To print a stack trace use the + /// form instead. + /// + /// + /// + /// + public static void ErrorExt(this ILog logger, Func callback) + { + try + { + if (!logger.IsErrorEnabled) + return; + + logger.Error(callback()); + } + catch (Exception ex) + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); + } + } + + /// + /// Log a message object with the level including + /// the stack trace of the passed + /// as a parameter. + /// + /// The logger on which the message is logged. + /// The lambda expression that gets the object to log. + /// The exception to log, including its stack trace. + /// + /// + /// See the form for more detailed information. + /// + /// + /// + /// + public static void ErrorExt(this ILog logger, Func callback, Exception exception) + { + try + { + if (!logger.IsErrorEnabled) + return; + + logger.Error(callback(), exception); + } + catch (Exception ex) + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); + } + } + + #endregion + + #region error extension that use the formatter + + /// Log a message object with the level. //TODO + /// + /// Log a message object with the level. + /// + /// The logger on which the message is logged. + /// The message object to log. + /// + /// + /// This method first checks if this logger is ERROR + /// enabled by reading the value property. + /// This check happens always and does not depend on the + /// implementation. If this logger is ERROR enabled, then it converts + /// the message object (passed as parameter) to a string by invoking the appropriate + /// . It then + /// proceeds to call all the registered appenders in this logger + /// and also higher in the hierarchy depending on the value of + /// the additivity flag. + /// + /// WARNING Note that passing an + /// to this method will print the name of the + /// but no stack trace. To print a stack trace use the + /// form instead. + /// + /// + /// + /// + public static void ErrorExt(this ILog logger, object message) + { + try + { + if (!logger.IsErrorEnabled) + return; + + logger.Error(message); + } + catch (Exception ex) + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); + } + } + + /// + /// Log a message object with the level including + /// the stack trace of the passed + /// as a parameter. + /// + /// The logger on which the message is logged. + /// The message object to log. + /// The exception to log, including its stack trace. + /// + /// + /// See the form for more detailed information. + /// + /// + /// + /// + public static void ErrorExt(this ILog logger, object message, Exception exception) + { + try + { + if (!logger.IsErrorEnabled) + return; + + logger.Error(message, exception); + } + catch (Exception ex) + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); + } + } + + #endregion + + #region error extension that use string format + + /// + /// Logs a formatted message string with the level. + /// + /// The logger on which the message is logged. + /// A String containing zero or more format items + /// An Object to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + public static void ErrorFormatExt(this ILog logger, string format, object arg0) + { + try + { + if (!logger.IsErrorEnabled) + return; + + logger.ErrorFormat(format, arg0); + } + catch (Exception ex) + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); + } + } + + /// + /// Logs a formatted message string with the level. + /// + /// The logger on which the message is logged. + /// A String containing zero or more format items + /// An Object array containing zero or more objects to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + public static void ErrorFormatExt(this ILog logger, string format, params object[] args) + { + try + { + if (!logger.IsErrorEnabled) + return; + + logger.ErrorFormat(format, args); + } + catch (Exception ex) + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); + } + } + + /// + /// Logs a formatted message string with the level. + /// + /// An that supplies culture-specific formatting information + /// The logger on which the message is logged. + /// A String containing zero or more format items + /// An Object array containing zero or more objects to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + public static void ErrorFormatExt(this ILog logger, IFormatProvider provider, string format, params object[] args) + { + try + { + if (!logger.IsErrorEnabled) + return; + + logger.ErrorFormat(provider, format, args); + } + catch (Exception ex) + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); + } + } + + /// + /// Logs a formatted message string with the level. + /// + /// The logger on which the message is logged. + /// A String containing zero or more format items + /// An Object to format + /// An Object to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + public static void ErrorFormatExt(this ILog logger, string format, object arg0, object arg1) + { + try + { + if (!logger.IsErrorEnabled) + return; + + logger.ErrorFormat(format, arg0, arg1); + } + catch (Exception ex) + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); + } + } + + /// + /// Logs a formatted message string with the level. + /// + /// The logger on which the message is logged. + /// A String containing zero or more format items + /// An Object to format + /// An Object to format + /// An Object to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + public static void ErrorFormatExt(this ILog logger, string format, object arg0, object arg1, object arg2) + { + try + { + if (!logger.IsErrorEnabled) + return; + + logger.ErrorFormat(format, arg0, arg1, arg2); + } + catch (Exception ex) + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); + } + } + + #endregion + + #endregion + + #region fatal extensions + + #region fatal extensions that uses log message lambda expression + + /// + /// Log a message object with the level. + /// + /// The logger on which the message is logged. + /// The lambda expression that gets the object to log. + /// + /// + /// This method first checks if this logger is FATAL + /// enabled by reading the value property. + /// This check happens always and does not depend on the + /// implementation. If this logger is FATAL enabled, then it converts + /// the message object (retrieved by invocation of the provided callback) to a + /// string by invoking the appropriate . + /// It then proceeds to call all the registered appenders in this logger + /// and also higher in the hierarchy depending on the value of + /// the additivity flag. + /// + /// WARNING Note that passing an + /// to this method will print the name of the + /// but no stack trace. To print a stack trace use the + /// form instead. + /// + /// + /// + /// + public static void FatalExt(this ILog logger, Func callback) + { + try + { + if (!logger.IsFatalEnabled) + return; + + logger.Fatal(callback()); + } + catch (Exception ex) + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); + } + } + + /// + /// Log a message object with the level including + /// the stack trace of the passed + /// as a parameter. + /// + /// The logger on which the message is logged. + /// The lambda expression that gets the object to log. + /// The exception to log, including its stack trace. + /// + /// + /// See the form for more detailed information. + /// + /// + /// + /// + public static void FatalExt(this ILog logger, Func callback, Exception exception) + { + try + { + if (!logger.IsFatalEnabled) + return; + + logger.Fatal(callback(), exception); + } + catch (Exception ex) + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); + } + } + + #endregion + + #region fatal extension that use the formatter + + /// Log a message object with the level. //TODO + /// + /// Log a message object with the level. + /// + /// The logger on which the message is logged. + /// The message object to log. + /// + /// + /// This method first checks if this logger is FATAL + /// enabled by reading the value property. + /// This check happens always and does not depend on the + /// implementation. If this logger is FATAL enabled, then it converts + /// the message object (passed as parameter) to a string by invoking the appropriate + /// . It then + /// proceeds to call all the registered appenders in this logger + /// and also higher in the hierarchy depending on the value of + /// the additivity flag. + /// + /// WARNING Note that passing an + /// to this method will print the name of the + /// but no stack trace. To print a stack trace use the + /// form instead. + /// + /// + /// + /// + public static void FatalExt(this ILog logger, object message) + { + try + { + if (!logger.IsFatalEnabled) + return; + + logger.Fatal(message); + } + catch (Exception ex) + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); + } + } + + /// + /// Log a message object with the level including + /// the stack trace of the passed + /// as a parameter. + /// + /// The logger on which the message is logged. + /// The message object to log. + /// The exception to log, including its stack trace. + /// + /// + /// See the form for more detailed information. + /// + /// + /// + /// + public static void FatalExt(this ILog logger, object message, Exception exception) + { + try + { + if (!logger.IsFatalEnabled) + return; + + logger.Fatal(message, exception); + } + catch (Exception ex) + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); + } + } + + #endregion + + #region fatal extension that use string format + + /// + /// Logs a formatted message string with the level. + /// + /// The logger on which the message is logged. + /// A String containing zero or more format items + /// An Object to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + public static void FatalFormatExt(this ILog logger, string format, object arg0) + { + try + { + if (!logger.IsFatalEnabled) + return; + + logger.FatalFormat(format, arg0); + } + catch (Exception ex) + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); + } + } + + /// + /// Logs a formatted message string with the level. + /// + /// The logger on which the message is logged. + /// A String containing zero or more format items + /// An Object array containing zero or more objects to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + public static void FatalFormatExt(this ILog logger, string format, params object[] args) + { + try + { + if (!logger.IsFatalEnabled) + return; + + logger.FatalFormat(format, args); + } + catch (Exception ex) + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); + } + } + + /// + /// Logs a formatted message string with the level. + /// + /// An that supplies culture-specific formatting information + /// The logger on which the message is logged. + /// A String containing zero or more format items + /// An Object array containing zero or more objects to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + public static void FatalFormatExt(this ILog logger, IFormatProvider provider, string format, params object[] args) + { + try + { + if (!logger.IsFatalEnabled) + return; + + logger.FatalFormat(provider, format, args); + } + catch (Exception ex) + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); + } + } + + /// + /// Logs a formatted message string with the level. + /// + /// The logger on which the message is logged. + /// A String containing zero or more format items + /// An Object to format + /// An Object to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + public static void FatalFormatExt(this ILog logger, string format, object arg0, object arg1) + { + try + { + if (!logger.IsFatalEnabled) + return; + + logger.FatalFormat(format, arg0, arg1); + } + catch (Exception ex) + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); + } + } + + /// + /// Logs a formatted message string with the level. + /// + /// The logger on which the message is logged. + /// A String containing zero or more format items + /// An Object to format + /// An Object to format + /// An Object to format + /// + /// + /// The message is formatted using the String.Format method. See + /// for details of the syntax of the format string and the behavior + /// of the formatting. + /// + /// + /// This method does not take an object to include in the + /// log event. To pass an use one of the + /// methods instead. + /// + /// + /// + /// + public static void FatalFormatExt(this ILog logger, string format, object arg0, object arg1, object arg2) + { + try + { + if (!logger.IsFatalEnabled) + return; + + logger.FatalFormat(format, arg0, arg1, arg2); + } + catch (Exception ex) + { + log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); + } + } + + #endregion + + #endregion + } } #endif diff --git a/src/log4net/Util/LevelMapping.cs b/src/log4net/Util/LevelMapping.cs index a2d4afff..aee83b23 100644 --- a/src/log4net/Util/LevelMapping.cs +++ b/src/log4net/Util/LevelMapping.cs @@ -24,127 +24,127 @@ namespace log4net.Util { - /// - /// Manages a mapping from levels to - /// - /// - /// - /// Manages an ordered mapping from instances - /// to subclasses. - /// - /// - /// Nicko Cadell - public sealed class LevelMapping : IOptionHandler - { - #region Public Instance Constructors - - /// - /// Default constructor - /// - /// - /// - /// Initialise a new instance of . - /// - /// - public LevelMapping() - { - } - - #endregion // Public Instance Constructors - - #region Public Instance Methods - - /// - /// Add a to this mapping - /// - /// the entry to add - /// - /// - /// If a has previously been added - /// for the same then that entry will be - /// overwritten. - /// - /// - public void Add(LevelMappingEntry entry) - { - if (m_entriesMap.ContainsKey(entry.Level)) - { - m_entriesMap.Remove(entry.Level); - } - m_entriesMap.Add(entry.Level, entry); - } - - /// - /// Lookup the mapping for the specified level - /// - /// the level to lookup - /// the for the level or null if no mapping found - /// - /// - /// Lookup the value for the specified level. Finds the nearest - /// mapping value for the level that is equal to or less than the - /// specified. - /// - /// - /// If no mapping could be found then null is returned. - /// - /// - public LevelMappingEntry Lookup(Level level) - { - if (m_entries != null) - { - foreach(LevelMappingEntry entry in m_entries) - { - if (level >= entry.Level) - { - return entry; - } - } - } - return null; - } - - #endregion // Public Instance Methods - - #region IOptionHandler Members - - /// - /// Initialize options - /// - /// - /// - /// Caches the sorted list of in an array - /// - /// - public void ActivateOptions() - { - Level[] sortKeys = new Level[m_entriesMap.Count]; - LevelMappingEntry[] sortValues = new LevelMappingEntry[m_entriesMap.Count]; - - m_entriesMap.Keys.CopyTo(sortKeys, 0); - m_entriesMap.Values.CopyTo(sortValues, 0); - - // Sort in level order - Array.Sort(sortKeys, sortValues, 0, sortKeys.Length, null); - - // Reverse list so that highest level is first - Array.Reverse(sortValues, 0, sortValues.Length); - - foreach(LevelMappingEntry entry in sortValues) - { - entry.ActivateOptions(); - } - - m_entries = sortValues; - } - - #endregion // IOptionHandler Members - - #region Private Instance Fields - - private Hashtable m_entriesMap = new Hashtable(); - private LevelMappingEntry[] m_entries = null; - - #endregion // Private Instance Fields - } + /// + /// Manages a mapping from levels to + /// + /// + /// + /// Manages an ordered mapping from instances + /// to subclasses. + /// + /// + /// Nicko Cadell + public sealed class LevelMapping : IOptionHandler + { + #region Public Instance Constructors + + /// + /// Default constructor + /// + /// + /// + /// Initialise a new instance of . + /// + /// + public LevelMapping() + { + } + + #endregion // Public Instance Constructors + + #region Public Instance Methods + + /// + /// Add a to this mapping + /// + /// the entry to add + /// + /// + /// If a has previously been added + /// for the same then that entry will be + /// overwritten. + /// + /// + public void Add(LevelMappingEntry entry) + { + if (m_entriesMap.ContainsKey(entry.Level)) + { + m_entriesMap.Remove(entry.Level); + } + m_entriesMap.Add(entry.Level, entry); + } + + /// + /// Lookup the mapping for the specified level + /// + /// the level to lookup + /// the for the level or null if no mapping found + /// + /// + /// Lookup the value for the specified level. Finds the nearest + /// mapping value for the level that is equal to or less than the + /// specified. + /// + /// + /// If no mapping could be found then null is returned. + /// + /// + public LevelMappingEntry Lookup(Level level) + { + if (m_entries != null) + { + foreach(LevelMappingEntry entry in m_entries) + { + if (level >= entry.Level) + { + return entry; + } + } + } + return null; + } + + #endregion // Public Instance Methods + + #region IOptionHandler Members + + /// + /// Initialize options + /// + /// + /// + /// Caches the sorted list of in an array + /// + /// + public void ActivateOptions() + { + Level[] sortKeys = new Level[m_entriesMap.Count]; + LevelMappingEntry[] sortValues = new LevelMappingEntry[m_entriesMap.Count]; + + m_entriesMap.Keys.CopyTo(sortKeys, 0); + m_entriesMap.Values.CopyTo(sortValues, 0); + + // Sort in level order + Array.Sort(sortKeys, sortValues, 0, sortKeys.Length, null); + + // Reverse list so that highest level is first + Array.Reverse(sortValues, 0, sortValues.Length); + + foreach(LevelMappingEntry entry in sortValues) + { + entry.ActivateOptions(); + } + + m_entries = sortValues; + } + + #endregion // IOptionHandler Members + + #region Private Instance Fields + + private Hashtable m_entriesMap = new Hashtable(); + private LevelMappingEntry[] m_entries = null; + + #endregion // Private Instance Fields + } } diff --git a/src/log4net/Util/LevelMappingEntry.cs b/src/log4net/Util/LevelMappingEntry.cs index 1a3975be..4bbe0044 100644 --- a/src/log4net/Util/LevelMappingEntry.cs +++ b/src/log4net/Util/LevelMappingEntry.cs @@ -24,77 +24,77 @@ namespace log4net.Util { - /// - /// An entry in the - /// - /// - /// - /// This is an abstract base class for types that are stored in the - /// object. - /// - /// - /// Nicko Cadell - public abstract class LevelMappingEntry : IOptionHandler - { - #region Public Instance Constructors + /// + /// An entry in the + /// + /// + /// + /// This is an abstract base class for types that are stored in the + /// object. + /// + /// + /// Nicko Cadell + public abstract class LevelMappingEntry : IOptionHandler + { + #region Public Instance Constructors - /// - /// Default protected constructor - /// - /// - /// - /// Default protected constructor - /// - /// - protected LevelMappingEntry() - { - } + /// + /// Default protected constructor + /// + /// + /// + /// Default protected constructor + /// + /// + protected LevelMappingEntry() + { + } - #endregion // Public Instance Constructors + #endregion // Public Instance Constructors - #region Public Instance Properties + #region Public Instance Properties - /// - /// The level that is the key for this mapping - /// - /// - /// The that is the key for this mapping - /// - /// - /// - /// Get or set the that is the key for this - /// mapping subclass. - /// - /// - public Level Level - { - get { return m_level; } - set { m_level = value; } - } + /// + /// The level that is the key for this mapping + /// + /// + /// The that is the key for this mapping + /// + /// + /// + /// Get or set the that is the key for this + /// mapping subclass. + /// + /// + public Level Level + { + get { return m_level; } + set { m_level = value; } + } - #endregion // Public Instance Properties + #endregion // Public Instance Properties - #region IOptionHandler Members + #region IOptionHandler Members - /// - /// Initialize any options defined on this entry - /// - /// - /// - /// Should be overridden by any classes that need to initialise based on their options - /// - /// - public virtual void ActivateOptions() - { - // default implementation is to do nothing - } + /// + /// Initialize any options defined on this entry + /// + /// + /// + /// Should be overridden by any classes that need to initialise based on their options + /// + /// + public virtual void ActivateOptions() + { + // default implementation is to do nothing + } - #endregion // IOptionHandler Members + #endregion // IOptionHandler Members - #region Private Instance Fields + #region Private Instance Fields - private Level m_level; + private Level m_level; - #endregion // Private Instance Fields - } + #endregion // Private Instance Fields + } } diff --git a/src/log4net/Util/LogLog.cs b/src/log4net/Util/LogLog.cs index 84f640e4..8c0f0a79 100644 --- a/src/log4net/Util/LogLog.cs +++ b/src/log4net/Util/LogLog.cs @@ -30,25 +30,25 @@ namespace log4net.Util /// public delegate void LogReceivedEventHandler(object source, LogReceivedEventArgs e); - /// - /// Outputs log statements from within the log4net assembly. - /// - /// - /// - /// Log4net components cannot make log4net logging calls. However, it is - /// sometimes useful for the user to learn about what log4net is - /// doing. - /// - /// - /// All log4net internal debug calls go to the standard output stream - /// whereas internal error messages are sent to the standard error output - /// stream. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public sealed class LogLog - { + /// + /// Outputs log statements from within the log4net assembly. + /// + /// + /// + /// Log4net components cannot make log4net logging calls. However, it is + /// sometimes useful for the user to learn about what log4net is + /// doing. + /// + /// + /// All log4net internal debug calls go to the standard output stream + /// whereas internal error messages are sent to the standard error output + /// stream. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public sealed class LogLog + { /// /// The event raised when an internal message has been received. /// @@ -63,18 +63,18 @@ public sealed class LogLog /// /// The Type that generated the internal message. /// - public Type Source - { - get { return source; } - } + public Type Source + { + get { return source; } + } /// /// The DateTime stamp of when the internal message was received. /// - public DateTime TimeStamp - { + public DateTime TimeStamp + { get { return timeStampUtc.ToLocalTime(); } - } + } /// /// The UTC DateTime stamp of when the internal message was received. @@ -82,7 +82,7 @@ public DateTime TimeStamp public DateTime TimeStampUtc { get { return timeStampUtc; } - } + } /// /// A string indicating the severity of the internal message. @@ -92,18 +92,18 @@ public DateTime TimeStampUtc /// "log4net:ERROR ", /// "log4net:WARN " /// - public string Prefix - { - get { return prefix; } - } + public string Prefix + { + get { return prefix; } + } /// /// The internal log message. /// - public string Message - { - get { return message; } - } + public string Message + { + get { return message; } + } /// /// The Exception related to the message. @@ -111,22 +111,22 @@ public string Message /// /// Optional. Will be null if no Exception was passed. /// - public Exception Exception - { - get { return exception; } - } + public Exception Exception + { + get { return exception; } + } /// /// Formats Prefix, Source, and Message in the same format as the value /// sent to Console.Out and Trace.Write. /// /// - public override string ToString() - { + public override string ToString() + { return Prefix + Source.Name + ": " + Message; - } + } - #region Private Instance Constructors + #region Private Instance Constructors /// /// Initializes a new instance of the class. @@ -135,142 +135,142 @@ public override string ToString() /// /// /// - public LogLog(Type source, string prefix, string message, Exception exception) - { + public LogLog(Type source, string prefix, string message, Exception exception) + { timeStampUtc = DateTime.UtcNow; - + this.source = source; - this.prefix = prefix; - this.message = message; - this.exception = exception; - } - - #endregion Private Instance Constructors - - #region Static Constructor - - /// - /// Static constructor that initializes logging by reading - /// settings from the application configuration file. - /// - /// - /// - /// The log4net.Internal.Debug application setting - /// controls internal debugging. This setting should be set - /// to true to enable debugging. - /// - /// - /// The log4net.Internal.Quiet application setting - /// suppresses all internal logging including error messages. - /// This setting should be set to true to enable message - /// suppression. - /// - /// - static LogLog() - { + this.prefix = prefix; + this.message = message; + this.exception = exception; + } + + #endregion Private Instance Constructors + + #region Static Constructor + + /// + /// Static constructor that initializes logging by reading + /// settings from the application configuration file. + /// + /// + /// + /// The log4net.Internal.Debug application setting + /// controls internal debugging. This setting should be set + /// to true to enable debugging. + /// + /// + /// The log4net.Internal.Quiet application setting + /// suppresses all internal logging including error messages. + /// This setting should be set to true to enable message + /// suppression. + /// + /// + static LogLog() + { #if !NETCF - try - { - InternalDebugging = OptionConverter.ToBoolean(SystemInfo.GetAppSetting("log4net.Internal.Debug"), false); - QuietMode = OptionConverter.ToBoolean(SystemInfo.GetAppSetting("log4net.Internal.Quiet"), false); - EmitInternalMessages = OptionConverter.ToBoolean(SystemInfo.GetAppSetting("log4net.Internal.Emit"), true); - } - catch(Exception ex) - { - // If an exception is thrown here then it looks like the config file does not - // parse correctly. - // - // We will leave debug OFF and print an Error message - Error(typeof(LogLog), "Exception while reading ConfigurationSettings. Check your .config file is well formed XML.", ex); - } + try + { + InternalDebugging = OptionConverter.ToBoolean(SystemInfo.GetAppSetting("log4net.Internal.Debug"), false); + QuietMode = OptionConverter.ToBoolean(SystemInfo.GetAppSetting("log4net.Internal.Quiet"), false); + EmitInternalMessages = OptionConverter.ToBoolean(SystemInfo.GetAppSetting("log4net.Internal.Emit"), true); + } + catch(Exception ex) + { + // If an exception is thrown here then it looks like the config file does not + // parse correctly. + // + // We will leave debug OFF and print an Error message + Error(typeof(LogLog), "Exception while reading ConfigurationSettings. Check your .config file is well formed XML.", ex); + } #endif - } - - #endregion Static Constructor - - #region Public Static Properties - - /// - /// Gets or sets a value indicating whether log4net internal logging - /// is enabled or disabled. - /// - /// - /// true if log4net internal logging is enabled, otherwise - /// false. - /// - /// - /// - /// When set to true, internal debug level logging will be - /// displayed. - /// - /// - /// This value can be set by setting the application setting - /// log4net.Internal.Debug in the application configuration - /// file. - /// - /// - /// The default value is false, i.e. debugging is - /// disabled. - /// - /// - /// - /// - /// The following example enables internal debugging using the - /// application configuration file : - /// - /// - /// - /// - /// - /// - /// - /// - /// - public static bool InternalDebugging - { - get { return s_debugEnabled; } - set { s_debugEnabled = value; } - } - - /// - /// Gets or sets a value indicating whether log4net should generate no output - /// from internal logging, not even for errors. - /// - /// - /// true if log4net should generate no output at all from internal - /// logging, otherwise false. - /// - /// - /// - /// When set to true will cause internal logging at all levels to be - /// suppressed. This means that no warning or error reports will be logged. - /// This option overrides the setting and - /// disables all debug also. - /// - /// This value can be set by setting the application setting - /// log4net.Internal.Quiet in the application configuration file. - /// - /// - /// The default value is false, i.e. internal logging is not - /// disabled. - /// - /// - /// - /// The following example disables internal logging using the - /// application configuration file : - /// - /// - /// - /// - /// - /// - /// - /// - public static bool QuietMode - { - get { return s_quietMode; } - set { s_quietMode = value; } - } + } + + #endregion Static Constructor + + #region Public Static Properties + + /// + /// Gets or sets a value indicating whether log4net internal logging + /// is enabled or disabled. + /// + /// + /// true if log4net internal logging is enabled, otherwise + /// false. + /// + /// + /// + /// When set to true, internal debug level logging will be + /// displayed. + /// + /// + /// This value can be set by setting the application setting + /// log4net.Internal.Debug in the application configuration + /// file. + /// + /// + /// The default value is false, i.e. debugging is + /// disabled. + /// + /// + /// + /// + /// The following example enables internal debugging using the + /// application configuration file : + /// + /// + /// + /// + /// + /// + /// + /// + /// + public static bool InternalDebugging + { + get { return s_debugEnabled; } + set { s_debugEnabled = value; } + } + + /// + /// Gets or sets a value indicating whether log4net should generate no output + /// from internal logging, not even for errors. + /// + /// + /// true if log4net should generate no output at all from internal + /// logging, otherwise false. + /// + /// + /// + /// When set to true will cause internal logging at all levels to be + /// suppressed. This means that no warning or error reports will be logged. + /// This option overrides the setting and + /// disables all debug also. + /// + /// This value can be set by setting the application setting + /// log4net.Internal.Quiet in the application configuration file. + /// + /// + /// The default value is false, i.e. internal logging is not + /// disabled. + /// + /// + /// + /// The following example disables internal logging using the + /// application configuration file : + /// + /// + /// + /// + /// + /// + /// + /// + public static bool QuietMode + { + get { return s_quietMode; } + set { s_quietMode = value; } + } /// /// @@ -281,9 +281,9 @@ public static bool EmitInternalMessages set { s_emitInternalMessages = value; } } - #endregion Public Static Properties + #endregion Public Static Properties - #region Public Static Methods + #region Public Static Methods /// /// Raises the LogReceived event when an internal messages is received. @@ -300,64 +300,64 @@ public static void OnLogReceived(Type source, string prefix, string message, Exc } } - /// - /// Test if LogLog.Debug is enabled for output. - /// - /// - /// true if Debug is enabled - /// - /// - /// - /// Test if LogLog.Debug is enabled for output. - /// - /// - public static bool IsDebugEnabled - { - get { return s_debugEnabled && !s_quietMode; } - } - - /// - /// Writes log4net internal debug messages to the - /// standard output stream. - /// + /// + /// Test if LogLog.Debug is enabled for output. + /// + /// + /// true if Debug is enabled + /// + /// + /// + /// Test if LogLog.Debug is enabled for output. + /// + /// + public static bool IsDebugEnabled + { + get { return s_debugEnabled && !s_quietMode; } + } + + /// + /// Writes log4net internal debug messages to the + /// standard output stream. + /// /// - /// The message to log. - /// - /// - /// All internal debug messages are prepended with - /// the string "log4net: ". - /// - /// - public static void Debug(Type source, string message) - { - if (IsDebugEnabled) - { + /// The message to log. + /// + /// + /// All internal debug messages are prepended with + /// the string "log4net: ". + /// + /// + public static void Debug(Type source, string message) + { + if (IsDebugEnabled) + { if (EmitInternalMessages) { EmitOutLine(PREFIX + message); } OnLogReceived(source, PREFIX, message, null); - } - } + } + } - /// - /// Writes log4net internal debug messages to the - /// standard output stream. - /// + /// + /// Writes log4net internal debug messages to the + /// standard output stream. + /// /// The Type that generated this message. - /// The message to log. - /// An exception to log. - /// - /// - /// All internal debug messages are prepended with - /// the string "log4net: ". - /// - /// - public static void Debug(Type source, string message, Exception exception) - { - if (IsDebugEnabled) - { + /// The message to log. + /// An exception to log. + /// + /// + /// All internal debug messages are prepended with + /// the string "log4net: ". + /// + /// + public static void Debug(Type source, string message, Exception exception) + { + if (IsDebugEnabled) + { if (EmitInternalMessages) { EmitOutLine(PREFIX + message); @@ -368,67 +368,67 @@ public static void Debug(Type source, string message, Exception exception) } OnLogReceived(source, PREFIX, message, exception); - } - } + } + } - /// - /// Test if LogLog.Warn is enabled for output. - /// - /// - /// true if Warn is enabled - /// - /// - /// - /// Test if LogLog.Warn is enabled for output. - /// - /// - public static bool IsWarnEnabled - { - get { return !s_quietMode; } - } - - /// - /// Writes log4net internal warning messages to the - /// standard error stream. - /// + /// + /// Test if LogLog.Warn is enabled for output. + /// + /// + /// true if Warn is enabled + /// + /// + /// + /// Test if LogLog.Warn is enabled for output. + /// + /// + public static bool IsWarnEnabled + { + get { return !s_quietMode; } + } + + /// + /// Writes log4net internal warning messages to the + /// standard error stream. + /// /// The Type that generated this message. - /// The message to log. - /// - /// - /// All internal warning messages are prepended with - /// the string "log4net:WARN ". - /// - /// - public static void Warn(Type source, string message) - { - if (IsWarnEnabled) - { + /// The message to log. + /// + /// + /// All internal warning messages are prepended with + /// the string "log4net:WARN ". + /// + /// + public static void Warn(Type source, string message) + { + if (IsWarnEnabled) + { if (EmitInternalMessages) { EmitErrorLine(WARN_PREFIX + message); } OnLogReceived(source, WARN_PREFIX, message, null); - } - } + } + } - /// - /// Writes log4net internal warning messages to the - /// standard error stream. - /// + /// + /// Writes log4net internal warning messages to the + /// standard error stream. + /// /// The Type that generated this message. - /// The message to log. - /// An exception to log. - /// - /// - /// All internal warning messages are prepended with - /// the string "log4net:WARN ". - /// - /// - public static void Warn(Type source, string message, Exception exception) - { - if (IsWarnEnabled) - { + /// The message to log. + /// An exception to log. + /// + /// + /// All internal warning messages are prepended with + /// the string "log4net:WARN ". + /// + /// + public static void Warn(Type source, string message, Exception exception) + { + if (IsWarnEnabled) + { if (EmitInternalMessages) { EmitErrorLine(WARN_PREFIX + message); @@ -439,67 +439,67 @@ public static void Warn(Type source, string message, Exception exception) } OnLogReceived(source, WARN_PREFIX, message, exception); - } - } - - /// - /// Test if LogLog.Error is enabled for output. - /// - /// - /// true if Error is enabled - /// - /// - /// - /// Test if LogLog.Error is enabled for output. - /// - /// - public static bool IsErrorEnabled - { - get { return !s_quietMode; } - } - - /// - /// Writes log4net internal error messages to the - /// standard error stream. - /// + } + } + + /// + /// Test if LogLog.Error is enabled for output. + /// + /// + /// true if Error is enabled + /// + /// + /// + /// Test if LogLog.Error is enabled for output. + /// + /// + public static bool IsErrorEnabled + { + get { return !s_quietMode; } + } + + /// + /// Writes log4net internal error messages to the + /// standard error stream. + /// /// The Type that generated this message. - /// The message to log. - /// - /// - /// All internal error messages are prepended with - /// the string "log4net:ERROR ". - /// - /// - public static void Error(Type source, string message) - { - if (IsErrorEnabled) - { + /// The message to log. + /// + /// + /// All internal error messages are prepended with + /// the string "log4net:ERROR ". + /// + /// + public static void Error(Type source, string message) + { + if (IsErrorEnabled) + { if (EmitInternalMessages) { EmitErrorLine(ERR_PREFIX + message); } OnLogReceived(source, ERR_PREFIX, message, null); - } - } + } + } - /// - /// Writes log4net internal error messages to the - /// standard error stream. - /// + /// + /// Writes log4net internal error messages to the + /// standard error stream. + /// /// The Type that generated this message. - /// The message to log. - /// An exception to log. - /// - /// - /// All internal debug messages are prepended with - /// the string "log4net:ERROR ". - /// - /// - public static void Error(Type source, string message, Exception exception) - { - if (IsErrorEnabled) - { + /// The message to log. + /// An exception to log. + /// + /// + /// All internal debug messages are prepended with + /// the string "log4net:ERROR ". + /// + /// + public static void Error(Type source, string message, Exception exception) + { + if (IsErrorEnabled) + { if (EmitInternalMessages) { EmitErrorLine(ERR_PREFIX + message); @@ -510,98 +510,98 @@ public static void Error(Type source, string message, Exception exception) } OnLogReceived(source, ERR_PREFIX, message, exception); - } - } - - #endregion Public Static Methods - - /// - /// Writes output to the standard output stream. - /// - /// The message to log. - /// - /// - /// Writes to both Console.Out and System.Diagnostics.Trace. - /// Note that the System.Diagnostics.Trace is not supported - /// on the Compact Framework. - /// - /// - /// If the AppDomain is not configured with a config file then - /// the call to System.Diagnostics.Trace may fail. This is only - /// an issue if you are programmatically creating your own AppDomains. - /// - /// - private static void EmitOutLine(string message) - { - try - { + } + } + + #endregion Public Static Methods + + /// + /// Writes output to the standard output stream. + /// + /// The message to log. + /// + /// + /// Writes to both Console.Out and System.Diagnostics.Trace. + /// Note that the System.Diagnostics.Trace is not supported + /// on the Compact Framework. + /// + /// + /// If the AppDomain is not configured with a config file then + /// the call to System.Diagnostics.Trace may fail. This is only + /// an issue if you are programmatically creating your own AppDomains. + /// + /// + private static void EmitOutLine(string message) + { + try + { #if NETCF - Console.WriteLine(message); - //System.Diagnostics.Debug.WriteLine(message); + Console.WriteLine(message); + //System.Diagnostics.Debug.WriteLine(message); #else - Console.Out.WriteLine(message); - Trace.WriteLine(message); + Console.Out.WriteLine(message); + Trace.WriteLine(message); #endif - } - catch - { - // Ignore exception, what else can we do? Not really a good idea to propagate back to the caller - } - } - - /// - /// Writes output to the standard error stream. - /// - /// The message to log. - /// - /// - /// Writes to both Console.Error and System.Diagnostics.Trace. - /// Note that the System.Diagnostics.Trace is not supported - /// on the Compact Framework. - /// - /// - /// If the AppDomain is not configured with a config file then - /// the call to System.Diagnostics.Trace may fail. This is only - /// an issue if you are programmatically creating your own AppDomains. - /// - /// - private static void EmitErrorLine(string message) - { - try - { + } + catch + { + // Ignore exception, what else can we do? Not really a good idea to propagate back to the caller + } + } + + /// + /// Writes output to the standard error stream. + /// + /// The message to log. + /// + /// + /// Writes to both Console.Error and System.Diagnostics.Trace. + /// Note that the System.Diagnostics.Trace is not supported + /// on the Compact Framework. + /// + /// + /// If the AppDomain is not configured with a config file then + /// the call to System.Diagnostics.Trace may fail. This is only + /// an issue if you are programmatically creating your own AppDomains. + /// + /// + private static void EmitErrorLine(string message) + { + try + { #if NETCF - Console.WriteLine(message); - //System.Diagnostics.Debug.WriteLine(message); + Console.WriteLine(message); + //System.Diagnostics.Debug.WriteLine(message); #else - Console.Error.WriteLine(message); - Trace.WriteLine(message); + Console.Error.WriteLine(message); + Trace.WriteLine(message); #endif - } - catch - { - // Ignore exception, what else can we do? Not really a good idea to propagate back to the caller - } - } + } + catch + { + // Ignore exception, what else can we do? Not really a good idea to propagate back to the caller + } + } - #region Private Static Fields + #region Private Static Fields - /// - /// Default debug level - /// - private static bool s_debugEnabled = false; + /// + /// Default debug level + /// + private static bool s_debugEnabled = false; - /// - /// In quietMode not even errors generate any output. - /// - private static bool s_quietMode = false; + /// + /// In quietMode not even errors generate any output. + /// + private static bool s_quietMode = false; private static bool s_emitInternalMessages = true; - private const string PREFIX = "log4net: "; - private const string ERR_PREFIX = "log4net:ERROR "; - private const string WARN_PREFIX = "log4net:WARN "; + private const string PREFIX = "log4net: "; + private const string ERR_PREFIX = "log4net:ERROR "; + private const string WARN_PREFIX = "log4net:WARN "; - #endregion Private Static Fields + #endregion Private Static Fields /// /// Subscribes to the LogLog.LogReceived event and stores messages @@ -646,7 +646,7 @@ public void Dispose() LogReceived -= handler; } } - } + } /// /// diff --git a/src/log4net/Util/LogicalThreadContextProperties.cs b/src/log4net/Util/LogicalThreadContextProperties.cs index 179c22b8..8a938943 100644 --- a/src/log4net/Util/LogicalThreadContextProperties.cs +++ b/src/log4net/Util/LogicalThreadContextProperties.cs @@ -31,251 +31,251 @@ namespace log4net.Util { - /// - /// Implementation of Properties collection for the - /// - /// - /// - /// Class implements a collection of properties that is specific to each thread. - /// The class is not synchronized as each thread has its own . - /// - /// - /// This class stores its properties in a slot on the named - /// log4net.Util.LogicalThreadContextProperties. - /// - /// - /// For .NET Standard 1.3 this class uses - /// System.Threading.AsyncLocal rather than . - /// - /// - /// The requires a link time - /// for the - /// . - /// If the calling code does not have this permission then this context will be disabled. - /// It will not store any property values set on it. - /// - /// - /// Nicko Cadell - public sealed class LogicalThreadContextProperties : ContextPropertiesBase - { + /// + /// Implementation of Properties collection for the + /// + /// + /// + /// Class implements a collection of properties that is specific to each thread. + /// The class is not synchronized as each thread has its own . + /// + /// + /// This class stores its properties in a slot on the named + /// log4net.Util.LogicalThreadContextProperties. + /// + /// + /// For .NET Standard 1.3 this class uses + /// System.Threading.AsyncLocal rather than . + /// + /// + /// The requires a link time + /// for the + /// . + /// If the calling code does not have this permission then this context will be disabled. + /// It will not store any property values set on it. + /// + /// + /// Nicko Cadell + public sealed class LogicalThreadContextProperties : ContextPropertiesBase + { #if NETSTANDARD - private static readonly AsyncLocal AsyncLocalDictionary = new AsyncLocal(); + private static readonly AsyncLocal AsyncLocalDictionary = new AsyncLocal(); #else - private const string c_SlotName = "log4net.Util.LogicalThreadContextProperties"; + private const string c_SlotName = "log4net.Util.LogicalThreadContextProperties"; #endif - - /// - /// Flag used to disable this context if we don't have permission to access the CallContext. - /// - private bool m_disabled = false; - - #region Public Instance Constructors + + /// + /// Flag used to disable this context if we don't have permission to access the CallContext. + /// + private bool m_disabled = false; + + #region Public Instance Constructors - /// - /// Constructor - /// - /// - /// - /// Initializes a new instance of the class. - /// - /// - internal LogicalThreadContextProperties() - { - } + /// + /// Constructor + /// + /// + /// + /// Initializes a new instance of the class. + /// + /// + internal LogicalThreadContextProperties() + { + } - #endregion Public Instance Constructors + #endregion Public Instance Constructors - #region Public Instance Properties + #region Public Instance Properties - /// - /// Gets or sets the value of a property - /// - /// - /// The value for the property with the specified key - /// - /// - /// - /// Get or set the property value for the specified. - /// - /// - public override object this[string key] - { - get - { - // Don't create the dictionary if it does not already exist - PropertiesDictionary dictionary = GetProperties(false); - if (dictionary != null) - { - return dictionary[key]; - } - return null; - } - set - { - // Force the dictionary to be created - PropertiesDictionary props = GetProperties(true); - // Reason for cloning the dictionary below: object instances set on the CallContext - // need to be immutable to correctly flow through async/await - PropertiesDictionary immutableProps = new PropertiesDictionary(props); - immutableProps[key] = value; - SetLogicalProperties(immutableProps); - } - } + /// + /// Gets or sets the value of a property + /// + /// + /// The value for the property with the specified key + /// + /// + /// + /// Get or set the property value for the specified. + /// + /// + public override object this[string key] + { + get + { + // Don't create the dictionary if it does not already exist + PropertiesDictionary dictionary = GetProperties(false); + if (dictionary != null) + { + return dictionary[key]; + } + return null; + } + set + { + // Force the dictionary to be created + PropertiesDictionary props = GetProperties(true); + // Reason for cloning the dictionary below: object instances set on the CallContext + // need to be immutable to correctly flow through async/await + PropertiesDictionary immutableProps = new PropertiesDictionary(props); + immutableProps[key] = value; + SetLogicalProperties(immutableProps); + } + } - #endregion Public Instance Properties + #endregion Public Instance Properties - #region Public Instance Methods + #region Public Instance Methods - /// - /// Remove a property - /// - /// the key for the entry to remove - /// - /// - /// Remove the value for the specified from the context. - /// - /// - public void Remove(string key) - { - PropertiesDictionary dictionary = GetProperties(false); - if (dictionary != null) - { - PropertiesDictionary immutableProps = new PropertiesDictionary(dictionary); - immutableProps.Remove(key); - SetLogicalProperties(immutableProps); - } - } + /// + /// Remove a property + /// + /// the key for the entry to remove + /// + /// + /// Remove the value for the specified from the context. + /// + /// + public void Remove(string key) + { + PropertiesDictionary dictionary = GetProperties(false); + if (dictionary != null) + { + PropertiesDictionary immutableProps = new PropertiesDictionary(dictionary); + immutableProps.Remove(key); + SetLogicalProperties(immutableProps); + } + } - /// - /// Clear all the context properties - /// - /// - /// - /// Clear all the context properties - /// - /// - public void Clear() - { - PropertiesDictionary dictionary = GetProperties(false); - if (dictionary != null) - { - PropertiesDictionary immutableProps = new PropertiesDictionary(); - SetLogicalProperties(immutableProps); - } - } + /// + /// Clear all the context properties + /// + /// + /// + /// Clear all the context properties + /// + /// + public void Clear() + { + PropertiesDictionary dictionary = GetProperties(false); + if (dictionary != null) + { + PropertiesDictionary immutableProps = new PropertiesDictionary(); + SetLogicalProperties(immutableProps); + } + } - #endregion Public Instance Methods + #endregion Public Instance Methods - #region Internal Instance Methods + #region Internal Instance Methods - /// - /// Get the PropertiesDictionary stored in the LocalDataStoreSlot for this thread. - /// - /// create the dictionary if it does not exist, otherwise return null if is does not exist - /// the properties for this thread - /// - /// - /// 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. - /// - /// - internal PropertiesDictionary GetProperties(bool create) - { - if (!m_disabled) - { - try - { - PropertiesDictionary properties = GetLogicalProperties(); - if (properties == null && create) - { - properties = new PropertiesDictionary(); - SetLogicalProperties(properties); - } - return properties; - } - catch (SecurityException secEx) - { - m_disabled = true; - - // Thrown if we don't have permission to read or write the CallContext - LogLog.Warn(declaringType, "SecurityException while accessing CallContext. Disabling LogicalThreadContextProperties", secEx); - } - } - - // Only get here is we are disabled because of a security exception - if (create) - { - return new PropertiesDictionary(); - } - return null; - } + /// + /// Get the PropertiesDictionary stored in the LocalDataStoreSlot for this thread. + /// + /// create the dictionary if it does not exist, otherwise return null if is does not exist + /// the properties for this thread + /// + /// + /// 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. + /// + /// + internal PropertiesDictionary GetProperties(bool create) + { + if (!m_disabled) + { + try + { + PropertiesDictionary properties = GetLogicalProperties(); + if (properties == null && create) + { + properties = new PropertiesDictionary(); + SetLogicalProperties(properties); + } + return properties; + } + catch (SecurityException secEx) + { + m_disabled = true; + + // Thrown if we don't have permission to read or write the CallContext + LogLog.Warn(declaringType, "SecurityException while accessing CallContext. Disabling LogicalThreadContextProperties", secEx); + } + } + + // Only get here is we are disabled because of a security exception + if (create) + { + return new PropertiesDictionary(); + } + return null; + } - #endregion Internal Instance Methods + #endregion Internal Instance Methods #region Private Static Methods /// - /// Gets the call context get data. - /// - /// The peroperties dictionary stored in the call context - /// - /// The method has a - /// security link demand, therfore we must put the method call in a seperate method - /// that we can wrap in an exception handler. - /// + /// Gets the call context get data. + /// + /// The peroperties dictionary stored in the call context + /// + /// The method has a + /// security link demand, therfore we must put the method call in a seperate method + /// that we can wrap in an exception handler. + /// #if NET_4_0 || MONO_4_0 || NETSTANDARD [System.Security.SecuritySafeCritical] #endif private static PropertiesDictionary GetLogicalProperties() - { + { #if NETSTANDARD return AsyncLocalDictionary.Value; #elif NET_2_0 || MONO_2_0 || MONO_3_5 || MONO_4_0 return CallContext.LogicalGetData(c_SlotName) as PropertiesDictionary; #else - return CallContext.GetData(c_SlotName) as PropertiesDictionary; + return CallContext.GetData(c_SlotName) as PropertiesDictionary; #endif - } + } - /// - /// Sets the call context data. - /// - /// The properties. - /// - /// The method has a - /// security link demand, therfore we must put the method call in a seperate method - /// that we can wrap in an exception handler. - /// + /// + /// Sets the call context data. + /// + /// The properties. + /// + /// The method has a + /// security link demand, therfore we must put the method call in a seperate method + /// that we can wrap in an exception handler. + /// #if NET_4_0 || MONO_4_0 || NETSTANDARD [System.Security.SecuritySafeCritical] #endif private static void SetLogicalProperties(PropertiesDictionary properties) - { + { #if NETSTANDARD - AsyncLocalDictionary.Value = properties; + AsyncLocalDictionary.Value = properties; #elif NET_2_0 || MONO_2_0 || MONO_3_5 || MONO_4_0 - CallContext.LogicalSetData(c_SlotName, properties); + CallContext.LogicalSetData(c_SlotName, properties); #else - CallContext.SetData(c_SlotName, properties); + CallContext.SetData(c_SlotName, properties); #endif } #endregion - #region Private Static Fields + #region Private Static Fields - /// - /// The fully qualified type of the LogicalThreadContextProperties class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(LogicalThreadContextProperties); + /// + /// The fully qualified type of the LogicalThreadContextProperties class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(LogicalThreadContextProperties); - #endregion Private Static Fields + #endregion Private Static Fields } } diff --git a/src/log4net/Util/LogicalThreadContextStack.cs b/src/log4net/Util/LogicalThreadContextStack.cs index dbad39a2..45993ebc 100644 --- a/src/log4net/Util/LogicalThreadContextStack.cs +++ b/src/log4net/Util/LogicalThreadContextStack.cs @@ -26,424 +26,424 @@ namespace log4net.Util { - /// - /// Delegate type used for LogicalThreadContextStack's callbacks. - /// - #if NET_2_0 || MONO_2_0 || NETSTANDARD - public delegate void TwoArgAction(T1 t1, T2 t2); - #else - public delegate void TwoArgAction(string t1, LogicalThreadContextStack t2); - #endif - - /// - /// Implementation of Stack for the - /// - /// - /// - /// Implementation of Stack for the - /// - /// - /// Nicko Cadell - public sealed class LogicalThreadContextStack : IFixingRequired - { - #region Private Instance Fields - - /// - /// The stack store. - /// - private Stack m_stack = new Stack(); - - /// - /// The name of this within the - /// . - /// - private string m_propertyKey; - - /// - /// The callback used to let the register a - /// new instance of a . - /// - #if NET_2_0 || MONO_2_0 || NETSTANDARD - private TwoArgAction m_registerNew; - #else - private TwoArgAction m_registerNew; - #endif - - #endregion Private Instance Fields - - #region Public Instance Constructors - - /// - /// Internal constructor - /// - /// - /// - /// Initializes a new instance of the class. - /// - /// - #if NET_2_0 || MONO_2_0 || NETSTANDARD - internal LogicalThreadContextStack(string propertyKey, TwoArgAction registerNew) - #else - internal LogicalThreadContextStack(string propertyKey, TwoArgAction registerNew) - #endif - { - m_propertyKey = propertyKey; - m_registerNew = registerNew; - } - - #endregion Public Instance Constructors - - #region Public Properties - - /// - /// The number of messages in the stack - /// - /// - /// The current number of messages in the stack - /// - /// - /// - /// The current number of messages in the stack. That is - /// the number of times has been called - /// minus the number of times has been called. - /// - /// - public int Count - { - get { return m_stack.Count; } - } - - #endregion // Public Properties - - #region Public Methods - - /// - /// Clears all the contextual information held in this stack. - /// - /// - /// - /// Clears all the contextual information held in this stack. - /// Only call this if you think that this thread is being reused after - /// a previous call execution which may not have completed correctly. - /// You do not need to use this method if you always guarantee to call - /// the method of the - /// returned from even in exceptional circumstances, - /// for example by using the using(log4net.LogicalThreadContext.Stacks["NDC"].Push("Stack_Message")) - /// syntax. - /// - /// - public void Clear() - { - m_registerNew(m_propertyKey, new LogicalThreadContextStack(m_propertyKey, m_registerNew)); - } - - /// - /// Removes the top context from this stack. - /// - /// The message in the context that was removed from the top of this stack. - /// - /// - /// Remove the top context from this stack, and return - /// it to the caller. If this stack is empty then an - /// empty string (not ) is returned. - /// - /// - public string Pop() - { - // copy current stack - Stack stack = new Stack(new Stack(m_stack)); - string result = ""; - if (stack.Count > 0) - { - result = ((StackFrame)(stack.Pop())).Message; - } - LogicalThreadContextStack ltcs = new LogicalThreadContextStack(m_propertyKey, m_registerNew); - ltcs.m_stack = stack; - m_registerNew(m_propertyKey, ltcs); - return result; - } - - /// - /// Pushes a new context message into this stack. - /// - /// The new context message. - /// - /// An that can be used to clean up the context stack. - /// - /// - /// - /// Pushes a new context onto this stack. An - /// is returned that can be used to clean up this stack. This - /// can be easily combined with the using keyword to scope the - /// context. - /// - /// - /// Simple example of using the Push method with the using keyword. - /// - /// using(log4net.LogicalThreadContext.Stacks["NDC"].Push("Stack_Message")) - /// { - /// log.Warn("This should have an ThreadContext Stack message"); - /// } - /// - /// - public IDisposable Push(string message) - { - // do modifications on a copy - Stack stack = new Stack(new Stack(m_stack)); - stack.Push(new StackFrame(message, (stack.Count > 0) ? (StackFrame)stack.Peek() : null)); - - LogicalThreadContextStack contextStack = new LogicalThreadContextStack(m_propertyKey, m_registerNew); - contextStack.m_stack = stack; - m_registerNew(m_propertyKey, contextStack); - return new AutoPopStackFrame(contextStack, stack.Count - 1); - } - - /// - /// Returns the top context from this stack. - /// - /// The message in the context from the top of this stack. - /// - /// - /// Returns the top context from this stack. If this stack is empty then an - /// empty string (not ) is returned. - /// - /// - public string Peek() - { - Stack stack = m_stack; - if (stack.Count > 0) - { - return ((StackFrame)stack.Peek()).Message; - } - return ""; - } - - #endregion Public Methods - - #region Internal Methods - - /// - /// Gets the current context information for this stack. - /// - /// The current context information. - internal string GetFullMessage() - { - Stack stack = m_stack; - if (stack.Count > 0) - { - return ((StackFrame)(stack.Peek())).FullMessage; - } - return null; - } - - /// - /// Gets and sets the internal stack used by this - /// - /// The internal storage stack - /// - /// - /// This property is provided only to support backward compatability - /// of the . Tytpically the internal stack should not - /// be modified. - /// - /// - internal Stack InternalStack - { - get { return m_stack; } - set { m_stack = value; } - } - - #endregion Internal Methods - - /// - /// Gets the current context information for this stack. - /// - /// Gets the current context information - /// - /// - /// Gets the current context information for this stack. - /// - /// - public override string ToString() - { - return GetFullMessage(); - } - - /// - /// Get a portable version of this object - /// - /// the portable instance of this object - /// - /// - /// Get a cross thread portable version of this object - /// - /// - object IFixingRequired.GetFixedObject() - { - return GetFullMessage(); - } - - /// - /// Inner class used to represent a single context frame in the stack. - /// - /// - /// - /// Inner class used to represent a single context frame in the stack. - /// - /// - 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 - - /// - /// Constructor - /// - /// The message for this context. - /// The parent context in the chain. - /// - /// - /// Initializes a new instance of the class - /// with the specified message and parent context. - /// - /// - 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 - - /// - /// Get the message. - /// - /// The message. - /// - /// - /// Get the message. - /// - /// - internal string Message - { - get { return m_message; } - } - - /// - /// Gets the full text of the context down to the root level. - /// - /// - /// The full text of the context down to the root level. - /// - /// - /// - /// Gets the full text of the context down to the root level. - /// - /// - internal string FullMessage - { - get - { - if (m_fullMessage == null && m_parent != null) - { - m_fullMessage = string.Concat(m_parent.FullMessage, " ", m_message); - } - return m_fullMessage; - } - } - - #endregion Internal Instance Properties - } - - /// - /// Struct returned from the method. - /// - /// - /// - /// This struct implements the and is designed to be used - /// with the pattern to remove the stack frame at the end of the scope. - /// - /// - private struct AutoPopStackFrame : IDisposable - { - #region Private Instance Fields - - /// - /// The depth to trim the stack to when this instance is disposed - /// - private int m_frameDepth; - - /// - /// The outer LogicalThreadContextStack. - /// - private LogicalThreadContextStack m_logicalThreadContextStack; - - #endregion Private Instance Fields - - #region Internal Instance Constructors - - /// - /// Constructor - /// - /// The internal stack used by the ThreadContextStack. - /// The depth to return the stack to when this object is disposed. - /// - /// - /// Initializes a new instance of the class with - /// the specified stack and return depth. - /// - /// - internal AutoPopStackFrame(LogicalThreadContextStack logicalThreadContextStack, int frameDepth) - { - m_frameDepth = frameDepth; - m_logicalThreadContextStack = logicalThreadContextStack; - } - - #endregion Internal Instance Constructors - - #region Implementation of IDisposable - - /// - /// Returns the stack to the correct depth. - /// - /// - /// - /// Returns the stack to the correct depth. - /// - /// - public void Dispose() - { - if (m_frameDepth >= 0 && m_logicalThreadContextStack.m_stack != null) - { - Stack stack = new Stack(new Stack(m_logicalThreadContextStack.m_stack)); - while (stack.Count > m_frameDepth) - { - stack.Pop(); - } - LogicalThreadContextStack ltcs = new LogicalThreadContextStack(m_logicalThreadContextStack.m_propertyKey, m_logicalThreadContextStack.m_registerNew); - ltcs.m_stack = stack; - m_logicalThreadContextStack.m_registerNew(m_logicalThreadContextStack.m_propertyKey, - ltcs); - } - } - - #endregion Implementation of IDisposable - } - - } + /// + /// Delegate type used for LogicalThreadContextStack's callbacks. + /// + #if NET_2_0 || MONO_2_0 || NETSTANDARD + public delegate void TwoArgAction(T1 t1, T2 t2); + #else + public delegate void TwoArgAction(string t1, LogicalThreadContextStack t2); + #endif + + /// + /// Implementation of Stack for the + /// + /// + /// + /// Implementation of Stack for the + /// + /// + /// Nicko Cadell + public sealed class LogicalThreadContextStack : IFixingRequired + { + #region Private Instance Fields + + /// + /// The stack store. + /// + private Stack m_stack = new Stack(); + + /// + /// The name of this within the + /// . + /// + private string m_propertyKey; + + /// + /// The callback used to let the register a + /// new instance of a . + /// + #if NET_2_0 || MONO_2_0 || NETSTANDARD + private TwoArgAction m_registerNew; + #else + private TwoArgAction m_registerNew; + #endif + + #endregion Private Instance Fields + + #region Public Instance Constructors + + /// + /// Internal constructor + /// + /// + /// + /// Initializes a new instance of the class. + /// + /// + #if NET_2_0 || MONO_2_0 || NETSTANDARD + internal LogicalThreadContextStack(string propertyKey, TwoArgAction registerNew) + #else + internal LogicalThreadContextStack(string propertyKey, TwoArgAction registerNew) + #endif + { + m_propertyKey = propertyKey; + m_registerNew = registerNew; + } + + #endregion Public Instance Constructors + + #region Public Properties + + /// + /// The number of messages in the stack + /// + /// + /// The current number of messages in the stack + /// + /// + /// + /// The current number of messages in the stack. That is + /// the number of times has been called + /// minus the number of times has been called. + /// + /// + public int Count + { + get { return m_stack.Count; } + } + + #endregion // Public Properties + + #region Public Methods + + /// + /// Clears all the contextual information held in this stack. + /// + /// + /// + /// Clears all the contextual information held in this stack. + /// Only call this if you think that this thread is being reused after + /// a previous call execution which may not have completed correctly. + /// You do not need to use this method if you always guarantee to call + /// the method of the + /// returned from even in exceptional circumstances, + /// for example by using the using(log4net.LogicalThreadContext.Stacks["NDC"].Push("Stack_Message")) + /// syntax. + /// + /// + public void Clear() + { + m_registerNew(m_propertyKey, new LogicalThreadContextStack(m_propertyKey, m_registerNew)); + } + + /// + /// Removes the top context from this stack. + /// + /// The message in the context that was removed from the top of this stack. + /// + /// + /// Remove the top context from this stack, and return + /// it to the caller. If this stack is empty then an + /// empty string (not ) is returned. + /// + /// + public string Pop() + { + // copy current stack + Stack stack = new Stack(new Stack(m_stack)); + string result = ""; + if (stack.Count > 0) + { + result = ((StackFrame)(stack.Pop())).Message; + } + LogicalThreadContextStack ltcs = new LogicalThreadContextStack(m_propertyKey, m_registerNew); + ltcs.m_stack = stack; + m_registerNew(m_propertyKey, ltcs); + return result; + } + + /// + /// Pushes a new context message into this stack. + /// + /// The new context message. + /// + /// An that can be used to clean up the context stack. + /// + /// + /// + /// Pushes a new context onto this stack. An + /// is returned that can be used to clean up this stack. This + /// can be easily combined with the using keyword to scope the + /// context. + /// + /// + /// Simple example of using the Push method with the using keyword. + /// + /// using(log4net.LogicalThreadContext.Stacks["NDC"].Push("Stack_Message")) + /// { + /// log.Warn("This should have an ThreadContext Stack message"); + /// } + /// + /// + public IDisposable Push(string message) + { + // do modifications on a copy + Stack stack = new Stack(new Stack(m_stack)); + stack.Push(new StackFrame(message, (stack.Count > 0) ? (StackFrame)stack.Peek() : null)); + + LogicalThreadContextStack contextStack = new LogicalThreadContextStack(m_propertyKey, m_registerNew); + contextStack.m_stack = stack; + m_registerNew(m_propertyKey, contextStack); + return new AutoPopStackFrame(contextStack, stack.Count - 1); + } + + /// + /// Returns the top context from this stack. + /// + /// The message in the context from the top of this stack. + /// + /// + /// Returns the top context from this stack. If this stack is empty then an + /// empty string (not ) is returned. + /// + /// + public string Peek() + { + Stack stack = m_stack; + if (stack.Count > 0) + { + return ((StackFrame)stack.Peek()).Message; + } + return ""; + } + + #endregion Public Methods + + #region Internal Methods + + /// + /// Gets the current context information for this stack. + /// + /// The current context information. + internal string GetFullMessage() + { + Stack stack = m_stack; + if (stack.Count > 0) + { + return ((StackFrame)(stack.Peek())).FullMessage; + } + return null; + } + + /// + /// Gets and sets the internal stack used by this + /// + /// The internal storage stack + /// + /// + /// This property is provided only to support backward compatability + /// of the . Tytpically the internal stack should not + /// be modified. + /// + /// + internal Stack InternalStack + { + get { return m_stack; } + set { m_stack = value; } + } + + #endregion Internal Methods + + /// + /// Gets the current context information for this stack. + /// + /// Gets the current context information + /// + /// + /// Gets the current context information for this stack. + /// + /// + public override string ToString() + { + return GetFullMessage(); + } + + /// + /// Get a portable version of this object + /// + /// the portable instance of this object + /// + /// + /// Get a cross thread portable version of this object + /// + /// + object IFixingRequired.GetFixedObject() + { + return GetFullMessage(); + } + + /// + /// Inner class used to represent a single context frame in the stack. + /// + /// + /// + /// Inner class used to represent a single context frame in the stack. + /// + /// + 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 + + /// + /// Constructor + /// + /// The message for this context. + /// The parent context in the chain. + /// + /// + /// Initializes a new instance of the class + /// with the specified message and parent context. + /// + /// + 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 + + /// + /// Get the message. + /// + /// The message. + /// + /// + /// Get the message. + /// + /// + internal string Message + { + get { return m_message; } + } + + /// + /// Gets the full text of the context down to the root level. + /// + /// + /// The full text of the context down to the root level. + /// + /// + /// + /// Gets the full text of the context down to the root level. + /// + /// + internal string FullMessage + { + get + { + if (m_fullMessage == null && m_parent != null) + { + m_fullMessage = string.Concat(m_parent.FullMessage, " ", m_message); + } + return m_fullMessage; + } + } + + #endregion Internal Instance Properties + } + + /// + /// Struct returned from the method. + /// + /// + /// + /// This struct implements the and is designed to be used + /// with the pattern to remove the stack frame at the end of the scope. + /// + /// + private struct AutoPopStackFrame : IDisposable + { + #region Private Instance Fields + + /// + /// The depth to trim the stack to when this instance is disposed + /// + private int m_frameDepth; + + /// + /// The outer LogicalThreadContextStack. + /// + private LogicalThreadContextStack m_logicalThreadContextStack; + + #endregion Private Instance Fields + + #region Internal Instance Constructors + + /// + /// Constructor + /// + /// The internal stack used by the ThreadContextStack. + /// The depth to return the stack to when this object is disposed. + /// + /// + /// Initializes a new instance of the class with + /// the specified stack and return depth. + /// + /// + internal AutoPopStackFrame(LogicalThreadContextStack logicalThreadContextStack, int frameDepth) + { + m_frameDepth = frameDepth; + m_logicalThreadContextStack = logicalThreadContextStack; + } + + #endregion Internal Instance Constructors + + #region Implementation of IDisposable + + /// + /// Returns the stack to the correct depth. + /// + /// + /// + /// Returns the stack to the correct depth. + /// + /// + public void Dispose() + { + if (m_frameDepth >= 0 && m_logicalThreadContextStack.m_stack != null) + { + Stack stack = new Stack(new Stack(m_logicalThreadContextStack.m_stack)); + while (stack.Count > m_frameDepth) + { + stack.Pop(); + } + LogicalThreadContextStack ltcs = new LogicalThreadContextStack(m_logicalThreadContextStack.m_propertyKey, m_logicalThreadContextStack.m_registerNew); + ltcs.m_stack = stack; + m_logicalThreadContextStack.m_registerNew(m_logicalThreadContextStack.m_propertyKey, + ltcs); + } + } + + #endregion Implementation of IDisposable + } + + } } #endif \ No newline at end of file diff --git a/src/log4net/Util/LogicalThreadContextStacks.cs b/src/log4net/Util/LogicalThreadContextStacks.cs index 7d4a2253..6ea5901c 100644 --- a/src/log4net/Util/LogicalThreadContextStacks.cs +++ b/src/log4net/Util/LogicalThreadContextStacks.cs @@ -22,121 +22,121 @@ namespace log4net.Util { - /// - /// Implementation of Stacks collection for the - /// - /// - /// - /// Implementation of Stacks collection for the - /// - /// - /// Nicko Cadell - public sealed class LogicalThreadContextStacks - { - private readonly LogicalThreadContextProperties m_properties; - - #region Public Instance Constructors - - /// - /// Internal constructor - /// - /// - /// - /// Initializes a new instance of the class. - /// - /// - internal LogicalThreadContextStacks(LogicalThreadContextProperties properties) - { - m_properties = properties; - } - - #endregion Public Instance Constructors - - #region Public Instance Properties - - /// - /// Gets the named thread context stack - /// - /// - /// The named stack - /// - /// - /// - /// Gets the named thread context stack - /// - /// - public LogicalThreadContextStack this[string key] - { - get - { - LogicalThreadContextStack stack = null; - - object propertyValue = m_properties[key]; - if (propertyValue == null) - { - // Stack does not exist, create + /// + /// Implementation of Stacks collection for the + /// + /// + /// + /// Implementation of Stacks collection for the + /// + /// + /// Nicko Cadell + public sealed class LogicalThreadContextStacks + { + private readonly LogicalThreadContextProperties m_properties; + + #region Public Instance Constructors + + /// + /// Internal constructor + /// + /// + /// + /// Initializes a new instance of the class. + /// + /// + internal LogicalThreadContextStacks(LogicalThreadContextProperties properties) + { + m_properties = properties; + } + + #endregion Public Instance Constructors + + #region Public Instance Properties + + /// + /// Gets the named thread context stack + /// + /// + /// The named stack + /// + /// + /// + /// Gets the named thread context stack + /// + /// + public LogicalThreadContextStack this[string key] + { + get + { + LogicalThreadContextStack stack = null; + + object propertyValue = m_properties[key]; + if (propertyValue == null) + { + // Stack does not exist, create #if NET_2_0 || MONO_2_0 || NETSTANDARD - stack = new LogicalThreadContextStack(key, registerNew); + stack = new LogicalThreadContextStack(key, registerNew); #else - stack = new LogicalThreadContextStack(key, new TwoArgAction(registerNew)); + stack = new LogicalThreadContextStack(key, new TwoArgAction(registerNew)); #endif - m_properties[key] = stack; - } - else - { - // Look for existing stack - stack = propertyValue as LogicalThreadContextStack; - if (stack == null) - { - // Property is not set to a stack! - string propertyValueString = SystemInfo.NullText; - - try - { - propertyValueString = propertyValue.ToString(); - } - catch - { - } - - LogLog.Error(declaringType, "ThreadContextStacks: Request for stack named [" + key + "] failed because a property with the same name exists which is a [" + propertyValue.GetType().Name + "] with value [" + propertyValueString + "]"); + m_properties[key] = stack; + } + else + { + // Look for existing stack + stack = propertyValue as LogicalThreadContextStack; + if (stack == null) + { + // Property is not set to a stack! + string propertyValueString = SystemInfo.NullText; + + try + { + propertyValueString = propertyValue.ToString(); + } + catch + { + } + + LogLog.Error(declaringType, "ThreadContextStacks: Request for stack named [" + key + "] failed because a property with the same name exists which is a [" + propertyValue.GetType().Name + "] with value [" + propertyValueString + "]"); #if NET_2_0 || MONO_2_0 || NETSTANDARD - stack = new LogicalThreadContextStack(key, registerNew); + stack = new LogicalThreadContextStack(key, registerNew); #else - stack = new LogicalThreadContextStack(key, new TwoArgAction(registerNew)); + stack = new LogicalThreadContextStack(key, new TwoArgAction(registerNew)); #endif - } - } + } + } - return stack; - } - } + return stack; + } + } - #endregion Public Instance Properties + #endregion Public Instance Properties - #region Private Instance Fields + #region Private Instance Fields - private void registerNew(string stackName, LogicalThreadContextStack stack) - { - m_properties[stackName] = stack; - } + private void registerNew(string stackName, LogicalThreadContextStack stack) + { + m_properties[stackName] = stack; + } - #endregion Private Instance Fields + #endregion Private Instance Fields - #region Private Static Fields + #region Private Static Fields - /// - /// The fully qualified type of the ThreadContextStacks class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(LogicalThreadContextStacks); + /// + /// The fully qualified type of the ThreadContextStacks class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(LogicalThreadContextStacks); - #endregion Private Static Fields - } + #endregion Private Static Fields + } } #endif diff --git a/src/log4net/Util/NativeError.cs b/src/log4net/Util/NativeError.cs index b527c53b..a17a40c5 100644 --- a/src/log4net/Util/NativeError.cs +++ b/src/log4net/Util/NativeError.cs @@ -30,90 +30,90 @@ namespace log4net.Util { - /// - /// Represents a native error code and message. - /// - /// - /// - /// Represents a Win32 platform native error. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public sealed class NativeError - { - #region Protected Instance Constructors + /// + /// Represents a native error code and message. + /// + /// + /// + /// Represents a Win32 platform native error. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public sealed class NativeError + { + #region Protected Instance Constructors - /// - /// Create an instance of the class with the specified - /// error number and message. - /// - /// The number of the native error. - /// The message of the native error. - /// - /// - /// Create an instance of the class with the specified - /// error number and message. - /// - /// - private NativeError(int number, string message) - { - m_number = number; - m_message = message; - } + /// + /// Create an instance of the class with the specified + /// error number and message. + /// + /// The number of the native error. + /// The message of the native error. + /// + /// + /// Create an instance of the class with the specified + /// error number and message. + /// + /// + private NativeError(int number, string message) + { + m_number = number; + m_message = message; + } - #endregion // Protected Instance Constructors + #endregion // Protected Instance Constructors - #region Public Instance Properties + #region Public Instance Properties - /// - /// Gets the number of the native error. - /// - /// - /// The number of the native error. - /// - /// - /// - /// Gets the number of the native error. - /// - /// - public int Number - { - get { return m_number; } - } + /// + /// Gets the number of the native error. + /// + /// + /// The number of the native error. + /// + /// + /// + /// Gets the number of the native error. + /// + /// + public int Number + { + get { return m_number; } + } - /// - /// Gets the message of the native error. - /// - /// - /// The message of the native error. - /// - /// - /// - /// - /// Gets the message of the native error. - /// - public string Message - { - get { return m_message; } - } + /// + /// Gets the message of the native error. + /// + /// + /// The message of the native error. + /// + /// + /// + /// + /// Gets the message of the native error. + /// + public string Message + { + get { return m_message; } + } - #endregion // Public Instance Properties + #endregion // Public Instance Properties - #region Public Static Methods + #region Public Static Methods - /// - /// Create a new instance of the class for the last Windows error. - /// - /// - /// An instance of the class for the last windows error. - /// - /// - /// - /// The message for the error number is lookup up using the - /// native Win32 FormatMessage function. - /// - /// + /// + /// Create a new instance of the class for the last Windows error. + /// + /// + /// An instance of the class for the last windows error. + /// + /// + /// + /// The message for the error number is lookup up using the + /// native Win32 FormatMessage function. + /// + /// #if NET_4_0 || MONO_4_0 || NETSTANDARD [System.Security.SecuritySafeCritical] #endif @@ -121,43 +121,43 @@ public string Message [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, UnmanagedCode = true)] #endif public static NativeError GetLastError() - { - int number = Marshal.GetLastWin32Error(); - return new NativeError(number, NativeError.GetErrorMessage(number)); - } + { + int number = Marshal.GetLastWin32Error(); + return new NativeError(number, NativeError.GetErrorMessage(number)); + } - /// - /// Create a new instance of the class. - /// - /// the error number for the native error - /// - /// An instance of the class for the specified - /// error number. - /// - /// - /// - /// The message for the specified error number is lookup up using the - /// native Win32 FormatMessage function. - /// - /// - public static NativeError GetError(int number) - { - return new NativeError(number, NativeError.GetErrorMessage(number)); - } + /// + /// Create a new instance of the class. + /// + /// the error number for the native error + /// + /// An instance of the class for the specified + /// error number. + /// + /// + /// + /// The message for the specified error number is lookup up using the + /// native Win32 FormatMessage function. + /// + /// + public static NativeError GetError(int number) + { + return new NativeError(number, NativeError.GetErrorMessage(number)); + } - /// - /// Retrieves the message corresponding with a Win32 message identifier. - /// - /// Message identifier for the requested message. - /// - /// The message corresponding with the specified message identifier. - /// - /// - /// - /// The message will be searched for in system message-table resource(s) - /// using the native FormatMessage function. - /// - /// + /// + /// Retrieves the message corresponding with a Win32 message identifier. + /// + /// Message identifier for the requested message. + /// + /// The message corresponding with the specified message identifier. + /// + /// + /// + /// The message will be searched for in system message-table resource(s) + /// using the native FormatMessage function. + /// + /// #if NET_4_0 || MONO_4_0 || NETSTANDARD [System.Security.SecuritySafeCritical] #endif @@ -165,126 +165,126 @@ public static NativeError GetError(int number) [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, UnmanagedCode = true)] #endif public static string GetErrorMessage(int messageId) - { - // Win32 constants - int FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100; // The function should allocates a buffer large enough to hold the formatted message - int FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200; // Insert sequences in the message definition are to be ignored - int FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000; // The function should search the system message-table resource(s) for the requested message + { + // Win32 constants + int FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100; // The function should allocates a buffer large enough to hold the formatted message + int FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200; // Insert sequences in the message definition are to be ignored + int FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000; // The function should search the system message-table resource(s) for the requested message - string msgBuf = ""; // buffer that will receive the message - IntPtr sourcePtr = new IntPtr(); // Location of the message definition, will be ignored - IntPtr argumentsPtr = new IntPtr(); // Pointer to array of values to insert, not supported as it requires unsafe code + string msgBuf = ""; // buffer that will receive the message + IntPtr sourcePtr = new IntPtr(); // Location of the message definition, will be ignored + IntPtr argumentsPtr = new IntPtr(); // Pointer to array of values to insert, not supported as it requires unsafe code - if (messageId != 0) - { - // If the function succeeds, the return value is the number of TCHARs stored in the output buffer, excluding the terminating null character - int messageSize = FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - ref sourcePtr, - messageId, - 0, - ref msgBuf, - 255, - argumentsPtr); + if (messageId != 0) + { + // If the function succeeds, the return value is the number of TCHARs stored in the output buffer, excluding the terminating null character + int messageSize = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + ref sourcePtr, + messageId, + 0, + ref msgBuf, + 255, + argumentsPtr); - if (messageSize > 0) - { - // Remove trailing null-terminating characters (\r\n) from the message - msgBuf = msgBuf.TrimEnd(new char[] {'\r', '\n'}); - } - else - { - // A message could not be located. - msgBuf = null; - } - } - else - { - msgBuf = null; - } + if (messageSize > 0) + { + // Remove trailing null-terminating characters (\r\n) from the message + msgBuf = msgBuf.TrimEnd(new char[] {'\r', '\n'}); + } + else + { + // A message could not be located. + msgBuf = null; + } + } + else + { + msgBuf = null; + } - return msgBuf; - } + return msgBuf; + } - #endregion // Public Static Methods + #endregion // Public Static Methods - #region Override Object Implementation + #region Override Object Implementation - /// - /// Return error information string - /// - /// error information string - /// - /// - /// Return error information string - /// - /// - public override string ToString() - { - return string.Format(CultureInfo.InvariantCulture, "0x{0:x8}", this.Number) + (this.Message != null ? ": " + this.Message : ""); - } + /// + /// Return error information string + /// + /// error information string + /// + /// + /// Return error information string + /// + /// + public override string ToString() + { + return string.Format(CultureInfo.InvariantCulture, "0x{0:x8}", this.Number) + (this.Message != null ? ": " + this.Message : ""); + } - #endregion // Override Object Implementation + #endregion // Override Object Implementation - #region Stubs For Native Function Calls + #region Stubs For Native Function Calls - /// - /// Formats a message string. - /// - /// Formatting options, and how to interpret the parameter. - /// Location of the message definition. - /// Message identifier for the requested message. - /// Language identifier for the requested message. - /// If includes FORMAT_MESSAGE_ALLOCATE_BUFFER, the function allocates a buffer using the LocalAlloc function, and places the pointer to the buffer at the address specified in . - /// If the FORMAT_MESSAGE_ALLOCATE_BUFFER flag is not set, this parameter specifies the maximum number of TCHARs that can be stored in the output buffer. If FORMAT_MESSAGE_ALLOCATE_BUFFER is set, this parameter specifies the minimum number of TCHARs to allocate for an output buffer. - /// Pointer to an array of values that are used as insert values in the formatted message. - /// - /// - /// The function requires a message definition as input. The message definition can come from a - /// buffer passed into the function. It can come from a message table resource in an - /// already-loaded module. Or the caller can ask the function to search the system's message - /// table resource(s) for the message definition. The function finds the message definition - /// in a message table resource based on a message identifier and a language identifier. - /// The function copies the formatted message text to an output buffer, processing any embedded - /// insert sequences if requested. - /// - /// - /// To prevent the usage of unsafe code, this stub does not support inserting values in the formatted message. - /// - /// - /// - /// - /// If the function succeeds, the return value is the number of TCHARs stored in the output - /// buffer, excluding the terminating null character. - /// - /// - /// If the function fails, the return value is zero. To get extended error information, - /// call . - /// - /// + /// + /// Formats a message string. + /// + /// Formatting options, and how to interpret the parameter. + /// Location of the message definition. + /// Message identifier for the requested message. + /// Language identifier for the requested message. + /// If includes FORMAT_MESSAGE_ALLOCATE_BUFFER, the function allocates a buffer using the LocalAlloc function, and places the pointer to the buffer at the address specified in . + /// If the FORMAT_MESSAGE_ALLOCATE_BUFFER flag is not set, this parameter specifies the maximum number of TCHARs that can be stored in the output buffer. If FORMAT_MESSAGE_ALLOCATE_BUFFER is set, this parameter specifies the minimum number of TCHARs to allocate for an output buffer. + /// Pointer to an array of values that are used as insert values in the formatted message. + /// + /// + /// The function requires a message definition as input. The message definition can come from a + /// buffer passed into the function. It can come from a message table resource in an + /// already-loaded module. Or the caller can ask the function to search the system's message + /// table resource(s) for the message definition. The function finds the message definition + /// in a message table resource based on a message identifier and a language identifier. + /// The function copies the formatted message text to an output buffer, processing any embedded + /// insert sequences if requested. + /// + /// + /// To prevent the usage of unsafe code, this stub does not support inserting values in the formatted message. + /// + /// + /// + /// + /// If the function succeeds, the return value is the number of TCHARs stored in the output + /// buffer, excluding the terminating null character. + /// + /// + /// If the function fails, the return value is zero. To get extended error information, + /// call . + /// + /// #if NETCF || NETSTANDARD - [DllImport("CoreDll.dll", SetLastError=true, CharSet=CharSet.Unicode)] + [DllImport("CoreDll.dll", SetLastError=true, CharSet=CharSet.Unicode)] #else - [DllImport("Kernel32.dll", SetLastError=true, CharSet=CharSet.Auto)] + [DllImport("Kernel32.dll", SetLastError=true, CharSet=CharSet.Auto)] #endif - private static extern int FormatMessage( - int dwFlags, - ref IntPtr lpSource, - int dwMessageId, - int dwLanguageId, - ref String lpBuffer, - int nSize, - IntPtr Arguments); + private static extern int FormatMessage( + int dwFlags, + ref IntPtr lpSource, + int dwMessageId, + int dwLanguageId, + ref String lpBuffer, + int nSize, + IntPtr Arguments); - #endregion // Stubs For Native Function Calls + #endregion // Stubs For Native Function Calls - #region Private Instance Fields + #region Private Instance Fields - private int m_number; - private string m_message; + private int m_number; + private string m_message; - #endregion - } + #endregion + } } #endif // !CLI_1_0 diff --git a/src/log4net/Util/NullDictionaryEnumerator.cs b/src/log4net/Util/NullDictionaryEnumerator.cs index 48af424e..53d15260 100644 --- a/src/log4net/Util/NullDictionaryEnumerator.cs +++ b/src/log4net/Util/NullDictionaryEnumerator.cs @@ -22,181 +22,181 @@ namespace log4net.Util { - /// - /// An always empty . - /// - /// - /// - /// A singleton implementation of the over a collection - /// that is empty and not modifiable. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public sealed class NullDictionaryEnumerator : IDictionaryEnumerator - { - #region Private Instance Constructors + /// + /// An always empty . + /// + /// + /// + /// A singleton implementation of the over a collection + /// that is empty and not modifiable. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public sealed class NullDictionaryEnumerator : IDictionaryEnumerator + { + #region Private Instance Constructors - /// - /// Initializes a new instance of the class. - /// - /// - /// - /// Uses a private access modifier to enforce the singleton pattern. - /// - /// - private NullDictionaryEnumerator() - { - } + /// + /// Initializes a new instance of the class. + /// + /// + /// + /// Uses a private access modifier to enforce the singleton pattern. + /// + /// + private NullDictionaryEnumerator() + { + } - #endregion Private Instance Constructors + #endregion Private Instance Constructors - #region Public Static Properties + #region Public Static Properties - /// - /// Gets the singleton instance of the . - /// - /// The singleton instance of the . - /// - /// - /// Gets the singleton instance of the . - /// - /// - public static NullDictionaryEnumerator Instance - { - get { return s_instance; } - } + /// + /// Gets the singleton instance of the . + /// + /// The singleton instance of the . + /// + /// + /// Gets the singleton instance of the . + /// + /// + public static NullDictionaryEnumerator Instance + { + get { return s_instance; } + } - #endregion Public Static Properties + #endregion Public Static Properties - #region Implementation of IEnumerator + #region Implementation of IEnumerator - /// - /// Gets the current object from the enumerator. - /// - /// - /// Throws an because the - /// never has a current value. - /// - /// - /// - /// As the enumerator is over an empty collection its - /// value cannot be moved over a valid position, therefore - /// will throw an . - /// - /// - /// The collection is empty and - /// cannot be positioned over a valid location. - public object Current - { - get { throw new InvalidOperationException(); } - } + /// + /// Gets the current object from the enumerator. + /// + /// + /// Throws an because the + /// never has a current value. + /// + /// + /// + /// As the enumerator is over an empty collection its + /// value cannot be moved over a valid position, therefore + /// will throw an . + /// + /// + /// The collection is empty and + /// cannot be positioned over a valid location. + public object Current + { + get { throw new InvalidOperationException(); } + } - /// - /// Test if the enumerator can advance, if so advance. - /// - /// false as the cannot advance. - /// - /// - /// As the enumerator is over an empty collection its - /// value cannot be moved over a valid position, therefore - /// will always return false. - /// - /// - public bool MoveNext() - { - return false; - } + /// + /// Test if the enumerator can advance, if so advance. + /// + /// false as the cannot advance. + /// + /// + /// As the enumerator is over an empty collection its + /// value cannot be moved over a valid position, therefore + /// will always return false. + /// + /// + public bool MoveNext() + { + return false; + } - /// - /// Resets the enumerator back to the start. - /// - /// - /// - /// As the enumerator is over an empty collection does nothing. - /// - /// - public void Reset() - { - } + /// + /// Resets the enumerator back to the start. + /// + /// + /// + /// As the enumerator is over an empty collection does nothing. + /// + /// + public void Reset() + { + } - #endregion Implementation of IEnumerator + #endregion Implementation of IEnumerator - #region Implementation of IDictionaryEnumerator + #region Implementation of IDictionaryEnumerator - /// - /// Gets the current key from the enumerator. - /// - /// - /// Throws an exception because the - /// never has a current value. - /// - /// - /// - /// As the enumerator is over an empty collection its - /// value cannot be moved over a valid position, therefore - /// will throw an . - /// - /// - /// The collection is empty and - /// cannot be positioned over a valid location. - public object Key - { - get { throw new InvalidOperationException(); } - } + /// + /// Gets the current key from the enumerator. + /// + /// + /// Throws an exception because the + /// never has a current value. + /// + /// + /// + /// As the enumerator is over an empty collection its + /// value cannot be moved over a valid position, therefore + /// will throw an . + /// + /// + /// The collection is empty and + /// cannot be positioned over a valid location. + public object Key + { + get { throw new InvalidOperationException(); } + } - /// - /// Gets the current value from the enumerator. - /// - /// The current value from the enumerator. - /// - /// Throws an because the - /// never has a current value. - /// - /// - /// - /// As the enumerator is over an empty collection its - /// value cannot be moved over a valid position, therefore - /// will throw an . - /// - /// - /// The collection is empty and - /// cannot be positioned over a valid location. - public object Value - { - get { throw new InvalidOperationException(); } - } + /// + /// Gets the current value from the enumerator. + /// + /// The current value from the enumerator. + /// + /// Throws an because the + /// never has a current value. + /// + /// + /// + /// As the enumerator is over an empty collection its + /// value cannot be moved over a valid position, therefore + /// will throw an . + /// + /// + /// The collection is empty and + /// cannot be positioned over a valid location. + public object Value + { + get { throw new InvalidOperationException(); } + } - /// - /// Gets the current entry from the enumerator. - /// - /// - /// Throws an because the - /// never has a current entry. - /// - /// - /// - /// As the enumerator is over an empty collection its - /// value cannot be moved over a valid position, therefore - /// will throw an . - /// - /// - /// The collection is empty and - /// cannot be positioned over a valid location. - public DictionaryEntry Entry - { - get { throw new InvalidOperationException(); } - } + /// + /// Gets the current entry from the enumerator. + /// + /// + /// Throws an because the + /// never has a current entry. + /// + /// + /// + /// As the enumerator is over an empty collection its + /// value cannot be moved over a valid position, therefore + /// will throw an . + /// + /// + /// The collection is empty and + /// cannot be positioned over a valid location. + public DictionaryEntry Entry + { + get { throw new InvalidOperationException(); } + } - #endregion Implementation of IDictionaryEnumerator + #endregion Implementation of IDictionaryEnumerator - #region Private Static Fields + #region Private Static Fields - /// - /// The singleton instance of the . - /// - private static readonly NullDictionaryEnumerator s_instance = new NullDictionaryEnumerator(); + /// + /// The singleton instance of the . + /// + private static readonly NullDictionaryEnumerator s_instance = new NullDictionaryEnumerator(); - #endregion Private Static Fields - } + #endregion Private Static Fields + } } diff --git a/src/log4net/Util/NullEnumerator.cs b/src/log4net/Util/NullEnumerator.cs index 4cb78060..05351f2e 100644 --- a/src/log4net/Util/NullEnumerator.cs +++ b/src/log4net/Util/NullEnumerator.cs @@ -22,113 +22,113 @@ namespace log4net.Util { - /// - /// An always empty . - /// - /// - /// - /// A singleton implementation of the over a collection - /// that is empty and not modifiable. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public sealed class NullEnumerator : IEnumerator - { - #region Private Instance Constructors + /// + /// An always empty . + /// + /// + /// + /// A singleton implementation of the over a collection + /// that is empty and not modifiable. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public sealed class NullEnumerator : IEnumerator + { + #region Private Instance Constructors - /// - /// Initializes a new instance of the class. - /// - /// - /// - /// Uses a private access modifier to enforce the singleton pattern. - /// - /// - private NullEnumerator() - { - } + /// + /// Initializes a new instance of the class. + /// + /// + /// + /// Uses a private access modifier to enforce the singleton pattern. + /// + /// + private NullEnumerator() + { + } - #endregion Private Instance Constructors + #endregion Private Instance Constructors - #region Public Static Properties + #region Public Static Properties - /// - /// Get the singleton instance of the . - /// - /// The singleton instance of the . - /// - /// - /// Gets the singleton instance of the . - /// - /// - public static NullEnumerator Instance - { - get { return s_instance; } - } + /// + /// Get the singleton instance of the . + /// + /// The singleton instance of the . + /// + /// + /// Gets the singleton instance of the . + /// + /// + public static NullEnumerator Instance + { + get { return s_instance; } + } - #endregion Public Static Properties + #endregion Public Static Properties - #region Implementation of IEnumerator + #region Implementation of IEnumerator - /// - /// Gets the current object from the enumerator. - /// - /// - /// Throws an because the - /// never has a current value. - /// - /// - /// - /// As the enumerator is over an empty collection its - /// value cannot be moved over a valid position, therefore - /// will throw an . - /// - /// - /// The collection is empty and - /// cannot be positioned over a valid location. - public object Current - { - get { throw new InvalidOperationException(); } - } + /// + /// Gets the current object from the enumerator. + /// + /// + /// Throws an because the + /// never has a current value. + /// + /// + /// + /// As the enumerator is over an empty collection its + /// value cannot be moved over a valid position, therefore + /// will throw an . + /// + /// + /// The collection is empty and + /// cannot be positioned over a valid location. + public object Current + { + get { throw new InvalidOperationException(); } + } - /// - /// Test if the enumerator can advance, if so advance - /// - /// false as the cannot advance. - /// - /// - /// As the enumerator is over an empty collection its - /// value cannot be moved over a valid position, therefore - /// will always return false. - /// - /// - public bool MoveNext() - { - return false; - } + /// + /// Test if the enumerator can advance, if so advance + /// + /// false as the cannot advance. + /// + /// + /// As the enumerator is over an empty collection its + /// value cannot be moved over a valid position, therefore + /// will always return false. + /// + /// + public bool MoveNext() + { + return false; + } - /// - /// Resets the enumerator back to the start. - /// - /// - /// - /// As the enumerator is over an empty collection does nothing. - /// - /// - public void Reset() - { - } + /// + /// Resets the enumerator back to the start. + /// + /// + /// + /// As the enumerator is over an empty collection does nothing. + /// + /// + public void Reset() + { + } - #endregion Implementation of IEnumerator + #endregion Implementation of IEnumerator - #region Private Static Fields + #region Private Static Fields - /// - /// The singleton instance of the . - /// - private static readonly NullEnumerator s_instance = new NullEnumerator(); + /// + /// The singleton instance of the . + /// + private static readonly NullEnumerator s_instance = new NullEnumerator(); - #endregion Private Static Fields - } + #endregion Private Static Fields + } } diff --git a/src/log4net/Util/NullSecurityContext.cs b/src/log4net/Util/NullSecurityContext.cs index 3196d1de..d01d7d35 100644 --- a/src/log4net/Util/NullSecurityContext.cs +++ b/src/log4net/Util/NullSecurityContext.cs @@ -23,54 +23,54 @@ namespace log4net.Util { - /// - /// A SecurityContext used when a SecurityContext is not required - /// - /// - /// - /// The is a no-op implementation of the - /// base class. It is used where a - /// is required but one has not been provided. - /// - /// - /// Nicko Cadell - public sealed class NullSecurityContext : SecurityContext - { - /// - /// Singleton instance of - /// - /// - /// - /// Singleton instance of - /// - /// - public static readonly NullSecurityContext Instance = new NullSecurityContext(); + /// + /// A SecurityContext used when a SecurityContext is not required + /// + /// + /// + /// The is a no-op implementation of the + /// base class. It is used where a + /// is required but one has not been provided. + /// + /// + /// Nicko Cadell + public sealed class NullSecurityContext : SecurityContext + { + /// + /// Singleton instance of + /// + /// + /// + /// Singleton instance of + /// + /// + public static readonly NullSecurityContext Instance = new NullSecurityContext(); - /// - /// Private constructor - /// - /// - /// - /// Private constructor for singleton pattern. - /// - /// - private NullSecurityContext() - { - } + /// + /// Private constructor + /// + /// + /// + /// Private constructor for singleton pattern. + /// + /// + private NullSecurityContext() + { + } - /// - /// Impersonate this SecurityContext - /// - /// State supplied by the caller - /// null - /// - /// - /// No impersonation is done and null is always returned. - /// - /// - public override IDisposable Impersonate(object state) - { - return null; - } - } + /// + /// Impersonate this SecurityContext + /// + /// State supplied by the caller + /// null + /// + /// + /// No impersonation is done and null is always returned. + /// + /// + public override IDisposable Impersonate(object state) + { + return null; + } + } } diff --git a/src/log4net/Util/OnlyOnceErrorHandler.cs b/src/log4net/Util/OnlyOnceErrorHandler.cs index 5f03d929..ba4f0d13 100644 --- a/src/log4net/Util/OnlyOnceErrorHandler.cs +++ b/src/log4net/Util/OnlyOnceErrorHandler.cs @@ -23,91 +23,91 @@ namespace log4net.Util { - /// - /// Implements log4net's default error handling policy which consists - /// of emitting a message for the first error in an appender and - /// ignoring all subsequent errors. - /// - /// - /// - /// The error message is processed using the LogLog sub-system by default. - /// - /// - /// This policy aims at protecting an otherwise working application - /// from being flooded with error messages when logging fails. - /// - /// - /// Nicko Cadell - /// Gert Driesen - /// Ron Grabowski - public class OnlyOnceErrorHandler : IErrorHandler - { - #region Public Instance Constructors - - /// - /// Default Constructor - /// - /// - /// - /// Initializes a new instance of the class. - /// - /// - public OnlyOnceErrorHandler() - { - m_prefix = ""; - } - - /// - /// Constructor - /// - /// The prefix to use for each message. - /// - /// - /// Initializes a new instance of the class - /// with the specified prefix. - /// - /// - public OnlyOnceErrorHandler(string prefix) - { - m_prefix = prefix; - } - - #endregion Public Instance Constructors - - #region Public Instance Methods - - /// - /// Reset the error handler back to its initial disabled state. - /// - public void Reset() - { - m_enabledDateUtc = DateTime.MinValue; - m_errorCode = ErrorCode.GenericFailure; - m_exception = null; - m_message = null; - m_firstTime = true; - } - - #region Implementation of IErrorHandler - - /// - /// Log an Error - /// - /// The error message. - /// The exception. - /// The internal error code. - /// - /// - /// Invokes if and only if this is the first error or the first error after has been called. - /// - /// - public void Error(string message, Exception e, ErrorCode errorCode) - { - if (m_firstTime) - { + /// + /// Implements log4net's default error handling policy which consists + /// of emitting a message for the first error in an appender and + /// ignoring all subsequent errors. + /// + /// + /// + /// The error message is processed using the LogLog sub-system by default. + /// + /// + /// This policy aims at protecting an otherwise working application + /// from being flooded with error messages when logging fails. + /// + /// + /// Nicko Cadell + /// Gert Driesen + /// Ron Grabowski + public class OnlyOnceErrorHandler : IErrorHandler + { + #region Public Instance Constructors + + /// + /// Default Constructor + /// + /// + /// + /// Initializes a new instance of the class. + /// + /// + public OnlyOnceErrorHandler() + { + m_prefix = ""; + } + + /// + /// Constructor + /// + /// The prefix to use for each message. + /// + /// + /// Initializes a new instance of the class + /// with the specified prefix. + /// + /// + public OnlyOnceErrorHandler(string prefix) + { + m_prefix = prefix; + } + + #endregion Public Instance Constructors + + #region Public Instance Methods + + /// + /// Reset the error handler back to its initial disabled state. + /// + public void Reset() + { + m_enabledDateUtc = DateTime.MinValue; + m_errorCode = ErrorCode.GenericFailure; + m_exception = null; + m_message = null; + m_firstTime = true; + } + + #region Implementation of IErrorHandler + + /// + /// Log an Error + /// + /// The error message. + /// The exception. + /// The internal error code. + /// + /// + /// Invokes if and only if this is the first error or the first error after has been called. + /// + /// + public void Error(string message, Exception e, ErrorCode errorCode) + { + if (m_firstTime) + { FirstError(message, e, errorCode); - } - } + } + } /// /// Log the very first error @@ -133,65 +133,65 @@ public virtual void FirstError(string message, Exception e, ErrorCode errorCode) } /// - /// Log an Error - /// - /// The error message. - /// The exception. - /// + /// Log an Error + /// + /// The error message. + /// The exception. + /// /// /// Invokes if and only if this is the first error or the first error after has been called. /// /// - public void Error(string message, Exception e) - { - Error(message, e, ErrorCode.GenericFailure); - } - - /// - /// Log an error - /// - /// The error message. - /// + public void Error(string message, Exception e) + { + Error(message, e, ErrorCode.GenericFailure); + } + + /// + /// Log an error + /// + /// The error message. + /// /// /// Invokes if and only if this is the first error or the first error after has been called. /// /// - public void Error(string message) - { - Error(message, null, ErrorCode.GenericFailure); - } - - #endregion Implementation of IErrorHandler - - #endregion - - #region Public Instance Properties - - /// - /// Is error logging enabled - /// - /// - /// - /// Is error logging enabled. Logging is only enabled for the - /// first error delivered to the . - /// - /// - public bool IsEnabled - { - get { return m_firstTime; } - } - - /// - /// The date the first error that trigged this error handler occurred, or if it has not been triggered. - /// - public DateTime EnabledDate - { - get + public void Error(string message) + { + Error(message, null, ErrorCode.GenericFailure); + } + + #endregion Implementation of IErrorHandler + + #endregion + + #region Public Instance Properties + + /// + /// Is error logging enabled + /// + /// + /// + /// Is error logging enabled. Logging is only enabled for the + /// first error delivered to the . + /// + /// + public bool IsEnabled + { + get { return m_firstTime; } + } + + /// + /// The date the first error that trigged this error handler occurred, or if it has not been triggered. + /// + public DateTime EnabledDate + { + get { if (m_enabledDateUtc == DateTime.MinValue) return DateTime.MinValue; return m_enabledDateUtc.ToLocalTime(); } - } + } /// /// The UTC date the first error that trigged this error handler occured, or if it has not been triggered. @@ -201,83 +201,83 @@ public DateTime EnabledDateUtc get { return m_enabledDateUtc; } } - /// - /// The message from the first error that trigged this error handler. - /// - public string ErrorMessage - { - get { return m_message; } - } - - /// - /// The exception from the first error that trigged this error handler. - /// - /// - /// May be . - /// - public Exception Exception - { - get { return m_exception; } - } - - /// - /// The error code from the first error that trigged this error handler. - /// - /// - /// Defaults to - /// - public ErrorCode ErrorCode - { - get { return m_errorCode; } - } - - #endregion - - #region Private Instance Fields - - /// - /// The UTC date the error was recorded. - /// - private DateTime m_enabledDateUtc; - - /// - /// Flag to indicate if it is the first error - /// - private bool m_firstTime = true; - - /// - /// The message recorded during the first error. - /// - private string m_message = null; - - /// - /// The exception recorded during the first error. - /// - private Exception m_exception = null; - - /// - /// The error code recorded during the first error. - /// - private ErrorCode m_errorCode = ErrorCode.GenericFailure; - - /// - /// String to prefix each message with - /// - private readonly string m_prefix; - - #endregion Private Instance Fields - - #region Private Static Fields - - /// - /// The fully qualified type of the OnlyOnceErrorHandler class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(OnlyOnceErrorHandler); - - #endregion - } + /// + /// The message from the first error that trigged this error handler. + /// + public string ErrorMessage + { + get { return m_message; } + } + + /// + /// The exception from the first error that trigged this error handler. + /// + /// + /// May be . + /// + public Exception Exception + { + get { return m_exception; } + } + + /// + /// The error code from the first error that trigged this error handler. + /// + /// + /// Defaults to + /// + public ErrorCode ErrorCode + { + get { return m_errorCode; } + } + + #endregion + + #region Private Instance Fields + + /// + /// The UTC date the error was recorded. + /// + private DateTime m_enabledDateUtc; + + /// + /// Flag to indicate if it is the first error + /// + private bool m_firstTime = true; + + /// + /// The message recorded during the first error. + /// + private string m_message = null; + + /// + /// The exception recorded during the first error. + /// + private Exception m_exception = null; + + /// + /// The error code recorded during the first error. + /// + private ErrorCode m_errorCode = ErrorCode.GenericFailure; + + /// + /// String to prefix each message with + /// + private readonly string m_prefix; + + #endregion Private Instance Fields + + #region Private Static Fields + + /// + /// The fully qualified type of the OnlyOnceErrorHandler class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(OnlyOnceErrorHandler); + + #endregion + } } diff --git a/src/log4net/Util/OptionConverter.cs b/src/log4net/Util/OptionConverter.cs index 21eabfe5..77075b7b 100644 --- a/src/log4net/Util/OptionConverter.cs +++ b/src/log4net/Util/OptionConverter.cs @@ -27,527 +27,527 @@ namespace log4net.Util { - /// - /// A convenience class to convert property values to specific types. - /// - /// - /// - /// Utility functions for converting types and parsing values. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public sealed class OptionConverter - { - #region Private Instance Constructors - - /// - /// Initializes a new instance of the class. - /// - /// - /// - /// Uses a private access modifier to prevent instantiation of this class. - /// - /// - private OptionConverter() - { - } - - #endregion Private Instance Constructors - - #region Public Static Methods - - /// - /// Converts a string to a value. - /// - /// String to convert. - /// The default value. - /// The value of . - /// - /// - /// If is "true", then true is returned. - /// If is "false", then false is returned. - /// Otherwise, is returned. - /// - /// - public static bool ToBoolean(string argValue, bool defaultValue) - { - if (argValue != null && argValue.Length > 0) - { - try - { - return bool.Parse(argValue); - } - catch(Exception e) - { - LogLog.Error(declaringType, "[" + argValue + "] is not in proper bool form.", e); - } - } - return defaultValue; - } - - /// - /// Parses a file size into a number. - /// - /// String to parse. - /// The default value. - /// The value of . - /// - /// - /// Parses a file size of the form: number[KB|MB|GB] into a - /// long value. It is scaled with the appropriate multiplier. - /// - /// - /// is returned when - /// cannot be converted to a value. - /// - /// - public static long ToFileSize(string argValue, long defaultValue) - { - if (argValue == null) - { - return defaultValue; - } - - string s = argValue.Trim().ToUpperInvariant(); - long multiplier = 1; - int index; - - if ((index = s.IndexOf("KB")) != -1) - { - multiplier = 1024; - s = s.Substring(0, index); - } - else if ((index = s.IndexOf("MB")) != -1) - { - multiplier = 1024 * 1024; - s = s.Substring(0, index); - } - else if ((index = s.IndexOf("GB")) != -1) - { - multiplier = 1024 * 1024 * 1024; - s = s.Substring(0, index); - } - if (s != null) - { - // Try again to remove whitespace between the number and the size specifier - s = s.Trim(); - - long longVal; - if (SystemInfo.TryParse(s, out longVal)) - { - return longVal * multiplier; - } - else - { - LogLog.Error(declaringType, "OptionConverter: ["+ s +"] is not in the correct file size syntax."); - } - } - return defaultValue; - } - - /// - /// Converts a string to an object. - /// - /// The target type to convert to. - /// The string to convert to an object. - /// - /// The object converted from a string or null when the - /// conversion failed. - /// - /// - /// - /// Converts a string to an object. Uses the converter registry to try - /// to convert the string value into the specified target type. - /// - /// - public static object ConvertStringTo(Type target, string txt) - { - if (target == null) - { - throw new ArgumentNullException("target"); - } - - // If we want a string we already have the correct type - if (typeof(string) == target || typeof(object) == target) - { - return txt; - } - - // First lets try to find a type converter - IConvertFrom typeConverter = ConverterRegistry.GetConvertFrom(target); - if (typeConverter != null && typeConverter.CanConvertFrom(typeof(string))) - { - // Found appropriate converter - return typeConverter.ConvertFrom(txt); - } - else - { + /// + /// A convenience class to convert property values to specific types. + /// + /// + /// + /// Utility functions for converting types and parsing values. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public sealed class OptionConverter + { + #region Private Instance Constructors + + /// + /// Initializes a new instance of the class. + /// + /// + /// + /// Uses a private access modifier to prevent instantiation of this class. + /// + /// + private OptionConverter() + { + } + + #endregion Private Instance Constructors + + #region Public Static Methods + + /// + /// Converts a string to a value. + /// + /// String to convert. + /// The default value. + /// The value of . + /// + /// + /// If is "true", then true is returned. + /// If is "false", then false is returned. + /// Otherwise, is returned. + /// + /// + public static bool ToBoolean(string argValue, bool defaultValue) + { + if (argValue != null && argValue.Length > 0) + { + try + { + return bool.Parse(argValue); + } + catch(Exception e) + { + LogLog.Error(declaringType, "[" + argValue + "] is not in proper bool form.", e); + } + } + return defaultValue; + } + + /// + /// Parses a file size into a number. + /// + /// String to parse. + /// The default value. + /// The value of . + /// + /// + /// Parses a file size of the form: number[KB|MB|GB] into a + /// long value. It is scaled with the appropriate multiplier. + /// + /// + /// is returned when + /// cannot be converted to a value. + /// + /// + public static long ToFileSize(string argValue, long defaultValue) + { + if (argValue == null) + { + return defaultValue; + } + + string s = argValue.Trim().ToUpperInvariant(); + long multiplier = 1; + int index; + + if ((index = s.IndexOf("KB")) != -1) + { + multiplier = 1024; + s = s.Substring(0, index); + } + else if ((index = s.IndexOf("MB")) != -1) + { + multiplier = 1024 * 1024; + s = s.Substring(0, index); + } + else if ((index = s.IndexOf("GB")) != -1) + { + multiplier = 1024 * 1024 * 1024; + s = s.Substring(0, index); + } + if (s != null) + { + // Try again to remove whitespace between the number and the size specifier + s = s.Trim(); + + long longVal; + if (SystemInfo.TryParse(s, out longVal)) + { + return longVal * multiplier; + } + else + { + LogLog.Error(declaringType, "OptionConverter: ["+ s +"] is not in the correct file size syntax."); + } + } + return defaultValue; + } + + /// + /// Converts a string to an object. + /// + /// The target type to convert to. + /// The string to convert to an object. + /// + /// The object converted from a string or null when the + /// conversion failed. + /// + /// + /// + /// Converts a string to an object. Uses the converter registry to try + /// to convert the string value into the specified target type. + /// + /// + public static object ConvertStringTo(Type target, string txt) + { + if (target == null) + { + throw new ArgumentNullException("target"); + } + + // If we want a string we already have the correct type + if (typeof(string) == target || typeof(object) == target) + { + return txt; + } + + // First lets try to find a type converter + IConvertFrom typeConverter = ConverterRegistry.GetConvertFrom(target); + if (typeConverter != null && typeConverter.CanConvertFrom(typeof(string))) + { + // Found appropriate converter + return typeConverter.ConvertFrom(txt); + } + else + { #if NETSTANDARD1_3 - if (target.GetTypeInfo().IsEnum) + if (target.GetTypeInfo().IsEnum) #else - if (target.IsEnum) + if (target.IsEnum) #endif - { - // Target type is an enum. - - // Use the Enum.Parse(EnumType, string) method to get the enum value - return ParseEnum(target, txt, true); - } - else - { - // We essentially make a guess that to convert from a string - // to an arbitrary type T there will be a static method defined on type T called Parse - // that will take an argument of type string. i.e. T.Parse(string)->T we call this - // method to convert the string to the type required by the property. - System.Reflection.MethodInfo meth = target.GetMethod("Parse", new Type[] {typeof(string)}); - if (meth != null) - { - // Call the Parse method + { + // Target type is an enum. + + // Use the Enum.Parse(EnumType, string) method to get the enum value + return ParseEnum(target, txt, true); + } + else + { + // We essentially make a guess that to convert from a string + // to an arbitrary type T there will be a static method defined on type T called Parse + // that will take an argument of type string. i.e. T.Parse(string)->T we call this + // method to convert the string to the type required by the property. + System.Reflection.MethodInfo meth = target.GetMethod("Parse", new Type[] {typeof(string)}); + if (meth != null) + { + // Call the Parse method #if NETSTANDARD1_3 - return meth.Invoke(target, new[] { txt }); + return meth.Invoke(target, new[] { txt }); #else - return meth.Invoke(null, BindingFlags.InvokeMethod, null, new object[] {txt}, CultureInfo.InvariantCulture); + return meth.Invoke(null, BindingFlags.InvokeMethod, null, new object[] {txt}, CultureInfo.InvariantCulture); #endif - } - else - { - // No Parse() method found. - } - } - } - return null; - } - -// /// -// /// Looks up the for the target type. -// /// -// /// The type to lookup the converter for. -// /// The converter for the specified type. -// public static IConvertFrom GetTypeConverter(Type target) -// { -// IConvertFrom converter = ConverterRegistry.GetConverter(target); -// if (converter == null) -// { -// throw new InvalidOperationException("No type converter defined for [" + target + "]"); -// } -// return converter; -// } - - /// - /// Checks if there is an appropriate type conversion from the source type to the target type. - /// - /// The type to convert from. - /// The type to convert to. - /// true if there is a conversion from the source type to the target type. - /// - /// Checks if there is an appropriate type conversion from the source type to the target type. - /// - /// - /// - public static bool CanConvertTypeTo(Type sourceType, Type targetType) - { - if (sourceType == null || targetType == null) - { - return false; - } - - // Check if we can assign directly from the source type to the target type - if (targetType.IsAssignableFrom(sourceType)) - { - return true; - } - - // Look for a To converter - IConvertTo tcSource = ConverterRegistry.GetConvertTo(sourceType, targetType); - if (tcSource != null) - { - if (tcSource.CanConvertTo(targetType)) - { - return true; - } - } - - // Look for a From converter - IConvertFrom tcTarget = ConverterRegistry.GetConvertFrom(targetType); - if (tcTarget != null) - { - if (tcTarget.CanConvertFrom(sourceType)) - { - return true; - } - } - - return false; - } - - /// - /// Converts an object to the target type. - /// - /// The object to convert to the target type. - /// The type to convert to. - /// The converted object. - /// - /// - /// Converts an object to the target type. - /// - /// - public static object ConvertTypeTo(object sourceInstance, Type targetType) - { - Type sourceType = sourceInstance.GetType(); - - // Check if we can assign directly from the source type to the target type - if (targetType.IsAssignableFrom(sourceType)) - { - return sourceInstance; - } - - // Look for a TO converter - IConvertTo tcSource = ConverterRegistry.GetConvertTo(sourceType, targetType); - if (tcSource != null) - { - if (tcSource.CanConvertTo(targetType)) - { - return tcSource.ConvertTo(sourceInstance, targetType); - } - } - - // Look for a FROM converter - IConvertFrom tcTarget = ConverterRegistry.GetConvertFrom(targetType); - if (tcTarget != null) - { - if (tcTarget.CanConvertFrom(sourceType)) - { - return tcTarget.ConvertFrom(sourceInstance); - } - } - - throw new ArgumentException("Cannot convert source object [" + sourceInstance.ToString() + "] to target type [" + targetType.Name + "]", "sourceInstance"); - } - -// /// -// /// Finds the value corresponding to in -// /// and then perform variable substitution -// /// on the found value. -// /// -// /// The key to lookup. -// /// The association to use for lookups. -// /// The substituted result. -// public static string FindAndSubst(string key, System.Collections.IDictionary props) -// { -// if (props == null) -// { -// throw new ArgumentNullException("props"); -// } + } + else + { + // No Parse() method found. + } + } + } + return null; + } + +// /// +// /// Looks up the for the target type. +// /// +// /// The type to lookup the converter for. +// /// The converter for the specified type. +// public static IConvertFrom GetTypeConverter(Type target) +// { +// IConvertFrom converter = ConverterRegistry.GetConverter(target); +// if (converter == null) +// { +// throw new InvalidOperationException("No type converter defined for [" + target + "]"); +// } +// return converter; +// } + + /// + /// Checks if there is an appropriate type conversion from the source type to the target type. + /// + /// The type to convert from. + /// The type to convert to. + /// true if there is a conversion from the source type to the target type. + /// + /// Checks if there is an appropriate type conversion from the source type to the target type. + /// + /// + /// + public static bool CanConvertTypeTo(Type sourceType, Type targetType) + { + if (sourceType == null || targetType == null) + { + return false; + } + + // Check if we can assign directly from the source type to the target type + if (targetType.IsAssignableFrom(sourceType)) + { + return true; + } + + // Look for a To converter + IConvertTo tcSource = ConverterRegistry.GetConvertTo(sourceType, targetType); + if (tcSource != null) + { + if (tcSource.CanConvertTo(targetType)) + { + return true; + } + } + + // Look for a From converter + IConvertFrom tcTarget = ConverterRegistry.GetConvertFrom(targetType); + if (tcTarget != null) + { + if (tcTarget.CanConvertFrom(sourceType)) + { + return true; + } + } + + return false; + } + + /// + /// Converts an object to the target type. + /// + /// The object to convert to the target type. + /// The type to convert to. + /// The converted object. + /// + /// + /// Converts an object to the target type. + /// + /// + public static object ConvertTypeTo(object sourceInstance, Type targetType) + { + Type sourceType = sourceInstance.GetType(); + + // Check if we can assign directly from the source type to the target type + if (targetType.IsAssignableFrom(sourceType)) + { + return sourceInstance; + } + + // Look for a TO converter + IConvertTo tcSource = ConverterRegistry.GetConvertTo(sourceType, targetType); + if (tcSource != null) + { + if (tcSource.CanConvertTo(targetType)) + { + return tcSource.ConvertTo(sourceInstance, targetType); + } + } + + // Look for a FROM converter + IConvertFrom tcTarget = ConverterRegistry.GetConvertFrom(targetType); + if (tcTarget != null) + { + if (tcTarget.CanConvertFrom(sourceType)) + { + return tcTarget.ConvertFrom(sourceInstance); + } + } + + throw new ArgumentException("Cannot convert source object [" + sourceInstance.ToString() + "] to target type [" + targetType.Name + "]", "sourceInstance"); + } + +// /// +// /// Finds the value corresponding to in +// /// and then perform variable substitution +// /// on the found value. +// /// +// /// The key to lookup. +// /// The association to use for lookups. +// /// The substituted result. +// public static string FindAndSubst(string key, System.Collections.IDictionary props) +// { +// if (props == null) +// { +// throw new ArgumentNullException("props"); +// } // -// string v = props[key] as string; -// if (v == null) -// { -// return null; -// } -// -// try -// { -// return SubstituteVariables(v, props); -// } -// catch(Exception e) -// { -// LogLog.Error(declaringType, "OptionConverter: Bad option value [" + v + "].", e); -// return v; -// } -// } - - /// - /// Instantiates an object given a class name. - /// - /// The fully qualified class name of the object to instantiate. - /// The class to which the new object should belong. - /// The object to return in case of non-fulfillment. - /// - /// An instance of the or - /// if the object could not be instantiated. - /// - /// - /// - /// Checks that the is a subclass of - /// . If that test fails or the object could - /// not be instantiated, then is returned. - /// - /// - public static object InstantiateByClassName(string className, Type superClass, object defaultValue) - { - if (className != null) - { - try - { +// string v = props[key] as string; +// if (v == null) +// { +// return null; +// } +// +// try +// { +// return SubstituteVariables(v, props); +// } +// catch(Exception e) +// { +// LogLog.Error(declaringType, "OptionConverter: Bad option value [" + v + "].", e); +// return v; +// } +// } + + /// + /// Instantiates an object given a class name. + /// + /// The fully qualified class name of the object to instantiate. + /// The class to which the new object should belong. + /// The object to return in case of non-fulfillment. + /// + /// An instance of the or + /// if the object could not be instantiated. + /// + /// + /// + /// Checks that the is a subclass of + /// . If that test fails or the object could + /// not be instantiated, then is returned. + /// + /// + public static object InstantiateByClassName(string className, Type superClass, object defaultValue) + { + if (className != null) + { + try + { #if NETSTANDARD1_3 - Type classObj = SystemInfo.GetTypeFromString(superClass.GetTypeInfo().Assembly, className, true, true); + Type classObj = SystemInfo.GetTypeFromString(superClass.GetTypeInfo().Assembly, className, true, true); #else - Type classObj = SystemInfo.GetTypeFromString(className, true, true); + Type classObj = SystemInfo.GetTypeFromString(className, true, true); #endif - if (!superClass.IsAssignableFrom(classObj)) - { - LogLog.Error(declaringType, "OptionConverter: A [" + className + "] object is not assignable to a [" + superClass.FullName + "] variable."); - return defaultValue; - } - return Activator.CreateInstance(classObj); - } - catch (Exception e) - { - LogLog.Error(declaringType, "Could not instantiate class [" + className + "].", e); - } - } - return defaultValue; - } - - /// - /// Performs variable substitution in string from the - /// values of keys found in . - /// - /// The string on which variable substitution is performed. - /// The dictionary to use to lookup variables. - /// The result of the substitutions. - /// - /// - /// The variable substitution delimiters are ${ and }. - /// - /// - /// For example, if props contains key=value, then the call - /// - /// - /// - /// string s = OptionConverter.SubstituteVariables("Value of key is ${key}."); - /// - /// - /// - /// will set the variable s to "Value of key is value.". - /// - /// - /// If no value could be found for the specified key, then substitution - /// defaults to an empty string. - /// - /// - /// For example, if system properties contains no value for the key - /// "nonExistentKey", then the call - /// - /// - /// - /// string s = OptionConverter.SubstituteVariables("Value of nonExistentKey is [${nonExistentKey}]"); - /// - /// - /// - /// will set s to "Value of nonExistentKey is []". - /// - /// - /// An Exception is thrown if contains a start - /// delimiter "${" which is not balanced by a stop delimiter "}". - /// - /// - public static string SubstituteVariables(string value, System.Collections.IDictionary props) - { - StringBuilder buf = new StringBuilder(); - - int i = 0; - int j, k; - - while(true) - { - j = value.IndexOf(DELIM_START, i); - if (j == -1) - { - if (i == 0) - { - return value; - } - else - { - buf.Append(value.Substring(i, value.Length - i)); - return buf.ToString(); - } - } - else - { - buf.Append(value.Substring(i, j - i)); - k = value.IndexOf(DELIM_STOP, j); - if (k == -1) - { - throw new LogException("[" + value + "] has no closing brace. Opening brace at position [" + j + "]"); - } - else - { - j += DELIM_START_LEN; - string key = value.Substring(j, k - j); - - string replacement = props[key] as string; - - if (replacement != null) - { - buf.Append(replacement); - } - i = k + DELIM_STOP_LEN; - } - } - } - } - - #endregion Public Static Methods - - #region Private Static Methods - - /// - /// Converts the string representation of the name or numeric value of one or - /// more enumerated constants to an equivalent enumerated object. - /// - /// The type to convert to. - /// The enum string value. - /// If true, ignore case; otherwise, regard case. - /// An object of type whose value is represented by . - private static object ParseEnum(System.Type enumType, string value, bool ignoreCase) - { + if (!superClass.IsAssignableFrom(classObj)) + { + LogLog.Error(declaringType, "OptionConverter: A [" + className + "] object is not assignable to a [" + superClass.FullName + "] variable."); + return defaultValue; + } + return Activator.CreateInstance(classObj); + } + catch (Exception e) + { + LogLog.Error(declaringType, "Could not instantiate class [" + className + "].", e); + } + } + return defaultValue; + } + + /// + /// Performs variable substitution in string from the + /// values of keys found in . + /// + /// The string on which variable substitution is performed. + /// The dictionary to use to lookup variables. + /// The result of the substitutions. + /// + /// + /// The variable substitution delimiters are ${ and }. + /// + /// + /// For example, if props contains key=value, then the call + /// + /// + /// + /// string s = OptionConverter.SubstituteVariables("Value of key is ${key}."); + /// + /// + /// + /// will set the variable s to "Value of key is value.". + /// + /// + /// If no value could be found for the specified key, then substitution + /// defaults to an empty string. + /// + /// + /// For example, if system properties contains no value for the key + /// "nonExistentKey", then the call + /// + /// + /// + /// string s = OptionConverter.SubstituteVariables("Value of nonExistentKey is [${nonExistentKey}]"); + /// + /// + /// + /// will set s to "Value of nonExistentKey is []". + /// + /// + /// An Exception is thrown if contains a start + /// delimiter "${" which is not balanced by a stop delimiter "}". + /// + /// + public static string SubstituteVariables(string value, System.Collections.IDictionary props) + { + StringBuilder buf = new StringBuilder(); + + int i = 0; + int j, k; + + while(true) + { + j = value.IndexOf(DELIM_START, i); + if (j == -1) + { + if (i == 0) + { + return value; + } + else + { + buf.Append(value.Substring(i, value.Length - i)); + return buf.ToString(); + } + } + else + { + buf.Append(value.Substring(i, j - i)); + k = value.IndexOf(DELIM_STOP, j); + if (k == -1) + { + throw new LogException("[" + value + "] has no closing brace. Opening brace at position [" + j + "]"); + } + else + { + j += DELIM_START_LEN; + string key = value.Substring(j, k - j); + + string replacement = props[key] as string; + + if (replacement != null) + { + buf.Append(replacement); + } + i = k + DELIM_STOP_LEN; + } + } + } + } + + #endregion Public Static Methods + + #region Private Static Methods + + /// + /// Converts the string representation of the name or numeric value of one or + /// more enumerated constants to an equivalent enumerated object. + /// + /// The type to convert to. + /// The enum string value. + /// If true, ignore case; otherwise, regard case. + /// An object of type whose value is represented by . + private static object ParseEnum(System.Type enumType, string value, bool ignoreCase) + { #if !NETCF - return Enum.Parse(enumType, value, ignoreCase); + return Enum.Parse(enumType, value, ignoreCase); #else - FieldInfo[] fields = enumType.GetFields(BindingFlags.Public | BindingFlags.Static); - - string[] names = value.Split(new char[] {','}); - for (int i = 0; i < names.Length; ++i) - { - names[i] = names [i].Trim(); - } - - long retVal = 0; - - try - { - // Attempt to convert to numeric type - return Enum.ToObject(enumType, Convert.ChangeType(value, typeof(long), CultureInfo.InvariantCulture)); - } - catch {} - - foreach (string name in names) - { - bool found = false; - foreach(FieldInfo field in fields) - { - if (String.Compare(name, field.Name, ignoreCase) == 0) - { - retVal |= ((IConvertible) field.GetValue(null)).ToInt64(CultureInfo.InvariantCulture); - found = true; - break; - } - } - if (!found) - { - throw new ArgumentException("Failed to lookup member [" + name + "] from Enum type [" + enumType.Name + "]"); - } - } - return Enum.ToObject(enumType, retVal); + FieldInfo[] fields = enumType.GetFields(BindingFlags.Public | BindingFlags.Static); + + string[] names = value.Split(new char[] {','}); + for (int i = 0; i < names.Length; ++i) + { + names[i] = names [i].Trim(); + } + + long retVal = 0; + + try + { + // Attempt to convert to numeric type + return Enum.ToObject(enumType, Convert.ChangeType(value, typeof(long), CultureInfo.InvariantCulture)); + } + catch {} + + foreach (string name in names) + { + bool found = false; + foreach(FieldInfo field in fields) + { + if (String.Compare(name, field.Name, ignoreCase) == 0) + { + retVal |= ((IConvertible) field.GetValue(null)).ToInt64(CultureInfo.InvariantCulture); + found = true; + break; + } + } + if (!found) + { + throw new ArgumentException("Failed to lookup member [" + name + "] from Enum type [" + enumType.Name + "]"); + } + } + return Enum.ToObject(enumType, retVal); #endif - } + } - #endregion Private Static Methods + #endregion Private Static Methods - #region Private Static Fields + #region Private Static Fields /// /// The fully qualified type of the OptionConverter class. @@ -558,11 +558,11 @@ private static object ParseEnum(System.Type enumType, string value, bool ignoreC /// private static readonly Type declaringType = typeof(OptionConverter); - private const string DELIM_START = "${"; - private const char DELIM_STOP = '}'; - private const int DELIM_START_LEN = 2; - private const int DELIM_STOP_LEN = 1; + private const string DELIM_START = "${"; + private const char DELIM_STOP = '}'; + private const int DELIM_START_LEN = 2; + private const int DELIM_STOP_LEN = 1; - #endregion Private Static Fields - } + #endregion Private Static Fields + } } diff --git a/src/log4net/Util/PatternConverter.cs b/src/log4net/Util/PatternConverter.cs index 9f9067b1..295a7495 100644 --- a/src/log4net/Util/PatternConverter.cs +++ b/src/log4net/Util/PatternConverter.cs @@ -26,154 +26,154 @@ namespace log4net.Util { - /// - /// Abstract class that provides the formatting functionality that - /// derived classes need. - /// - /// - /// - /// Conversion specifiers in a conversion patterns are parsed to - /// individual PatternConverters. Each of which is responsible for - /// converting a logging event in a converter specific manner. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public abstract class PatternConverter - { - #region Protected Instance Constructors - - /// - /// Protected constructor - /// - /// - /// - /// Initializes a new instance of the class. - /// - /// - protected PatternConverter() - { - } - - #endregion Protected Instance Constructors - - #region Public Instance Properties - - /// - /// Get the next pattern converter in the chain - /// - /// - /// the next pattern converter in the chain - /// - /// - /// - /// Get the next pattern converter in the chain - /// - /// - public virtual PatternConverter Next - { - get { return m_next; } - } - - /// - /// Gets or sets the formatting info for this converter - /// - /// - /// The formatting info for this converter - /// - /// - /// - /// Gets or sets the formatting info for this converter - /// - /// - public virtual FormattingInfo FormattingInfo - { - get { return new FormattingInfo(m_min, m_max, m_leftAlign); } - set - { - m_min = value.Min; - m_max = value.Max; - m_leftAlign = value.LeftAlign; - } - } - - /// - /// Gets or sets the option value for this converter - /// - /// - /// The option for this converter - /// - /// - /// - /// Gets or sets the option value for this converter - /// - /// - public virtual string Option - { - get { return m_option; } - set { m_option = value; } - } - - #endregion Public Instance Properties - - #region Protected Abstract Methods - - /// - /// Evaluate this pattern converter and write the output to a writer. - /// - /// that will receive the formatted result. - /// The state object on which the pattern converter should be executed. - /// - /// - /// Derived pattern converters must override this method in order to - /// convert conversion specifiers in the appropriate way. - /// - /// - protected abstract void Convert(TextWriter writer, object state); - - #endregion Protected Abstract Methods - - #region Public Instance Methods - - /// - /// Set the next pattern converter in the chains - /// - /// the pattern converter that should follow this converter in the chain - /// the next converter - /// - /// - /// The PatternConverter can merge with its neighbor during this method (or a sub class). - /// Therefore the return value may or may not be the value of the argument passed in. - /// - /// - public virtual PatternConverter SetNext(PatternConverter patternConverter) - { - m_next = patternConverter; - return m_next; - } - - /// - /// Write the pattern converter to the writer with appropriate formatting - /// - /// that will receive the formatted result. - /// The state object on which the pattern converter should be executed. - /// - /// - /// This method calls to allow the subclass to perform - /// appropriate conversion of the pattern converter. If formatting options have - /// been specified via the then this method will - /// apply those formattings before writing the output. - /// - /// - public virtual void Format(TextWriter writer, object state) - { - if (m_min < 0 && m_max == int.MaxValue) - { - // Formatting options are not in use - Convert(writer, state); - } - else - { + /// + /// Abstract class that provides the formatting functionality that + /// derived classes need. + /// + /// + /// + /// Conversion specifiers in a conversion patterns are parsed to + /// individual PatternConverters. Each of which is responsible for + /// converting a logging event in a converter specific manner. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public abstract class PatternConverter + { + #region Protected Instance Constructors + + /// + /// Protected constructor + /// + /// + /// + /// Initializes a new instance of the class. + /// + /// + protected PatternConverter() + { + } + + #endregion Protected Instance Constructors + + #region Public Instance Properties + + /// + /// Get the next pattern converter in the chain + /// + /// + /// the next pattern converter in the chain + /// + /// + /// + /// Get the next pattern converter in the chain + /// + /// + public virtual PatternConverter Next + { + get { return m_next; } + } + + /// + /// Gets or sets the formatting info for this converter + /// + /// + /// The formatting info for this converter + /// + /// + /// + /// Gets or sets the formatting info for this converter + /// + /// + public virtual FormattingInfo FormattingInfo + { + get { return new FormattingInfo(m_min, m_max, m_leftAlign); } + set + { + m_min = value.Min; + m_max = value.Max; + m_leftAlign = value.LeftAlign; + } + } + + /// + /// Gets or sets the option value for this converter + /// + /// + /// The option for this converter + /// + /// + /// + /// Gets or sets the option value for this converter + /// + /// + public virtual string Option + { + get { return m_option; } + set { m_option = value; } + } + + #endregion Public Instance Properties + + #region Protected Abstract Methods + + /// + /// Evaluate this pattern converter and write the output to a writer. + /// + /// that will receive the formatted result. + /// The state object on which the pattern converter should be executed. + /// + /// + /// Derived pattern converters must override this method in order to + /// convert conversion specifiers in the appropriate way. + /// + /// + protected abstract void Convert(TextWriter writer, object state); + + #endregion Protected Abstract Methods + + #region Public Instance Methods + + /// + /// Set the next pattern converter in the chains + /// + /// the pattern converter that should follow this converter in the chain + /// the next converter + /// + /// + /// The PatternConverter can merge with its neighbor during this method (or a sub class). + /// Therefore the return value may or may not be the value of the argument passed in. + /// + /// + public virtual PatternConverter SetNext(PatternConverter patternConverter) + { + m_next = patternConverter; + return m_next; + } + + /// + /// Write the pattern converter to the writer with appropriate formatting + /// + /// that will receive the formatted result. + /// The state object on which the pattern converter should be executed. + /// + /// + /// This method calls to allow the subclass to perform + /// appropriate conversion of the pattern converter. If formatting options have + /// been specified via the then this method will + /// apply those formattings before writing the output. + /// + /// + public virtual void Format(TextWriter writer, object state) + { + if (m_min < 0 && m_max == int.MaxValue) + { + // Formatting options are not in use + Convert(writer, state); + } + else + { string msg = null; int len; lock (m_formatWriter) @@ -195,193 +195,193 @@ public virtual void Format(TextWriter writer, object state) } } - if (len < m_min) - { - if (m_leftAlign) - { - writer.Write(msg); - SpacePad(writer, m_min - len); - } - else - { - SpacePad(writer, m_min - len); - writer.Write(msg); - } - } - else - { - writer.Write(msg); - } - } - } - - private static readonly string[] SPACES = { " ", " ", " ", " ", // 1,2,4,8 spaces - " ", // 16 spaces - " " }; // 32 spaces - - /// - /// Fast space padding method. - /// - /// to which the spaces will be appended. - /// The number of spaces to be padded. - /// - /// - /// Fast space padding method. - /// - /// - protected static void SpacePad(TextWriter writer, int length) - { - while(length >= 32) - { - writer.Write(SPACES[5]); - length -= 32; - } + if (len < m_min) + { + if (m_leftAlign) + { + writer.Write(msg); + SpacePad(writer, m_min - len); + } + else + { + SpacePad(writer, m_min - len); + writer.Write(msg); + } + } + else + { + writer.Write(msg); + } + } + } + + private static readonly string[] SPACES = { " ", " ", " ", " ", // 1,2,4,8 spaces + " ", // 16 spaces + " " }; // 32 spaces + + /// + /// Fast space padding method. + /// + /// to which the spaces will be appended. + /// The number of spaces to be padded. + /// + /// + /// Fast space padding method. + /// + /// + protected static void SpacePad(TextWriter writer, int length) + { + while(length >= 32) + { + writer.Write(SPACES[5]); + length -= 32; + } - for(int i = 4; i >= 0; i--) - { - if ((length & (1< - /// The option string to the converter - /// - private string m_option = null; - - private ReusableStringWriter m_formatWriter = new ReusableStringWriter(System.Globalization.CultureInfo.InvariantCulture); - - #endregion Private Instance Fields - - #region Constants - - /// - /// Initial buffer size - /// - private const int c_renderBufferSize = 256; - - /// - /// Maximum buffer size before it is recycled - /// - private const int c_renderBufferMaxCapacity = 1024; - - #endregion - - #region Static Methods - - /// - /// Write an dictionary to a - /// - /// the writer to write to - /// a to use for object conversion - /// the value to write to the writer - /// - /// - /// Writes the to a writer in the form: - /// - /// - /// {key1=value1, key2=value2, key3=value3} - /// - /// - /// If the specified - /// is not null then it is used to render the key and value to text, otherwise - /// the object's ToString method is called. - /// - /// - protected static void WriteDictionary(TextWriter writer, ILoggerRepository repository, IDictionary value) - { - WriteDictionary(writer, repository, value.GetEnumerator()); - } - - /// - /// Write an dictionary to a - /// - /// the writer to write to - /// a to use for object conversion - /// the value to write to the writer - /// - /// - /// Writes the to a writer in the form: - /// - /// - /// {key1=value1, key2=value2, key3=value3} - /// - /// - /// If the specified - /// is not null then it is used to render the key and value to text, otherwise - /// the object's ToString method is called. - /// - /// - protected static void WriteDictionary(TextWriter writer, ILoggerRepository repository, IDictionaryEnumerator value) - { - writer.Write("{"); - - bool first = true; - - // Write out all the dictionary key value pairs - while (value.MoveNext()) - { - if (first) - { - first = false; - } - else - { - writer.Write(", "); - } - WriteObject(writer, repository, value.Key); - writer.Write("="); - WriteObject(writer, repository, value.Value); - } - - writer.Write("}"); - } - - /// - /// Write an object to a - /// - /// the writer to write to - /// a to use for object conversion - /// the value to write to the writer - /// - /// - /// Writes the Object to a writer. If the specified - /// is not null then it is used to render the object to text, otherwise - /// the object's ToString method is called. - /// - /// - protected static void WriteObject(TextWriter writer, ILoggerRepository repository, object value) - { - if (repository != null) - { - repository.RendererMap.FindAndRender(value, writer); - } - else - { - // Don't have a repository to render with so just have to rely on ToString - if (value == null) - { - writer.Write( SystemInfo.NullText ); - } - else - { - writer.Write( value.ToString() ); - } - } - } - - #endregion + for(int i = 4; i >= 0; i--) + { + if ((length & (1< + /// The option string to the converter + /// + private string m_option = null; + + private ReusableStringWriter m_formatWriter = new ReusableStringWriter(System.Globalization.CultureInfo.InvariantCulture); + + #endregion Private Instance Fields + + #region Constants + + /// + /// Initial buffer size + /// + private const int c_renderBufferSize = 256; + + /// + /// Maximum buffer size before it is recycled + /// + private const int c_renderBufferMaxCapacity = 1024; + + #endregion + + #region Static Methods + + /// + /// Write an dictionary to a + /// + /// the writer to write to + /// a to use for object conversion + /// the value to write to the writer + /// + /// + /// Writes the to a writer in the form: + /// + /// + /// {key1=value1, key2=value2, key3=value3} + /// + /// + /// If the specified + /// is not null then it is used to render the key and value to text, otherwise + /// the object's ToString method is called. + /// + /// + protected static void WriteDictionary(TextWriter writer, ILoggerRepository repository, IDictionary value) + { + WriteDictionary(writer, repository, value.GetEnumerator()); + } + + /// + /// Write an dictionary to a + /// + /// the writer to write to + /// a to use for object conversion + /// the value to write to the writer + /// + /// + /// Writes the to a writer in the form: + /// + /// + /// {key1=value1, key2=value2, key3=value3} + /// + /// + /// If the specified + /// is not null then it is used to render the key and value to text, otherwise + /// the object's ToString method is called. + /// + /// + protected static void WriteDictionary(TextWriter writer, ILoggerRepository repository, IDictionaryEnumerator value) + { + writer.Write("{"); + + bool first = true; + + // Write out all the dictionary key value pairs + while (value.MoveNext()) + { + if (first) + { + first = false; + } + else + { + writer.Write(", "); + } + WriteObject(writer, repository, value.Key); + writer.Write("="); + WriteObject(writer, repository, value.Value); + } + + writer.Write("}"); + } + + /// + /// Write an object to a + /// + /// the writer to write to + /// a to use for object conversion + /// the value to write to the writer + /// + /// + /// Writes the Object to a writer. If the specified + /// is not null then it is used to render the object to text, otherwise + /// the object's ToString method is called. + /// + /// + protected static void WriteObject(TextWriter writer, ILoggerRepository repository, object value) + { + if (repository != null) + { + repository.RendererMap.FindAndRender(value, writer); + } + else + { + // Don't have a repository to render with so just have to rely on ToString + if (value == null) + { + writer.Write( SystemInfo.NullText ); + } + else + { + writer.Write( value.ToString() ); + } + } + } + + #endregion private PropertiesDictionary properties; @@ -389,9 +389,9 @@ protected static void WriteObject(TextWriter writer, ILoggerRepository repositor /// /// public PropertiesDictionary Properties - { - get { return properties; } - set { properties = value; } - } - } + { + get { return properties; } + set { properties = value; } + } + } } diff --git a/src/log4net/Util/PatternParser.cs b/src/log4net/Util/PatternParser.cs index 7dfbb326..fc4c40b4 100644 --- a/src/log4net/Util/PatternParser.cs +++ b/src/log4net/Util/PatternParser.cs @@ -26,410 +26,410 @@ namespace log4net.Util { - /// - /// Most of the work of the class - /// is delegated to the PatternParser class. - /// - /// - /// - /// The PatternParser processes a pattern string and - /// returns a chain of objects. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public sealed class PatternParser - { - #region Public Instance Constructors - - /// - /// Constructor - /// - /// The pattern to parse. - /// - /// - /// Initializes a new instance of the class - /// with the specified pattern string. - /// - /// - public PatternParser(string pattern) - { - m_pattern = pattern; - } - - #endregion Public Instance Constructors - - #region Public Instance Methods - - /// - /// Parses the pattern into a chain of pattern converters. - /// - /// The head of a chain of pattern converters. - /// - /// - /// Parses the pattern into a chain of pattern converters. - /// - /// - public PatternConverter Parse() - { - string[] converterNamesCache = BuildCache(); - - ParseInternal(m_pattern, converterNamesCache); - - return m_head; - } - - #endregion Public Instance Methods - - #region Public Instance Properties - - /// - /// Get the converter registry used by this parser - /// - /// - /// The converter registry used by this parser - /// - /// - /// - /// Get the converter registry used by this parser - /// - /// - public Hashtable PatternConverters - { - get { return m_patternConverters; } - } - - #endregion Public Instance Properties - - #region Private Instance Methods - - /// - /// Build the unified cache of converters from the static and instance maps - /// - /// the list of all the converter names - /// - /// - /// Build the unified cache of converters from the static and instance maps - /// - /// - private string[] BuildCache() - { - string[] converterNamesCache = new string[m_patternConverters.Keys.Count]; - m_patternConverters.Keys.CopyTo(converterNamesCache, 0); - - // sort array so that longer strings come first - Array.Sort(converterNamesCache, 0, converterNamesCache.Length, StringLengthComparer.Instance); - - return converterNamesCache; - } - - #region StringLengthComparer - - /// - /// Sort strings by length - /// - /// - /// - /// that orders strings by string length. - /// The longest strings are placed first - /// - /// - private sealed class StringLengthComparer : IComparer - { - public static readonly StringLengthComparer Instance = new StringLengthComparer(); - - private StringLengthComparer() - { - } - - #region Implementation of IComparer - - public int Compare(object x, object y) - { - string s1 = x as string; - string s2 = y as string; - - if (s1 == null && s2 == null) - { - return 0; - } - if (s1 == null) - { - return 1; - } - if (s2 == null) - { - return -1; - } - - return s2.Length.CompareTo(s1.Length); - } - - #endregion - } - - #endregion // StringLengthComparer - - /// - /// Internal method to parse the specified pattern to find specified matches - /// - /// the pattern to parse - /// the converter names to match in the pattern - /// - /// - /// The matches param must be sorted such that longer strings come before shorter ones. - /// - /// - private void ParseInternal(string pattern, string[] matches) - { - int offset = 0; - while(offset < pattern.Length) - { - int i = pattern.IndexOf('%', offset); - if (i < 0 || i == pattern.Length - 1) - { - ProcessLiteral(pattern.Substring(offset)); - offset = pattern.Length; - } - else - { - if (pattern[i+1] == '%') - { - // Escaped - ProcessLiteral(pattern.Substring(offset, i - offset + 1)); - offset = i + 2; - } - else - { - ProcessLiteral(pattern.Substring(offset, i - offset)); - offset = i + 1; - - FormattingInfo formattingInfo = new FormattingInfo(); - - // Process formatting options - - // Look for the align flag - if (offset < pattern.Length) - { - if (pattern[offset] == '-') - { - // Seen align flag - formattingInfo.LeftAlign = true; - offset++; - } - } - // Look for the minimum length - while (offset < pattern.Length && char.IsDigit(pattern[offset])) - { - // Seen digit - if (formattingInfo.Min < 0) - { - formattingInfo.Min = 0; - } - - formattingInfo.Min = (formattingInfo.Min * 10) + int.Parse(pattern[offset].ToString(), NumberFormatInfo.InvariantInfo); - - offset++; - } - // Look for the separator between min and max - if (offset < pattern.Length) - { - if (pattern[offset] == '.') - { - // Seen separator - offset++; - } - } - // Look for the maximum length - while (offset < pattern.Length && char.IsDigit(pattern[offset])) - { - // Seen digit - if (formattingInfo.Max == int.MaxValue) - { - formattingInfo.Max = 0; - } - - formattingInfo.Max = (formattingInfo.Max * 10) + int.Parse(pattern[offset].ToString(), NumberFormatInfo.InvariantInfo); - - offset++; - } - - int remainingStringLength = pattern.Length - offset; - - // Look for pattern - for(int m=0; m - /// Process a parsed literal - /// - /// the literal text - private void ProcessLiteral(string text) - { - if (text.Length > 0) - { - // Convert into a pattern - ProcessConverter("literal", text, new FormattingInfo()); - } - } - - /// - /// Process a parsed converter pattern - /// - /// the name of the converter - /// the optional option for the converter - /// the formatting info for the converter - private void ProcessConverter(string converterName, string option, FormattingInfo formattingInfo) - { - LogLog.Debug(declaringType, "Converter ["+converterName+"] Option ["+option+"] Format [min="+formattingInfo.Min+",max="+formattingInfo.Max+",leftAlign="+formattingInfo.LeftAlign+"]"); - - // Lookup the converter type + /// + /// Most of the work of the class + /// is delegated to the PatternParser class. + /// + /// + /// + /// The PatternParser processes a pattern string and + /// returns a chain of objects. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public sealed class PatternParser + { + #region Public Instance Constructors + + /// + /// Constructor + /// + /// The pattern to parse. + /// + /// + /// Initializes a new instance of the class + /// with the specified pattern string. + /// + /// + public PatternParser(string pattern) + { + m_pattern = pattern; + } + + #endregion Public Instance Constructors + + #region Public Instance Methods + + /// + /// Parses the pattern into a chain of pattern converters. + /// + /// The head of a chain of pattern converters. + /// + /// + /// Parses the pattern into a chain of pattern converters. + /// + /// + public PatternConverter Parse() + { + string[] converterNamesCache = BuildCache(); + + ParseInternal(m_pattern, converterNamesCache); + + return m_head; + } + + #endregion Public Instance Methods + + #region Public Instance Properties + + /// + /// Get the converter registry used by this parser + /// + /// + /// The converter registry used by this parser + /// + /// + /// + /// Get the converter registry used by this parser + /// + /// + public Hashtable PatternConverters + { + get { return m_patternConverters; } + } + + #endregion Public Instance Properties + + #region Private Instance Methods + + /// + /// Build the unified cache of converters from the static and instance maps + /// + /// the list of all the converter names + /// + /// + /// Build the unified cache of converters from the static and instance maps + /// + /// + private string[] BuildCache() + { + string[] converterNamesCache = new string[m_patternConverters.Keys.Count]; + m_patternConverters.Keys.CopyTo(converterNamesCache, 0); + + // sort array so that longer strings come first + Array.Sort(converterNamesCache, 0, converterNamesCache.Length, StringLengthComparer.Instance); + + return converterNamesCache; + } + + #region StringLengthComparer + + /// + /// Sort strings by length + /// + /// + /// + /// that orders strings by string length. + /// The longest strings are placed first + /// + /// + private sealed class StringLengthComparer : IComparer + { + public static readonly StringLengthComparer Instance = new StringLengthComparer(); + + private StringLengthComparer() + { + } + + #region Implementation of IComparer + + public int Compare(object x, object y) + { + string s1 = x as string; + string s2 = y as string; + + if (s1 == null && s2 == null) + { + return 0; + } + if (s1 == null) + { + return 1; + } + if (s2 == null) + { + return -1; + } + + return s2.Length.CompareTo(s1.Length); + } + + #endregion + } + + #endregion // StringLengthComparer + + /// + /// Internal method to parse the specified pattern to find specified matches + /// + /// the pattern to parse + /// the converter names to match in the pattern + /// + /// + /// The matches param must be sorted such that longer strings come before shorter ones. + /// + /// + private void ParseInternal(string pattern, string[] matches) + { + int offset = 0; + while(offset < pattern.Length) + { + int i = pattern.IndexOf('%', offset); + if (i < 0 || i == pattern.Length - 1) + { + ProcessLiteral(pattern.Substring(offset)); + offset = pattern.Length; + } + else + { + if (pattern[i+1] == '%') + { + // Escaped + ProcessLiteral(pattern.Substring(offset, i - offset + 1)); + offset = i + 2; + } + else + { + ProcessLiteral(pattern.Substring(offset, i - offset)); + offset = i + 1; + + FormattingInfo formattingInfo = new FormattingInfo(); + + // Process formatting options + + // Look for the align flag + if (offset < pattern.Length) + { + if (pattern[offset] == '-') + { + // Seen align flag + formattingInfo.LeftAlign = true; + offset++; + } + } + // Look for the minimum length + while (offset < pattern.Length && char.IsDigit(pattern[offset])) + { + // Seen digit + if (formattingInfo.Min < 0) + { + formattingInfo.Min = 0; + } + + formattingInfo.Min = (formattingInfo.Min * 10) + int.Parse(pattern[offset].ToString(), NumberFormatInfo.InvariantInfo); + + offset++; + } + // Look for the separator between min and max + if (offset < pattern.Length) + { + if (pattern[offset] == '.') + { + // Seen separator + offset++; + } + } + // Look for the maximum length + while (offset < pattern.Length && char.IsDigit(pattern[offset])) + { + // Seen digit + if (formattingInfo.Max == int.MaxValue) + { + formattingInfo.Max = 0; + } + + formattingInfo.Max = (formattingInfo.Max * 10) + int.Parse(pattern[offset].ToString(), NumberFormatInfo.InvariantInfo); + + offset++; + } + + int remainingStringLength = pattern.Length - offset; + + // Look for pattern + for(int m=0; m + /// Process a parsed literal + /// + /// the literal text + private void ProcessLiteral(string text) + { + if (text.Length > 0) + { + // Convert into a pattern + ProcessConverter("literal", text, new FormattingInfo()); + } + } + + /// + /// Process a parsed converter pattern + /// + /// the name of the converter + /// the optional option for the converter + /// the formatting info for the converter + private void ProcessConverter(string converterName, string option, FormattingInfo formattingInfo) + { + LogLog.Debug(declaringType, "Converter ["+converterName+"] Option ["+option+"] Format [min="+formattingInfo.Min+",max="+formattingInfo.Max+",leftAlign="+formattingInfo.LeftAlign+"]"); + + // Lookup the converter type ConverterInfo converterInfo = (ConverterInfo)m_patternConverters[converterName]; - if (converterInfo == null) - { - LogLog.Error(declaringType, "Unknown converter name ["+converterName+"] in conversion pattern."); - } - else - { - // Create the pattern converter - PatternConverter pc = null; - try - { + if (converterInfo == null) + { + LogLog.Error(declaringType, "Unknown converter name ["+converterName+"] in conversion pattern."); + } + else + { + // Create the pattern converter + PatternConverter pc = null; + try + { pc = (PatternConverter)Activator.CreateInstance(converterInfo.Type); - } - catch(Exception createInstanceEx) - { + } + catch(Exception createInstanceEx) + { LogLog.Error(declaringType, "Failed to create instance of Type [" + converterInfo.Type.FullName + "] using default constructor. Exception: " + createInstanceEx.ToString()); - } + } - // formattingInfo variable is an instance variable, occasionally reset - // and used over and over again - pc.FormattingInfo = formattingInfo; - pc.Option = option; + // formattingInfo variable is an instance variable, occasionally reset + // and used over and over again + pc.FormattingInfo = formattingInfo; + pc.Option = option; pc.Properties = converterInfo.Properties; - IOptionHandler optionHandler = pc as IOptionHandler; - if (optionHandler != null) - { - optionHandler.ActivateOptions(); - } - - AddConverter(pc); - } - } - - /// - /// Resets the internal state of the parser and adds the specified pattern converter - /// to the chain. - /// - /// The pattern converter to add. - private void AddConverter(PatternConverter pc) - { - // Add the pattern converter to the list. - - if (m_head == null) - { - m_head = m_tail = pc; - } - else - { - // Set the next converter on the tail - // Update the tail reference - // note that a converter may combine the 'next' into itself - // and therefore the tail would not change! - m_tail = m_tail.SetNext(pc); - } - } - - #endregion Protected Instance Methods - - #region Private Constants - - private const char ESCAPE_CHAR = '%'; + IOptionHandler optionHandler = pc as IOptionHandler; + if (optionHandler != null) + { + optionHandler.ActivateOptions(); + } + + AddConverter(pc); + } + } + + /// + /// Resets the internal state of the parser and adds the specified pattern converter + /// to the chain. + /// + /// The pattern converter to add. + private void AddConverter(PatternConverter pc) + { + // Add the pattern converter to the list. + + if (m_head == null) + { + m_head = m_tail = pc; + } + else + { + // Set the next converter on the tail + // Update the tail reference + // note that a converter may combine the 'next' into itself + // and therefore the tail would not change! + m_tail = m_tail.SetNext(pc); + } + } + + #endregion Protected Instance Methods + + #region Private Constants + + private const char ESCAPE_CHAR = '%'; - #endregion Private Constants - - #region Private Instance Fields - - /// - /// The first pattern converter in the chain - /// - private PatternConverter m_head; - - /// - /// the last pattern converter in the chain - /// - private PatternConverter m_tail; - - /// - /// The pattern - /// - private string m_pattern; - - /// - /// Internal map of converter identifiers to converter types - /// - /// - /// - /// This map overrides the static s_globalRulesRegistry map. - /// - /// - private Hashtable m_patternConverters = new Hashtable(); - - #endregion Private Instance Fields - - #region Private Static Fields - - /// - /// The fully qualified type of the PatternParser class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(PatternParser); - - #endregion Private Static Fields - } + #endregion Private Constants + + #region Private Instance Fields + + /// + /// The first pattern converter in the chain + /// + private PatternConverter m_head; + + /// + /// the last pattern converter in the chain + /// + private PatternConverter m_tail; + + /// + /// The pattern + /// + private string m_pattern; + + /// + /// Internal map of converter identifiers to converter types + /// + /// + /// + /// This map overrides the static s_globalRulesRegistry map. + /// + /// + private Hashtable m_patternConverters = new Hashtable(); + + #endregion Private Instance Fields + + #region Private Static Fields + + /// + /// The fully qualified type of the PatternParser class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(PatternParser); + + #endregion Private Static Fields + } } diff --git a/src/log4net/Util/PatternString.cs b/src/log4net/Util/PatternString.cs index c7d924b9..cb5c4461 100644 --- a/src/log4net/Util/PatternString.cs +++ b/src/log4net/Util/PatternString.cs @@ -26,464 +26,464 @@ namespace log4net.Util { - /// - /// This class implements a patterned string. - /// - /// - /// - /// This string has embedded patterns that are resolved and expanded - /// when the string is formatted. - /// - /// - /// This class functions similarly to the - /// in that it accepts a pattern and renders it to a string. Unlike the - /// however the PatternString - /// does not render the properties of a specific but - /// of the process in general. - /// - /// - /// The recognized conversion pattern names are: - /// - /// - /// - /// Conversion Pattern Name - /// Effect - /// - /// - /// appdomain - /// - /// - /// Used to output the friendly name of the current AppDomain. - /// - /// - /// - /// - /// appsetting - /// - /// - /// Used to output the value of a specific appSetting key in the application - /// configuration file. - /// - /// - /// - /// - /// date - /// - /// - /// Used to output the current date and time in the local time zone. - /// To output the date in universal time use the %utcdate pattern. - /// The date conversion - /// specifier may be followed by a date format specifier enclosed - /// between braces. For example, %date{HH:mm:ss,fff} or - /// %date{dd MMM yyyy HH:mm:ss,fff}. If no date format specifier is - /// given then ISO8601 format is - /// assumed (). - /// - /// - /// The date format specifier admits the same syntax as the - /// time pattern string of the . - /// - /// - /// For better results it is recommended to use the log4net date - /// formatters. These can be specified using one of the strings - /// "ABSOLUTE", "DATE" and "ISO8601" for specifying - /// , - /// and respectively - /// . For example, - /// %date{ISO8601} or %date{ABSOLUTE}. - /// - /// - /// These dedicated date formatters perform significantly - /// better than . - /// - /// - /// - /// - /// env - /// - /// - /// Used to output the a specific environment variable. The key to - /// lookup must be specified within braces and directly following the - /// pattern specifier, e.g. %env{COMPUTERNAME} would include the value - /// of the COMPUTERNAME environment variable. - /// - /// - /// The env pattern is not supported on the .NET Compact Framework. - /// - /// - /// - /// - /// identity - /// - /// - /// Used to output the user name for the currently active user - /// (Principal.Identity.Name). - /// - /// - /// - /// - /// newline - /// - /// - /// Outputs the platform dependent line separator character or - /// characters. - /// - /// - /// This conversion pattern name offers the same performance as using - /// non-portable line separator strings such as "\n", or "\r\n". - /// Thus, it is the preferred way of specifying a line separator. - /// - /// - /// - /// - /// processid - /// - /// - /// Used to output the system process ID for the current process. - /// - /// - /// - /// - /// property - /// - /// - /// Used to output a specific context property. The key to - /// lookup must be specified within braces and directly following the - /// pattern specifier, e.g. %property{user} 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 stored in logging contexts. By default - /// the log4net:HostName property is set to the name of machine on - /// which the event was originally logged. - /// - /// - /// If no key is specified, e.g. %property then all the keys and their - /// values are printed in a comma separated list. - /// - /// - /// 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. - /// - /// - /// - /// the thread properties - /// - /// The that are set on the current - /// thread. These properties are shared by all events logged on this thread. - /// - /// - /// - /// the global properties - /// - /// The that are set globally. These - /// properties are shared by all the threads in the AppDomain. - /// - /// - /// - /// - /// - /// - /// random - /// - /// - /// Used to output a random string of characters. The string is made up of - /// uppercase letters and numbers. By default the string is 4 characters long. - /// The length of the string can be specified within braces directly following the - /// pattern specifier, e.g. %random{8} would output an 8 character string. - /// - /// - /// - /// - /// username - /// - /// - /// Used to output the WindowsIdentity for the currently - /// active user. - /// - /// - /// - /// - /// utcdate - /// - /// - /// Used to output the date of the logging event in universal time. - /// The date conversion - /// specifier may be followed by a date format specifier enclosed - /// between braces. For example, %utcdate{HH:mm:ss,fff} or - /// %utcdate{dd MMM yyyy HH:mm:ss,fff}. If no date format specifier is - /// given then ISO8601 format is - /// assumed (). - /// - /// - /// The date format specifier admits the same syntax as the - /// time pattern string of the . - /// - /// - /// For better results it is recommended to use the log4net date - /// formatters. These can be specified using one of the strings - /// "ABSOLUTE", "DATE" and "ISO8601" for specifying - /// , - /// and respectively - /// . For example, - /// %utcdate{ISO8601} or %utcdate{ABSOLUTE}. - /// - /// - /// These dedicated date formatters perform significantly - /// better than . - /// - /// - /// - /// - /// % - /// - /// - /// The sequence %% outputs a single percent sign. - /// - /// - /// - /// - /// - /// Additional pattern converters may be registered with a specific - /// instance using or - /// . - /// - /// - /// See the for details on the - /// format modifiers supported by the patterns. - /// - /// - /// Nicko Cadell - public class PatternString : IOptionHandler - { - #region Static Fields + /// + /// This class implements a patterned string. + /// + /// + /// + /// This string has embedded patterns that are resolved and expanded + /// when the string is formatted. + /// + /// + /// This class functions similarly to the + /// in that it accepts a pattern and renders it to a string. Unlike the + /// however the PatternString + /// does not render the properties of a specific but + /// of the process in general. + /// + /// + /// The recognized conversion pattern names are: + /// + /// + /// + /// Conversion Pattern Name + /// Effect + /// + /// + /// appdomain + /// + /// + /// Used to output the friendly name of the current AppDomain. + /// + /// + /// + /// + /// appsetting + /// + /// + /// Used to output the value of a specific appSetting key in the application + /// configuration file. + /// + /// + /// + /// + /// date + /// + /// + /// Used to output the current date and time in the local time zone. + /// To output the date in universal time use the %utcdate pattern. + /// The date conversion + /// specifier may be followed by a date format specifier enclosed + /// between braces. For example, %date{HH:mm:ss,fff} or + /// %date{dd MMM yyyy HH:mm:ss,fff}. If no date format specifier is + /// given then ISO8601 format is + /// assumed (). + /// + /// + /// The date format specifier admits the same syntax as the + /// time pattern string of the . + /// + /// + /// For better results it is recommended to use the log4net date + /// formatters. These can be specified using one of the strings + /// "ABSOLUTE", "DATE" and "ISO8601" for specifying + /// , + /// and respectively + /// . For example, + /// %date{ISO8601} or %date{ABSOLUTE}. + /// + /// + /// These dedicated date formatters perform significantly + /// better than . + /// + /// + /// + /// + /// env + /// + /// + /// Used to output the a specific environment variable. The key to + /// lookup must be specified within braces and directly following the + /// pattern specifier, e.g. %env{COMPUTERNAME} would include the value + /// of the COMPUTERNAME environment variable. + /// + /// + /// The env pattern is not supported on the .NET Compact Framework. + /// + /// + /// + /// + /// identity + /// + /// + /// Used to output the user name for the currently active user + /// (Principal.Identity.Name). + /// + /// + /// + /// + /// newline + /// + /// + /// Outputs the platform dependent line separator character or + /// characters. + /// + /// + /// This conversion pattern name offers the same performance as using + /// non-portable line separator strings such as "\n", or "\r\n". + /// Thus, it is the preferred way of specifying a line separator. + /// + /// + /// + /// + /// processid + /// + /// + /// Used to output the system process ID for the current process. + /// + /// + /// + /// + /// property + /// + /// + /// Used to output a specific context property. The key to + /// lookup must be specified within braces and directly following the + /// pattern specifier, e.g. %property{user} 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 stored in logging contexts. By default + /// the log4net:HostName property is set to the name of machine on + /// which the event was originally logged. + /// + /// + /// If no key is specified, e.g. %property then all the keys and their + /// values are printed in a comma separated list. + /// + /// + /// 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. + /// + /// + /// + /// the thread properties + /// + /// The that are set on the current + /// thread. These properties are shared by all events logged on this thread. + /// + /// + /// + /// the global properties + /// + /// The that are set globally. These + /// properties are shared by all the threads in the AppDomain. + /// + /// + /// + /// + /// + /// + /// random + /// + /// + /// Used to output a random string of characters. The string is made up of + /// uppercase letters and numbers. By default the string is 4 characters long. + /// The length of the string can be specified within braces directly following the + /// pattern specifier, e.g. %random{8} would output an 8 character string. + /// + /// + /// + /// + /// username + /// + /// + /// Used to output the WindowsIdentity for the currently + /// active user. + /// + /// + /// + /// + /// utcdate + /// + /// + /// Used to output the date of the logging event in universal time. + /// The date conversion + /// specifier may be followed by a date format specifier enclosed + /// between braces. For example, %utcdate{HH:mm:ss,fff} or + /// %utcdate{dd MMM yyyy HH:mm:ss,fff}. If no date format specifier is + /// given then ISO8601 format is + /// assumed (). + /// + /// + /// The date format specifier admits the same syntax as the + /// time pattern string of the . + /// + /// + /// For better results it is recommended to use the log4net date + /// formatters. These can be specified using one of the strings + /// "ABSOLUTE", "DATE" and "ISO8601" for specifying + /// , + /// and respectively + /// . For example, + /// %utcdate{ISO8601} or %utcdate{ABSOLUTE}. + /// + /// + /// These dedicated date formatters perform significantly + /// better than . + /// + /// + /// + /// + /// % + /// + /// + /// The sequence %% outputs a single percent sign. + /// + /// + /// + /// + /// + /// Additional pattern converters may be registered with a specific + /// instance using or + /// . + /// + /// + /// See the for details on the + /// format modifiers supported by the patterns. + /// + /// + /// Nicko Cadell + public class PatternString : IOptionHandler + { + #region Static Fields - /// - /// Internal map of converter identifiers to converter types. - /// - private static Hashtable s_globalRulesRegistry; + /// + /// Internal map of converter identifiers to converter types. + /// + private static Hashtable s_globalRulesRegistry; - #endregion Static Fields + #endregion Static Fields - #region Member Variables + #region Member Variables - /// - /// the pattern - /// - private string m_pattern; + /// + /// the pattern + /// + private string m_pattern; - /// - /// the head of the pattern converter chain - /// - private PatternConverter m_head; + /// + /// the head of the pattern converter chain + /// + private PatternConverter m_head; - /// - /// patterns defined on this PatternString only - /// - private Hashtable m_instanceRulesRegistry = new Hashtable(); + /// + /// patterns defined on this PatternString only + /// + private Hashtable m_instanceRulesRegistry = new Hashtable(); - #endregion + #endregion - #region Static Constructor + #region Static Constructor - /// - /// Initialize the global registry - /// - static PatternString() - { - s_globalRulesRegistry = new Hashtable(18); + /// + /// Initialize the global registry + /// + static PatternString() + { + s_globalRulesRegistry = new Hashtable(18); - s_globalRulesRegistry.Add("appdomain", typeof(AppDomainPatternConverter)); - s_globalRulesRegistry.Add("date", typeof(DatePatternConverter)); + s_globalRulesRegistry.Add("appdomain", typeof(AppDomainPatternConverter)); + s_globalRulesRegistry.Add("date", typeof(DatePatternConverter)); #if !NETCF - s_globalRulesRegistry.Add("env", typeof(EnvironmentPatternConverter)); + s_globalRulesRegistry.Add("env", typeof(EnvironmentPatternConverter)); #if !NETSTANDARD1_3 // EnvironmentFolderPathPatternConverter not yet supported - s_globalRulesRegistry.Add("envFolderPath", typeof(EnvironmentFolderPathPatternConverter)); + s_globalRulesRegistry.Add("envFolderPath", typeof(EnvironmentFolderPathPatternConverter)); #endif #endif - s_globalRulesRegistry.Add("identity", typeof(IdentityPatternConverter)); - s_globalRulesRegistry.Add("literal", typeof(LiteralPatternConverter)); - s_globalRulesRegistry.Add("newline", typeof(NewLinePatternConverter)); - s_globalRulesRegistry.Add("processid", typeof(ProcessIdPatternConverter)); - s_globalRulesRegistry.Add("property", typeof(PropertyPatternConverter)); - s_globalRulesRegistry.Add("random", typeof(RandomStringPatternConverter)); - s_globalRulesRegistry.Add("username", typeof(UserNamePatternConverter)); + s_globalRulesRegistry.Add("identity", typeof(IdentityPatternConverter)); + s_globalRulesRegistry.Add("literal", typeof(LiteralPatternConverter)); + s_globalRulesRegistry.Add("newline", typeof(NewLinePatternConverter)); + s_globalRulesRegistry.Add("processid", typeof(ProcessIdPatternConverter)); + s_globalRulesRegistry.Add("property", typeof(PropertyPatternConverter)); + s_globalRulesRegistry.Add("random", typeof(RandomStringPatternConverter)); + s_globalRulesRegistry.Add("username", typeof(UserNamePatternConverter)); - s_globalRulesRegistry.Add("utcdate", typeof(UtcDatePatternConverter)); - s_globalRulesRegistry.Add("utcDate", typeof(UtcDatePatternConverter)); - s_globalRulesRegistry.Add("UtcDate", typeof(UtcDatePatternConverter)); + s_globalRulesRegistry.Add("utcdate", typeof(UtcDatePatternConverter)); + s_globalRulesRegistry.Add("utcDate", typeof(UtcDatePatternConverter)); + s_globalRulesRegistry.Add("UtcDate", typeof(UtcDatePatternConverter)); #if !NETCF && !NETSTANDARD1_3 - // TODO - have added common variants of casing like utcdate above. - // Wouldn't it be better to use a case-insensitive Hashtable? - s_globalRulesRegistry.Add("appsetting", typeof(AppSettingPatternConverter)); - s_globalRulesRegistry.Add("appSetting", typeof(AppSettingPatternConverter)); - s_globalRulesRegistry.Add("AppSetting", typeof(AppSettingPatternConverter)); + // TODO - have added common variants of casing like utcdate above. + // Wouldn't it be better to use a case-insensitive Hashtable? + s_globalRulesRegistry.Add("appsetting", typeof(AppSettingPatternConverter)); + s_globalRulesRegistry.Add("appSetting", typeof(AppSettingPatternConverter)); + s_globalRulesRegistry.Add("AppSetting", typeof(AppSettingPatternConverter)); #endif - } + } - #endregion Static Constructor + #endregion Static Constructor - #region Constructors + #region Constructors - /// - /// Default constructor - /// - /// - /// - /// Initialize a new instance of - /// - /// - public PatternString() - { - } + /// + /// Default constructor + /// + /// + /// + /// Initialize a new instance of + /// + /// + public PatternString() + { + } - /// - /// Constructs a PatternString - /// - /// The pattern to use with this PatternString - /// - /// - /// Initialize a new instance of with the pattern specified. - /// - /// - public PatternString(string pattern) - { - m_pattern = pattern; - ActivateOptions(); - } + /// + /// Constructs a PatternString + /// + /// The pattern to use with this PatternString + /// + /// + /// Initialize a new instance of with the pattern specified. + /// + /// + public PatternString(string pattern) + { + m_pattern = pattern; + ActivateOptions(); + } - #endregion + #endregion - /// - /// Gets or sets the pattern formatting string - /// - /// - /// The pattern formatting string - /// - /// - /// - /// The ConversionPattern option. This is the string which - /// controls formatting and consists of a mix of literal content and - /// conversion specifiers. - /// - /// - public string ConversionPattern - { - get { return m_pattern; } - set { m_pattern = value; } - } + /// + /// Gets or sets the pattern formatting string + /// + /// + /// The pattern formatting string + /// + /// + /// + /// The ConversionPattern option. This is the string which + /// controls formatting and consists of a mix of literal content and + /// conversion specifiers. + /// + /// + public string ConversionPattern + { + get { return m_pattern; } + set { m_pattern = value; } + } - #region Implementation of IOptionHandler + #region Implementation of IOptionHandler - /// - /// Initialize object options - /// - /// - /// - /// This is part of the delayed object - /// activation scheme. The method must - /// be called on this object after the configuration properties have - /// been set. Until is called this - /// object is in an undefined state and must not be used. - /// - /// - /// If any of the configuration properties are modified then - /// must be called again. - /// - /// - public virtual void ActivateOptions() - { - m_head = CreatePatternParser(m_pattern).Parse(); - } + /// + /// Initialize object options + /// + /// + /// + /// This is part of the delayed object + /// activation scheme. The method must + /// be called on this object after the configuration properties have + /// been set. Until is called this + /// object is in an undefined state and must not be used. + /// + /// + /// If any of the configuration properties are modified then + /// must be called again. + /// + /// + public virtual void ActivateOptions() + { + m_head = CreatePatternParser(m_pattern).Parse(); + } - #endregion + #endregion - /// - /// Create the used to parse the pattern - /// - /// the pattern to parse - /// The - /// - /// - /// Returns PatternParser used to parse the conversion string. Subclasses - /// may override this to return a subclass of PatternParser which recognize - /// custom conversion pattern name. - /// - /// - private PatternParser CreatePatternParser(string pattern) - { - PatternParser patternParser = new PatternParser(pattern); + /// + /// Create the used to parse the pattern + /// + /// the pattern to parse + /// The + /// + /// + /// Returns PatternParser used to parse the conversion string. Subclasses + /// may override this to return a subclass of PatternParser which recognize + /// custom conversion pattern name. + /// + /// + private PatternParser CreatePatternParser(string pattern) + { + PatternParser patternParser = new PatternParser(pattern); - // Add all the builtin patterns - foreach(DictionaryEntry entry in s_globalRulesRegistry) - { + // Add all the builtin patterns + foreach(DictionaryEntry entry in s_globalRulesRegistry) + { ConverterInfo converterInfo = new ConverterInfo(); converterInfo.Name = (string)entry.Key; converterInfo.Type = (Type)entry.Value; patternParser.PatternConverters.Add(entry.Key, converterInfo); - } - // Add the instance patterns - foreach(DictionaryEntry entry in m_instanceRulesRegistry) - { - patternParser.PatternConverters[entry.Key] = entry.Value; - } + } + // Add the instance patterns + foreach(DictionaryEntry entry in m_instanceRulesRegistry) + { + patternParser.PatternConverters[entry.Key] = entry.Value; + } - return patternParser; - } + return patternParser; + } - /// - /// Produces a formatted string as specified by the conversion pattern. - /// - /// The TextWriter to write the formatted event to - /// - /// - /// Format the pattern to the . - /// - /// - public void Format(TextWriter writer) - { - if (writer == null) - { - throw new ArgumentNullException("writer"); - } + /// + /// Produces a formatted string as specified by the conversion pattern. + /// + /// The TextWriter to write the formatted event to + /// + /// + /// Format the pattern to the . + /// + /// + public void Format(TextWriter writer) + { + if (writer == null) + { + throw new ArgumentNullException("writer"); + } - PatternConverter c = m_head; + PatternConverter c = m_head; - // loop through the chain of pattern converters - while(c != null) - { - c.Format(writer, null); - c = c.Next; - } - } + // loop through the chain of pattern converters + while(c != null) + { + c.Format(writer, null); + c = c.Next; + } + } - /// - /// Format the pattern as a string - /// - /// the pattern formatted as a string - /// - /// - /// Format the pattern to a string. - /// - /// - public string Format() - { - using StringWriter writer = new StringWriter(System.Globalization.CultureInfo.InvariantCulture); - Format(writer); - return writer.ToString(); - } + /// + /// Format the pattern as a string + /// + /// the pattern formatted as a string + /// + /// + /// Format the pattern to a string. + /// + /// + public string Format() + { + using StringWriter writer = new StringWriter(System.Globalization.CultureInfo.InvariantCulture); + Format(writer); + return writer.ToString(); + } - /// - /// Add a converter to this PatternString - /// - /// the converter info - /// - /// - /// This version of the method is used by the configurator. - /// Programmatic users should use the alternative method. - /// - /// - public void AddConverter(ConverterInfo converterInfo) - { + /// + /// Add a converter to this PatternString + /// + /// the converter info + /// + /// + /// This version of the method is used by the configurator. + /// Programmatic users should use the alternative method. + /// + /// + public void AddConverter(ConverterInfo converterInfo) + { if (converterInfo == null) throw new ArgumentNullException("converterInfo"); if (!typeof(PatternConverter).IsAssignableFrom(converterInfo.Type)) @@ -491,28 +491,28 @@ public void AddConverter(ConverterInfo converterInfo) throw new ArgumentException("The converter type specified [" + converterInfo.Type + "] must be a subclass of log4net.Util.PatternConverter", "converterInfo"); } m_instanceRulesRegistry[converterInfo.Name] = converterInfo; - } + } - /// - /// Add a converter to this PatternString - /// - /// the name of the conversion pattern for this converter - /// the type of the converter - /// - /// - /// Add a converter to this PatternString - /// - /// - public void AddConverter(string name, Type type) - { - if (name == null) throw new ArgumentNullException("name"); - if (type == null) throw new ArgumentNullException("type"); + /// + /// Add a converter to this PatternString + /// + /// the name of the conversion pattern for this converter + /// the type of the converter + /// + /// + /// Add a converter to this PatternString + /// + /// + public void AddConverter(string name, Type type) + { + if (name == null) throw new ArgumentNullException("name"); + if (type == null) throw new ArgumentNullException("type"); ConverterInfo converterInfo = new ConverterInfo(); converterInfo.Name = name; converterInfo.Type = type; AddConverter(converterInfo); - } - } + } + } } diff --git a/src/log4net/Util/PatternStringConverters/AppDomainPatternConverter.cs b/src/log4net/Util/PatternStringConverters/AppDomainPatternConverter.cs index 9a20d652..a874299a 100644 --- a/src/log4net/Util/PatternStringConverters/AppDomainPatternConverter.cs +++ b/src/log4net/Util/PatternStringConverters/AppDomainPatternConverter.cs @@ -25,30 +25,30 @@ namespace log4net.Util.PatternStringConverters { - /// - /// Write the name of the current AppDomain to the output - /// - /// - /// - /// Write the name of the current AppDomain to the output writer - /// - /// - /// Nicko Cadell - internal sealed class AppDomainPatternConverter : PatternConverter - { - /// - /// Write the name of the current AppDomain to the output - /// - /// the writer to write to - /// null, state is not set - /// - /// - /// Writes name of the current AppDomain to the output . - /// - /// - protected override void Convert(TextWriter writer, object state) - { - writer.Write( SystemInfo.ApplicationFriendlyName ); - } - } + /// + /// Write the name of the current AppDomain to the output + /// + /// + /// + /// Write the name of the current AppDomain to the output writer + /// + /// + /// Nicko Cadell + internal sealed class AppDomainPatternConverter : PatternConverter + { + /// + /// Write the name of the current AppDomain to the output + /// + /// the writer to write to + /// null, state is not set + /// + /// + /// Writes name of the current AppDomain to the output . + /// + /// + protected override void Convert(TextWriter writer, object state) + { + writer.Write( SystemInfo.ApplicationFriendlyName ); + } + } } diff --git a/src/log4net/Util/PatternStringConverters/DatePatternConverter.cs b/src/log4net/Util/PatternStringConverters/DatePatternConverter.cs index 40ffd779..315ce0a2 100644 --- a/src/log4net/Util/PatternStringConverters/DatePatternConverter.cs +++ b/src/log4net/Util/PatternStringConverters/DatePatternConverter.cs @@ -25,165 +25,165 @@ namespace log4net.Util.PatternStringConverters { - /// - /// Write the current date to the output - /// - /// - /// - /// Date pattern converter, uses a to format - /// the current date and time to the writer as a string. - /// - /// - /// The value of the determines - /// the formatting of the date. The following values are allowed: - /// - /// - /// Option value - /// Output - /// - /// - /// ISO8601 - /// - /// Uses the formatter. - /// Formats using the "yyyy-MM-dd HH:mm:ss,fff" pattern. - /// - /// - /// - /// DATE - /// - /// Uses the formatter. - /// Formats using the "dd MMM yyyy HH:mm:ss,fff" for example, "06 Nov 1994 15:49:37,459". - /// - /// - /// - /// ABSOLUTE - /// - /// Uses the formatter. - /// Formats using the "HH:mm:ss,fff" for example, "15:49:37,459". - /// - /// - /// - /// other - /// - /// Any other pattern string uses the formatter. - /// This formatter passes the pattern string to the - /// method. - /// For details on valid patterns see - /// DateTimeFormatInfo Class. - /// - /// - /// - /// - /// - /// The date and time is in the local time zone and is rendered in that zone. - /// To output the time in Universal time see . - /// - /// - /// Nicko Cadell - internal class DatePatternConverter : PatternConverter, IOptionHandler - { - /// - /// The used to render the date to a string - /// - /// - /// - /// The used to render the date to a string - /// - /// - protected IDateFormatter m_dateFormatter; - - #region Implementation of IOptionHandler + /// + /// Write the current date to the output + /// + /// + /// + /// Date pattern converter, uses a to format + /// the current date and time to the writer as a string. + /// + /// + /// The value of the determines + /// the formatting of the date. The following values are allowed: + /// + /// + /// Option value + /// Output + /// + /// + /// ISO8601 + /// + /// Uses the formatter. + /// Formats using the "yyyy-MM-dd HH:mm:ss,fff" pattern. + /// + /// + /// + /// DATE + /// + /// Uses the formatter. + /// Formats using the "dd MMM yyyy HH:mm:ss,fff" for example, "06 Nov 1994 15:49:37,459". + /// + /// + /// + /// ABSOLUTE + /// + /// Uses the formatter. + /// Formats using the "HH:mm:ss,fff" for example, "15:49:37,459". + /// + /// + /// + /// other + /// + /// Any other pattern string uses the formatter. + /// This formatter passes the pattern string to the + /// method. + /// For details on valid patterns see + /// DateTimeFormatInfo Class. + /// + /// + /// + /// + /// + /// The date and time is in the local time zone and is rendered in that zone. + /// To output the time in Universal time see . + /// + /// + /// Nicko Cadell + internal class DatePatternConverter : PatternConverter, IOptionHandler + { + /// + /// The used to render the date to a string + /// + /// + /// + /// The used to render the date to a string + /// + /// + protected IDateFormatter m_dateFormatter; + + #region Implementation of IOptionHandler - /// - /// Initialize the converter options - /// - /// - /// - /// This is part of the delayed object - /// activation scheme. The method must - /// be called on this object after the configuration properties have - /// been set. Until is called this - /// object is in an undefined state and must not be used. - /// - /// - /// If any of the configuration properties are modified then - /// must be called again. - /// - /// - public void ActivateOptions() - { - string dateFormatStr = Option; + /// + /// Initialize the converter options + /// + /// + /// + /// This is part of the delayed object + /// activation scheme. The method must + /// be called on this object after the configuration properties have + /// been set. Until is called this + /// object is in an undefined state and must not be used. + /// + /// + /// If any of the configuration properties are modified then + /// must be called again. + /// + /// + public void ActivateOptions() + { + string dateFormatStr = Option; - if (dateFormatStr == null) - { - dateFormatStr = AbsoluteTimeDateFormatter.Iso8601TimeDateFormat; - } - - if (SystemInfo.EqualsIgnoringCase(dateFormatStr, AbsoluteTimeDateFormatter.Iso8601TimeDateFormat)) - { - m_dateFormatter = new Iso8601DateFormatter(); - } - else if (SystemInfo.EqualsIgnoringCase(dateFormatStr, AbsoluteTimeDateFormatter.AbsoluteTimeDateFormat)) - { - m_dateFormatter = new AbsoluteTimeDateFormatter(); - } - else if (SystemInfo.EqualsIgnoringCase(dateFormatStr, AbsoluteTimeDateFormatter.DateAndTimeDateFormat)) - { - m_dateFormatter = new DateTimeDateFormatter(); - } - else - { - try - { - m_dateFormatter = new SimpleDateFormatter(dateFormatStr); - } - catch (Exception e) - { - LogLog.Error(declaringType, "Could not instantiate SimpleDateFormatter with ["+dateFormatStr+"]", e); - m_dateFormatter = new Iso8601DateFormatter(); - } - } - } + if (dateFormatStr == null) + { + dateFormatStr = AbsoluteTimeDateFormatter.Iso8601TimeDateFormat; + } + + if (SystemInfo.EqualsIgnoringCase(dateFormatStr, AbsoluteTimeDateFormatter.Iso8601TimeDateFormat)) + { + m_dateFormatter = new Iso8601DateFormatter(); + } + else if (SystemInfo.EqualsIgnoringCase(dateFormatStr, AbsoluteTimeDateFormatter.AbsoluteTimeDateFormat)) + { + m_dateFormatter = new AbsoluteTimeDateFormatter(); + } + else if (SystemInfo.EqualsIgnoringCase(dateFormatStr, AbsoluteTimeDateFormatter.DateAndTimeDateFormat)) + { + m_dateFormatter = new DateTimeDateFormatter(); + } + else + { + try + { + m_dateFormatter = new SimpleDateFormatter(dateFormatStr); + } + catch (Exception e) + { + LogLog.Error(declaringType, "Could not instantiate SimpleDateFormatter with ["+dateFormatStr+"]", e); + m_dateFormatter = new Iso8601DateFormatter(); + } + } + } - #endregion + #endregion - /// - /// Write the current date to the output - /// - /// that will receive the formatted result. - /// null, state is not set - /// - /// - /// Pass the current date and time to the - /// for it to render it to the writer. - /// - /// - /// The date and time passed is in the local time zone. - /// - /// - protected override void Convert(TextWriter writer, object state) - { - try - { - m_dateFormatter.FormatDate(DateTime.Now, writer); - } - catch (Exception ex) - { - LogLog.Error(declaringType, "Error occurred while converting date.", ex); - } - } + /// + /// Write the current date to the output + /// + /// that will receive the formatted result. + /// null, state is not set + /// + /// + /// Pass the current date and time to the + /// for it to render it to the writer. + /// + /// + /// The date and time passed is in the local time zone. + /// + /// + protected override void Convert(TextWriter writer, object state) + { + try + { + m_dateFormatter.FormatDate(DateTime.Now, writer); + } + catch (Exception ex) + { + LogLog.Error(declaringType, "Error occurred while converting date.", ex); + } + } - #region Private Static Fields + #region Private Static Fields - /// - /// The fully qualified type of the DatePatternConverter class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(DatePatternConverter); + /// + /// The fully qualified type of the DatePatternConverter class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(DatePatternConverter); - #endregion Private Static Fields - } + #endregion Private Static Fields + } } diff --git a/src/log4net/Util/PatternStringConverters/EnvironmentPatternConverter.cs b/src/log4net/Util/PatternStringConverters/EnvironmentPatternConverter.cs index 70851298..8b011a5a 100644 --- a/src/log4net/Util/PatternStringConverters/EnvironmentPatternConverter.cs +++ b/src/log4net/Util/PatternStringConverters/EnvironmentPatternConverter.cs @@ -25,87 +25,87 @@ namespace log4net.Util.PatternStringConverters { - /// - /// Write an environment variable to the output - /// - /// - /// - /// Write an environment variable to the output writer. - /// The value of the determines - /// the name of the variable to output. - /// - /// - /// Nicko Cadell - internal sealed class EnvironmentPatternConverter : PatternConverter - { - /// - /// Write an environment variable to the output - /// - /// the writer to write to - /// null, state is not set - /// - /// - /// Writes the environment variable to the output . - /// The name of the environment variable to output must be set - /// using the - /// property. - /// - /// - protected override void Convert(TextWriter writer, object state) - { - try - { - if (this.Option != null && this.Option.Length > 0) - { - // Lookup the environment variable - string envValue = Environment.GetEnvironmentVariable(this.Option); + /// + /// Write an environment variable to the output + /// + /// + /// + /// Write an environment variable to the output writer. + /// The value of the determines + /// the name of the variable to output. + /// + /// + /// Nicko Cadell + internal sealed class EnvironmentPatternConverter : PatternConverter + { + /// + /// Write an environment variable to the output + /// + /// the writer to write to + /// null, state is not set + /// + /// + /// Writes the environment variable to the output . + /// The name of the environment variable to output must be set + /// using the + /// property. + /// + /// + protected override void Convert(TextWriter writer, object state) + { + try + { + if (this.Option != null && this.Option.Length > 0) + { + // Lookup the environment variable + string envValue = Environment.GetEnvironmentVariable(this.Option); #if NET_2_0 || NETSTANDARD2_0 // If we didn't see it for the process, try a user level variable. - if (envValue == null) - { - envValue = Environment.GetEnvironmentVariable(this.Option, EnvironmentVariableTarget.User); - } + if (envValue == null) + { + envValue = Environment.GetEnvironmentVariable(this.Option, EnvironmentVariableTarget.User); + } // If we still didn't find it, try a system level one. - if (envValue == null) - { - envValue = Environment.GetEnvironmentVariable(this.Option, EnvironmentVariableTarget.Machine); - } -#endif + if (envValue == null) + { + envValue = Environment.GetEnvironmentVariable(this.Option, EnvironmentVariableTarget.Machine); + } +#endif - if (envValue != null && envValue.Length > 0) - { - writer.Write(envValue); - } - } - } - catch(System.Security.SecurityException secEx) - { - // This security exception will occur if the caller does not have - // unrestricted environment permission. If this occurs the expansion - // will be skipped with the following warning message. - LogLog.Debug(declaringType, "Security exception while trying to expand environment variables. Error Ignored. No Expansion.", secEx); - } - catch (Exception ex) - { - LogLog.Error(declaringType, "Error occurred while converting environment variable.", ex); - } - } + if (envValue != null && envValue.Length > 0) + { + writer.Write(envValue); + } + } + } + catch(System.Security.SecurityException secEx) + { + // This security exception will occur if the caller does not have + // unrestricted environment permission. If this occurs the expansion + // will be skipped with the following warning message. + LogLog.Debug(declaringType, "Security exception while trying to expand environment variables. Error Ignored. No Expansion.", secEx); + } + catch (Exception ex) + { + LogLog.Error(declaringType, "Error occurred while converting environment variable.", ex); + } + } - #region Private Static Fields + #region Private Static Fields - /// - /// The fully qualified type of the EnvironmentPatternConverter class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(EnvironmentPatternConverter); + /// + /// The fully qualified type of the EnvironmentPatternConverter class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(EnvironmentPatternConverter); - #endregion Private Static Fields - } + #endregion Private Static Fields + } } #endif // !NETCF diff --git a/src/log4net/Util/PatternStringConverters/IdentityPatternConverter.cs b/src/log4net/Util/PatternStringConverters/IdentityPatternConverter.cs index f3ee8605..f31ca0d9 100644 --- a/src/log4net/Util/PatternStringConverters/IdentityPatternConverter.cs +++ b/src/log4net/Util/PatternStringConverters/IdentityPatternConverter.cs @@ -25,64 +25,64 @@ namespace log4net.Util.PatternStringConverters { - /// - /// Write the current thread identity to the output - /// - /// - /// - /// Write the current thread identity to the output writer - /// - /// - /// Nicko Cadell - internal sealed class IdentityPatternConverter : PatternConverter - { - /// - /// Write the current thread identity to the output - /// - /// the writer to write to - /// null, state is not set - /// - /// - /// Writes the current thread identity to the output . - /// - /// - protected override void Convert(TextWriter writer, object state) - { + /// + /// Write the current thread identity to the output + /// + /// + /// + /// Write the current thread identity to the output writer + /// + /// + /// Nicko Cadell + internal sealed class IdentityPatternConverter : PatternConverter + { + /// + /// Write the current thread identity to the output + /// + /// the writer to write to + /// null, state is not set + /// + /// + /// Writes the current thread identity to the output . + /// + /// + protected override void Convert(TextWriter writer, object state) + { #if (NETCF || SSCLI || NETSTANDARD1_3) - // On compact framework there's no notion of current thread principals - writer.Write( SystemInfo.NotAvailableText ); + // On compact framework there's no notion of current thread principals + writer.Write( SystemInfo.NotAvailableText ); #else - try - { - if (System.Threading.Thread.CurrentPrincipal != null && - System.Threading.Thread.CurrentPrincipal.Identity != null && - System.Threading.Thread.CurrentPrincipal.Identity.Name != null) - { - writer.Write( System.Threading.Thread.CurrentPrincipal.Identity.Name ); - } - } - catch(System.Security.SecurityException) - { - // This security exception will occur if the caller does not have - // some undefined set of SecurityPermission flags. - LogLog.Debug(declaringType, "Security exception while trying to get current thread principal. Error Ignored."); + try + { + if (System.Threading.Thread.CurrentPrincipal != null && + System.Threading.Thread.CurrentPrincipal.Identity != null && + System.Threading.Thread.CurrentPrincipal.Identity.Name != null) + { + writer.Write( System.Threading.Thread.CurrentPrincipal.Identity.Name ); + } + } + catch(System.Security.SecurityException) + { + // This security exception will occur if the caller does not have + // some undefined set of SecurityPermission flags. + LogLog.Debug(declaringType, "Security exception while trying to get current thread principal. Error Ignored."); - writer.Write( SystemInfo.NotAvailableText ); - } + writer.Write( SystemInfo.NotAvailableText ); + } #endif - } + } - #region Private Static Fields + #region Private Static Fields - /// - /// The fully qualified type of the IdentityPatternConverter class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(IdentityPatternConverter); + /// + /// The fully qualified type of the IdentityPatternConverter class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(IdentityPatternConverter); - #endregion Private Static Fields - } + #endregion Private Static Fields + } } diff --git a/src/log4net/Util/PatternStringConverters/LiteralPatternConverter.cs b/src/log4net/Util/PatternStringConverters/LiteralPatternConverter.cs index 3f3e2420..bcdf7e4d 100644 --- a/src/log4net/Util/PatternStringConverters/LiteralPatternConverter.cs +++ b/src/log4net/Util/PatternStringConverters/LiteralPatternConverter.cs @@ -25,83 +25,83 @@ namespace log4net.Util.PatternStringConverters { - /// - /// Pattern converter for literal string instances in the pattern - /// - /// - /// - /// Writes the literal string value specified in the - /// property to - /// the output. - /// - /// - /// Nicko Cadell - internal class LiteralPatternConverter : PatternConverter - { - /// - /// Set the next converter in the chain - /// - /// The next pattern converter in the chain - /// The next pattern converter - /// - /// - /// Special case the building of the pattern converter chain - /// for instances. Two adjacent - /// literals in the pattern can be represented by a single combined - /// pattern converter. This implementation detects when a - /// is added to the chain - /// after this converter and combines its value with this converter's - /// literal value. - /// - /// - public override PatternConverter SetNext(PatternConverter pc) - { - LiteralPatternConverter literalPc = pc as LiteralPatternConverter; - if (literalPc != null) - { - // Combine the two adjacent literals together - Option = Option + literalPc.Option; + /// + /// Pattern converter for literal string instances in the pattern + /// + /// + /// + /// Writes the literal string value specified in the + /// property to + /// the output. + /// + /// + /// Nicko Cadell + internal class LiteralPatternConverter : PatternConverter + { + /// + /// Set the next converter in the chain + /// + /// The next pattern converter in the chain + /// The next pattern converter + /// + /// + /// Special case the building of the pattern converter chain + /// for instances. Two adjacent + /// literals in the pattern can be represented by a single combined + /// pattern converter. This implementation detects when a + /// is added to the chain + /// after this converter and combines its value with this converter's + /// literal value. + /// + /// + public override PatternConverter SetNext(PatternConverter pc) + { + LiteralPatternConverter literalPc = pc as LiteralPatternConverter; + if (literalPc != null) + { + // Combine the two adjacent literals together + Option = Option + literalPc.Option; - // We are the next converter now - return this; - } + // We are the next converter now + return this; + } - return base.SetNext(pc); - } + return base.SetNext(pc); + } - /// - /// Write the literal to the output - /// - /// the writer to write to - /// null, not set - /// - /// - /// Override the formatting behavior to ignore the FormattingInfo - /// because we have a literal instead. - /// - /// - /// Writes the value of - /// to the output . - /// - /// - public override void Format(TextWriter writer, object state) - { - writer.Write(Option); - } + /// + /// Write the literal to the output + /// + /// the writer to write to + /// null, not set + /// + /// + /// Override the formatting behavior to ignore the FormattingInfo + /// because we have a literal instead. + /// + /// + /// Writes the value of + /// to the output . + /// + /// + public override void Format(TextWriter writer, object state) + { + writer.Write(Option); + } - /// - /// Convert this pattern into the rendered message - /// - /// that will receive the formatted result. - /// null, not set - /// - /// - /// This method is not used. - /// - /// - protected override void Convert(TextWriter writer, object state) - { - throw new InvalidOperationException("Should never get here because of the overridden Format method"); - } - } + /// + /// Convert this pattern into the rendered message + /// + /// that will receive the formatted result. + /// null, not set + /// + /// + /// This method is not used. + /// + /// + protected override void Convert(TextWriter writer, object state) + { + throw new InvalidOperationException("Should never get here because of the overridden Format method"); + } + } } diff --git a/src/log4net/Util/PatternStringConverters/NewLinePatternConverter.cs b/src/log4net/Util/PatternStringConverters/NewLinePatternConverter.cs index 2ba276f4..2d663a03 100644 --- a/src/log4net/Util/PatternStringConverters/NewLinePatternConverter.cs +++ b/src/log4net/Util/PatternStringConverters/NewLinePatternConverter.cs @@ -21,66 +21,66 @@ namespace log4net.Util.PatternStringConverters { - /// - /// Writes a newline to the output - /// - /// - /// - /// Writes the system dependent line terminator to the output. - /// This behavior can be overridden by setting the : - /// - /// - /// - /// Option Value - /// Output - /// - /// - /// DOS - /// DOS or Windows line terminator "\r\n" - /// - /// - /// UNIX - /// UNIX line terminator "\n" - /// - /// - /// - /// Nicko Cadell - internal sealed class NewLinePatternConverter : LiteralPatternConverter, IOptionHandler - { - #region Implementation of IOptionHandler + /// + /// Writes a newline to the output + /// + /// + /// + /// Writes the system dependent line terminator to the output. + /// This behavior can be overridden by setting the : + /// + /// + /// + /// Option Value + /// Output + /// + /// + /// DOS + /// DOS or Windows line terminator "\r\n" + /// + /// + /// UNIX + /// UNIX line terminator "\n" + /// + /// + /// + /// Nicko Cadell + internal sealed class NewLinePatternConverter : LiteralPatternConverter, IOptionHandler + { + #region Implementation of IOptionHandler - /// - /// Initialize the converter - /// - /// - /// - /// This is part of the delayed object - /// activation scheme. The method must - /// be called on this object after the configuration properties have - /// been set. Until is called this - /// object is in an undefined state and must not be used. - /// - /// - /// If any of the configuration properties are modified then - /// must be called again. - /// - /// - public void ActivateOptions() - { - if (SystemInfo.EqualsIgnoringCase(Option, "DOS")) - { - Option = "\r\n"; - } - else if (SystemInfo.EqualsIgnoringCase(Option, "UNIX")) - { - Option = "\n"; - } - else - { - Option = SystemInfo.NewLine; - } - } + /// + /// Initialize the converter + /// + /// + /// + /// This is part of the delayed object + /// activation scheme. The method must + /// be called on this object after the configuration properties have + /// been set. Until is called this + /// object is in an undefined state and must not be used. + /// + /// + /// If any of the configuration properties are modified then + /// must be called again. + /// + /// + public void ActivateOptions() + { + if (SystemInfo.EqualsIgnoringCase(Option, "DOS")) + { + Option = "\r\n"; + } + else if (SystemInfo.EqualsIgnoringCase(Option, "UNIX")) + { + Option = "\n"; + } + else + { + Option = SystemInfo.NewLine; + } + } - #endregion - } + #endregion + } } diff --git a/src/log4net/Util/PatternStringConverters/ProcessIdPatternConverter.cs b/src/log4net/Util/PatternStringConverters/ProcessIdPatternConverter.cs index fbb796d8..d4e197e4 100644 --- a/src/log4net/Util/PatternStringConverters/ProcessIdPatternConverter.cs +++ b/src/log4net/Util/PatternStringConverters/ProcessIdPatternConverter.cs @@ -22,62 +22,62 @@ namespace log4net.Util.PatternStringConverters { - /// - /// Write the current process ID to the output - /// - /// - /// - /// Write the current process ID to the output writer - /// - /// - /// Nicko Cadell - internal sealed class ProcessIdPatternConverter : PatternConverter - { - /// - /// Write the current process ID to the output - /// - /// the writer to write to - /// null, state is not set - /// - /// - /// Write the current process ID to the output . - /// - /// + /// + /// Write the current process ID to the output + /// + /// + /// + /// Write the current process ID to the output writer + /// + /// + /// Nicko Cadell + internal sealed class ProcessIdPatternConverter : PatternConverter + { + /// + /// Write the current process ID to the output + /// + /// the writer to write to + /// null, state is not set + /// + /// + /// Write the current process ID to the output . + /// + /// #if NET_4_0 || MONO_4_0 || NETSTANDARD [System.Security.SecuritySafeCritical] #endif protected override void Convert(TextWriter writer, object state) - { + { #if (NETCF || SSCLI) - // On compact framework there is no System.Diagnostics.Process class - writer.Write( SystemInfo.NotAvailableText ); + // On compact framework there is no System.Diagnostics.Process class + writer.Write( SystemInfo.NotAvailableText ); #else - try - { - writer.Write( System.Diagnostics.Process.GetCurrentProcess().Id ); - } - catch(System.Security.SecurityException) - { - // This security exception will occur if the caller does not have - // some undefined set of SecurityPermission flags. - LogLog.Debug(declaringType, "Security exception while trying to get current process id. Error Ignored."); + try + { + writer.Write( System.Diagnostics.Process.GetCurrentProcess().Id ); + } + catch(System.Security.SecurityException) + { + // This security exception will occur if the caller does not have + // some undefined set of SecurityPermission flags. + LogLog.Debug(declaringType, "Security exception while trying to get current process id. Error Ignored."); - writer.Write( SystemInfo.NotAvailableText ); - } + writer.Write( SystemInfo.NotAvailableText ); + } #endif - } + } - #region Private Static Fields + #region Private Static Fields - /// - /// The fully qualified type of the ProcessIdPatternConverter class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(ProcessIdPatternConverter); + /// + /// The fully qualified type of the ProcessIdPatternConverter class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(ProcessIdPatternConverter); - #endregion Private Static Fields - } + #endregion Private Static Fields + } } diff --git a/src/log4net/Util/PatternStringConverters/PropertyPatternConverter.cs b/src/log4net/Util/PatternStringConverters/PropertyPatternConverter.cs index bf81f2aa..76f4239f 100644 --- a/src/log4net/Util/PatternStringConverters/PropertyPatternConverter.cs +++ b/src/log4net/Util/PatternStringConverters/PropertyPatternConverter.cs @@ -21,72 +21,72 @@ namespace log4net.Util.PatternStringConverters { - /// - /// Property pattern converter - /// - /// - /// - /// This pattern converter reads the thread and global properties. - /// The thread properties take priority over global properties. - /// See for details of the - /// thread properties. See for - /// details of the global properties. - /// - /// - /// If the is specified then that will be used to - /// lookup a single property. If no is specified - /// then all properties will be dumped as a list of key value pairs. - /// - /// - /// Nicko Cadell - internal sealed class PropertyPatternConverter : PatternConverter - { - /// - /// Write the property value to the output - /// - /// that will receive the formatted result. - /// null, state is not set - /// - /// - /// Writes out the value of a named property. The property name - /// should be set in the - /// property. - /// - /// - /// If the is set to null - /// then all the properties are written as key value pairs. - /// - /// - protected override void Convert(TextWriter writer, object state) - { - CompositeProperties compositeProperties = new CompositeProperties(); + /// + /// Property pattern converter + /// + /// + /// + /// This pattern converter reads the thread and global properties. + /// The thread properties take priority over global properties. + /// See for details of the + /// thread properties. See for + /// details of the global properties. + /// + /// + /// If the is specified then that will be used to + /// lookup a single property. If no is specified + /// then all properties will be dumped as a list of key value pairs. + /// + /// + /// Nicko Cadell + internal sealed class PropertyPatternConverter : PatternConverter + { + /// + /// Write the property value to the output + /// + /// that will receive the formatted result. + /// null, state is not set + /// + /// + /// Writes out the value of a named property. The property name + /// should be set in the + /// property. + /// + /// + /// If the is set to null + /// then all the properties are written as key value pairs. + /// + /// + protected override void Convert(TextWriter writer, object state) + { + CompositeProperties compositeProperties = new CompositeProperties(); #if !NETCF - PropertiesDictionary logicalThreadProperties = LogicalThreadContext.Properties.GetProperties(false); - if (logicalThreadProperties != null) - { - compositeProperties.Add(logicalThreadProperties); - } + PropertiesDictionary logicalThreadProperties = LogicalThreadContext.Properties.GetProperties(false); + if (logicalThreadProperties != null) + { + compositeProperties.Add(logicalThreadProperties); + } #endif - PropertiesDictionary threadProperties = ThreadContext.Properties.GetProperties(false); - if (threadProperties != null) - { - compositeProperties.Add(threadProperties); - } + PropertiesDictionary threadProperties = ThreadContext.Properties.GetProperties(false); + if (threadProperties != null) + { + compositeProperties.Add(threadProperties); + } - // TODO: Add Repository Properties - compositeProperties.Add(GlobalContext.Properties.GetReadOnlyProperties()); + // 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()); - } - } - } + 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()); + } + } + } } diff --git a/src/log4net/Util/PatternStringConverters/RandomStringPatternConverter.cs b/src/log4net/Util/PatternStringConverters/RandomStringPatternConverter.cs index 015cfd7f..8b11c45c 100644 --- a/src/log4net/Util/PatternStringConverters/RandomStringPatternConverter.cs +++ b/src/log4net/Util/PatternStringConverters/RandomStringPatternConverter.cs @@ -27,130 +27,130 @@ namespace log4net.Util.PatternStringConverters { - /// - /// A Pattern converter that generates a string of random characters - /// - /// - /// - /// The converter generates a string of random characters. By default - /// the string is length 4. This can be changed by setting the - /// to the string value of the length required. - /// - /// - /// The random characters in the string are limited to uppercase letters - /// and numbers only. - /// - /// - /// The random number generator used by this class is not cryptographically secure. - /// - /// - /// Nicko Cadell - internal sealed class RandomStringPatternConverter : PatternConverter, IOptionHandler - { - /// - /// Shared random number generator - /// - private static readonly Random s_random = new Random(); + /// + /// A Pattern converter that generates a string of random characters + /// + /// + /// + /// The converter generates a string of random characters. By default + /// the string is length 4. This can be changed by setting the + /// to the string value of the length required. + /// + /// + /// The random characters in the string are limited to uppercase letters + /// and numbers only. + /// + /// + /// The random number generator used by this class is not cryptographically secure. + /// + /// + /// Nicko Cadell + internal sealed class RandomStringPatternConverter : PatternConverter, IOptionHandler + { + /// + /// Shared random number generator + /// + private static readonly Random s_random = new Random(); - /// - /// Length of random string to generate. Default length 4. - /// - private int m_length = 4; + /// + /// Length of random string to generate. Default length 4. + /// + private int m_length = 4; - #region Implementation of IOptionHandler + #region Implementation of IOptionHandler - /// - /// Initialize the converter options - /// - /// - /// - /// This is part of the delayed object - /// activation scheme. The method must - /// be called on this object after the configuration properties have - /// been set. Until is called this - /// object is in an undefined state and must not be used. - /// - /// - /// If any of the configuration properties are modified then - /// must be called again. - /// - /// - public void ActivateOptions() - { - string optionStr = Option; - if (optionStr != null && optionStr.Length > 0) - { - int lengthVal; - if (SystemInfo.TryParse(optionStr, out lengthVal)) - { - m_length = lengthVal; - } - else - { - LogLog.Error(declaringType, "RandomStringPatternConverter: Could not convert Option ["+optionStr+"] to Length Int32"); - } - } - } + /// + /// Initialize the converter options + /// + /// + /// + /// This is part of the delayed object + /// activation scheme. The method must + /// be called on this object after the configuration properties have + /// been set. Until is called this + /// object is in an undefined state and must not be used. + /// + /// + /// If any of the configuration properties are modified then + /// must be called again. + /// + /// + public void ActivateOptions() + { + string optionStr = Option; + if (optionStr != null && optionStr.Length > 0) + { + int lengthVal; + if (SystemInfo.TryParse(optionStr, out lengthVal)) + { + m_length = lengthVal; + } + else + { + LogLog.Error(declaringType, "RandomStringPatternConverter: Could not convert Option ["+optionStr+"] to Length Int32"); + } + } + } - #endregion + #endregion - /// - /// Write a randoim string to the output - /// - /// the writer to write to - /// null, state is not set - /// - /// - /// Write a randoim string to the output . - /// - /// - protected override void Convert(TextWriter writer, object state) - { - try - { - lock(s_random) - { - for(int i=0; i + /// Write a randoim string to the output + /// + /// the writer to write to + /// null, state is not set + /// + /// + /// Write a randoim string to the output . + /// + /// + protected override void Convert(TextWriter writer, object state) + { + try + { + lock(s_random) + { + for(int i=0; i - /// The fully qualified type of the RandomStringPatternConverter class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(RandomStringPatternConverter); + /// + /// The fully qualified type of the RandomStringPatternConverter class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(RandomStringPatternConverter); - #endregion Private Static Fields - } + #endregion Private Static Fields + } } diff --git a/src/log4net/Util/PatternStringConverters/UserNamePatternConverter.cs b/src/log4net/Util/PatternStringConverters/UserNamePatternConverter.cs index 9cc69fd9..896e51dc 100644 --- a/src/log4net/Util/PatternStringConverters/UserNamePatternConverter.cs +++ b/src/log4net/Util/PatternStringConverters/UserNamePatternConverter.cs @@ -22,64 +22,64 @@ namespace log4net.Util.PatternStringConverters { - /// - /// Write the current threads username to the output - /// - /// - /// - /// Write the current threads username to the output writer - /// - /// - /// Nicko Cadell - internal sealed class UserNamePatternConverter : PatternConverter - { - /// - /// Write the current threads username to the output - /// - /// the writer to write to - /// null, state is not set - /// - /// - /// Write the current threads username to the output . - /// - /// - protected override void Convert(TextWriter writer, object state) - { + /// + /// Write the current threads username to the output + /// + /// + /// + /// Write the current threads username to the output writer + /// + /// + /// Nicko Cadell + internal sealed class UserNamePatternConverter : PatternConverter + { + /// + /// Write the current threads username to the output + /// + /// the writer to write to + /// null, state is not set + /// + /// + /// Write the current threads username to the output . + /// + /// + protected override void Convert(TextWriter writer, object state) + { #if (NETCF || SSCLI || NETSTANDARD1_3) - // On compact framework there's no notion of current Windows user - writer.Write( SystemInfo.NotAvailableText ); + // On compact framework there's no notion of current Windows user + writer.Write( SystemInfo.NotAvailableText ); #else - try - { - System.Security.Principal.WindowsIdentity windowsIdentity = null; - windowsIdentity = System.Security.Principal.WindowsIdentity.GetCurrent(); - if (windowsIdentity != null && windowsIdentity.Name != null) - { - writer.Write( windowsIdentity.Name ); - } - } - catch(System.Security.SecurityException) - { - // This security exception will occur if the caller does not have - // some undefined set of SecurityPermission flags. - LogLog.Debug(declaringType, "Security exception while trying to get current windows identity. Error Ignored."); + try + { + System.Security.Principal.WindowsIdentity windowsIdentity = null; + windowsIdentity = System.Security.Principal.WindowsIdentity.GetCurrent(); + if (windowsIdentity != null && windowsIdentity.Name != null) + { + writer.Write( windowsIdentity.Name ); + } + } + catch(System.Security.SecurityException) + { + // This security exception will occur if the caller does not have + // some undefined set of SecurityPermission flags. + LogLog.Debug(declaringType, "Security exception while trying to get current windows identity. Error Ignored."); - writer.Write( SystemInfo.NotAvailableText ); - } + writer.Write( SystemInfo.NotAvailableText ); + } #endif - } + } - #region Private Static Fields + #region Private Static Fields - /// - /// The fully qualified type of the UserNamePatternConverter class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(UserNamePatternConverter); + /// + /// The fully qualified type of the UserNamePatternConverter class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(UserNamePatternConverter); - #endregion Private Static Fields - } + #endregion Private Static Fields + } } diff --git a/src/log4net/Util/PatternStringConverters/UtcDatePatternConverter.cs b/src/log4net/Util/PatternStringConverters/UtcDatePatternConverter.cs index 31d5f7f1..6c59484e 100644 --- a/src/log4net/Util/PatternStringConverters/UtcDatePatternConverter.cs +++ b/src/log4net/Util/PatternStringConverters/UtcDatePatternConverter.cs @@ -27,60 +27,60 @@ namespace log4net.Util.PatternStringConverters { - /// - /// Write the UTC date time to the output - /// - /// - /// - /// Date pattern converter, uses a to format - /// the current date and time in Universal time. - /// - /// - /// See the for details on the date pattern syntax. - /// - /// - /// - /// Nicko Cadell - internal class UtcDatePatternConverter : DatePatternConverter - { - /// - /// Write the current date and time to the output - /// - /// that will receive the formatted result. - /// null, state is not set - /// - /// - /// Pass the current date and time to the - /// for it to render it to the writer. - /// - /// - /// The date is in Universal time when it is rendered. - /// - /// - /// - protected override void Convert(TextWriter writer, object state) - { - try - { - m_dateFormatter.FormatDate(DateTime.UtcNow, writer); - } - catch (Exception ex) - { - LogLog.Error(declaringType, "Error occurred while converting date.", ex); - } - } + /// + /// Write the UTC date time to the output + /// + /// + /// + /// Date pattern converter, uses a to format + /// the current date and time in Universal time. + /// + /// + /// See the for details on the date pattern syntax. + /// + /// + /// + /// Nicko Cadell + internal class UtcDatePatternConverter : DatePatternConverter + { + /// + /// Write the current date and time to the output + /// + /// that will receive the formatted result. + /// null, state is not set + /// + /// + /// Pass the current date and time to the + /// for it to render it to the writer. + /// + /// + /// The date is in Universal time when it is rendered. + /// + /// + /// + protected override void Convert(TextWriter writer, object state) + { + try + { + m_dateFormatter.FormatDate(DateTime.UtcNow, writer); + } + catch (Exception ex) + { + LogLog.Error(declaringType, "Error occurred while converting date.", ex); + } + } - #region Private Static Fields + #region Private Static Fields - /// - /// The fully qualified type of the UtcDatePatternConverter class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(UtcDatePatternConverter); + /// + /// The fully qualified type of the UtcDatePatternConverter class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(UtcDatePatternConverter); - #endregion Private Static Fields - } + #endregion Private Static Fields + } } diff --git a/src/log4net/Util/PropertiesDictionary.cs b/src/log4net/Util/PropertiesDictionary.cs index e70fb203..ce72e981 100644 --- a/src/log4net/Util/PropertiesDictionary.cs +++ b/src/log4net/Util/PropertiesDictionary.cs @@ -23,311 +23,311 @@ namespace log4net.Util { - /// - /// String keyed object map. - /// - /// - /// - /// While this collection is serializable only member - /// objects that are serializable will - /// be serialized along with this collection. - /// - /// - /// Nicko Cadell - /// Gert Driesen + /// + /// String keyed object map. + /// + /// + /// + /// While this collection is serializable only member + /// objects that are serializable will + /// be serialized along with this collection. + /// + /// + /// Nicko Cadell + /// Gert Driesen #if NETCF - public sealed class PropertiesDictionary : ReadOnlyPropertiesDictionary, IDictionary + public sealed class PropertiesDictionary : ReadOnlyPropertiesDictionary, IDictionary #else - [Serializable] - public sealed class PropertiesDictionary : ReadOnlyPropertiesDictionary, ISerializable, IDictionary + [Serializable] + public sealed class PropertiesDictionary : ReadOnlyPropertiesDictionary, ISerializable, IDictionary #endif - { - #region Public Instance Constructors - - /// - /// Constructor - /// - /// - /// - /// Initializes a new instance of the class. - /// - /// - public PropertiesDictionary() - { - } - - /// - /// Constructor - /// - /// properties to copy - /// - /// - /// Initializes a new instance of the class. - /// - /// - public PropertiesDictionary(ReadOnlyPropertiesDictionary propertiesDictionary) : base(propertiesDictionary) - { - } - - #endregion Public Instance Constructors - - #region Private Instance Constructors + { + #region Public Instance Constructors + + /// + /// Constructor + /// + /// + /// + /// Initializes a new instance of the class. + /// + /// + public PropertiesDictionary() + { + } + + /// + /// Constructor + /// + /// properties to copy + /// + /// + /// Initializes a new instance of the class. + /// + /// + public PropertiesDictionary(ReadOnlyPropertiesDictionary propertiesDictionary) : base(propertiesDictionary) + { + } + + #endregion Public Instance Constructors + + #region Private Instance Constructors #if !NETCF - /// - /// Initializes a new instance of the class - /// with serialized data. - /// - /// The that holds the serialized object data. - /// The that contains contextual information about the source or destination. - /// - /// - /// Because this class is sealed the serialization constructor is private. - /// - /// - private PropertiesDictionary(SerializationInfo info, StreamingContext context) : base(info, context) - { - } + /// + /// Initializes a new instance of the class + /// with serialized data. + /// + /// The that holds the serialized object data. + /// The that contains contextual information about the source or destination. + /// + /// + /// Because this class is sealed the serialization constructor is private. + /// + /// + private PropertiesDictionary(SerializationInfo info, StreamingContext context) : base(info, context) + { + } #endif - #endregion Protected Instance Constructors - - #region Public Instance Properties - - /// - /// Gets or sets the value of the property with the specified key. - /// - /// - /// The value of the property with the specified key. - /// - /// The key of the property to get or set. - /// - /// - /// The property value will only be serialized if it is serializable. - /// If it cannot be serialized it will be silently ignored if - /// a serialization operation is performed. - /// - /// - public override object this[string key] - { - get { return InnerHashtable[key]; } - set { InnerHashtable[key] = value; } - } - - #endregion Public Instance Properties - - #region Public Instance Methods - - /// - /// Remove the entry with the specified key from this dictionary - /// - /// the key for the entry to remove - /// - /// - /// Remove the entry with the specified key from this dictionary - /// - /// - public void Remove(string key) - { - InnerHashtable.Remove(key); - } - - #endregion Public Instance Methods - - #region Implementation of IDictionary - - /// - /// See - /// - /// an enumerator - /// - /// - /// Returns a over the contest of this collection. - /// - /// - IDictionaryEnumerator IDictionary.GetEnumerator() - { - return InnerHashtable.GetEnumerator(); - } - - /// - /// See - /// - /// the key to remove - /// - /// - /// Remove the entry with the specified key from this dictionary - /// - /// - void IDictionary.Remove(object key) - { - InnerHashtable.Remove(key); - } - - /// - /// See - /// - /// the key to lookup in the collection - /// true if the collection contains the specified key - /// - /// - /// Test if this collection contains a specified key. - /// - /// - bool IDictionary.Contains(object key) - { - return InnerHashtable.Contains(key); - } - - /// - /// Remove all properties from the properties collection - /// - /// - /// - /// Remove all properties from the properties collection - /// - /// - public override void Clear() - { - InnerHashtable.Clear(); - } - - /// - /// See - /// - /// the key - /// the value to store for the key - /// - /// - /// Store a value for the specified . - /// - /// - /// Thrown if the is not a string - void IDictionary.Add(object key, object value) - { - if (!(key is string)) - { - throw new ArgumentException("key must be a string", "key"); - } - InnerHashtable.Add(key, value); - } - - /// - /// See - /// - /// - /// false - /// - /// - /// - /// This collection is modifiable. This property always - /// returns false. - /// - /// - bool IDictionary.IsReadOnly - { - get { return false; } - } - - /// - /// See - /// - /// - /// The value for the key specified. - /// - /// - /// - /// Get or set a value for the specified . - /// - /// - /// Thrown if the is not a string - object IDictionary.this[object key] - { - get - { - if (!(key is string)) - { - throw new ArgumentException("key must be a string", "key"); - } - return InnerHashtable[key]; - } - set - { - if (!(key is string)) - { - throw new ArgumentException("key must be a string", "key"); - } - InnerHashtable[key] = value; - } - } - - /// - /// See - /// - ICollection IDictionary.Values - { - get { return InnerHashtable.Values; } - } - - /// - /// See - /// - ICollection IDictionary.Keys - { - get { return InnerHashtable.Keys; } - } - - /// - /// See - /// - bool IDictionary.IsFixedSize - { - get { return false; } - } - - #endregion - - #region Implementation of ICollection - - /// - /// See - /// - /// - /// - void ICollection.CopyTo(Array array, int index) - { - InnerHashtable.CopyTo(array, index); - } - - /// - /// See - /// - bool ICollection.IsSynchronized - { - get { return InnerHashtable.IsSynchronized; } - } - - /// - /// See - /// - object ICollection.SyncRoot - { - get { return InnerHashtable.SyncRoot; } - } - - #endregion - - #region Implementation of IEnumerable - - /// - /// See - /// - IEnumerator IEnumerable.GetEnumerator() - { - return ((IEnumerable)InnerHashtable).GetEnumerator(); - } - - #endregion - } + #endregion Protected Instance Constructors + + #region Public Instance Properties + + /// + /// Gets or sets the value of the property with the specified key. + /// + /// + /// The value of the property with the specified key. + /// + /// The key of the property to get or set. + /// + /// + /// The property value will only be serialized if it is serializable. + /// If it cannot be serialized it will be silently ignored if + /// a serialization operation is performed. + /// + /// + public override object this[string key] + { + get { return InnerHashtable[key]; } + set { InnerHashtable[key] = value; } + } + + #endregion Public Instance Properties + + #region Public Instance Methods + + /// + /// Remove the entry with the specified key from this dictionary + /// + /// the key for the entry to remove + /// + /// + /// Remove the entry with the specified key from this dictionary + /// + /// + public void Remove(string key) + { + InnerHashtable.Remove(key); + } + + #endregion Public Instance Methods + + #region Implementation of IDictionary + + /// + /// See + /// + /// an enumerator + /// + /// + /// Returns a over the contest of this collection. + /// + /// + IDictionaryEnumerator IDictionary.GetEnumerator() + { + return InnerHashtable.GetEnumerator(); + } + + /// + /// See + /// + /// the key to remove + /// + /// + /// Remove the entry with the specified key from this dictionary + /// + /// + void IDictionary.Remove(object key) + { + InnerHashtable.Remove(key); + } + + /// + /// See + /// + /// the key to lookup in the collection + /// true if the collection contains the specified key + /// + /// + /// Test if this collection contains a specified key. + /// + /// + bool IDictionary.Contains(object key) + { + return InnerHashtable.Contains(key); + } + + /// + /// Remove all properties from the properties collection + /// + /// + /// + /// Remove all properties from the properties collection + /// + /// + public override void Clear() + { + InnerHashtable.Clear(); + } + + /// + /// See + /// + /// the key + /// the value to store for the key + /// + /// + /// Store a value for the specified . + /// + /// + /// Thrown if the is not a string + void IDictionary.Add(object key, object value) + { + if (!(key is string)) + { + throw new ArgumentException("key must be a string", "key"); + } + InnerHashtable.Add(key, value); + } + + /// + /// See + /// + /// + /// false + /// + /// + /// + /// This collection is modifiable. This property always + /// returns false. + /// + /// + bool IDictionary.IsReadOnly + { + get { return false; } + } + + /// + /// See + /// + /// + /// The value for the key specified. + /// + /// + /// + /// Get or set a value for the specified . + /// + /// + /// Thrown if the is not a string + object IDictionary.this[object key] + { + get + { + if (!(key is string)) + { + throw new ArgumentException("key must be a string", "key"); + } + return InnerHashtable[key]; + } + set + { + if (!(key is string)) + { + throw new ArgumentException("key must be a string", "key"); + } + InnerHashtable[key] = value; + } + } + + /// + /// See + /// + ICollection IDictionary.Values + { + get { return InnerHashtable.Values; } + } + + /// + /// See + /// + ICollection IDictionary.Keys + { + get { return InnerHashtable.Keys; } + } + + /// + /// See + /// + bool IDictionary.IsFixedSize + { + get { return false; } + } + + #endregion + + #region Implementation of ICollection + + /// + /// See + /// + /// + /// + void ICollection.CopyTo(Array array, int index) + { + InnerHashtable.CopyTo(array, index); + } + + /// + /// See + /// + bool ICollection.IsSynchronized + { + get { return InnerHashtable.IsSynchronized; } + } + + /// + /// See + /// + object ICollection.SyncRoot + { + get { return InnerHashtable.SyncRoot; } + } + + #endregion + + #region Implementation of IEnumerable + + /// + /// See + /// + IEnumerator IEnumerable.GetEnumerator() + { + return ((IEnumerable)InnerHashtable).GetEnumerator(); + } + + #endregion + } } diff --git a/src/log4net/Util/ProtectCloseTextWriter.cs b/src/log4net/Util/ProtectCloseTextWriter.cs index a90f283f..d0c2446f 100644 --- a/src/log4net/Util/ProtectCloseTextWriter.cs +++ b/src/log4net/Util/ProtectCloseTextWriter.cs @@ -25,69 +25,69 @@ namespace log4net.Util { - /// - /// A that ignores the message - /// - /// - /// - /// This writer is used in special cases where it is necessary - /// to protect a writer from being closed by a client. - /// - /// - /// Nicko Cadell - public class ProtectCloseTextWriter : TextWriterAdapter - { - #region Public Instance Constructors + /// + /// A that ignores the message + /// + /// + /// + /// This writer is used in special cases where it is necessary + /// to protect a writer from being closed by a client. + /// + /// + /// Nicko Cadell + public class ProtectCloseTextWriter : TextWriterAdapter + { + #region Public Instance Constructors - /// - /// Constructor - /// - /// the writer to actually write to - /// - /// - /// Create a new ProtectCloseTextWriter using a writer - /// - /// - public ProtectCloseTextWriter(TextWriter writer) : base(writer) - { - } + /// + /// Constructor + /// + /// the writer to actually write to + /// + /// + /// Create a new ProtectCloseTextWriter using a writer + /// + /// + public ProtectCloseTextWriter(TextWriter writer) : base(writer) + { + } - #endregion Public Instance Constructors + #endregion Public Instance Constructors - #region Public Properties + #region Public Properties - /// - /// Attach this instance to a different underlying - /// - /// the writer to attach to - /// - /// - /// Attach this instance to a different underlying - /// - /// - public void Attach(TextWriter writer) - { - this.Writer = writer; - } + /// + /// Attach this instance to a different underlying + /// + /// the writer to attach to + /// + /// + /// Attach this instance to a different underlying + /// + /// + public void Attach(TextWriter writer) + { + this.Writer = writer; + } - #endregion + #endregion - #region Override Implementation of TextWriter + #region Override Implementation of TextWriter - /// - /// Does not close the underlying output writer. - /// - /// - /// - /// Does not close the underlying output writer. - /// This method does nothing. - /// - /// - public override void Close() - { - // do nothing - } + /// + /// Does not close the underlying output writer. + /// + /// + /// + /// Does not close the underlying output writer. + /// This method does nothing. + /// + /// + public override void Close() + { + // do nothing + } - #endregion Public Instance Methods - } + #endregion Public Instance Methods + } } diff --git a/src/log4net/Util/QuietTextWriter.cs b/src/log4net/Util/QuietTextWriter.cs index 6f3c757b..f74c9c0b 100644 --- a/src/log4net/Util/QuietTextWriter.cs +++ b/src/log4net/Util/QuietTextWriter.cs @@ -24,182 +24,182 @@ namespace log4net.Util { - /// - /// that does not leak exceptions - /// - /// - /// - /// does not throw exceptions when things go wrong. - /// Instead, it delegates error handling to its . - /// - /// - /// Nicko Cadell - /// Gert Driesen - public class QuietTextWriter : TextWriterAdapter - { - #region Public Instance Constructors - - /// - /// Constructor - /// - /// the writer to actually write to - /// the error handler to report error to - /// - /// - /// Create a new QuietTextWriter using a writer and error handler - /// - /// - public QuietTextWriter(TextWriter writer, IErrorHandler errorHandler) : base(writer) - { - if (errorHandler == null) - { - throw new ArgumentNullException("errorHandler"); - } - ErrorHandler = errorHandler; - } - - #endregion Public Instance Constructors - - #region Public Instance Properties - - /// - /// Gets or sets the error handler that all errors are passed to. - /// - /// - /// The error handler that all errors are passed to. - /// - /// - /// - /// Gets or sets the error handler that all errors are passed to. - /// - /// - public IErrorHandler ErrorHandler - { - get { return m_errorHandler; } - set - { - if (value == null) - { - // This is a programming error on the part of the enclosing appender. - throw new ArgumentNullException("value"); - } - m_errorHandler = value; - } - } - - /// - /// Gets a value indicating whether this writer is closed. - /// - /// - /// true if this writer is closed, otherwise false. - /// - /// - /// - /// Gets a value indicating whether this writer is closed. - /// - /// - public bool Closed - { - get { return m_closed; } - } - - #endregion Public Instance Properties - - #region Override Implementation of TextWriter - - /// - /// Writes a character to the underlying writer - /// - /// the char to write - /// - /// - /// Writes a character to the underlying writer - /// - /// - public override void Write(char value) - { - try - { - base.Write(value); - } - catch(Exception e) - { - m_errorHandler.Error("Failed to write [" + value + "].", e, ErrorCode.WriteFailure); - } - } + /// + /// that does not leak exceptions + /// + /// + /// + /// does not throw exceptions when things go wrong. + /// Instead, it delegates error handling to its . + /// + /// + /// Nicko Cadell + /// Gert Driesen + public class QuietTextWriter : TextWriterAdapter + { + #region Public Instance Constructors + + /// + /// Constructor + /// + /// the writer to actually write to + /// the error handler to report error to + /// + /// + /// Create a new QuietTextWriter using a writer and error handler + /// + /// + public QuietTextWriter(TextWriter writer, IErrorHandler errorHandler) : base(writer) + { + if (errorHandler == null) + { + throw new ArgumentNullException("errorHandler"); + } + ErrorHandler = errorHandler; + } + + #endregion Public Instance Constructors + + #region Public Instance Properties + + /// + /// Gets or sets the error handler that all errors are passed to. + /// + /// + /// The error handler that all errors are passed to. + /// + /// + /// + /// Gets or sets the error handler that all errors are passed to. + /// + /// + public IErrorHandler ErrorHandler + { + get { return m_errorHandler; } + set + { + if (value == null) + { + // This is a programming error on the part of the enclosing appender. + throw new ArgumentNullException("value"); + } + m_errorHandler = value; + } + } + + /// + /// Gets a value indicating whether this writer is closed. + /// + /// + /// true if this writer is closed, otherwise false. + /// + /// + /// + /// Gets a value indicating whether this writer is closed. + /// + /// + public bool Closed + { + get { return m_closed; } + } + + #endregion Public Instance Properties + + #region Override Implementation of TextWriter + + /// + /// Writes a character to the underlying writer + /// + /// the char to write + /// + /// + /// Writes a character to the underlying writer + /// + /// + public override void Write(char value) + { + try + { + base.Write(value); + } + catch(Exception e) + { + m_errorHandler.Error("Failed to write [" + value + "].", e, ErrorCode.WriteFailure); + } + } - /// - /// Writes a buffer to the underlying writer - /// - /// the buffer to write - /// the start index to write from - /// the number of characters to write - /// - /// - /// Writes a buffer to the underlying writer - /// - /// - public override void Write(char[] buffer, int index, int count) - { - try - { - base.Write(buffer, index, count); - } - catch(Exception e) - { - m_errorHandler.Error("Failed to write buffer.", e, ErrorCode.WriteFailure); - } - } + /// + /// Writes a buffer to the underlying writer + /// + /// the buffer to write + /// the start index to write from + /// the number of characters to write + /// + /// + /// Writes a buffer to the underlying writer + /// + /// + public override void Write(char[] buffer, int index, int count) + { + try + { + base.Write(buffer, index, count); + } + catch(Exception e) + { + m_errorHandler.Error("Failed to write buffer.", e, ErrorCode.WriteFailure); + } + } - /// - /// Writes a string to the output. - /// - /// The string data to write to the output. - /// - /// - /// Writes a string to the output. - /// - /// - public override void Write(string value) - { - try - { - base.Write(value); - } - catch(Exception e) - { - m_errorHandler.Error("Failed to write [" + value + "].", e, ErrorCode.WriteFailure); - } - } - - /// - /// Closes the underlying output writer. - /// - /// - /// - /// Closes the underlying output writer. - /// - /// - public override void Close() - { - m_closed = true; - base.Close(); - } - - #endregion Public Instance Methods - - #region Private Instance Fields - - /// - /// The error handler instance to pass all errors to - /// - private IErrorHandler m_errorHandler; - - /// - /// Flag to indicate if this writer is closed - /// - private bool m_closed = false; - - #endregion Private Instance Fields - } + /// + /// Writes a string to the output. + /// + /// The string data to write to the output. + /// + /// + /// Writes a string to the output. + /// + /// + public override void Write(string value) + { + try + { + base.Write(value); + } + catch(Exception e) + { + m_errorHandler.Error("Failed to write [" + value + "].", e, ErrorCode.WriteFailure); + } + } + + /// + /// Closes the underlying output writer. + /// + /// + /// + /// Closes the underlying output writer. + /// + /// + public override void Close() + { + m_closed = true; + base.Close(); + } + + #endregion Public Instance Methods + + #region Private Instance Fields + + /// + /// The error handler instance to pass all errors to + /// + private IErrorHandler m_errorHandler; + + /// + /// Flag to indicate if this writer is closed + /// + private bool m_closed = false; + + #endregion Private Instance Fields + } } diff --git a/src/log4net/Util/ReadOnlyPropertiesDictionary.cs b/src/log4net/Util/ReadOnlyPropertiesDictionary.cs index be37baf0..632ce8ca 100644 --- a/src/log4net/Util/ReadOnlyPropertiesDictionary.cs +++ b/src/log4net/Util/ReadOnlyPropertiesDictionary.cs @@ -27,200 +27,200 @@ namespace log4net.Util { - /// - /// String keyed object map that is read only. - /// - /// - /// - /// This collection is readonly and cannot be modified. - /// - /// - /// While this collection is serializable only member - /// objects that are serializable will - /// be serialized along with this collection. - /// - /// - /// Nicko Cadell - /// Gert Driesen + /// + /// String keyed object map that is read only. + /// + /// + /// + /// This collection is readonly and cannot be modified. + /// + /// + /// While this collection is serializable only member + /// objects that are serializable will + /// be serialized along with this collection. + /// + /// + /// Nicko Cadell + /// Gert Driesen #if NETCF - public class ReadOnlyPropertiesDictionary : IDictionary + public class ReadOnlyPropertiesDictionary : IDictionary #else - [Serializable] public class ReadOnlyPropertiesDictionary : ISerializable, IDictionary + [Serializable] public class ReadOnlyPropertiesDictionary : ISerializable, IDictionary #endif - { - #region Private Instance Fields - - /// - /// The Hashtable used to store the properties data - /// - private readonly Hashtable m_hashtable = new Hashtable(); - - #endregion Private Instance Fields - - #region Public Instance Constructors - - /// - /// Constructor - /// - /// - /// - /// Initializes a new instance of the class. - /// - /// - public ReadOnlyPropertiesDictionary() - { - } - - /// - /// Copy Constructor - /// - /// properties to copy - /// - /// - /// Initializes a new instance of the class. - /// - /// - public ReadOnlyPropertiesDictionary(ReadOnlyPropertiesDictionary propertiesDictionary) - { - foreach(DictionaryEntry entry in propertiesDictionary) - { - InnerHashtable.Add(entry.Key, entry.Value); - } - } - - #endregion Public Instance Constructors - - #region Private Instance Constructors + { + #region Private Instance Fields + + /// + /// The Hashtable used to store the properties data + /// + private readonly Hashtable m_hashtable = new Hashtable(); + + #endregion Private Instance Fields + + #region Public Instance Constructors + + /// + /// Constructor + /// + /// + /// + /// Initializes a new instance of the class. + /// + /// + public ReadOnlyPropertiesDictionary() + { + } + + /// + /// Copy Constructor + /// + /// properties to copy + /// + /// + /// Initializes a new instance of the class. + /// + /// + public ReadOnlyPropertiesDictionary(ReadOnlyPropertiesDictionary propertiesDictionary) + { + foreach(DictionaryEntry entry in propertiesDictionary) + { + InnerHashtable.Add(entry.Key, entry.Value); + } + } + + #endregion Public Instance Constructors + + #region Private Instance Constructors #if !NETCF - /// - /// Deserialization constructor - /// - /// The that holds the serialized object data. - /// The that contains contextual information about the source or destination. - /// - /// - /// Initializes a new instance of the class - /// with serialized data. - /// - /// - protected ReadOnlyPropertiesDictionary(SerializationInfo info, StreamingContext context) - { - foreach(var entry in info) - { - // The keys are stored as Xml encoded names - InnerHashtable[XmlConvert.DecodeName(entry.Name)] = entry.Value; - } - } + /// + /// Deserialization constructor + /// + /// The that holds the serialized object data. + /// The that contains contextual information about the source or destination. + /// + /// + /// Initializes a new instance of the class + /// with serialized data. + /// + /// + protected ReadOnlyPropertiesDictionary(SerializationInfo info, StreamingContext context) + { + foreach(var entry in info) + { + // The keys are stored as Xml encoded names + InnerHashtable[XmlConvert.DecodeName(entry.Name)] = entry.Value; + } + } #endif - #endregion Protected Instance Constructors - - #region Public Instance Properties - - /// - /// Gets the key names. - /// - /// An array of all the keys. - /// - /// - /// Gets the key names. - /// - /// - public string[] GetKeys() - { - var keys = new String[InnerHashtable.Count]; - InnerHashtable.Keys.CopyTo(keys, 0); - return keys; - } - - /// - /// Gets or sets the value of the property with the specified key. - /// - /// - /// The value of the property with the specified key. - /// - /// The key of the property to get or set. - /// - /// - /// The property value will only be serialized if it is serializable. - /// If it cannot be serialized it will be silently ignored if - /// a serialization operation is performed. - /// - /// - public virtual object this[string key] - { - get { return InnerHashtable[key]; } - set { throw new NotSupportedException("This is a Read Only Dictionary and can not be modified"); } - } - - #endregion Public Instance Properties - - #region Public Instance Methods - - /// - /// Test if the dictionary contains a specified key - /// - /// the key to look for - /// true if the dictionary contains the specified key - /// - /// - /// Test if the dictionary contains a specified key - /// - /// - public bool Contains(string key) - { - return InnerHashtable.Contains(key); - } - - #endregion - - /// - /// The hashtable used to store the properties - /// - /// - /// The internal collection used to store the properties - /// - /// - /// - /// The hashtable used to store the properties - /// - /// - protected Hashtable InnerHashtable - { - get { return m_hashtable; } - } - - #region Implementation of ISerializable + #endregion Protected Instance Constructors + + #region Public Instance Properties + + /// + /// Gets the key names. + /// + /// An array of all the keys. + /// + /// + /// Gets the key names. + /// + /// + public string[] GetKeys() + { + var keys = new String[InnerHashtable.Count]; + InnerHashtable.Keys.CopyTo(keys, 0); + return keys; + } + + /// + /// Gets or sets the value of the property with the specified key. + /// + /// + /// The value of the property with the specified key. + /// + /// The key of the property to get or set. + /// + /// + /// The property value will only be serialized if it is serializable. + /// If it cannot be serialized it will be silently ignored if + /// a serialization operation is performed. + /// + /// + public virtual object this[string key] + { + get { return InnerHashtable[key]; } + set { throw new NotSupportedException("This is a Read Only Dictionary and can not be modified"); } + } + + #endregion Public Instance Properties + + #region Public Instance Methods + + /// + /// Test if the dictionary contains a specified key + /// + /// the key to look for + /// true if the dictionary contains the specified key + /// + /// + /// Test if the dictionary contains a specified key + /// + /// + public bool Contains(string key) + { + return InnerHashtable.Contains(key); + } + + #endregion + + /// + /// The hashtable used to store the properties + /// + /// + /// The internal collection used to store the properties + /// + /// + /// + /// The hashtable used to store the properties + /// + /// + protected Hashtable InnerHashtable + { + get { return m_hashtable; } + } + + #region Implementation of ISerializable #if !NETCF - /// - /// Serializes this object into the provided. - /// - /// The to populate with data. - /// The destination for this serialization. - /// - /// - /// Serializes this object into the provided. - /// - /// + /// + /// Serializes this object into the provided. + /// + /// The to populate with data. + /// The destination for this serialization. + /// + /// + /// Serializes this object into the provided. + /// + /// #if NET_4_0 || MONO_4_0 || NETSTANDARD [System.Security.SecurityCritical] #endif #if !NETCF && !NETSTANDARD1_3 - [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, SerializationFormatter = true)] + [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, SerializationFormatter = true)] #endif public virtual void GetObjectData(SerializationInfo info, StreamingContext context) - { - foreach(DictionaryEntry entry in InnerHashtable.Clone() as IDictionary) - { - var entryKey = entry.Key as string; - if (entryKey is null) - { - continue; - } + { + foreach(DictionaryEntry entry in InnerHashtable.Clone() as IDictionary) + { + var entryKey = entry.Key as string; + if (entryKey is null) + { + continue; + } - var entryValue = entry.Value; + var entryValue = entry.Value; // If value is serializable then we add it to the list #if NETSTANDARD1_3 @@ -228,172 +228,172 @@ public virtual void GetObjectData(SerializationInfo info, StreamingContext conte #else var isSerializable = entryValue?.GetType().IsSerializable ?? false; #endif - if (!isSerializable) - { - continue; - } - - // Store the keys as an Xml encoded local name as it may contain colons (':') - // which are NOT escaped by the Xml Serialization framework. - // This must be a bug in the serialization framework as we cannot be expected - // to know the implementation details of all the possible transport layers. - var localKeyName = XmlConvert.EncodeLocalName(entryKey); - if (localKeyName is not null) - { - info.AddValue(localKeyName, entryValue); - } - } - } + if (!isSerializable) + { + continue; + } + + // Store the keys as an Xml encoded local name as it may contain colons (':') + // which are NOT escaped by the Xml Serialization framework. + // This must be a bug in the serialization framework as we cannot be expected + // to know the implementation details of all the possible transport layers. + var localKeyName = XmlConvert.EncodeLocalName(entryKey); + if (localKeyName is not null) + { + info.AddValue(localKeyName, entryValue); + } + } + } #endif - #endregion Implementation of ISerializable - - #region Implementation of IDictionary - - /// - /// See - /// - IDictionaryEnumerator IDictionary.GetEnumerator() - { - return InnerHashtable.GetEnumerator(); - } - - /// - /// See - /// - /// - void IDictionary.Remove(object key) - { - throw new NotSupportedException("This is a Read Only Dictionary and can not be modified"); - } - - /// - /// See - /// - /// - /// - bool IDictionary.Contains(object key) - { - return InnerHashtable.Contains(key); - } - - /// - /// Remove all properties from the properties collection - /// - public virtual void Clear() - { - throw new NotSupportedException("This is a Read Only Dictionary and can not be modified"); - } - - /// - /// See - /// - /// - /// - void IDictionary.Add(object key, object value) - { - throw new NotSupportedException("This is a Read Only Dictionary and can not be modified"); - } - - /// - /// See - /// - bool IDictionary.IsReadOnly - { - get { return true; } - } - - /// - /// See - /// - object IDictionary.this[object key] - { - get - { - if (!(key is string)) throw new ArgumentException("key must be a string"); - return InnerHashtable[key]; - } - set - { - throw new NotSupportedException("This is a Read Only Dictionary and can not be modified"); - } - } - - /// - /// See - /// - ICollection IDictionary.Values - { - get { return InnerHashtable.Values; } - } - - /// - /// See - /// - ICollection IDictionary.Keys - { - get { return InnerHashtable.Keys; } - } - - /// - /// See - /// - bool IDictionary.IsFixedSize - { - get { return InnerHashtable.IsFixedSize; } - } - - #endregion - - #region Implementation of ICollection - - /// - /// See - /// - /// - /// - void ICollection.CopyTo(Array array, int index) - { - InnerHashtable.CopyTo(array, index); - } - - /// - /// See - /// - bool ICollection.IsSynchronized - { - get { return InnerHashtable.IsSynchronized; } - } - - /// - /// The number of properties in this collection - /// - public int Count - { - get { return InnerHashtable.Count; } - } - - /// - /// See - /// - object ICollection.SyncRoot - { - get { return InnerHashtable.SyncRoot; } - } - - #endregion - - #region Implementation of IEnumerable - - /// - /// See - /// - IEnumerator IEnumerable.GetEnumerator() - { - return ((IEnumerable)InnerHashtable).GetEnumerator(); - } - - #endregion - } + #endregion Implementation of ISerializable + + #region Implementation of IDictionary + + /// + /// See + /// + IDictionaryEnumerator IDictionary.GetEnumerator() + { + return InnerHashtable.GetEnumerator(); + } + + /// + /// See + /// + /// + void IDictionary.Remove(object key) + { + throw new NotSupportedException("This is a Read Only Dictionary and can not be modified"); + } + + /// + /// See + /// + /// + /// + bool IDictionary.Contains(object key) + { + return InnerHashtable.Contains(key); + } + + /// + /// Remove all properties from the properties collection + /// + public virtual void Clear() + { + throw new NotSupportedException("This is a Read Only Dictionary and can not be modified"); + } + + /// + /// See + /// + /// + /// + void IDictionary.Add(object key, object value) + { + throw new NotSupportedException("This is a Read Only Dictionary and can not be modified"); + } + + /// + /// See + /// + bool IDictionary.IsReadOnly + { + get { return true; } + } + + /// + /// See + /// + object IDictionary.this[object key] + { + get + { + if (!(key is string)) throw new ArgumentException("key must be a string"); + return InnerHashtable[key]; + } + set + { + throw new NotSupportedException("This is a Read Only Dictionary and can not be modified"); + } + } + + /// + /// See + /// + ICollection IDictionary.Values + { + get { return InnerHashtable.Values; } + } + + /// + /// See + /// + ICollection IDictionary.Keys + { + get { return InnerHashtable.Keys; } + } + + /// + /// See + /// + bool IDictionary.IsFixedSize + { + get { return InnerHashtable.IsFixedSize; } + } + + #endregion + + #region Implementation of ICollection + + /// + /// See + /// + /// + /// + void ICollection.CopyTo(Array array, int index) + { + InnerHashtable.CopyTo(array, index); + } + + /// + /// See + /// + bool ICollection.IsSynchronized + { + get { return InnerHashtable.IsSynchronized; } + } + + /// + /// The number of properties in this collection + /// + public int Count + { + get { return InnerHashtable.Count; } + } + + /// + /// See + /// + object ICollection.SyncRoot + { + get { return InnerHashtable.SyncRoot; } + } + + #endregion + + #region Implementation of IEnumerable + + /// + /// See + /// + IEnumerator IEnumerable.GetEnumerator() + { + return ((IEnumerable)InnerHashtable).GetEnumerator(); + } + + #endregion + } } diff --git a/src/log4net/Util/ReaderWriterLock.cs b/src/log4net/Util/ReaderWriterLock.cs index 3c70b9d0..7654d395 100644 --- a/src/log4net/Util/ReaderWriterLock.cs +++ b/src/log4net/Util/ReaderWriterLock.cs @@ -28,164 +28,164 @@ namespace log4net.Util { - /// - /// Defines a lock that supports single writers and multiple readers - /// - /// - /// - /// ReaderWriterLock is used to synchronize access to a resource. - /// At any given time, it allows either concurrent read access for - /// multiple threads, or write access for a single thread. In a - /// situation where a resource is changed infrequently, a - /// ReaderWriterLock provides better throughput than a simple - /// one-at-a-time lock, such as . - /// - /// - /// If a platform does not support a System.Threading.ReaderWriterLock - /// implementation then all readers and writers are serialized. Therefore - /// the caller must not rely on multiple simultaneous readers. - /// - /// - /// Nicko Cadell - public sealed class ReaderWriterLock - { - #region Instance Constructors - - /// - /// Constructor - /// - /// - /// - /// Initializes a new instance of the class. - /// - /// - public ReaderWriterLock() - { + /// + /// Defines a lock that supports single writers and multiple readers + /// + /// + /// + /// ReaderWriterLock is used to synchronize access to a resource. + /// At any given time, it allows either concurrent read access for + /// multiple threads, or write access for a single thread. In a + /// situation where a resource is changed infrequently, a + /// ReaderWriterLock provides better throughput than a simple + /// one-at-a-time lock, such as . + /// + /// + /// If a platform does not support a System.Threading.ReaderWriterLock + /// implementation then all readers and writers are serialized. Therefore + /// the caller must not rely on multiple simultaneous readers. + /// + /// + /// Nicko Cadell + public sealed class ReaderWriterLock + { + #region Instance Constructors + + /// + /// Constructor + /// + /// + /// + /// Initializes a new instance of the class. + /// + /// + public ReaderWriterLock() + { #if HAS_READERWRITERLOCK #if HAS_READERWRITERLOCKSLIM - m_lock = new System.Threading.ReaderWriterLockSlim(System.Threading.LockRecursionPolicy.SupportsRecursion); + m_lock = new System.Threading.ReaderWriterLockSlim(System.Threading.LockRecursionPolicy.SupportsRecursion); #else - m_lock = new System.Threading.ReaderWriterLock(); + m_lock = new System.Threading.ReaderWriterLock(); #endif #endif - } + } - #endregion Private Instance Constructors + #endregion Private Instance Constructors - #region Public Methods - - /// - /// Acquires a reader lock - /// - /// - /// - /// blocks if a different thread has the writer - /// lock, or if at least one thread is waiting for the writer lock. - /// - /// - public void AcquireReaderLock() - { + #region Public Methods + + /// + /// Acquires a reader lock + /// + /// + /// + /// blocks if a different thread has the writer + /// lock, or if at least one thread is waiting for the writer lock. + /// + /// + public void AcquireReaderLock() + { #if HAS_READERWRITERLOCK #if HAS_READERWRITERLOCKSLIM // prevent ThreadAbort while updating state, see https://issues.apache.org/jira/browse/LOG4NET-443 try { } finally { - m_lock.EnterReadLock(); + m_lock.EnterReadLock(); } #else - m_lock.AcquireReaderLock(-1); + m_lock.AcquireReaderLock(-1); #endif #else - System.Threading.Monitor.Enter(this); + System.Threading.Monitor.Enter(this); #endif - } - - /// - /// Decrements the lock count - /// - /// - /// - /// decrements the lock count. When the count - /// reaches zero, the lock is released. - /// - /// - public void ReleaseReaderLock() - { + } + + /// + /// Decrements the lock count + /// + /// + /// + /// decrements the lock count. When the count + /// reaches zero, the lock is released. + /// + /// + public void ReleaseReaderLock() + { #if HAS_READERWRITERLOCK #if HAS_READERWRITERLOCKSLIM - m_lock.ExitReadLock(); + m_lock.ExitReadLock(); #else - m_lock.ReleaseReaderLock(); + m_lock.ReleaseReaderLock(); #endif #else - System.Threading.Monitor.Exit(this); + System.Threading.Monitor.Exit(this); #endif - } - - /// - /// Acquires the writer lock - /// - /// - /// - /// This method blocks if another thread has a reader lock or writer lock. - /// - /// - public void AcquireWriterLock() - { + } + + /// + /// Acquires the writer lock + /// + /// + /// + /// This method blocks if another thread has a reader lock or writer lock. + /// + /// + public void AcquireWriterLock() + { #if HAS_READERWRITERLOCK #if HAS_READERWRITERLOCKSLIM // prevent ThreadAbort while updating state, see https://issues.apache.org/jira/browse/LOG4NET-443 try { } finally { - m_lock.EnterWriteLock(); + m_lock.EnterWriteLock(); } #else - m_lock.AcquireWriterLock(-1); + m_lock.AcquireWriterLock(-1); #endif #else - System.Threading.Monitor.Enter(this); + System.Threading.Monitor.Enter(this); #endif - } - - /// - /// Decrements the lock count on the writer lock - /// - /// - /// - /// ReleaseWriterLock decrements the writer lock count. - /// When the count reaches zero, the writer lock is released. - /// - /// - public void ReleaseWriterLock() - { + } + + /// + /// Decrements the lock count on the writer lock + /// + /// + /// + /// ReleaseWriterLock decrements the writer lock count. + /// When the count reaches zero, the writer lock is released. + /// + /// + public void ReleaseWriterLock() + { #if HAS_READERWRITERLOCK #if HAS_READERWRITERLOCKSLIM - m_lock.ExitWriteLock(); + m_lock.ExitWriteLock(); #else - m_lock.ReleaseWriterLock(); + m_lock.ReleaseWriterLock(); #endif #else - System.Threading.Monitor.Exit(this); + System.Threading.Monitor.Exit(this); #endif - } + } - #endregion Public Methods + #endregion Public Methods - #region Private Members + #region Private Members #if HAS_READERWRITERLOCK #if HAS_READERWRITERLOCKSLIM - private System.Threading.ReaderWriterLockSlim m_lock; + private System.Threading.ReaderWriterLockSlim m_lock; #else - private System.Threading.ReaderWriterLock m_lock; + private System.Threading.ReaderWriterLock m_lock; #endif #endif - #endregion - } + #endregion + } } \ No newline at end of file diff --git a/src/log4net/Util/ReusableStringWriter.cs b/src/log4net/Util/ReusableStringWriter.cs index 8c1aad13..3a7edee9 100644 --- a/src/log4net/Util/ReusableStringWriter.cs +++ b/src/log4net/Util/ReusableStringWriter.cs @@ -23,72 +23,72 @@ namespace log4net.Util { - /// - /// A that can be and reused - /// - /// - /// - /// A that can be and reused. - /// This uses a single buffer for string operations. - /// - /// - /// Nicko Cadell - public class ReusableStringWriter : StringWriter - { - #region Constructor + /// + /// A that can be and reused + /// + /// + /// + /// A that can be and reused. + /// This uses a single buffer for string operations. + /// + /// + /// Nicko Cadell + public class ReusableStringWriter : StringWriter + { + #region Constructor - /// - /// Create an instance of - /// - /// the format provider to use - /// - /// - /// Create an instance of - /// - /// - public ReusableStringWriter(IFormatProvider formatProvider) : base(formatProvider) - { - } + /// + /// Create an instance of + /// + /// the format provider to use + /// + /// + /// Create an instance of + /// + /// + public ReusableStringWriter(IFormatProvider formatProvider) : base(formatProvider) + { + } - #endregion + #endregion - /// - /// Override Dispose to prevent closing of writer - /// - /// flag - /// - /// - /// Override Dispose to prevent closing of writer - /// - /// - protected override void Dispose(bool disposing) - { - // Do not close the writer - } + /// + /// Override Dispose to prevent closing of writer + /// + /// flag + /// + /// + /// Override Dispose to prevent closing of writer + /// + /// + protected override void Dispose(bool disposing) + { + // Do not close the writer + } - /// - /// Reset this string writer so that it can be reused. - /// - /// the maximum buffer capacity before it is trimmed - /// the default size to make the buffer - /// - /// - /// Reset this string writer so that it can be reused. - /// The internal buffers are cleared and reset. - /// - /// - public void Reset(int maxCapacity, int defaultSize) - { - // Reset working string buffer - StringBuilder sb = this.GetStringBuilder(); + /// + /// Reset this string writer so that it can be reused. + /// + /// the maximum buffer capacity before it is trimmed + /// the default size to make the buffer + /// + /// + /// Reset this string writer so that it can be reused. + /// The internal buffers are cleared and reset. + /// + /// + public void Reset(int maxCapacity, int defaultSize) + { + // Reset working string buffer + StringBuilder sb = this.GetStringBuilder(); - sb.Length = 0; - - // Check if over max size - if (sb.Capacity > maxCapacity) - { - sb.Capacity = defaultSize; - } - } - } + sb.Length = 0; + + // Check if over max size + if (sb.Capacity > maxCapacity) + { + sb.Capacity = defaultSize; + } + } + } } diff --git a/src/log4net/Util/SystemInfo.cs b/src/log4net/Util/SystemInfo.cs index 821a2307..5cf7980a 100644 --- a/src/log4net/Util/SystemInfo.cs +++ b/src/log4net/Util/SystemInfo.cs @@ -29,1307 +29,1307 @@ namespace log4net.Util { - /// - /// Utility class for system specific information. - /// - /// - /// - /// Utility class of static methods for system specific information. - /// - /// - /// Nicko Cadell - /// Gert Driesen - /// Alexey Solofnenko - public sealed class SystemInfo - { - #region Private Constants - - private const string DEFAULT_NULL_TEXT = "(null)"; - private const string DEFAULT_NOT_AVAILABLE_TEXT = "NOT AVAILABLE"; - - #endregion - - #region Private Instance Constructors - - /// - /// Private constructor to prevent instances. - /// - /// - /// - /// Only static methods are exposed from this type. - /// - /// - private SystemInfo() - { - } - - #endregion Private Instance Constructors - - #region Public Static Constructor - - /// - /// Initialize default values for private static fields. - /// - /// - /// - /// Only static methods are exposed from this type. - /// - /// - static SystemInfo() - { - string nullText = DEFAULT_NULL_TEXT; - string notAvailableText = DEFAULT_NOT_AVAILABLE_TEXT; + /// + /// Utility class for system specific information. + /// + /// + /// + /// Utility class of static methods for system specific information. + /// + /// + /// Nicko Cadell + /// Gert Driesen + /// Alexey Solofnenko + public sealed class SystemInfo + { + #region Private Constants + + private const string DEFAULT_NULL_TEXT = "(null)"; + private const string DEFAULT_NOT_AVAILABLE_TEXT = "NOT AVAILABLE"; + + #endregion + + #region Private Instance Constructors + + /// + /// Private constructor to prevent instances. + /// + /// + /// + /// Only static methods are exposed from this type. + /// + /// + private SystemInfo() + { + } + + #endregion Private Instance Constructors + + #region Public Static Constructor + + /// + /// Initialize default values for private static fields. + /// + /// + /// + /// Only static methods are exposed from this type. + /// + /// + static SystemInfo() + { + string nullText = DEFAULT_NULL_TEXT; + string notAvailableText = DEFAULT_NOT_AVAILABLE_TEXT; #if !NETCF - // Look for log4net.NullText in AppSettings - string nullTextAppSettingsKey = SystemInfo.GetAppSetting("log4net.NullText"); - if (nullTextAppSettingsKey != null && nullTextAppSettingsKey.Length > 0) - { - LogLog.Debug(declaringType, "Initializing NullText value to [" + nullTextAppSettingsKey + "]."); - nullText = nullTextAppSettingsKey; - } - - // Look for log4net.NotAvailableText in AppSettings - string notAvailableTextAppSettingsKey = SystemInfo.GetAppSetting("log4net.NotAvailableText"); - if (notAvailableTextAppSettingsKey != null && notAvailableTextAppSettingsKey.Length > 0) - { - LogLog.Debug(declaringType, "Initializing NotAvailableText value to [" + notAvailableTextAppSettingsKey + "]."); - notAvailableText = notAvailableTextAppSettingsKey; - } + // Look for log4net.NullText in AppSettings + string nullTextAppSettingsKey = SystemInfo.GetAppSetting("log4net.NullText"); + if (nullTextAppSettingsKey != null && nullTextAppSettingsKey.Length > 0) + { + LogLog.Debug(declaringType, "Initializing NullText value to [" + nullTextAppSettingsKey + "]."); + nullText = nullTextAppSettingsKey; + } + + // Look for log4net.NotAvailableText in AppSettings + string notAvailableTextAppSettingsKey = SystemInfo.GetAppSetting("log4net.NotAvailableText"); + if (notAvailableTextAppSettingsKey != null && notAvailableTextAppSettingsKey.Length > 0) + { + LogLog.Debug(declaringType, "Initializing NotAvailableText value to [" + notAvailableTextAppSettingsKey + "]."); + notAvailableText = notAvailableTextAppSettingsKey; + } #endif - s_notAvailableText = notAvailableText; - s_nullText = nullText; - } - - #endregion - - #region Public Static Properties - - /// - /// Gets the system dependent line terminator. - /// - /// - /// The system dependent line terminator. - /// - /// - /// - /// Gets the system dependent line terminator. - /// - /// - public static string NewLine - { - get - { + s_notAvailableText = notAvailableText; + s_nullText = nullText; + } + + #endregion + + #region Public Static Properties + + /// + /// Gets the system dependent line terminator. + /// + /// + /// The system dependent line terminator. + /// + /// + /// + /// Gets the system dependent line terminator. + /// + /// + public static string NewLine + { + get + { #if NETCF - return "\r\n"; + return "\r\n"; #else - return System.Environment.NewLine; + return System.Environment.NewLine; #endif - } - } - - /// - /// Gets the base directory for this . - /// - /// The base directory path for the current . - /// - /// - /// Gets the base directory for this . - /// - /// - /// The value returned may be either a local file path or a URI. - /// - /// - public static string ApplicationBaseDirectory - { - get - { + } + } + + /// + /// Gets the base directory for this . + /// + /// The base directory path for the current . + /// + /// + /// Gets the base directory for this . + /// + /// + /// The value returned may be either a local file path or a URI. + /// + /// + public static string ApplicationBaseDirectory + { + get + { #if NETCF -- return System.IO.Path.GetDirectoryName(SystemInfo.EntryAssemblyLocation) + System.IO.Path.DirectorySeparatorChar; +- return System.IO.Path.GetDirectoryName(SystemInfo.EntryAssemblyLocation) + System.IO.Path.DirectorySeparatorChar; #elif NETSTANDARD1_3 - return Directory.GetCurrentDirectory(); + return Directory.GetCurrentDirectory(); #else - return AppDomain.CurrentDomain.BaseDirectory; + return AppDomain.CurrentDomain.BaseDirectory; #endif - } - } - - /// - /// Gets the path to the configuration file for the current . - /// - /// The path to the configuration file for the current . - /// - /// - /// The .NET Compact Framework 1.0 does not have a concept of a configuration - /// file. For this runtime, we use the entry assembly location as the root for - /// the configuration file name. - /// - /// - /// The value returned may be either a local file path or a URI. - /// - /// - public static string ConfigurationFileLocation - { - get - { + } + } + + /// + /// Gets the path to the configuration file for the current . + /// + /// The path to the configuration file for the current . + /// + /// + /// The .NET Compact Framework 1.0 does not have a concept of a configuration + /// file. For this runtime, we use the entry assembly location as the root for + /// the configuration file name. + /// + /// + /// The value returned may be either a local file path or a URI. + /// + /// + public static string ConfigurationFileLocation + { + get + { #if NETCF || NETSTANDARD - return SystemInfo.EntryAssemblyLocation+".config"; + return SystemInfo.EntryAssemblyLocation+".config"; #else - return System.AppDomain.CurrentDomain.SetupInformation.ConfigurationFile; + return System.AppDomain.CurrentDomain.SetupInformation.ConfigurationFile; #endif - } - } - - private static string entryAssemblyLocation; - - /// - /// Gets the path to the file that first executed in the current . - /// - /// The path to the entry assembly. - /// - /// - /// Gets the path to the file that first executed in the current . - /// - /// - public static string EntryAssemblyLocation - { - get - { - if (entryAssemblyLocation != null) - return entryAssemblyLocation; + } + } + + private static string entryAssemblyLocation; + + /// + /// Gets the path to the file that first executed in the current . + /// + /// The path to the entry assembly. + /// + /// + /// Gets the path to the file that first executed in the current . + /// + /// + public static string EntryAssemblyLocation + { + get + { + if (entryAssemblyLocation != null) + return entryAssemblyLocation; #if NETCF - return entryAssemblyLocation = SystemInfo.NativeEntryAssemblyLocation; + return entryAssemblyLocation = SystemInfo.NativeEntryAssemblyLocation; #elif NETSTANDARD1_3 // TODO GetEntryAssembly is available for netstandard1.5 - return entryAssemblyLocation = AppContext.BaseDirectory; + return entryAssemblyLocation = AppContext.BaseDirectory; #else - return entryAssemblyLocation = Assembly.GetEntryAssembly()?.Location - ?? throw new InvalidOperationException($"Unable to determine EntryAssembly location: EntryAssembly is null. Try explicitly setting {nameof(SystemInfo)}.{nameof(EntryAssemblyLocation)}"); + return entryAssemblyLocation = Assembly.GetEntryAssembly()?.Location + ?? throw new InvalidOperationException($"Unable to determine EntryAssembly location: EntryAssembly is null. Try explicitly setting {nameof(SystemInfo)}.{nameof(EntryAssemblyLocation)}"); #endif - } - set => entryAssemblyLocation = value; - } - - /// - /// Gets the ID of the current thread. - /// - /// The ID of the current thread. - /// - /// - /// On the .NET framework, the AppDomain.GetCurrentThreadId method - /// is used to obtain the thread ID for the current thread. This is the - /// operating system ID for the thread. - /// - /// - /// On the .NET Compact Framework 1.0 it is not possible to get the - /// operating system thread ID for the current thread. The native method - /// GetCurrentThreadId is implemented inline in a header file - /// and cannot be called. - /// - /// - /// On the .NET Framework 2.0 the Thread.ManagedThreadId is used as this - /// gives a stable id unrelated to the operating system thread ID which may - /// change if the runtime is using fibers. - /// - /// - public static int CurrentThreadId - { - get - { + } + set => entryAssemblyLocation = value; + } + + /// + /// Gets the ID of the current thread. + /// + /// The ID of the current thread. + /// + /// + /// On the .NET framework, the AppDomain.GetCurrentThreadId method + /// is used to obtain the thread ID for the current thread. This is the + /// operating system ID for the thread. + /// + /// + /// On the .NET Compact Framework 1.0 it is not possible to get the + /// operating system thread ID for the current thread. The native method + /// GetCurrentThreadId is implemented inline in a header file + /// and cannot be called. + /// + /// + /// On the .NET Framework 2.0 the Thread.ManagedThreadId is used as this + /// gives a stable id unrelated to the operating system thread ID which may + /// change if the runtime is using fibers. + /// + /// + public static int CurrentThreadId + { + get + { #if NETCF_1_0 - return System.Threading.Thread.CurrentThread.GetHashCode(); + return System.Threading.Thread.CurrentThread.GetHashCode(); #elif NET_2_0 || NETCF_2_0 || MONO_2_0 || MONO_3_5 || MONO_4_0 || NETSTANDARD - return System.Threading.Thread.CurrentThread.ManagedThreadId; + return System.Threading.Thread.CurrentThread.ManagedThreadId; #else - return AppDomain.GetCurrentThreadId(); + return AppDomain.GetCurrentThreadId(); #endif - } - } - - /// - /// Get the host name or machine name for the current machine - /// - /// - /// The hostname or machine name - /// - /// - /// - /// Get the host name or machine name for the current machine - /// - /// - /// The host name () or - /// the machine name (Environment.MachineName) for - /// the current machine, or if neither of these are available - /// then NOT AVAILABLE is returned. - /// - /// - public static string HostName - { - get - { - if (s_hostName == null) - { - - // Get the DNS host name of the current machine - try - { - // Lookup the host name - s_hostName = System.Net.Dns.GetHostName(); - } - catch (System.Net.Sockets.SocketException) - { - LogLog.Debug(declaringType, "Socket exception occurred while getting the dns hostname. Error Ignored."); - } - catch (System.Security.SecurityException) - { - // We may get a security exception looking up the hostname - // You must have Unrestricted DnsPermission to access resource - LogLog.Debug(declaringType, "Security exception occurred while getting the dns hostname. Error Ignored."); - } - catch (Exception ex) - { - LogLog.Debug(declaringType, "Some other exception occurred while getting the dns hostname. Error Ignored.", ex); - } - - // Get the NETBIOS machine name of the current machine - if (s_hostName == null || s_hostName.Length == 0) - { - try - { + } + } + + /// + /// Get the host name or machine name for the current machine + /// + /// + /// The hostname or machine name + /// + /// + /// + /// Get the host name or machine name for the current machine + /// + /// + /// The host name () or + /// the machine name (Environment.MachineName) for + /// the current machine, or if neither of these are available + /// then NOT AVAILABLE is returned. + /// + /// + public static string HostName + { + get + { + if (s_hostName == null) + { + + // Get the DNS host name of the current machine + try + { + // Lookup the host name + s_hostName = System.Net.Dns.GetHostName(); + } + catch (System.Net.Sockets.SocketException) + { + LogLog.Debug(declaringType, "Socket exception occurred while getting the dns hostname. Error Ignored."); + } + catch (System.Security.SecurityException) + { + // We may get a security exception looking up the hostname + // You must have Unrestricted DnsPermission to access resource + LogLog.Debug(declaringType, "Security exception occurred while getting the dns hostname. Error Ignored."); + } + catch (Exception ex) + { + LogLog.Debug(declaringType, "Some other exception occurred while getting the dns hostname. Error Ignored.", ex); + } + + // Get the NETBIOS machine name of the current machine + if (s_hostName == null || s_hostName.Length == 0) + { + try + { #if NETSTANDARD1_3 - s_hostName = Environment.GetEnvironmentVariable("COMPUTERNAME"); + s_hostName = Environment.GetEnvironmentVariable("COMPUTERNAME"); #elif (!SSCLI && !NETCF) - s_hostName = Environment.MachineName; + s_hostName = Environment.MachineName; #endif - } - catch (InvalidOperationException) - { - } - catch (System.Security.SecurityException) - { - // We may get a security exception looking up the machine name - // You must have Unrestricted EnvironmentPermission to access resource - } - } - - // Couldn't find a value - if (s_hostName == null || s_hostName.Length == 0) - { - s_hostName = s_notAvailableText; - LogLog.Debug(declaringType, "Could not determine the hostname. Error Ignored. Empty host name will be used"); - } - } - return s_hostName; - } - } - - /// - /// Get this application's friendly name - /// - /// - /// The friendly name of this application as a string - /// - /// - /// - /// If available the name of the application is retrieved from - /// the AppDomain using AppDomain.CurrentDomain.FriendlyName. - /// - /// - /// Otherwise the file name of the entry assembly is used. - /// - /// - public static string ApplicationFriendlyName - { - get - { - if (s_appFriendlyName == null) - { - try - { + } + catch (InvalidOperationException) + { + } + catch (System.Security.SecurityException) + { + // We may get a security exception looking up the machine name + // You must have Unrestricted EnvironmentPermission to access resource + } + } + + // Couldn't find a value + if (s_hostName == null || s_hostName.Length == 0) + { + s_hostName = s_notAvailableText; + LogLog.Debug(declaringType, "Could not determine the hostname. Error Ignored. Empty host name will be used"); + } + } + return s_hostName; + } + } + + /// + /// Get this application's friendly name + /// + /// + /// The friendly name of this application as a string + /// + /// + /// + /// If available the name of the application is retrieved from + /// the AppDomain using AppDomain.CurrentDomain.FriendlyName. + /// + /// + /// Otherwise the file name of the entry assembly is used. + /// + /// + public static string ApplicationFriendlyName + { + get + { + if (s_appFriendlyName == null) + { + try + { #if !NETCF && !NETSTANDARD1_3 - s_appFriendlyName = AppDomain.CurrentDomain.FriendlyName; + s_appFriendlyName = AppDomain.CurrentDomain.FriendlyName; #endif - } - catch (System.Security.SecurityException) - { - // This security exception will occur if the caller does not have - // some undefined set of SecurityPermission flags. - LogLog.Debug(declaringType, "Security exception while trying to get current domain friendly name. Error Ignored."); - } - - if (s_appFriendlyName == null || s_appFriendlyName.Length == 0) - { - try - { - string assemblyLocation = SystemInfo.EntryAssemblyLocation; - s_appFriendlyName = System.IO.Path.GetFileName(assemblyLocation); - } - catch (System.Security.SecurityException) - { - // Caller needs path discovery permission - } - } - - if (s_appFriendlyName == null || s_appFriendlyName.Length == 0) - { - s_appFriendlyName = s_notAvailableText; - } - } - return s_appFriendlyName; - } - } - - /// - /// Get the start time for the current process. - /// - /// - /// - /// This is the time at which the log4net library was loaded into the - /// AppDomain. Due to reports of a hang in the call to System.Diagnostics.Process.StartTime - /// this is not the start time for the current process. - /// - /// - /// The log4net library should be loaded by an application early during its - /// startup, therefore this start time should be a good approximation for - /// the actual start time. - /// - /// - /// Note that AppDomains may be loaded and unloaded within the - /// same process without the process terminating, however this start time - /// will be set per AppDomain. - /// - /// - [Obsolete("Use ProcessStartTimeUtc and convert to local time if needed.")] - public static DateTime ProcessStartTime - { - get { return s_processStartTimeUtc.ToLocalTime(); } - } - - /// - /// Get the UTC start time for the current process. - /// - /// - /// - /// This is the UTC time at which the log4net library was loaded into the - /// AppDomain. Due to reports of a hang in the call to System.Diagnostics.Process.StartTime - /// this is not the start time for the current process. - /// - /// - /// The log4net library should be loaded by an application early during its - /// startup, therefore this start time should be a good approximation for - /// the actual start time. - /// - /// - /// Note that AppDomains may be loaded and unloaded within the - /// same process without the process terminating, however this start time - /// will be set per AppDomain. - /// - /// - public static DateTime ProcessStartTimeUtc - { - get { return s_processStartTimeUtc; } - } - - /// - /// Text to output when a null is encountered. - /// - /// - /// - /// Use this value to indicate a null has been encountered while - /// outputting a string representation of an item. - /// - /// - /// The default value is (null). This value can be overridden by specifying - /// a value for the log4net.NullText appSetting in the application's - /// .config file. - /// - /// - public static string NullText - { - get { return s_nullText; } - set { s_nullText = value; } - } - - /// - /// Text to output when an unsupported feature is requested. - /// - /// - /// - /// Use this value when an unsupported feature is requested. - /// - /// - /// The default value is NOT AVAILABLE. This value can be overridden by specifying - /// a value for the log4net.NotAvailableText appSetting in the application's - /// .config file. - /// - /// - public static string NotAvailableText - { - get { return s_notAvailableText; } - set { s_notAvailableText = value; } - } - - #endregion Public Static Properties - - #region Public Static Methods - - /// - /// Gets the assembly location path for the specified assembly. - /// - /// The assembly to get the location for. - /// The location of the assembly. - /// - /// - /// This method does not guarantee to return the correct path - /// to the assembly. If only tries to give an indication as to - /// where the assembly was loaded from. - /// - /// - public static string AssemblyLocationInfo(Assembly myAssembly) - { + } + catch (System.Security.SecurityException) + { + // This security exception will occur if the caller does not have + // some undefined set of SecurityPermission flags. + LogLog.Debug(declaringType, "Security exception while trying to get current domain friendly name. Error Ignored."); + } + + if (s_appFriendlyName == null || s_appFriendlyName.Length == 0) + { + try + { + string assemblyLocation = SystemInfo.EntryAssemblyLocation; + s_appFriendlyName = System.IO.Path.GetFileName(assemblyLocation); + } + catch (System.Security.SecurityException) + { + // Caller needs path discovery permission + } + } + + if (s_appFriendlyName == null || s_appFriendlyName.Length == 0) + { + s_appFriendlyName = s_notAvailableText; + } + } + return s_appFriendlyName; + } + } + + /// + /// Get the start time for the current process. + /// + /// + /// + /// This is the time at which the log4net library was loaded into the + /// AppDomain. Due to reports of a hang in the call to System.Diagnostics.Process.StartTime + /// this is not the start time for the current process. + /// + /// + /// The log4net library should be loaded by an application early during its + /// startup, therefore this start time should be a good approximation for + /// the actual start time. + /// + /// + /// Note that AppDomains may be loaded and unloaded within the + /// same process without the process terminating, however this start time + /// will be set per AppDomain. + /// + /// + [Obsolete("Use ProcessStartTimeUtc and convert to local time if needed.")] + public static DateTime ProcessStartTime + { + get { return s_processStartTimeUtc.ToLocalTime(); } + } + + /// + /// Get the UTC start time for the current process. + /// + /// + /// + /// This is the UTC time at which the log4net library was loaded into the + /// AppDomain. Due to reports of a hang in the call to System.Diagnostics.Process.StartTime + /// this is not the start time for the current process. + /// + /// + /// The log4net library should be loaded by an application early during its + /// startup, therefore this start time should be a good approximation for + /// the actual start time. + /// + /// + /// Note that AppDomains may be loaded and unloaded within the + /// same process without the process terminating, however this start time + /// will be set per AppDomain. + /// + /// + public static DateTime ProcessStartTimeUtc + { + get { return s_processStartTimeUtc; } + } + + /// + /// Text to output when a null is encountered. + /// + /// + /// + /// Use this value to indicate a null has been encountered while + /// outputting a string representation of an item. + /// + /// + /// The default value is (null). This value can be overridden by specifying + /// a value for the log4net.NullText appSetting in the application's + /// .config file. + /// + /// + public static string NullText + { + get { return s_nullText; } + set { s_nullText = value; } + } + + /// + /// Text to output when an unsupported feature is requested. + /// + /// + /// + /// Use this value when an unsupported feature is requested. + /// + /// + /// The default value is NOT AVAILABLE. This value can be overridden by specifying + /// a value for the log4net.NotAvailableText appSetting in the application's + /// .config file. + /// + /// + public static string NotAvailableText + { + get { return s_notAvailableText; } + set { s_notAvailableText = value; } + } + + #endregion Public Static Properties + + #region Public Static Methods + + /// + /// Gets the assembly location path for the specified assembly. + /// + /// The assembly to get the location for. + /// The location of the assembly. + /// + /// + /// This method does not guarantee to return the correct path + /// to the assembly. If only tries to give an indication as to + /// where the assembly was loaded from. + /// + /// + public static string AssemblyLocationInfo(Assembly myAssembly) + { #if NETCF - return "Not supported on Microsoft .NET Compact Framework"; + return "Not supported on Microsoft .NET Compact Framework"; #elif NETSTANDARD1_3 - return "Not supported on .NET Core"; + return "Not supported on .NET Core"; #else - if (myAssembly.GlobalAssemblyCache) - { - return "Global Assembly Cache"; - } - else - { - try - { + if (myAssembly.GlobalAssemblyCache) + { + return "Global Assembly Cache"; + } + else + { + try + { #if NET_4_0 || MONO_4_0 - if (myAssembly.IsDynamic) - { - return "Dynamic Assembly"; - } + if (myAssembly.IsDynamic) + { + return "Dynamic Assembly"; + } #else #if !NETSTANDARD2_0 - if (myAssembly is System.Reflection.Emit.AssemblyBuilder) - { - return "Dynamic Assembly"; - } + if (myAssembly is System.Reflection.Emit.AssemblyBuilder) + { + return "Dynamic Assembly"; + } #endif - if (myAssembly.GetType().FullName == "System.Reflection.Emit.InternalAssemblyBuilder") - { - return "Dynamic Assembly"; - } + if (myAssembly.GetType().FullName == "System.Reflection.Emit.InternalAssemblyBuilder") + { + return "Dynamic Assembly"; + } #endif - else - { - // This call requires FileIOPermission for access to the path - // if we don't have permission then we just ignore it and - // carry on. - return myAssembly.Location; - } - } - catch (NotSupportedException) - { - // The location information may be unavailable for dynamic assemblies and a NotSupportedException - // is thrown in those cases. See: http://msdn.microsoft.com/de-de/library/system.reflection.assembly.location.aspx - return "Dynamic Assembly"; - } - catch (TargetInvocationException ex) - { - return "Location Detect Failed (" + ex.Message + ")"; - } - catch (ArgumentException ex) - { - return "Location Detect Failed (" + ex.Message + ")"; - } - catch (System.Security.SecurityException) - { - return "Location Permission Denied"; - } - } + else + { + // This call requires FileIOPermission for access to the path + // if we don't have permission then we just ignore it and + // carry on. + return myAssembly.Location; + } + } + catch (NotSupportedException) + { + // The location information may be unavailable for dynamic assemblies and a NotSupportedException + // is thrown in those cases. See: http://msdn.microsoft.com/de-de/library/system.reflection.assembly.location.aspx + return "Dynamic Assembly"; + } + catch (TargetInvocationException ex) + { + return "Location Detect Failed (" + ex.Message + ")"; + } + catch (ArgumentException ex) + { + return "Location Detect Failed (" + ex.Message + ")"; + } + catch (System.Security.SecurityException) + { + return "Location Permission Denied"; + } + } #endif - } - - /// - /// Gets the fully qualified name of the , including - /// the name of the assembly from which the was - /// loaded. - /// - /// The to get the fully qualified name for. - /// The fully qualified name for the . - /// - /// - /// This is equivalent to the Type.AssemblyQualifiedName property, - /// but this method works on the .NET Compact Framework 1.0 as well as - /// the full .NET runtime. - /// - /// - public static string AssemblyQualifiedName(Type type) - { - return type.FullName + ", " + } + + /// + /// Gets the fully qualified name of the , including + /// the name of the assembly from which the was + /// loaded. + /// + /// The to get the fully qualified name for. + /// The fully qualified name for the . + /// + /// + /// This is equivalent to the Type.AssemblyQualifiedName property, + /// but this method works on the .NET Compact Framework 1.0 as well as + /// the full .NET runtime. + /// + /// + public static string AssemblyQualifiedName(Type type) + { + return type.FullName + ", " #if NETSTANDARD1_3 - + type.GetTypeInfo().Assembly.FullName; + + type.GetTypeInfo().Assembly.FullName; #else - + type.Assembly.FullName; + + type.Assembly.FullName; #endif - } - - /// - /// Gets the short name of the . - /// - /// The to get the name for. - /// The short name of the . - /// - /// - /// The short name of the assembly is the - /// without the version, culture, or public key. i.e. it is just the - /// assembly's file name without the extension. - /// - /// - /// Use this rather than Assembly.GetName().Name because that - /// is not available on the Compact Framework. - /// - /// - /// Because of a FileIOPermission security demand we cannot do - /// the obvious Assembly.GetName().Name. We are allowed to get - /// the of the assembly so we - /// start from there and strip out just the assembly name. - /// - /// - public static string AssemblyShortName(Assembly myAssembly) - { - string name = myAssembly.FullName; - int offset = name.IndexOf(','); - if (offset > 0) - { - name = name.Substring(0, offset); - } - return name.Trim(); - - // TODO: Do we need to unescape the assembly name string? - // Doc says '\' is an escape char but has this already been - // done by the string loader? - } - - /// - /// Gets the file name portion of the , including the extension. - /// - /// The to get the file name for. - /// The file name of the assembly. - /// - /// - /// Gets the file name portion of the , including the extension. - /// - /// - public static string AssemblyFileName(Assembly myAssembly) - { + } + + /// + /// Gets the short name of the . + /// + /// The to get the name for. + /// The short name of the . + /// + /// + /// The short name of the assembly is the + /// without the version, culture, or public key. i.e. it is just the + /// assembly's file name without the extension. + /// + /// + /// Use this rather than Assembly.GetName().Name because that + /// is not available on the Compact Framework. + /// + /// + /// Because of a FileIOPermission security demand we cannot do + /// the obvious Assembly.GetName().Name. We are allowed to get + /// the of the assembly so we + /// start from there and strip out just the assembly name. + /// + /// + public static string AssemblyShortName(Assembly myAssembly) + { + string name = myAssembly.FullName; + int offset = name.IndexOf(','); + if (offset > 0) + { + name = name.Substring(0, offset); + } + return name.Trim(); + + // TODO: Do we need to unescape the assembly name string? + // Doc says '\' is an escape char but has this already been + // done by the string loader? + } + + /// + /// Gets the file name portion of the , including the extension. + /// + /// The to get the file name for. + /// The file name of the assembly. + /// + /// + /// Gets the file name portion of the , including the extension. + /// + /// + public static string AssemblyFileName(Assembly myAssembly) + { #if NETCF || NETSTANDARD1_3 // TODO Assembly.Location is in netstandard1.5 System.Reflection - // This is not very good because it assumes that only - // the entry assembly can be an EXE. In fact multiple - // EXEs can be loaded in to a process. - - string assemblyShortName = SystemInfo.AssemblyShortName(myAssembly); - string entryAssemblyShortName = System.IO.Path.GetFileNameWithoutExtension(SystemInfo.EntryAssemblyLocation); - - if (string.Compare(assemblyShortName, entryAssemblyShortName, true) == 0) - { - // assembly is entry assembly - return assemblyShortName + ".exe"; - } - else - { - // assembly is not entry assembly - return assemblyShortName + ".dll"; - } + // This is not very good because it assumes that only + // the entry assembly can be an EXE. In fact multiple + // EXEs can be loaded in to a process. + + string assemblyShortName = SystemInfo.AssemblyShortName(myAssembly); + string entryAssemblyShortName = System.IO.Path.GetFileNameWithoutExtension(SystemInfo.EntryAssemblyLocation); + + if (string.Compare(assemblyShortName, entryAssemblyShortName, true) == 0) + { + // assembly is entry assembly + return assemblyShortName + ".exe"; + } + else + { + // assembly is not entry assembly + return assemblyShortName + ".dll"; + } #else - return System.IO.Path.GetFileName(myAssembly.Location); + return System.IO.Path.GetFileName(myAssembly.Location); #endif - } - - /// - /// Loads the type specified in the type string. - /// - /// A sibling type to use to load the type. - /// The name of the type to load. - /// Flag set to true to throw an exception if the type cannot be loaded. - /// true to ignore the case of the type name; otherwise, false - /// The type loaded or null if it could not be loaded. - /// - /// - /// If the type name is fully qualified, i.e. if contains an assembly name in - /// the type name, the type will be loaded from the system using - /// . - /// - /// - /// If the type name is not fully qualified, it will be loaded from the assembly - /// containing the specified relative type. If the type is not found in the assembly - /// then all the loaded assemblies will be searched for the type. - /// - /// - public static Type GetTypeFromString(Type relativeType, string typeName, bool throwOnError, bool ignoreCase) - { + } + + /// + /// Loads the type specified in the type string. + /// + /// A sibling type to use to load the type. + /// The name of the type to load. + /// Flag set to true to throw an exception if the type cannot be loaded. + /// true to ignore the case of the type name; otherwise, false + /// The type loaded or null if it could not be loaded. + /// + /// + /// If the type name is fully qualified, i.e. if contains an assembly name in + /// the type name, the type will be loaded from the system using + /// . + /// + /// + /// If the type name is not fully qualified, it will be loaded from the assembly + /// containing the specified relative type. If the type is not found in the assembly + /// then all the loaded assemblies will be searched for the type. + /// + /// + public static Type GetTypeFromString(Type relativeType, string typeName, bool throwOnError, bool ignoreCase) + { #if NETSTANDARD1_3 - return GetTypeFromString(relativeType.GetTypeInfo().Assembly, typeName, throwOnError, ignoreCase); + return GetTypeFromString(relativeType.GetTypeInfo().Assembly, typeName, throwOnError, ignoreCase); #else - return GetTypeFromString(relativeType.Assembly, typeName, throwOnError, ignoreCase); + return GetTypeFromString(relativeType.Assembly, typeName, throwOnError, ignoreCase); #endif - } + } #if !NETSTANDARD1_3 - /// - /// Loads the type specified in the type string. - /// - /// The name of the type to load. - /// Flag set to true to throw an exception if the type cannot be loaded. - /// true to ignore the case of the type name; otherwise, false - /// The type loaded or null if it could not be loaded. - /// - /// - /// If the type name is fully qualified, i.e. if contains an assembly name in - /// the type name, the type will be loaded from the system using - /// . - /// - /// - /// If the type name is not fully qualified it will be loaded from the - /// assembly that is directly calling this method. If the type is not found - /// in the assembly then all the loaded assemblies will be searched for the type. - /// - /// - public static Type GetTypeFromString(string typeName, bool throwOnError, bool ignoreCase) - { - return GetTypeFromString(Assembly.GetCallingAssembly(), typeName, throwOnError, ignoreCase); - } + /// + /// Loads the type specified in the type string. + /// + /// The name of the type to load. + /// Flag set to true to throw an exception if the type cannot be loaded. + /// true to ignore the case of the type name; otherwise, false + /// The type loaded or null if it could not be loaded. + /// + /// + /// If the type name is fully qualified, i.e. if contains an assembly name in + /// the type name, the type will be loaded from the system using + /// . + /// + /// + /// If the type name is not fully qualified it will be loaded from the + /// assembly that is directly calling this method. If the type is not found + /// in the assembly then all the loaded assemblies will be searched for the type. + /// + /// + public static Type GetTypeFromString(string typeName, bool throwOnError, bool ignoreCase) + { + return GetTypeFromString(Assembly.GetCallingAssembly(), typeName, throwOnError, ignoreCase); + } #endif - /// - /// Loads the type specified in the type string. - /// - /// An assembly to load the type from. - /// The name of the type to load. - /// Flag set to true to throw an exception if the type cannot be loaded. - /// true to ignore the case of the type name; otherwise, false - /// The type loaded or null if it could not be loaded. - /// - /// - /// If the type name is fully qualified, i.e. if contains an assembly name in - /// the type name, the type will be loaded from the system using - /// . - /// - /// - /// If the type name is not fully qualified it will be loaded from the specified - /// assembly. If the type is not found in the assembly then all the loaded assemblies - /// will be searched for the type. - /// - /// - public static Type GetTypeFromString(Assembly relativeAssembly, string typeName, bool throwOnError, bool ignoreCase) - { - // Check if the type name specifies the assembly name - if (typeName.IndexOf(',') == -1) - { - //LogLog.Debug(declaringType, "SystemInfo: Loading type ["+typeName+"] from assembly ["+relativeAssembly.FullName+"]"); + /// + /// Loads the type specified in the type string. + /// + /// An assembly to load the type from. + /// The name of the type to load. + /// Flag set to true to throw an exception if the type cannot be loaded. + /// true to ignore the case of the type name; otherwise, false + /// The type loaded or null if it could not be loaded. + /// + /// + /// If the type name is fully qualified, i.e. if contains an assembly name in + /// the type name, the type will be loaded from the system using + /// . + /// + /// + /// If the type name is not fully qualified it will be loaded from the specified + /// assembly. If the type is not found in the assembly then all the loaded assemblies + /// will be searched for the type. + /// + /// + public static Type GetTypeFromString(Assembly relativeAssembly, string typeName, bool throwOnError, bool ignoreCase) + { + // Check if the type name specifies the assembly name + if (typeName.IndexOf(',') == -1) + { + //LogLog.Debug(declaringType, "SystemInfo: Loading type ["+typeName+"] from assembly ["+relativeAssembly.FullName+"]"); #if NETSTANDARD1_3 - return relativeAssembly.GetType(typeName, throwOnError, ignoreCase); + return relativeAssembly.GetType(typeName, throwOnError, ignoreCase); #elif NETCF - return relativeAssembly.GetType(typeName, throwOnError); + return relativeAssembly.GetType(typeName, throwOnError); #else - // Attempt to lookup the type from the relativeAssembly - Type type = relativeAssembly.GetType(typeName, false, ignoreCase); - if (type != null) - { - // Found type in relative assembly - //LogLog.Debug(declaringType, "SystemInfo: Loaded type ["+typeName+"] from assembly ["+relativeAssembly.FullName+"]"); - return type; - } - - Assembly[] loadedAssemblies = null; - try - { - loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies(); - } - catch (System.Security.SecurityException) - { - // Insufficient permissions to get the list of loaded assemblies - } - - if (loadedAssemblies != null) - { - Type fallback = null; - // Search the loaded assemblies for the type - foreach (Assembly assembly in loadedAssemblies) - { - Type t = assembly.GetType(typeName, false, ignoreCase); - if (t != null) - { - // Found type in loaded assembly - LogLog.Debug(declaringType, "Loaded type [" + typeName + "] from assembly [" + assembly.FullName + "] by searching loaded assemblies."); - if (assembly.GlobalAssemblyCache) - { - fallback = t; - } - else - { - return t; - } - } - } - if (fallback != null) - { - return fallback; - } - } - - // Didn't find the type - if (throwOnError) - { - throw new TypeLoadException("Could not load type [" + typeName + "]. Tried assembly [" + relativeAssembly.FullName + "] and all loaded assemblies"); - } - return null; + // Attempt to lookup the type from the relativeAssembly + Type type = relativeAssembly.GetType(typeName, false, ignoreCase); + if (type != null) + { + // Found type in relative assembly + //LogLog.Debug(declaringType, "SystemInfo: Loaded type ["+typeName+"] from assembly ["+relativeAssembly.FullName+"]"); + return type; + } + + Assembly[] loadedAssemblies = null; + try + { + loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies(); + } + catch (System.Security.SecurityException) + { + // Insufficient permissions to get the list of loaded assemblies + } + + if (loadedAssemblies != null) + { + Type fallback = null; + // Search the loaded assemblies for the type + foreach (Assembly assembly in loadedAssemblies) + { + Type t = assembly.GetType(typeName, false, ignoreCase); + if (t != null) + { + // Found type in loaded assembly + LogLog.Debug(declaringType, "Loaded type [" + typeName + "] from assembly [" + assembly.FullName + "] by searching loaded assemblies."); + if (assembly.GlobalAssemblyCache) + { + fallback = t; + } + else + { + return t; + } + } + } + if (fallback != null) + { + return fallback; + } + } + + // Didn't find the type + if (throwOnError) + { + throw new TypeLoadException("Could not load type [" + typeName + "]. Tried assembly [" + relativeAssembly.FullName + "] and all loaded assemblies"); + } + return null; #endif - } - else - { - // Includes explicit assembly name - //LogLog.Debug(declaringType, "SystemInfo: Loading type ["+typeName+"] from global Type"); + } + else + { + // Includes explicit assembly name + //LogLog.Debug(declaringType, "SystemInfo: Loading type ["+typeName+"] from global Type"); #if NETCF - // In NETCF 2 and 3 arg versions seem to behave differently - // https://issues.apache.org/jira/browse/LOG4NET-113 - return Type.GetType(typeName, throwOnError); + // In NETCF 2 and 3 arg versions seem to behave differently + // https://issues.apache.org/jira/browse/LOG4NET-113 + return Type.GetType(typeName, throwOnError); #else - return Type.GetType(typeName, throwOnError, ignoreCase); + return Type.GetType(typeName, throwOnError, ignoreCase); #endif - } - } - - - /// - /// Generate a new guid - /// - /// A new Guid - /// - /// - /// Generate a new guid - /// - /// - public static Guid NewGuid() - { + } + } + + + /// + /// Generate a new guid + /// + /// A new Guid + /// + /// + /// Generate a new guid + /// + /// + public static Guid NewGuid() + { #if NETCF_1_0 - return PocketGuid.NewGuid(); + return PocketGuid.NewGuid(); #else - return Guid.NewGuid(); + return Guid.NewGuid(); #endif - } - - /// - /// Create an - /// - /// The name of the parameter that caused the exception - /// The value of the argument that causes this exception - /// The message that describes the error - /// the ArgumentOutOfRangeException object - /// - /// - /// Create a new instance of the class - /// with a specified error message, the parameter name, and the value - /// of the argument. - /// - /// - /// The Compact Framework does not support the 3 parameter constructor for the - /// type. This method provides an - /// implementation that works for all platforms. - /// - /// - public static ArgumentOutOfRangeException CreateArgumentOutOfRangeException(string parameterName, object actualValue, string message) - { + } + + /// + /// Create an + /// + /// The name of the parameter that caused the exception + /// The value of the argument that causes this exception + /// The message that describes the error + /// the ArgumentOutOfRangeException object + /// + /// + /// Create a new instance of the class + /// with a specified error message, the parameter name, and the value + /// of the argument. + /// + /// + /// The Compact Framework does not support the 3 parameter constructor for the + /// type. This method provides an + /// implementation that works for all platforms. + /// + /// + public static ArgumentOutOfRangeException CreateArgumentOutOfRangeException(string parameterName, object actualValue, string message) + { #if NETCF_1_0 - return new ArgumentOutOfRangeException(message + " [param=" + parameterName + "] [value=" + actualValue + "]"); + return new ArgumentOutOfRangeException(message + " [param=" + parameterName + "] [value=" + actualValue + "]"); #elif NETCF_2_0 - return new ArgumentOutOfRangeException(parameterName, message + " [value=" + actualValue + "]"); + return new ArgumentOutOfRangeException(parameterName, message + " [value=" + actualValue + "]"); #else - return new ArgumentOutOfRangeException(parameterName, actualValue, message); + return new ArgumentOutOfRangeException(parameterName, actualValue, message); #endif - } - - - /// - /// Parse a string into an value - /// - /// the string to parse - /// out param where the parsed value is placed - /// true if the string was able to be parsed into an integer - /// - /// - /// Attempts to parse the string into an integer. If the string cannot - /// be parsed then this method returns false. The method does not throw an exception. - /// - /// - public static bool TryParse(string s, out int val) - { + } + + + /// + /// Parse a string into an value + /// + /// the string to parse + /// out param where the parsed value is placed + /// true if the string was able to be parsed into an integer + /// + /// + /// Attempts to parse the string into an integer. If the string cannot + /// be parsed then this method returns false. The method does not throw an exception. + /// + /// + public static bool TryParse(string s, out int val) + { #if NETCF - val = 0; - try - { - val = int.Parse(s, System.Globalization.NumberStyles.Integer, System.Globalization.CultureInfo.InvariantCulture); - return true; - } - catch - { - } - - return false; + val = 0; + try + { + val = int.Parse(s, System.Globalization.NumberStyles.Integer, System.Globalization.CultureInfo.InvariantCulture); + return true; + } + catch + { + } + + return false; #else - // Initialise out param - val = 0; - - try - { - double doubleVal; - if (Double.TryParse(s, System.Globalization.NumberStyles.Integer, System.Globalization.CultureInfo.InvariantCulture, out doubleVal)) - { - val = Convert.ToInt32(doubleVal); - return true; - } - } - catch - { - // Ignore exception, just return false - } - - return false; + // Initialise out param + val = 0; + + try + { + double doubleVal; + if (Double.TryParse(s, System.Globalization.NumberStyles.Integer, System.Globalization.CultureInfo.InvariantCulture, out doubleVal)) + { + val = Convert.ToInt32(doubleVal); + return true; + } + } + catch + { + // Ignore exception, just return false + } + + return false; #endif - } - - /// - /// Parse a string into an value - /// - /// the string to parse - /// out param where the parsed value is placed - /// true if the string was able to be parsed into an integer - /// - /// - /// Attempts to parse the string into an integer. If the string cannot - /// be parsed then this method returns false. The method does not throw an exception. - /// - /// - public static bool TryParse(string s, out long val) - { + } + + /// + /// Parse a string into an value + /// + /// the string to parse + /// out param where the parsed value is placed + /// true if the string was able to be parsed into an integer + /// + /// + /// Attempts to parse the string into an integer. If the string cannot + /// be parsed then this method returns false. The method does not throw an exception. + /// + /// + public static bool TryParse(string s, out long val) + { #if NETCF - val = 0; - try - { - val = long.Parse(s, System.Globalization.NumberStyles.Integer, System.Globalization.CultureInfo.InvariantCulture); - return true; - } - catch - { - } - - return false; + val = 0; + try + { + val = long.Parse(s, System.Globalization.NumberStyles.Integer, System.Globalization.CultureInfo.InvariantCulture); + return true; + } + catch + { + } + + return false; #else - // Initialise out param - val = 0; - - try - { - double doubleVal; - if (Double.TryParse(s, System.Globalization.NumberStyles.Integer, System.Globalization.CultureInfo.InvariantCulture, out doubleVal)) - { - val = Convert.ToInt64(doubleVal); - return true; - } - } - catch - { - // Ignore exception, just return false - } - - return false; + // Initialise out param + val = 0; + + try + { + double doubleVal; + if (Double.TryParse(s, System.Globalization.NumberStyles.Integer, System.Globalization.CultureInfo.InvariantCulture, out doubleVal)) + { + val = Convert.ToInt64(doubleVal); + return true; + } + } + catch + { + // Ignore exception, just return false + } + + return false; #endif - } - - /// - /// Parse a string into an value - /// - /// the string to parse - /// out param where the parsed value is placed - /// true if the string was able to be parsed into an integer - /// - /// - /// Attempts to parse the string into an integer. If the string cannot - /// be parsed then this method returns false. The method does not throw an exception. - /// - /// - public static bool TryParse(string s, out short val) - { + } + + /// + /// Parse a string into an value + /// + /// the string to parse + /// out param where the parsed value is placed + /// true if the string was able to be parsed into an integer + /// + /// + /// Attempts to parse the string into an integer. If the string cannot + /// be parsed then this method returns false. The method does not throw an exception. + /// + /// + public static bool TryParse(string s, out short val) + { #if NETCF - val = 0; - try - { - val = short.Parse(s, System.Globalization.NumberStyles.Integer, System.Globalization.CultureInfo.InvariantCulture); - return true; - } - catch - { - } - - return false; + val = 0; + try + { + val = short.Parse(s, System.Globalization.NumberStyles.Integer, System.Globalization.CultureInfo.InvariantCulture); + return true; + } + catch + { + } + + return false; #else - // Initialise out param - val = 0; - - try - { - double doubleVal; - if (Double.TryParse(s, System.Globalization.NumberStyles.Integer, System.Globalization.CultureInfo.InvariantCulture, out doubleVal)) - { - val = Convert.ToInt16(doubleVal); - return true; - } - } - catch - { - // Ignore exception, just return false - } - - return false; + // Initialise out param + val = 0; + + try + { + double doubleVal; + if (Double.TryParse(s, System.Globalization.NumberStyles.Integer, System.Globalization.CultureInfo.InvariantCulture, out doubleVal)) + { + val = Convert.ToInt16(doubleVal); + return true; + } + } + catch + { + // Ignore exception, just return false + } + + return false; #endif - } - - /// - /// Lookup an application setting - /// - /// the application settings key to lookup - /// the value for the key, or null - /// - /// - /// Configuration APIs are not supported under the Compact Framework - /// - /// - public static string GetAppSetting(string key) - { - try - { + } + + /// + /// Lookup an application setting + /// + /// the application settings key to lookup + /// the value for the key, or null + /// + /// + /// Configuration APIs are not supported under the Compact Framework + /// + /// + public static string GetAppSetting(string key) + { + try + { #if NETCF || NETSTANDARD1_3 - // Configuration APIs are not suported under the Compact Framework + // Configuration APIs are not suported under the Compact Framework #elif NET_2_0 || NETSTANDARD2_0 - return ConfigurationManager.AppSettings[key]; + return ConfigurationManager.AppSettings[key]; #else - return ConfigurationSettings.AppSettings[key]; + return ConfigurationSettings.AppSettings[key]; #endif - } - catch (Exception ex) - { - // If an exception is thrown here then it looks like the config file does not parse correctly. - LogLog.Error(declaringType, "Exception while reading ConfigurationSettings. Check your .config file is well formed XML.", ex); - } - return null; - } - - /// - /// Convert a path into a fully qualified local file path. - /// - /// The path to convert. - /// The fully qualified path. - /// - /// - /// Converts the path specified to a fully - /// qualified path. If the path is relative it is - /// taken as relative from the application base - /// directory. - /// - /// - /// The path specified must be a local file path, a URI is not supported. - /// - /// - public static string ConvertToFullPath(string path) - { - if (path == null) - { - throw new ArgumentNullException("path"); - } - - string baseDirectory = ""; - try - { - string applicationBaseDirectory = SystemInfo.ApplicationBaseDirectory; - if (applicationBaseDirectory != null) - { - // applicationBaseDirectory may be a URI not a local file path - Uri applicationBaseDirectoryUri = new Uri(applicationBaseDirectory); - if (applicationBaseDirectoryUri.IsFile) - { - baseDirectory = applicationBaseDirectoryUri.LocalPath; - } - } - } - catch - { - // Ignore URI exceptions & SecurityExceptions from SystemInfo.ApplicationBaseDirectory - } - - if (baseDirectory != null && baseDirectory.Length > 0) - { - // Note that Path.Combine will return the second path if it is rooted - return Path.GetFullPath(Path.Combine(baseDirectory, path)); - } - return Path.GetFullPath(path); - } - - /// - /// Creates a new case-insensitive instance of the class with the default initial capacity. - /// - /// A new case-insensitive instance of the class with the default initial capacity - /// - /// - /// The new Hashtable instance uses the default load factor, the CaseInsensitiveHashCodeProvider, and the CaseInsensitiveComparer. - /// - /// - public static Hashtable CreateCaseInsensitiveHashtable() - { + } + catch (Exception ex) + { + // If an exception is thrown here then it looks like the config file does not parse correctly. + LogLog.Error(declaringType, "Exception while reading ConfigurationSettings. Check your .config file is well formed XML.", ex); + } + return null; + } + + /// + /// Convert a path into a fully qualified local file path. + /// + /// The path to convert. + /// The fully qualified path. + /// + /// + /// Converts the path specified to a fully + /// qualified path. If the path is relative it is + /// taken as relative from the application base + /// directory. + /// + /// + /// The path specified must be a local file path, a URI is not supported. + /// + /// + public static string ConvertToFullPath(string path) + { + if (path == null) + { + throw new ArgumentNullException("path"); + } + + string baseDirectory = ""; + try + { + string applicationBaseDirectory = SystemInfo.ApplicationBaseDirectory; + if (applicationBaseDirectory != null) + { + // applicationBaseDirectory may be a URI not a local file path + Uri applicationBaseDirectoryUri = new Uri(applicationBaseDirectory); + if (applicationBaseDirectoryUri.IsFile) + { + baseDirectory = applicationBaseDirectoryUri.LocalPath; + } + } + } + catch + { + // Ignore URI exceptions & SecurityExceptions from SystemInfo.ApplicationBaseDirectory + } + + if (baseDirectory != null && baseDirectory.Length > 0) + { + // Note that Path.Combine will return the second path if it is rooted + return Path.GetFullPath(Path.Combine(baseDirectory, path)); + } + return Path.GetFullPath(path); + } + + /// + /// Creates a new case-insensitive instance of the class with the default initial capacity. + /// + /// A new case-insensitive instance of the class with the default initial capacity + /// + /// + /// The new Hashtable instance uses the default load factor, the CaseInsensitiveHashCodeProvider, and the CaseInsensitiveComparer. + /// + /// + public static Hashtable CreateCaseInsensitiveHashtable() + { #if NETCF_1_0 - return new Hashtable(CaseInsensitiveHashCodeProvider.Default, CaseInsensitiveComparer.Default); + return new Hashtable(CaseInsensitiveHashCodeProvider.Default, CaseInsensitiveComparer.Default); #elif NETCF_2_0 || NET_2_0 || MONO_2_0 || MONO_3_5 || MONO_4_0 - return new Hashtable(StringComparer.OrdinalIgnoreCase); + return new Hashtable(StringComparer.OrdinalIgnoreCase); #else - return System.Collections.Specialized.CollectionsUtil.CreateCaseInsensitiveHashtable(); + return System.Collections.Specialized.CollectionsUtil.CreateCaseInsensitiveHashtable(); #endif - } - - /// - /// Tests two strings for equality, the ignoring case. - /// - /// - /// If the platform permits, culture information is ignored completely (ordinal comparison). - /// The aim of this method is to provide a fast comparison that deals with null and ignores different casing. - /// It is not supposed to deal with various, culture-specific habits. - /// Use it to compare against pure ASCII constants, like keywords etc. - /// - /// The one string. - /// The other string. - /// true if the strings are equal, false otherwise. - public static Boolean EqualsIgnoringCase(String a, String b) - { + } + + /// + /// Tests two strings for equality, the ignoring case. + /// + /// + /// If the platform permits, culture information is ignored completely (ordinal comparison). + /// The aim of this method is to provide a fast comparison that deals with null and ignores different casing. + /// It is not supposed to deal with various, culture-specific habits. + /// Use it to compare against pure ASCII constants, like keywords etc. + /// + /// The one string. + /// The other string. + /// true if the strings are equal, false otherwise. + public static Boolean EqualsIgnoringCase(String a, String b) + { #if NET_1_0 || NET_1_1 || NETCF_1_0 - return string.Compare(a, b, true, System.Globalization.CultureInfo.InvariantCulture) == 0 + return string.Compare(a, b, true, System.Globalization.CultureInfo.InvariantCulture) == 0 #elif NETSTANDARD1_3 - return CultureInfo.InvariantCulture.CompareInfo.Compare(a, b, CompareOptions.IgnoreCase) == 0; + return CultureInfo.InvariantCulture.CompareInfo.Compare(a, b, CompareOptions.IgnoreCase) == 0; #else // >= .NET-2.0 - return String.Equals(a, b, StringComparison.OrdinalIgnoreCase); + return String.Equals(a, b, StringComparison.OrdinalIgnoreCase); #endif - } + } - #endregion Public Static Methods + #endregion Public Static Methods - #region Private Static Methods + #region Private Static Methods #if NETCF - private static string NativeEntryAssemblyLocation - { - get - { - StringBuilder moduleName = null; - - IntPtr moduleHandle = GetModuleHandle(IntPtr.Zero); - - if (moduleHandle != IntPtr.Zero) - { - moduleName = new StringBuilder(255); - if (GetModuleFileName(moduleHandle, moduleName, moduleName.Capacity) == 0) - { - throw new NotSupportedException(NativeError.GetLastError().ToString()); - } - } - else - { - throw new NotSupportedException(NativeError.GetLastError().ToString()); - } - - return moduleName.ToString(); - } - } - - [DllImport("CoreDll.dll", SetLastError=true, CharSet=CharSet.Unicode)] - private static extern IntPtr GetModuleHandle(IntPtr ModuleName); - - [DllImport("CoreDll.dll", SetLastError=true, CharSet=CharSet.Unicode)] - private static extern Int32 GetModuleFileName( - IntPtr hModule, - StringBuilder ModuleName, - Int32 cch); + private static string NativeEntryAssemblyLocation + { + get + { + StringBuilder moduleName = null; + + IntPtr moduleHandle = GetModuleHandle(IntPtr.Zero); + + if (moduleHandle != IntPtr.Zero) + { + moduleName = new StringBuilder(255); + if (GetModuleFileName(moduleHandle, moduleName, moduleName.Capacity) == 0) + { + throw new NotSupportedException(NativeError.GetLastError().ToString()); + } + } + else + { + throw new NotSupportedException(NativeError.GetLastError().ToString()); + } + + return moduleName.ToString(); + } + } + + [DllImport("CoreDll.dll", SetLastError=true, CharSet=CharSet.Unicode)] + private static extern IntPtr GetModuleHandle(IntPtr ModuleName); + + [DllImport("CoreDll.dll", SetLastError=true, CharSet=CharSet.Unicode)] + private static extern Int32 GetModuleFileName( + IntPtr hModule, + StringBuilder ModuleName, + Int32 cch); #endif - #endregion Private Static Methods - - #region Public Static Fields - - /// - /// Gets an empty array of types. - /// - /// - /// - /// The Type.EmptyTypes field is not available on - /// the .NET Compact Framework 1.0. - /// - /// - public static readonly Type[] EmptyTypes = new Type[0]; - - #endregion Public Static Fields - - #region Private Static Fields - - /// - /// The fully qualified type of the SystemInfo class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(SystemInfo); - - /// - /// Cache the host name for the current machine - /// - private static string s_hostName; - - /// - /// Cache the application friendly name - /// - private static string s_appFriendlyName; - - /// - /// Text to output when a null is encountered. - /// - private static string s_nullText; - - /// - /// Text to output when an unsupported feature is requested. - /// - private static string s_notAvailableText; - - /// - /// Start time for the current process. - /// - private static DateTime s_processStartTimeUtc = DateTime.UtcNow; - - #endregion - - #region Compact Framework Helper Classes + #endregion Private Static Methods + + #region Public Static Fields + + /// + /// Gets an empty array of types. + /// + /// + /// + /// The Type.EmptyTypes field is not available on + /// the .NET Compact Framework 1.0. + /// + /// + public static readonly Type[] EmptyTypes = new Type[0]; + + #endregion Public Static Fields + + #region Private Static Fields + + /// + /// The fully qualified type of the SystemInfo class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(SystemInfo); + + /// + /// Cache the host name for the current machine + /// + private static string s_hostName; + + /// + /// Cache the application friendly name + /// + private static string s_appFriendlyName; + + /// + /// Text to output when a null is encountered. + /// + private static string s_nullText; + + /// + /// Text to output when an unsupported feature is requested. + /// + private static string s_notAvailableText; + + /// + /// Start time for the current process. + /// + private static DateTime s_processStartTimeUtc = DateTime.UtcNow; + + #endregion + + #region Compact Framework Helper Classes #if NETCF_1_0 - /// - /// Generate GUIDs on the .NET Compact Framework. - /// - public class PocketGuid - { - // guid variant types - private enum GuidVariant - { - ReservedNCS = 0x00, - Standard = 0x02, - ReservedMicrosoft = 0x06, - ReservedFuture = 0x07 - } - - // guid version types - private enum GuidVersion - { - TimeBased = 0x01, - Reserved = 0x02, - NameBased = 0x03, - Random = 0x04 - } - - // constants that are used in the class - private class Const - { - // number of bytes in guid - public const int ByteArraySize = 16; - - // multiplex variant info - public const int VariantByte = 8; - public const int VariantByteMask = 0x3f; - public const int VariantByteShift = 6; - - // multiplex version info - public const int VersionByte = 7; - public const int VersionByteMask = 0x0f; - public const int VersionByteShift = 4; - } - - // imports for the crypto api functions - private class WinApi - { - public const uint PROV_RSA_FULL = 1; - public const uint CRYPT_VERIFYCONTEXT = 0xf0000000; - - [DllImport("CoreDll.dll")] - public static extern bool CryptAcquireContext( - ref IntPtr phProv, string pszContainer, string pszProvider, - uint dwProvType, uint dwFlags); - - [DllImport("CoreDll.dll")] - public static extern bool CryptReleaseContext( - IntPtr hProv, uint dwFlags); - - [DllImport("CoreDll.dll")] - public static extern bool CryptGenRandom( - IntPtr hProv, int dwLen, byte[] pbBuffer); - } - - // all static methods - private PocketGuid() - { - } - - /// - /// Return a new System.Guid object. - /// - public static Guid NewGuid() - { - IntPtr hCryptProv = IntPtr.Zero; - Guid guid = Guid.Empty; - - try - { - // holds random bits for guid - byte[] bits = new byte[Const.ByteArraySize]; - - // get crypto provider handle - if (!WinApi.CryptAcquireContext(ref hCryptProv, null, null, - WinApi.PROV_RSA_FULL, WinApi.CRYPT_VERIFYCONTEXT)) - { - throw new SystemException( - "Failed to acquire cryptography handle."); - } - - // generate a 128 bit (16 byte) cryptographically random number - if (!WinApi.CryptGenRandom(hCryptProv, bits.Length, bits)) - { - throw new SystemException( - "Failed to generate cryptography random bytes."); - } - - // set the variant - bits[Const.VariantByte] &= Const.VariantByteMask; - bits[Const.VariantByte] |= - ((int)GuidVariant.Standard << Const.VariantByteShift); - - // set the version - bits[Const.VersionByte] &= Const.VersionByteMask; - bits[Const.VersionByte] |= - ((int)GuidVersion.Random << Const.VersionByteShift); - - // create the new System.Guid object - guid = new Guid(bits); - } - finally - { - // release the crypto provider handle - if (hCryptProv != IntPtr.Zero) - WinApi.CryptReleaseContext(hCryptProv, 0); - } - - return guid; - } - } + /// + /// Generate GUIDs on the .NET Compact Framework. + /// + public class PocketGuid + { + // guid variant types + private enum GuidVariant + { + ReservedNCS = 0x00, + Standard = 0x02, + ReservedMicrosoft = 0x06, + ReservedFuture = 0x07 + } + + // guid version types + private enum GuidVersion + { + TimeBased = 0x01, + Reserved = 0x02, + NameBased = 0x03, + Random = 0x04 + } + + // constants that are used in the class + private class Const + { + // number of bytes in guid + public const int ByteArraySize = 16; + + // multiplex variant info + public const int VariantByte = 8; + public const int VariantByteMask = 0x3f; + public const int VariantByteShift = 6; + + // multiplex version info + public const int VersionByte = 7; + public const int VersionByteMask = 0x0f; + public const int VersionByteShift = 4; + } + + // imports for the crypto api functions + private class WinApi + { + public const uint PROV_RSA_FULL = 1; + public const uint CRYPT_VERIFYCONTEXT = 0xf0000000; + + [DllImport("CoreDll.dll")] + public static extern bool CryptAcquireContext( + ref IntPtr phProv, string pszContainer, string pszProvider, + uint dwProvType, uint dwFlags); + + [DllImport("CoreDll.dll")] + public static extern bool CryptReleaseContext( + IntPtr hProv, uint dwFlags); + + [DllImport("CoreDll.dll")] + public static extern bool CryptGenRandom( + IntPtr hProv, int dwLen, byte[] pbBuffer); + } + + // all static methods + private PocketGuid() + { + } + + /// + /// Return a new System.Guid object. + /// + public static Guid NewGuid() + { + IntPtr hCryptProv = IntPtr.Zero; + Guid guid = Guid.Empty; + + try + { + // holds random bits for guid + byte[] bits = new byte[Const.ByteArraySize]; + + // get crypto provider handle + if (!WinApi.CryptAcquireContext(ref hCryptProv, null, null, + WinApi.PROV_RSA_FULL, WinApi.CRYPT_VERIFYCONTEXT)) + { + throw new SystemException( + "Failed to acquire cryptography handle."); + } + + // generate a 128 bit (16 byte) cryptographically random number + if (!WinApi.CryptGenRandom(hCryptProv, bits.Length, bits)) + { + throw new SystemException( + "Failed to generate cryptography random bytes."); + } + + // set the variant + bits[Const.VariantByte] &= Const.VariantByteMask; + bits[Const.VariantByte] |= + ((int)GuidVariant.Standard << Const.VariantByteShift); + + // set the version + bits[Const.VersionByte] &= Const.VersionByteMask; + bits[Const.VersionByte] |= + ((int)GuidVersion.Random << Const.VersionByteShift); + + // create the new System.Guid object + guid = new Guid(bits); + } + finally + { + // release the crypto provider handle + if (hCryptProv != IntPtr.Zero) + WinApi.CryptReleaseContext(hCryptProv, 0); + } + + return guid; + } + } #endif - #endregion Compact Framework Helper Classes - } + #endregion Compact Framework Helper Classes + } } diff --git a/src/log4net/Util/SystemStringFormat.cs b/src/log4net/Util/SystemStringFormat.cs index f28f0777..9b558f39 100644 --- a/src/log4net/Util/SystemStringFormat.cs +++ b/src/log4net/Util/SystemStringFormat.cs @@ -24,222 +24,222 @@ 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; - - /// - /// Format - /// - public string Format { get; set; } - - /// - /// Args - /// - public object[] Args { get; set; } - - #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; - Format = format; - Args = args; - } - - #endregion Constructor - - /// - /// Format the string and arguments - /// - /// the formatted string - public override string ToString() - { - return StringFormat(m_provider, Format, 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); - } + /// + /// 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; + + /// + /// Format + /// + public string Format { get; set; } + + /// + /// Args + /// + public object[] Args { get; set; } + + #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; + Format = format; + Args = args; + } + + #endregion Constructor + + /// + /// Format the string and arguments + /// + /// the formatted string + public override string ToString() + { + return StringFormat(m_provider, Format, 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 && !NETSTANDARD - catch - { - log4net.Util.LogLog.Warn(declaringType, "Exception while rendering format ["+format+"]"); - return StringFormatError(null, format, args); - } + 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."; - } + } + + /// + /// 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 && !NETSTANDARD - catch - { - log4net.Util.LogLog.Error(declaringType, "INTERNAL ERROR during StringFormat error handling"); - return "Exception during StringFormat. See Internal Log."; - } + 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(""); - } + } + + /// + /// 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 && !NETSTANDARD - catch - { - buffer.Append(""); - } + catch + { + buffer.Append(""); + } #endif - } - } + } + } - #endregion StringFormat + #endregion StringFormat - #region Private Static Fields + #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 static readonly Type declaringType = typeof(SystemStringFormat); + /// + /// The fully qualified type of the SystemStringFormat class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(SystemStringFormat); - #endregion Private Static Fields - } + #endregion Private Static Fields + } } diff --git a/src/log4net/Util/TextWriterAdapter.cs b/src/log4net/Util/TextWriterAdapter.cs index 851eac48..e130e58b 100644 --- a/src/log4net/Util/TextWriterAdapter.cs +++ b/src/log4net/Util/TextWriterAdapter.cs @@ -24,216 +24,216 @@ namespace log4net.Util { - /// - /// Adapter that extends and forwards all - /// messages to an instance of . - /// - /// - /// - /// Adapter that extends and forwards all - /// messages to an instance of . - /// - /// - /// Nicko Cadell - public abstract class TextWriterAdapter : TextWriter - { - #region Private Member Variables - - /// - /// The writer to forward messages to - /// - private TextWriter m_writer; - - #endregion - - #region Constructors - - /// - /// Create an instance of that forwards all - /// messages to a . - /// - /// The to forward to - /// - /// - /// Create an instance of that forwards all - /// messages to a . - /// - /// - protected TextWriterAdapter(TextWriter writer) : base(CultureInfo.InvariantCulture) - { - m_writer = writer; - } - - #endregion - - #region Protected Instance Properties - - /// - /// Gets or sets the underlying . - /// - /// - /// The underlying . - /// - /// - /// - /// Gets or sets the underlying . - /// - /// - protected TextWriter Writer - { - get { return m_writer; } - set { m_writer = value; } - } - - #endregion Protected Instance Properties - - #region Public Properties + /// + /// Adapter that extends and forwards all + /// messages to an instance of . + /// + /// + /// + /// Adapter that extends and forwards all + /// messages to an instance of . + /// + /// + /// Nicko Cadell + public abstract class TextWriterAdapter : TextWriter + { + #region Private Member Variables + + /// + /// The writer to forward messages to + /// + private TextWriter m_writer; + + #endregion + + #region Constructors + + /// + /// Create an instance of that forwards all + /// messages to a . + /// + /// The to forward to + /// + /// + /// Create an instance of that forwards all + /// messages to a . + /// + /// + protected TextWriterAdapter(TextWriter writer) : base(CultureInfo.InvariantCulture) + { + m_writer = writer; + } + + #endregion + + #region Protected Instance Properties + + /// + /// Gets or sets the underlying . + /// + /// + /// The underlying . + /// + /// + /// + /// Gets or sets the underlying . + /// + /// + protected TextWriter Writer + { + get { return m_writer; } + set { m_writer = value; } + } + + #endregion Protected Instance Properties + + #region Public Properties - /// - /// The Encoding in which the output is written - /// - /// - /// The - /// - /// - /// - /// The Encoding in which the output is written - /// - /// - public override Encoding Encoding - { - get { return m_writer.Encoding; } - } - - /// - /// Gets an object that controls formatting - /// - /// - /// The format provider - /// - /// - /// - /// Gets an object that controls formatting - /// - /// - public override IFormatProvider FormatProvider - { - get { return m_writer.FormatProvider; } - } - - /// - /// Gets or sets the line terminator string used by the TextWriter - /// - /// - /// The line terminator to use - /// - /// - /// - /// Gets or sets the line terminator string used by the TextWriter - /// - /// - public override String NewLine - { - get { return m_writer.NewLine; } - set { m_writer.NewLine = value; } - } - - #endregion - - #region Public Methods - - /// - /// Closes the writer and releases any system resources associated with the writer - /// - /// - /// - /// - /// + /// + /// The Encoding in which the output is written + /// + /// + /// The + /// + /// + /// + /// The Encoding in which the output is written + /// + /// + public override Encoding Encoding + { + get { return m_writer.Encoding; } + } + + /// + /// Gets an object that controls formatting + /// + /// + /// The format provider + /// + /// + /// + /// Gets an object that controls formatting + /// + /// + public override IFormatProvider FormatProvider + { + get { return m_writer.FormatProvider; } + } + + /// + /// Gets or sets the line terminator string used by the TextWriter + /// + /// + /// The line terminator to use + /// + /// + /// + /// Gets or sets the line terminator string used by the TextWriter + /// + /// + public override String NewLine + { + get { return m_writer.NewLine; } + set { m_writer.NewLine = value; } + } + + #endregion + + #region Public Methods + + /// + /// Closes the writer and releases any system resources associated with the writer + /// + /// + /// + /// + /// #if !NETSTANDARD1_3 - override + override #else - virtual + virtual #endif - public void Close() - { - m_writer.Close(); - } - - /// - /// Dispose this writer - /// - /// flag indicating if we are being disposed - /// - /// - /// Dispose this writer - /// - /// - protected override void Dispose(bool disposing) - { - if (disposing) - { - ((IDisposable)m_writer).Dispose(); - } - } - - /// - /// Flushes any buffered output - /// - /// - /// - /// Clears all buffers for the writer and causes any buffered data to be written - /// to the underlying device - /// - /// - public override void Flush() - { - m_writer.Flush(); - } - - /// - /// Writes a character to the wrapped TextWriter - /// - /// the value to write to the TextWriter - /// - /// - /// Writes a character to the wrapped TextWriter - /// - /// - public override void Write(char value) - { - m_writer.Write(value); - } + public void Close() + { + m_writer.Close(); + } + + /// + /// Dispose this writer + /// + /// flag indicating if we are being disposed + /// + /// + /// Dispose this writer + /// + /// + protected override void Dispose(bool disposing) + { + if (disposing) + { + ((IDisposable)m_writer).Dispose(); + } + } + + /// + /// Flushes any buffered output + /// + /// + /// + /// Clears all buffers for the writer and causes any buffered data to be written + /// to the underlying device + /// + /// + public override void Flush() + { + m_writer.Flush(); + } + + /// + /// Writes a character to the wrapped TextWriter + /// + /// the value to write to the TextWriter + /// + /// + /// Writes a character to the wrapped TextWriter + /// + /// + public override void Write(char value) + { + m_writer.Write(value); + } - /// - /// Writes a character buffer to the wrapped TextWriter - /// - /// the data buffer - /// the start index - /// the number of characters to write - /// - /// - /// Writes a character buffer to the wrapped TextWriter - /// - /// - public override void Write(char[] buffer, int index, int count) - { - m_writer.Write(buffer, index, count); - } + /// + /// Writes a character buffer to the wrapped TextWriter + /// + /// the data buffer + /// the start index + /// the number of characters to write + /// + /// + /// Writes a character buffer to the wrapped TextWriter + /// + /// + public override void Write(char[] buffer, int index, int count) + { + m_writer.Write(buffer, index, count); + } - /// - /// Writes a string to the wrapped TextWriter - /// - /// the value to write to the TextWriter - /// - /// - /// Writes a string to the wrapped TextWriter - /// - /// - public override void Write(String value) - { - m_writer.Write(value); - } - - #endregion - } + /// + /// Writes a string to the wrapped TextWriter + /// + /// the value to write to the TextWriter + /// + /// + /// Writes a string to the wrapped TextWriter + /// + /// + public override void Write(String value) + { + m_writer.Write(value); + } + + #endregion + } } diff --git a/src/log4net/Util/ThreadContextProperties.cs b/src/log4net/Util/ThreadContextProperties.cs index e002c1be..a35697b2 100644 --- a/src/log4net/Util/ThreadContextProperties.cs +++ b/src/log4net/Util/ThreadContextProperties.cs @@ -24,177 +24,177 @@ namespace log4net.Util { - /// - /// Implementation of Properties collection for the - /// - /// - /// - /// Class implements a collection of properties that is specific to each thread. - /// The class is not synchronized as each thread has its own . - /// - /// - /// Nicko Cadell - public sealed class ThreadContextProperties : ContextPropertiesBase - { - #region Private Instance Fields + /// + /// Implementation of Properties collection for the + /// + /// + /// + /// Class implements a collection of properties that is specific to each thread. + /// The class is not synchronized as each thread has its own . + /// + /// + /// Nicko Cadell + public sealed class ThreadContextProperties : ContextPropertiesBase + { + #region Private Instance Fields #if NETCF - /// - /// The thread local data slot to use to store a PropertiesDictionary. - /// - private readonly static LocalDataStoreSlot s_threadLocalSlot = System.Threading.Thread.AllocateDataSlot(); + /// + /// The thread local data slot to use to store a PropertiesDictionary. + /// + private readonly static LocalDataStoreSlot s_threadLocalSlot = System.Threading.Thread.AllocateDataSlot(); #else - /// - /// Each thread will automatically have its instance. - /// - [ThreadStatic] - private static PropertiesDictionary _dictionary; + /// + /// Each thread will automatically have its instance. + /// + [ThreadStatic] + private static PropertiesDictionary _dictionary; #endif - #endregion Private Instance Fields - - #region Public Instance Constructors - - /// - /// Internal constructor - /// - /// - /// - /// Initializes a new instance of the class. - /// - /// - internal ThreadContextProperties() - { - } - - #endregion Public Instance Constructors - - #region Public Instance Properties - - /// - /// Gets or sets the value of a property - /// - /// - /// The value for the property with the specified key - /// - /// - /// - /// Gets or sets the value of a property - /// - /// - public override object this[string key] - { - get - { + #endregion Private Instance Fields + + #region Public Instance Constructors + + /// + /// Internal constructor + /// + /// + /// + /// Initializes a new instance of the class. + /// + /// + internal ThreadContextProperties() + { + } + + #endregion Public Instance Constructors + + #region Public Instance Properties + + /// + /// Gets or sets the value of a property + /// + /// + /// The value for the property with the specified key + /// + /// + /// + /// Gets or sets the value of a property + /// + /// + public override object this[string key] + { + get + { #if NETCF - PropertiesDictionary _dictionary = GetProperties(false); + PropertiesDictionary _dictionary = GetProperties(false); #endif - if (_dictionary != null) - { - return _dictionary[key]; - } - return null; - } - set - { - GetProperties(true)[key] = value; - } - } - - #endregion Public Instance Properties - - #region Public Instance Methods - - /// - /// Remove a property - /// - /// the key for the entry to remove - /// - /// - /// Remove a property - /// - /// - public void Remove(string key) - { + if (_dictionary != null) + { + return _dictionary[key]; + } + return null; + } + set + { + GetProperties(true)[key] = value; + } + } + + #endregion Public Instance Properties + + #region Public Instance Methods + + /// + /// Remove a property + /// + /// the key for the entry to remove + /// + /// + /// Remove a property + /// + /// + public void Remove(string key) + { #if NETCF - PropertiesDictionary _dictionary = GetProperties(false); + PropertiesDictionary _dictionary = GetProperties(false); #endif - if (_dictionary != null) - { - _dictionary.Remove(key); - } - } - - /// - /// Get the keys stored in the properties. - /// - /// - /// Gets the keys stored in the properties. - /// - /// a set of the defined keys - public string[] GetKeys() - { + if (_dictionary != null) + { + _dictionary.Remove(key); + } + } + + /// + /// Get the keys stored in the properties. + /// + /// + /// Gets the keys stored in the properties. + /// + /// a set of the defined keys + public string[] GetKeys() + { #if NETCF - PropertiesDictionary _dictionary = GetProperties(false); + PropertiesDictionary _dictionary = GetProperties(false); #endif - if (_dictionary != null) - { - return _dictionary.GetKeys(); - } - return null; - } - - /// - /// Clear all properties - /// - /// - /// - /// Clear all properties - /// - /// - public void Clear() - { + if (_dictionary != null) + { + return _dictionary.GetKeys(); + } + return null; + } + + /// + /// Clear all properties + /// + /// + /// + /// Clear all properties + /// + /// + public void Clear() + { #if NETCF - PropertiesDictionary _dictionary = GetProperties(false); + PropertiesDictionary _dictionary = GetProperties(false); #endif - if (_dictionary != null) - { - _dictionary.Clear(); - } - } - - #endregion Public Instance Methods - - #region Internal Instance Methods - - /// - /// Get the PropertiesDictionary for this thread. - /// - /// create the dictionary if it does not exist, otherwise return null if does not exist - /// the properties for this thread - /// - /// - /// 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 doing so. - /// - /// - internal PropertiesDictionary GetProperties(bool create) - { + if (_dictionary != null) + { + _dictionary.Clear(); + } + } + + #endregion Public Instance Methods + + #region Internal Instance Methods + + /// + /// Get the PropertiesDictionary for this thread. + /// + /// create the dictionary if it does not exist, otherwise return null if does not exist + /// the properties for this thread + /// + /// + /// 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 doing so. + /// + /// + internal PropertiesDictionary GetProperties(bool create) + { #if NETCF - PropertiesDictionary _dictionary = (PropertiesDictionary)System.Threading.Thread.GetData(s_threadLocalSlot); + PropertiesDictionary _dictionary = (PropertiesDictionary)System.Threading.Thread.GetData(s_threadLocalSlot); #endif - if (_dictionary == null && create) - { - _dictionary = new PropertiesDictionary(); + if (_dictionary == null && create) + { + _dictionary = new PropertiesDictionary(); #if NETCF - System.Threading.Thread.SetData(s_threadLocalSlot, _dictionary); + System.Threading.Thread.SetData(s_threadLocalSlot, _dictionary); #endif - } - return _dictionary; - } + } + return _dictionary; + } - #endregion Internal Instance Methods - } + #endregion Internal Instance Methods + } } diff --git a/src/log4net/Util/ThreadContextStack.cs b/src/log4net/Util/ThreadContextStack.cs index 53d6fbae..2d51b817 100644 --- a/src/log4net/Util/ThreadContextStack.cs +++ b/src/log4net/Util/ThreadContextStack.cs @@ -27,429 +27,429 @@ namespace log4net.Util { - /// - /// Implementation of Stack for the - /// - /// - /// - /// Implementation of Stack for the - /// - /// - /// Nicko Cadell - public sealed class ThreadContextStack : IFixingRequired - { - #region Private Static Fields - - /// - /// The stack store. - /// - private Stack m_stack = new Stack(); - - #endregion Private Static Fields - - #region Public Instance Constructors - - /// - /// Internal constructor - /// - /// - /// - /// Initializes a new instance of the class. - /// - /// - internal ThreadContextStack() - { - } - - #endregion Public Instance Constructors - - #region Public Properties - - /// - /// The number of messages in the stack - /// - /// - /// The current number of messages in the stack - /// - /// - /// - /// The current number of messages in the stack. That is - /// the number of times has been called - /// minus the number of times has been called. - /// - /// - public int Count - { - get { return m_stack.Count; } - } - - #endregion // Public Properties - - #region Public Methods - - /// - /// Clears all the contextual information held in this stack. - /// - /// - /// - /// Clears all the contextual information held in this stack. - /// Only call this if you think that this tread is being reused after - /// a previous call execution which may not have completed correctly. - /// You do not need to use this method if you always guarantee to call - /// the method of the - /// returned from even in exceptional circumstances, - /// for example by using the using(log4net.ThreadContext.Stacks["NDC"].Push("Stack_Message")) - /// syntax. - /// - /// - public void Clear() - { - m_stack.Clear(); - } - - /// - /// Removes the top context from this stack. - /// - /// The message in the context that was removed from the top of this stack. - /// - /// - /// Remove the top context from this stack, and return - /// it to the caller. If this stack is empty then an - /// empty string (not ) is returned. - /// - /// - public string Pop() - { - Stack stack = m_stack; - if (stack.Count > 0) - { - return ((StackFrame)(stack.Pop())).Message; - } - return ""; - } - - /// - /// Pushes a new context message into this stack. - /// - /// The new context message. - /// - /// An that can be used to clean up the context stack. - /// - /// - /// - /// Pushes a new context onto this stack. An - /// is returned that can be used to clean up this stack. This - /// can be easily combined with the using keyword to scope the - /// context. - /// - /// - /// Simple example of using the Push method with the using keyword. - /// - /// using(log4net.ThreadContext.Stacks["NDC"].Push("Stack_Message")) - /// { - /// log.Warn("This should have an ThreadContext Stack message"); - /// } - /// - /// - 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); - } - - /// - /// Returns the top context from this stack. - /// - /// The message in the context from the top of this stack. - /// - /// - /// Returns the top context from this stack. If this stack is empty then an - /// empty string (not ) is returned. - /// - /// - public string Peek() - { - Stack stack = m_stack; - if (stack.Count > 0) - { - return ((StackFrame)stack.Peek()).Message; - } - return ""; - } - - #endregion Public Methods - - #region Internal Methods - - /// - /// Gets the current context information for this stack. - /// - /// The current context information. - internal string GetFullMessage() - { - Stack stack = m_stack; - if (stack.Count > 0) - { - return ((StackFrame)(stack.Peek())).FullMessage; - } - return null; - } - - /// - /// Gets and sets the internal stack used by this - /// - /// The internal storage stack - /// - /// - /// This property is provided only to support backward compatability - /// of the . Tytpically the internal stack should not - /// be modified. - /// - /// - internal Stack InternalStack - { - get { return m_stack; } - set { m_stack = value; } - } + /// + /// Implementation of Stack for the + /// + /// + /// + /// Implementation of Stack for the + /// + /// + /// Nicko Cadell + public sealed class ThreadContextStack : IFixingRequired + { + #region Private Static Fields + + /// + /// The stack store. + /// + private Stack m_stack = new Stack(); + + #endregion Private Static Fields + + #region Public Instance Constructors + + /// + /// Internal constructor + /// + /// + /// + /// Initializes a new instance of the class. + /// + /// + internal ThreadContextStack() + { + } + + #endregion Public Instance Constructors + + #region Public Properties + + /// + /// The number of messages in the stack + /// + /// + /// The current number of messages in the stack + /// + /// + /// + /// The current number of messages in the stack. That is + /// the number of times has been called + /// minus the number of times has been called. + /// + /// + public int Count + { + get { return m_stack.Count; } + } + + #endregion // Public Properties + + #region Public Methods + + /// + /// Clears all the contextual information held in this stack. + /// + /// + /// + /// Clears all the contextual information held in this stack. + /// Only call this if you think that this tread is being reused after + /// a previous call execution which may not have completed correctly. + /// You do not need to use this method if you always guarantee to call + /// the method of the + /// returned from even in exceptional circumstances, + /// for example by using the using(log4net.ThreadContext.Stacks["NDC"].Push("Stack_Message")) + /// syntax. + /// + /// + public void Clear() + { + m_stack.Clear(); + } + + /// + /// Removes the top context from this stack. + /// + /// The message in the context that was removed from the top of this stack. + /// + /// + /// Remove the top context from this stack, and return + /// it to the caller. If this stack is empty then an + /// empty string (not ) is returned. + /// + /// + public string Pop() + { + Stack stack = m_stack; + if (stack.Count > 0) + { + return ((StackFrame)(stack.Pop())).Message; + } + return ""; + } + + /// + /// Pushes a new context message into this stack. + /// + /// The new context message. + /// + /// An that can be used to clean up the context stack. + /// + /// + /// + /// Pushes a new context onto this stack. An + /// is returned that can be used to clean up this stack. This + /// can be easily combined with the using keyword to scope the + /// context. + /// + /// + /// Simple example of using the Push method with the using keyword. + /// + /// using(log4net.ThreadContext.Stacks["NDC"].Push("Stack_Message")) + /// { + /// log.Warn("This should have an ThreadContext Stack message"); + /// } + /// + /// + 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); + } + + /// + /// Returns the top context from this stack. + /// + /// The message in the context from the top of this stack. + /// + /// + /// Returns the top context from this stack. If this stack is empty then an + /// empty string (not ) is returned. + /// + /// + public string Peek() + { + Stack stack = m_stack; + if (stack.Count > 0) + { + return ((StackFrame)stack.Peek()).Message; + } + return ""; + } + + #endregion Public Methods + + #region Internal Methods + + /// + /// Gets the current context information for this stack. + /// + /// The current context information. + internal string GetFullMessage() + { + Stack stack = m_stack; + if (stack.Count > 0) + { + return ((StackFrame)(stack.Peek())).FullMessage; + } + return null; + } + + /// + /// Gets and sets the internal stack used by this + /// + /// The internal storage stack + /// + /// + /// This property is provided only to support backward compatability + /// of the . Tytpically the internal stack should not + /// be modified. + /// + /// + internal Stack InternalStack + { + get { return m_stack; } + set { m_stack = value; } + } - #endregion Internal Methods - - /// - /// Gets the current context information for this stack. - /// - /// Gets the current context information - /// - /// - /// Gets the current context information for this stack. - /// - /// - public override string ToString() - { - return GetFullMessage(); - } - - /// - /// Get a portable version of this object - /// - /// the portable instance of this object - /// - /// - /// Get a cross thread portable version of this object - /// - /// - object IFixingRequired.GetFixedObject() - { - return GetFullMessage(); - } - - /// - /// Inner class used to represent a single context frame in the stack. - /// - /// - /// - /// Inner class used to represent a single context frame in the stack. - /// - /// - private sealed class StackFrame - { - #region Private Instance Fields - - private readonly string m_message; - private readonly StackFrame m_parent; - private string m_fullMessage = null; + #endregion Internal Methods + + /// + /// Gets the current context information for this stack. + /// + /// Gets the current context information + /// + /// + /// Gets the current context information for this stack. + /// + /// + public override string ToString() + { + return GetFullMessage(); + } + + /// + /// Get a portable version of this object + /// + /// the portable instance of this object + /// + /// + /// Get a cross thread portable version of this object + /// + /// + object IFixingRequired.GetFixedObject() + { + return GetFullMessage(); + } + + /// + /// Inner class used to represent a single context frame in the stack. + /// + /// + /// + /// Inner class used to represent a single context frame in the stack. + /// + /// + 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 - - /// - /// Constructor - /// - /// The message for this context. - /// The parent context in the chain. - /// - /// - /// Initializes a new instance of the class - /// with the specified message and parent context. - /// - /// - 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 - - /// - /// Get the message. - /// - /// The message. - /// - /// - /// Get the message. - /// - /// - internal string Message - { - get { return m_message; } - } - - /// - /// Gets the full text of the context down to the root level. - /// - /// - /// The full text of the context down to the root level. - /// - /// - /// - /// Gets the full text of the context down to the root level. - /// - /// - internal string FullMessage - { - get - { - if (m_fullMessage == null && m_parent != null) - { - m_fullMessage = string.Concat(m_parent.FullMessage, " ", m_message); - } - return m_fullMessage; - } - } - - #endregion Internal Instance Properties - } - - /// - /// Struct returned from the method. - /// - /// - /// - /// This struct implements the and is designed to be used - /// with the pattern to remove the stack frame at the end of the scope. - /// - /// - private struct AutoPopStackFrame : IDisposable - { - #region Private Instance Fields - - /// - /// The ThreadContextStack internal stack - /// - private Stack m_frameStack; - - /// - /// The depth to trim the stack to when this instance is disposed - /// - private int m_frameDepth; - - #endregion Private Instance Fields - - #region Internal Instance Constructors - - /// - /// Constructor - /// - /// The internal stack used by the ThreadContextStack. - /// The depth to return the stack to when this object is disposed. - /// - /// - /// Initializes a new instance of the class with - /// the specified stack and return depth. - /// - /// - internal AutoPopStackFrame(Stack frameStack, int frameDepth) - { - m_frameStack = frameStack; - m_frameDepth = frameDepth; - } - - #endregion Internal Instance Constructors - - #region Implementation of IDisposable - - /// - /// Returns the stack to the correct depth. - /// - /// - /// - /// Returns the stack to the correct depth. - /// - /// - public void Dispose() - { - if (m_frameDepth >= 0 && m_frameStack != null) - { - while(m_frameStack.Count > m_frameDepth) - { - m_frameStack.Pop(); - } - } - } - - #endregion Implementation of IDisposable - } + #endregion + + #region Internal Instance Constructors + + /// + /// Constructor + /// + /// The message for this context. + /// The parent context in the chain. + /// + /// + /// Initializes a new instance of the class + /// with the specified message and parent context. + /// + /// + 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 + + /// + /// Get the message. + /// + /// The message. + /// + /// + /// Get the message. + /// + /// + internal string Message + { + get { return m_message; } + } + + /// + /// Gets the full text of the context down to the root level. + /// + /// + /// The full text of the context down to the root level. + /// + /// + /// + /// Gets the full text of the context down to the root level. + /// + /// + internal string FullMessage + { + get + { + if (m_fullMessage == null && m_parent != null) + { + m_fullMessage = string.Concat(m_parent.FullMessage, " ", m_message); + } + return m_fullMessage; + } + } + + #endregion Internal Instance Properties + } + + /// + /// Struct returned from the method. + /// + /// + /// + /// This struct implements the and is designed to be used + /// with the pattern to remove the stack frame at the end of the scope. + /// + /// + private struct AutoPopStackFrame : IDisposable + { + #region Private Instance Fields + + /// + /// The ThreadContextStack internal stack + /// + private Stack m_frameStack; + + /// + /// The depth to trim the stack to when this instance is disposed + /// + private int m_frameDepth; + + #endregion Private Instance Fields + + #region Internal Instance Constructors + + /// + /// Constructor + /// + /// The internal stack used by the ThreadContextStack. + /// The depth to return the stack to when this object is disposed. + /// + /// + /// Initializes a new instance of the class with + /// the specified stack and return depth. + /// + /// + internal AutoPopStackFrame(Stack frameStack, int frameDepth) + { + m_frameStack = frameStack; + m_frameDepth = frameDepth; + } + + #endregion Internal Instance Constructors + + #region Implementation of IDisposable + + /// + /// Returns the stack to the correct depth. + /// + /// + /// + /// Returns the stack to the correct depth. + /// + /// + 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_1_0 - /// - /// Subclass of to - /// provide missing methods. - /// - /// - /// - /// The Compact Framework version of the - /// class is missing the Clear and Clone methods. - /// This subclass adds implementations of those missing methods. - /// - /// - public class Stack : System.Collections.Stack - { - /// - /// Clears the stack of all elements. - /// - /// - /// - /// Clears the stack of all elements. - /// - /// - public void Clear() - { - while(Count > 0) - { - Pop(); - } - } - - /// - /// Makes a shallow copy of the stack's elements. - /// - /// A new stack that has a shallow copy of the stack's elements. - /// - /// - /// Makes a shallow copy of the stack's elements. - /// - /// - public Stack Clone() - { - Stack res = new Stack(); - object[] items = ToArray(); - foreach(object item in items) - { - res.Push(item); - } - return res; - } - } + /// + /// Subclass of to + /// provide missing methods. + /// + /// + /// + /// The Compact Framework version of the + /// class is missing the Clear and Clone methods. + /// This subclass adds implementations of those missing methods. + /// + /// + public class Stack : System.Collections.Stack + { + /// + /// Clears the stack of all elements. + /// + /// + /// + /// Clears the stack of all elements. + /// + /// + public void Clear() + { + while(Count > 0) + { + Pop(); + } + } + + /// + /// Makes a shallow copy of the stack's elements. + /// + /// A new stack that has a shallow copy of the stack's elements. + /// + /// + /// Makes a shallow copy of the stack's elements. + /// + /// + public Stack Clone() + { + Stack res = new Stack(); + object[] items = ToArray(); + foreach(object item in items) + { + res.Push(item); + } + return res; + } + } #endif - } + } } diff --git a/src/log4net/Util/ThreadContextStacks.cs b/src/log4net/Util/ThreadContextStacks.cs index 0e9c1980..20219daf 100644 --- a/src/log4net/Util/ThreadContextStacks.cs +++ b/src/log4net/Util/ThreadContextStacks.cs @@ -22,103 +22,103 @@ namespace log4net.Util { - /// - /// Implementation of Stacks collection for the - /// - /// - /// - /// Implementation of Stacks collection for the - /// - /// - /// Nicko Cadell - public sealed class ThreadContextStacks - { - private readonly ContextPropertiesBase m_properties; - - #region Public Instance Constructors - - /// - /// Internal constructor - /// - /// - /// - /// Initializes a new instance of the class. - /// - /// - internal ThreadContextStacks(ContextPropertiesBase properties) - { - m_properties = properties; - } - - #endregion Public Instance Constructors - - #region Public Instance Properties - - /// - /// Gets the named thread context stack - /// - /// - /// The named stack - /// - /// - /// - /// Gets the named thread context stack - /// - /// - public ThreadContextStack this[string key] - { - get - { - ThreadContextStack stack = null; - - object propertyValue = m_properties[key]; - if (propertyValue == null) - { - // Stack does not exist, create - stack = new ThreadContextStack(); - m_properties[key] = stack; - } - else - { - // Look for existing stack - stack = propertyValue as ThreadContextStack; - if (stack == null) - { - // Property is not set to a stack! - string propertyValueString = SystemInfo.NullText; - - try - { - propertyValueString = propertyValue.ToString(); - } - catch - { - } - - LogLog.Error(declaringType, "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 - - #region Private Static Fields - - /// - /// The fully qualified type of the ThreadContextStacks class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(ThreadContextStacks); - - #endregion Private Static Fields - } + /// + /// Implementation of Stacks collection for the + /// + /// + /// + /// Implementation of Stacks collection for the + /// + /// + /// Nicko Cadell + public sealed class ThreadContextStacks + { + private readonly ContextPropertiesBase m_properties; + + #region Public Instance Constructors + + /// + /// Internal constructor + /// + /// + /// + /// Initializes a new instance of the class. + /// + /// + internal ThreadContextStacks(ContextPropertiesBase properties) + { + m_properties = properties; + } + + #endregion Public Instance Constructors + + #region Public Instance Properties + + /// + /// Gets the named thread context stack + /// + /// + /// The named stack + /// + /// + /// + /// Gets the named thread context stack + /// + /// + public ThreadContextStack this[string key] + { + get + { + ThreadContextStack stack = null; + + object propertyValue = m_properties[key]; + if (propertyValue == null) + { + // Stack does not exist, create + stack = new ThreadContextStack(); + m_properties[key] = stack; + } + else + { + // Look for existing stack + stack = propertyValue as ThreadContextStack; + if (stack == null) + { + // Property is not set to a stack! + string propertyValueString = SystemInfo.NullText; + + try + { + propertyValueString = propertyValue.ToString(); + } + catch + { + } + + LogLog.Error(declaringType, "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 + + #region Private Static Fields + + /// + /// The fully qualified type of the ThreadContextStacks class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(ThreadContextStacks); + + #endregion Private Static Fields + } } diff --git a/src/log4net/Util/Transform.cs b/src/log4net/Util/Transform.cs index 7e8f4086..1689b34c 100644 --- a/src/log4net/Util/Transform.cs +++ b/src/log4net/Util/Transform.cs @@ -24,177 +24,177 @@ namespace log4net.Util { - /// - /// Utility class for transforming strings. - /// - /// - /// - /// Utility class for transforming strings. - /// - /// - /// Nicko Cadell - /// Gert Driesen - public sealed class Transform - { - #region Private Instance Constructors - - /// - /// Initializes a new instance of the class. - /// - /// - /// - /// Uses a private access modifier to prevent instantiation of this class. - /// - /// - private Transform() - { - } - - #endregion Private Instance Constructors - - #region XML String Methods - - /// - /// Write a string to an - /// - /// the writer to write to - /// the string to write - /// The string to replace non XML compliant chars with - /// - /// - /// The test is escaped either using XML escape entities - /// or using CDATA sections. - /// - /// - public static void WriteEscapedXmlString(XmlWriter writer, string textData, string invalidCharReplacement) - { - string stringData = MaskXmlInvalidCharacters(textData, invalidCharReplacement); - // Write either escaped text or CDATA sections - - int weightCData = 12 * (1 + CountSubstrings(stringData, CDATA_END)); - int weightStringEscapes = 3*(CountSubstrings(stringData, "<") + CountSubstrings(stringData, ">")) + 4*CountSubstrings(stringData, "&"); - - if (weightStringEscapes <= weightCData) - { - // Write string using string escapes - writer.WriteString(stringData); - } - else - { - // Write string using CDATA section - - int end = stringData.IndexOf(CDATA_END); - - if (end < 0) - { - writer.WriteCData(stringData); - } - else - { - int start = 0; - while (end > -1) - { - writer.WriteCData(stringData.Substring(start, end - start)); - if (end == stringData.Length - 3) - { - start = stringData.Length; - writer.WriteString(CDATA_END); - break; - } - else - { - writer.WriteString(CDATA_UNESCAPABLE_TOKEN); - start = end + 2; - end = stringData.IndexOf(CDATA_END, start); - } - } - - if (start < stringData.Length) - { - writer.WriteCData(stringData.Substring(start)); - } - } - } - } - - /// - /// Replace invalid XML characters in text string - /// - /// the XML text input string - /// the string to use in place of invalid characters - /// A string that does not contain invalid XML characters. - /// - /// - /// Certain Unicode code points are not allowed in the XML InfoSet, for - /// details see: http://www.w3.org/TR/REC-xml/#charsets. - /// - /// - /// This method replaces any illegal characters in the input string - /// with the mask string specified. - /// - /// - public static string MaskXmlInvalidCharacters(string textData, string mask) - { - return INVALIDCHARS.Replace(textData, mask); - } - - #endregion XML String Methods - - #region Private Helper Methods - - /// - /// Count the number of times that the substring occurs in the text - /// - /// the text to search - /// the substring to find - /// the number of times the substring occurs in the text - /// - /// - /// The substring is assumed to be non repeating within itself. - /// - /// - private static int CountSubstrings(string text, string substring) - { - int count = 0; - int offset = 0; - int length = text.Length; - int substringLength = substring.Length; - - if (length == 0) - { - return 0; - } - if (substringLength == 0) - { - return 0; - } - - while(offset < length) - { - int index = text.IndexOf(substring, offset); - - if (index == -1) - { - break; - } - - count++; - offset = index + substringLength; - } - return count; - } - - #endregion - - #region Private Static Fields - - private const string CDATA_END = "]]>"; - private const string CDATA_UNESCAPABLE_TOKEN = "]]"; + /// + /// Utility class for transforming strings. + /// + /// + /// + /// Utility class for transforming strings. + /// + /// + /// Nicko Cadell + /// Gert Driesen + public sealed class Transform + { + #region Private Instance Constructors + + /// + /// Initializes a new instance of the class. + /// + /// + /// + /// Uses a private access modifier to prevent instantiation of this class. + /// + /// + private Transform() + { + } + + #endregion Private Instance Constructors + + #region XML String Methods + + /// + /// Write a string to an + /// + /// the writer to write to + /// the string to write + /// The string to replace non XML compliant chars with + /// + /// + /// The test is escaped either using XML escape entities + /// or using CDATA sections. + /// + /// + public static void WriteEscapedXmlString(XmlWriter writer, string textData, string invalidCharReplacement) + { + string stringData = MaskXmlInvalidCharacters(textData, invalidCharReplacement); + // Write either escaped text or CDATA sections + + int weightCData = 12 * (1 + CountSubstrings(stringData, CDATA_END)); + int weightStringEscapes = 3*(CountSubstrings(stringData, "<") + CountSubstrings(stringData, ">")) + 4*CountSubstrings(stringData, "&"); + + if (weightStringEscapes <= weightCData) + { + // Write string using string escapes + writer.WriteString(stringData); + } + else + { + // Write string using CDATA section + + int end = stringData.IndexOf(CDATA_END); + + if (end < 0) + { + writer.WriteCData(stringData); + } + else + { + int start = 0; + while (end > -1) + { + writer.WriteCData(stringData.Substring(start, end - start)); + if (end == stringData.Length - 3) + { + start = stringData.Length; + writer.WriteString(CDATA_END); + break; + } + else + { + writer.WriteString(CDATA_UNESCAPABLE_TOKEN); + start = end + 2; + end = stringData.IndexOf(CDATA_END, start); + } + } + + if (start < stringData.Length) + { + writer.WriteCData(stringData.Substring(start)); + } + } + } + } + + /// + /// Replace invalid XML characters in text string + /// + /// the XML text input string + /// the string to use in place of invalid characters + /// A string that does not contain invalid XML characters. + /// + /// + /// Certain Unicode code points are not allowed in the XML InfoSet, for + /// details see: http://www.w3.org/TR/REC-xml/#charsets. + /// + /// + /// This method replaces any illegal characters in the input string + /// with the mask string specified. + /// + /// + public static string MaskXmlInvalidCharacters(string textData, string mask) + { + return INVALIDCHARS.Replace(textData, mask); + } + + #endregion XML String Methods + + #region Private Helper Methods + + /// + /// Count the number of times that the substring occurs in the text + /// + /// the text to search + /// the substring to find + /// the number of times the substring occurs in the text + /// + /// + /// The substring is assumed to be non repeating within itself. + /// + /// + private static int CountSubstrings(string text, string substring) + { + int count = 0; + int offset = 0; + int length = text.Length; + int substringLength = substring.Length; + + if (length == 0) + { + return 0; + } + if (substringLength == 0) + { + return 0; + } + + while(offset < length) + { + int index = text.IndexOf(substring, offset); + + if (index == -1) + { + break; + } + + count++; + offset = index + substringLength; + } + return count; + } + + #endregion + + #region Private Static Fields + + private const string CDATA_END = "]]>"; + private const string CDATA_UNESCAPABLE_TOKEN = "]]"; /// /// Characters illegal in XML 1.0 /// - private static Regex INVALIDCHARS=new Regex(@"[^\x09\x0A\x0D\x20-\uD7FF\uE000-\uFFFD]",RegexOptions.Compiled); - #endregion Private Static Fields - } + private static Regex INVALIDCHARS=new Regex(@"[^\x09\x0A\x0D\x20-\uD7FF\uE000-\uFFFD]",RegexOptions.Compiled); + #endregion Private Static Fields + } } diff --git a/src/log4net/Util/TypeConverters/BooleanConverter.cs b/src/log4net/Util/TypeConverters/BooleanConverter.cs index 7853c45a..7ca64966 100644 --- a/src/log4net/Util/TypeConverters/BooleanConverter.cs +++ b/src/log4net/Util/TypeConverters/BooleanConverter.cs @@ -21,65 +21,65 @@ namespace log4net.Util.TypeConverters { - /// - /// Type converter for Boolean. - /// - /// - /// - /// Supports conversion from string to bool type. - /// - /// - /// - /// - /// - /// Nicko Cadell - /// Gert Driesen - internal class BooleanConverter : IConvertFrom - { - #region Implementation of IConvertFrom + /// + /// Type converter for Boolean. + /// + /// + /// + /// Supports conversion from string to bool type. + /// + /// + /// + /// + /// + /// Nicko Cadell + /// Gert Driesen + internal class BooleanConverter : IConvertFrom + { + #region Implementation of IConvertFrom - /// - /// Can the source type be converted to the type supported by this object - /// - /// the type to convert - /// true if the conversion is possible - /// - /// - /// Returns true if the is - /// the type. - /// - /// - public bool CanConvertFrom(Type sourceType) - { - return (sourceType == typeof(string)); - } + /// + /// Can the source type be converted to the type supported by this object + /// + /// the type to convert + /// true if the conversion is possible + /// + /// + /// Returns true if the is + /// the type. + /// + /// + public bool CanConvertFrom(Type sourceType) + { + return (sourceType == typeof(string)); + } - /// - /// Convert the source object to the type supported by this object - /// - /// the object to convert - /// the converted object - /// - /// - /// Uses the method to convert the - /// argument to a . - /// - /// - /// - /// The object cannot be converted to the - /// target type. To check for this condition use the - /// method. - /// - public object ConvertFrom(object source) - { - string str = source as string; - if (str != null) - { - return bool.Parse(str); - } - throw ConversionNotSupportedException.Create(typeof(bool), source); - } + /// + /// Convert the source object to the type supported by this object + /// + /// the object to convert + /// the converted object + /// + /// + /// Uses the method to convert the + /// argument to a . + /// + /// + /// + /// The object cannot be converted to the + /// target type. To check for this condition use the + /// method. + /// + public object ConvertFrom(object source) + { + string str = source as string; + if (str != null) + { + return bool.Parse(str); + } + throw ConversionNotSupportedException.Create(typeof(bool), source); + } - #endregion - } + #endregion + } } diff --git a/src/log4net/Util/TypeConverters/ConversionNotSupportedException.cs b/src/log4net/Util/TypeConverters/ConversionNotSupportedException.cs index 717e8bcf..ea59d980 100644 --- a/src/log4net/Util/TypeConverters/ConversionNotSupportedException.cs +++ b/src/log4net/Util/TypeConverters/ConversionNotSupportedException.cs @@ -24,135 +24,135 @@ namespace log4net.Util.TypeConverters { - /// - /// Exception base type for conversion errors. - /// - /// - /// - /// This type extends . It - /// does not add any new functionality but does differentiate the - /// type of exception being thrown. - /// - /// - /// Nicko Cadell - /// Gert Driesen + /// + /// Exception base type for conversion errors. + /// + /// + /// + /// This type extends . It + /// does not add any new functionality but does differentiate the + /// type of exception being thrown. + /// + /// + /// Nicko Cadell + /// Gert Driesen #if !NETCF - [Serializable] + [Serializable] #endif #if NETSTANDARD1_3 - public class ConversionNotSupportedException : Exception + public class ConversionNotSupportedException : Exception #else - public class ConversionNotSupportedException : ApplicationException + public class ConversionNotSupportedException : ApplicationException #endif - { - #region Public Instance Constructors + { + #region Public Instance Constructors - /// - /// Constructor - /// - /// - /// - /// Initializes a new instance of the class. - /// - /// - public ConversionNotSupportedException() - { - } + /// + /// Constructor + /// + /// + /// + /// Initializes a new instance of the class. + /// + /// + public ConversionNotSupportedException() + { + } - /// - /// Constructor - /// - /// A message to include with the exception. - /// - /// - /// Initializes a new instance of the class - /// with the specified message. - /// - /// - public ConversionNotSupportedException(String message) : base(message) - { - } - - /// - /// Constructor - /// - /// A message to include with the exception. - /// A nested exception to include. - /// - /// - /// Initializes a new instance of the class - /// with the specified message and inner exception. - /// - /// - public ConversionNotSupportedException(String message, Exception innerException) : base(message, innerException) - { - } + /// + /// Constructor + /// + /// A message to include with the exception. + /// + /// + /// Initializes a new instance of the class + /// with the specified message. + /// + /// + public ConversionNotSupportedException(String message) : base(message) + { + } + + /// + /// Constructor + /// + /// A message to include with the exception. + /// A nested exception to include. + /// + /// + /// Initializes a new instance of the class + /// with the specified message and inner exception. + /// + /// + public ConversionNotSupportedException(String message, Exception innerException) : base(message, innerException) + { + } - #endregion Public Instance Constructors + #endregion Public Instance Constructors - #region Protected Instance Constructors + #region Protected Instance Constructors #if !NETCF && !NETSTANDARD1_3 - /// - /// Serialization constructor - /// - /// The that holds the serialized object data about the exception being thrown. - /// The that contains contextual information about the source or destination. - /// - /// - /// Initializes a new instance of the class - /// with serialized data. - /// - /// - protected ConversionNotSupportedException(SerializationInfo info, StreamingContext context) : base(info, context) - { - } + /// + /// Serialization constructor + /// + /// The that holds the serialized object data about the exception being thrown. + /// The that contains contextual information about the source or destination. + /// + /// + /// Initializes a new instance of the class + /// with serialized data. + /// + /// + protected ConversionNotSupportedException(SerializationInfo info, StreamingContext context) : base(info, context) + { + } #endif - #endregion Protected Instance Constructors + #endregion Protected Instance Constructors - #region Public Static Methods + #region Public Static Methods - /// - /// Creates a new instance of the class. - /// - /// The conversion destination type. - /// The value to convert. - /// An instance of the . - /// - /// - /// Creates a new instance of the class. - /// - /// - public static ConversionNotSupportedException Create(Type destinationType, object sourceValue) - { - return Create(destinationType, sourceValue, null); - } + /// + /// Creates a new instance of the class. + /// + /// The conversion destination type. + /// The value to convert. + /// An instance of the . + /// + /// + /// Creates a new instance of the class. + /// + /// + public static ConversionNotSupportedException Create(Type destinationType, object sourceValue) + { + return Create(destinationType, sourceValue, null); + } - /// - /// Creates a new instance of the class. - /// - /// The conversion destination type. - /// The value to convert. - /// A nested exception to include. - /// An instance of the . - /// - /// - /// Creates a new instance of the class. - /// - /// - public static ConversionNotSupportedException Create(Type destinationType, object sourceValue, Exception innerException) - { - if (sourceValue == null) - { - return new ConversionNotSupportedException("Cannot convert value [null] to type ["+destinationType+"]", innerException); - } - else - { - return new ConversionNotSupportedException("Cannot convert from type ["+sourceValue.GetType()+"] value ["+sourceValue+"] to type ["+destinationType+"]", innerException); - } - } + /// + /// Creates a new instance of the class. + /// + /// The conversion destination type. + /// The value to convert. + /// A nested exception to include. + /// An instance of the . + /// + /// + /// Creates a new instance of the class. + /// + /// + public static ConversionNotSupportedException Create(Type destinationType, object sourceValue, Exception innerException) + { + if (sourceValue == null) + { + return new ConversionNotSupportedException("Cannot convert value [null] to type ["+destinationType+"]", innerException); + } + else + { + return new ConversionNotSupportedException("Cannot convert from type ["+sourceValue.GetType()+"] value ["+sourceValue+"] to type ["+destinationType+"]", innerException); + } + } - #endregion Public Static Methods - } + #endregion Public Static Methods + } } diff --git a/src/log4net/Util/TypeConverters/ConverterRegistry.cs b/src/log4net/Util/TypeConverters/ConverterRegistry.cs index e20bbd52..bc0fa10c 100644 --- a/src/log4net/Util/TypeConverters/ConverterRegistry.cs +++ b/src/log4net/Util/TypeConverters/ConverterRegistry.cs @@ -25,280 +25,280 @@ namespace log4net.Util.TypeConverters { - /// - /// Register of type converters for specific types. - /// - /// - /// - /// Maintains a registry of type converters used to convert between - /// types. - /// - /// - /// Use the and - /// methods to register new converters. - /// The and methods - /// lookup appropriate converters to use. - /// - /// - /// - /// - /// Nicko Cadell - /// Gert Driesen - public sealed class ConverterRegistry - { - #region Private Constructors + /// + /// Register of type converters for specific types. + /// + /// + /// + /// Maintains a registry of type converters used to convert between + /// types. + /// + /// + /// Use the and + /// methods to register new converters. + /// The and methods + /// lookup appropriate converters to use. + /// + /// + /// + /// + /// Nicko Cadell + /// Gert Driesen + public sealed class ConverterRegistry + { + #region Private Constructors - /// - /// Private constructor - /// - /// - /// Initializes a new instance of the class. - /// - private ConverterRegistry() - { - } + /// + /// Private constructor + /// + /// + /// Initializes a new instance of the class. + /// + private ConverterRegistry() + { + } - #endregion Private Constructors + #endregion Private Constructors - #region Static Constructor + #region Static Constructor - /// - /// Static constructor. - /// - /// - /// - /// This constructor defines the intrinsic type converters. - /// - /// - static ConverterRegistry() - { - // Add predefined converters here - AddConverter(typeof(bool), typeof(BooleanConverter)); - AddConverter(typeof(System.Text.Encoding), typeof(EncodingConverter)); - AddConverter(typeof(System.Type), typeof(TypeConverter)); - AddConverter(typeof(log4net.Layout.PatternLayout), typeof(PatternLayoutConverter)); - AddConverter(typeof(log4net.Util.PatternString), typeof(PatternStringConverter)); - AddConverter(typeof(System.Net.IPAddress), typeof(IPAddressConverter)); - } + /// + /// Static constructor. + /// + /// + /// + /// This constructor defines the intrinsic type converters. + /// + /// + static ConverterRegistry() + { + // Add predefined converters here + AddConverter(typeof(bool), typeof(BooleanConverter)); + AddConverter(typeof(System.Text.Encoding), typeof(EncodingConverter)); + AddConverter(typeof(System.Type), typeof(TypeConverter)); + AddConverter(typeof(log4net.Layout.PatternLayout), typeof(PatternLayoutConverter)); + AddConverter(typeof(log4net.Util.PatternString), typeof(PatternStringConverter)); + AddConverter(typeof(System.Net.IPAddress), typeof(IPAddressConverter)); + } - #endregion Static Constructor + #endregion Static Constructor - #region Public Static Methods + #region Public Static Methods - /// - /// Adds a converter for a specific type. - /// - /// The type being converted to. - /// The type converter to use to convert to the destination type. - /// - /// - /// Adds a converter instance for a specific type. - /// - /// - public static void AddConverter(Type destinationType, object converter) - { - if (destinationType != null && converter != null) - { - lock(s_type2converter) - { - s_type2converter[destinationType] = converter; - } - } - } + /// + /// Adds a converter for a specific type. + /// + /// The type being converted to. + /// The type converter to use to convert to the destination type. + /// + /// + /// Adds a converter instance for a specific type. + /// + /// + public static void AddConverter(Type destinationType, object converter) + { + if (destinationType != null && converter != null) + { + lock(s_type2converter) + { + s_type2converter[destinationType] = converter; + } + } + } - /// - /// Adds a converter for a specific type. - /// - /// The type being converted to. - /// The type of the type converter to use to convert to the destination type. - /// - /// - /// Adds a converter for a specific type. - /// - /// - public static void AddConverter(Type destinationType, Type converterType) - { - AddConverter(destinationType, CreateConverterInstance(converterType)); - } + /// + /// Adds a converter for a specific type. + /// + /// The type being converted to. + /// The type of the type converter to use to convert to the destination type. + /// + /// + /// Adds a converter for a specific type. + /// + /// + public static void AddConverter(Type destinationType, Type converterType) + { + AddConverter(destinationType, CreateConverterInstance(converterType)); + } - /// - /// Gets the type converter to use to convert values to the destination type. - /// - /// The type being converted from. - /// The type being converted to. - /// - /// The type converter instance to use for type conversions or null - /// if no type converter is found. - /// - /// - /// - /// Gets the type converter to use to convert values to the destination type. - /// - /// - public static IConvertTo GetConvertTo(Type sourceType, Type destinationType) - { - // TODO: Support inheriting type converters. - // i.e. getting a type converter for a base of sourceType + /// + /// Gets the type converter to use to convert values to the destination type. + /// + /// The type being converted from. + /// The type being converted to. + /// + /// The type converter instance to use for type conversions or null + /// if no type converter is found. + /// + /// + /// + /// Gets the type converter to use to convert values to the destination type. + /// + /// + public static IConvertTo GetConvertTo(Type sourceType, Type destinationType) + { + // TODO: Support inheriting type converters. + // i.e. getting a type converter for a base of sourceType - // TODO: Is destinationType required? We don't use it for anything. + // TODO: Is destinationType required? We don't use it for anything. - lock(s_type2converter) - { - // Lookup in the static registry - IConvertTo converter = s_type2converter[sourceType] as IConvertTo; + lock(s_type2converter) + { + // Lookup in the static registry + IConvertTo converter = s_type2converter[sourceType] as IConvertTo; - if (converter == null) - { - // Lookup using attributes - converter = GetConverterFromAttribute(sourceType) as IConvertTo; + if (converter == null) + { + // Lookup using attributes + converter = GetConverterFromAttribute(sourceType) as IConvertTo; - if (converter != null) - { - // Store in registry - s_type2converter[sourceType] = converter; - } - } + if (converter != null) + { + // Store in registry + s_type2converter[sourceType] = converter; + } + } - return converter; - } - } + return converter; + } + } - /// - /// Gets the type converter to use to convert values to the destination type. - /// - /// The type being converted to. - /// - /// The type converter instance to use for type conversions or null - /// if no type converter is found. - /// - /// - /// - /// Gets the type converter to use to convert values to the destination type. - /// - /// - public static IConvertFrom GetConvertFrom(Type destinationType) - { - // TODO: Support inheriting type converters. - // i.e. getting a type converter for a base of destinationType + /// + /// Gets the type converter to use to convert values to the destination type. + /// + /// The type being converted to. + /// + /// The type converter instance to use for type conversions or null + /// if no type converter is found. + /// + /// + /// + /// Gets the type converter to use to convert values to the destination type. + /// + /// + public static IConvertFrom GetConvertFrom(Type destinationType) + { + // TODO: Support inheriting type converters. + // i.e. getting a type converter for a base of destinationType - lock(s_type2converter) - { - // Lookup in the static registry - IConvertFrom converter = s_type2converter[destinationType] as IConvertFrom; + lock(s_type2converter) + { + // Lookup in the static registry + IConvertFrom converter = s_type2converter[destinationType] as IConvertFrom; - if (converter == null) - { - // Lookup using attributes - converter = GetConverterFromAttribute(destinationType) as IConvertFrom; + if (converter == null) + { + // Lookup using attributes + converter = GetConverterFromAttribute(destinationType) as IConvertFrom; - if (converter != null) - { - // Store in registry - s_type2converter[destinationType] = converter; - } - } + if (converter != null) + { + // Store in registry + s_type2converter[destinationType] = converter; + } + } - return converter; - } - } - - /// - /// Lookups the type converter to use as specified by the attributes on the - /// destination type. - /// - /// The type being converted to. - /// - /// The type converter instance to use for type conversions or null - /// if no type converter is found. - /// - private static object GetConverterFromAttribute(Type destinationType) - { - // Look for an attribute on the destination type - var attributes = destinationType + return converter; + } + } + + /// + /// Lookups the type converter to use as specified by the attributes on the + /// destination type. + /// + /// The type being converted to. + /// + /// The type converter instance to use for type conversions or null + /// if no type converter is found. + /// + private static object GetConverterFromAttribute(Type destinationType) + { + // Look for an attribute on the destination type + var attributes = destinationType #if NETSTANDARD1_3 - .GetTypeInfo() + .GetTypeInfo() #endif - .GetCustomAttributes(typeof(TypeConverterAttribute), true); - if (attributes is null) - { - // I assume the original null check is perhaps for CF or older .NET versions -- please leave in place - return null; - } + .GetCustomAttributes(typeof(TypeConverterAttribute), true); + if (attributes is null) + { + // I assume the original null check is perhaps for CF or older .NET versions -- please leave in place + return null; + } - foreach (var attribute in attributes) - { - var tcAttr = attribute as TypeConverterAttribute; - if (tcAttr != null) - { - var converterType = SystemInfo.GetTypeFromString(destinationType, tcAttr.ConverterTypeName, false, true); - return CreateConverterInstance(converterType); - } - } + foreach (var attribute in attributes) + { + var tcAttr = attribute as TypeConverterAttribute; + if (tcAttr != null) + { + var converterType = SystemInfo.GetTypeFromString(destinationType, tcAttr.ConverterTypeName, false, true); + return CreateConverterInstance(converterType); + } + } - // Not found converter using attributes - return null; - } + // Not found converter using attributes + return null; + } - /// - /// Creates the instance of the type converter. - /// - /// The type of the type converter. - /// - /// The type converter instance to use for type conversions or null - /// if no type converter is found. - /// - /// - /// - /// The type specified for the type converter must implement - /// the or interfaces - /// and must have a public default (no argument) constructor. - /// - /// - private static object CreateConverterInstance(Type converterType) - { - if (converterType == null) - { - throw new ArgumentNullException("converterType", "CreateConverterInstance cannot create instance, converterType is null"); - } + /// + /// Creates the instance of the type converter. + /// + /// The type of the type converter. + /// + /// The type converter instance to use for type conversions or null + /// if no type converter is found. + /// + /// + /// + /// The type specified for the type converter must implement + /// the or interfaces + /// and must have a public default (no argument) constructor. + /// + /// + private static object CreateConverterInstance(Type converterType) + { + if (converterType == null) + { + throw new ArgumentNullException("converterType", "CreateConverterInstance cannot create instance, converterType is null"); + } - // Check type is a converter - if (typeof(IConvertFrom).IsAssignableFrom(converterType) || typeof(IConvertTo).IsAssignableFrom(converterType)) - { - try - { - // Create the type converter - return Activator.CreateInstance(converterType); - } - catch(Exception ex) - { - LogLog.Error(declaringType, "Cannot CreateConverterInstance of type ["+converterType.FullName+"], Exception in call to Activator.CreateInstance", ex); - } - } - else - { - LogLog.Error(declaringType, "Cannot CreateConverterInstance of type ["+converterType.FullName+"], type does not implement IConvertFrom or IConvertTo"); - } - return null; - } + // Check type is a converter + if (typeof(IConvertFrom).IsAssignableFrom(converterType) || typeof(IConvertTo).IsAssignableFrom(converterType)) + { + try + { + // Create the type converter + return Activator.CreateInstance(converterType); + } + catch(Exception ex) + { + LogLog.Error(declaringType, "Cannot CreateConverterInstance of type ["+converterType.FullName+"], Exception in call to Activator.CreateInstance", ex); + } + } + else + { + LogLog.Error(declaringType, "Cannot CreateConverterInstance of type ["+converterType.FullName+"], type does not implement IConvertFrom or IConvertTo"); + } + return null; + } - #endregion Public Static Methods + #endregion Public Static Methods - #region Private Static Fields + #region Private Static Fields - /// - /// The fully qualified type of the ConverterRegistry class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(ConverterRegistry); + /// + /// The fully qualified type of the ConverterRegistry class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(ConverterRegistry); - /// - /// Mapping from to type converter. - /// - private static Hashtable s_type2converter = new Hashtable(); + /// + /// Mapping from to type converter. + /// + private static Hashtable s_type2converter = new Hashtable(); - #endregion - } + #endregion + } } diff --git a/src/log4net/Util/TypeConverters/EncodingConverter.cs b/src/log4net/Util/TypeConverters/EncodingConverter.cs index 93c9eac9..27dd4bb0 100644 --- a/src/log4net/Util/TypeConverters/EncodingConverter.cs +++ b/src/log4net/Util/TypeConverters/EncodingConverter.cs @@ -22,65 +22,65 @@ namespace log4net.Util.TypeConverters { - /// - /// Supports conversion from string to type. - /// - /// - /// - /// Supports conversion from string to type. - /// - /// - /// - /// - /// - /// Nicko Cadell - /// Gert Driesen - internal class EncodingConverter : IConvertFrom - { - #region Implementation of IConvertFrom + /// + /// Supports conversion from string to type. + /// + /// + /// + /// Supports conversion from string to type. + /// + /// + /// + /// + /// + /// Nicko Cadell + /// Gert Driesen + internal class EncodingConverter : IConvertFrom + { + #region Implementation of IConvertFrom - /// - /// Can the source type be converted to the type supported by this object - /// - /// the type to convert - /// true if the conversion is possible - /// - /// - /// Returns true if the is - /// the type. - /// - /// - public bool CanConvertFrom(Type sourceType) - { - return (sourceType == typeof(string)); - } + /// + /// Can the source type be converted to the type supported by this object + /// + /// the type to convert + /// true if the conversion is possible + /// + /// + /// Returns true if the is + /// the type. + /// + /// + public bool CanConvertFrom(Type sourceType) + { + return (sourceType == typeof(string)); + } - /// - /// Overrides the ConvertFrom method of IConvertFrom. - /// - /// the object to convert to an encoding - /// the encoding - /// - /// - /// Uses the method to - /// convert the argument to an . - /// - /// - /// - /// The object cannot be converted to the - /// target type. To check for this condition use the - /// method. - /// - public object ConvertFrom(object source) - { - string str = source as string; - if (str != null) - { - return Encoding.GetEncoding(str); - } - throw ConversionNotSupportedException.Create(typeof(Encoding), source); - } + /// + /// Overrides the ConvertFrom method of IConvertFrom. + /// + /// the object to convert to an encoding + /// the encoding + /// + /// + /// Uses the method to + /// convert the argument to an . + /// + /// + /// + /// The object cannot be converted to the + /// target type. To check for this condition use the + /// method. + /// + public object ConvertFrom(object source) + { + string str = source as string; + if (str != null) + { + return Encoding.GetEncoding(str); + } + throw ConversionNotSupportedException.Create(typeof(Encoding), source); + } - #endregion - } + #endregion + } } diff --git a/src/log4net/Util/TypeConverters/IConvertFrom.cs b/src/log4net/Util/TypeConverters/IConvertFrom.cs index 1dbd4738..f34f9b28 100644 --- a/src/log4net/Util/TypeConverters/IConvertFrom.cs +++ b/src/log4net/Util/TypeConverters/IConvertFrom.cs @@ -21,43 +21,43 @@ namespace log4net.Util.TypeConverters { - /// - /// Interface supported by type converters - /// - /// - /// - /// This interface supports conversion from arbitrary types - /// to a single target type. See . - /// - /// - /// Nicko Cadell - /// Gert Driesen - public interface IConvertFrom - { - /// - /// Can the source type be converted to the type supported by this object - /// - /// the type to convert - /// true if the conversion is possible - /// - /// - /// Test if the can be converted to the - /// type supported by this converter. - /// - /// - bool CanConvertFrom(Type sourceType); + /// + /// Interface supported by type converters + /// + /// + /// + /// This interface supports conversion from arbitrary types + /// to a single target type. See . + /// + /// + /// Nicko Cadell + /// Gert Driesen + public interface IConvertFrom + { + /// + /// Can the source type be converted to the type supported by this object + /// + /// the type to convert + /// true if the conversion is possible + /// + /// + /// Test if the can be converted to the + /// type supported by this converter. + /// + /// + bool CanConvertFrom(Type sourceType); - /// - /// Convert the source object to the type supported by this object - /// - /// the object to convert - /// the converted object - /// - /// - /// Converts the to the type supported - /// by this converter. - /// - /// - object ConvertFrom(object source); - } + /// + /// Convert the source object to the type supported by this object + /// + /// the object to convert + /// the converted object + /// + /// + /// Converts the to the type supported + /// by this converter. + /// + /// + object ConvertFrom(object source); + } } diff --git a/src/log4net/Util/TypeConverters/IConvertTo.cs b/src/log4net/Util/TypeConverters/IConvertTo.cs index e9863728..abd748fe 100644 --- a/src/log4net/Util/TypeConverters/IConvertTo.cs +++ b/src/log4net/Util/TypeConverters/IConvertTo.cs @@ -21,43 +21,43 @@ namespace log4net.Util.TypeConverters { - /// - /// Interface supported by type converters - /// - /// - /// - /// This interface supports conversion from a single type to arbitrary types. - /// See . - /// - /// - /// Nicko Cadell - public interface IConvertTo - { - /// - /// Returns whether this converter can convert the object to the specified type - /// - /// A Type that represents the type you want to convert to - /// true if the conversion is possible - /// - /// - /// Test if the type supported by this converter can be converted to the - /// . - /// - /// - bool CanConvertTo(Type targetType); + /// + /// Interface supported by type converters + /// + /// + /// + /// This interface supports conversion from a single type to arbitrary types. + /// See . + /// + /// + /// Nicko Cadell + public interface IConvertTo + { + /// + /// Returns whether this converter can convert the object to the specified type + /// + /// A Type that represents the type you want to convert to + /// true if the conversion is possible + /// + /// + /// Test if the type supported by this converter can be converted to the + /// . + /// + /// + bool CanConvertTo(Type targetType); - /// - /// Converts the given value object to the specified type, using the arguments - /// - /// the object to convert - /// The Type to convert the value parameter to - /// the converted object - /// - /// - /// Converts the (which must be of the type supported - /// by this converter) to the specified.. - /// - /// - object ConvertTo(object source, Type targetType); - } + /// + /// Converts the given value object to the specified type, using the arguments + /// + /// the object to convert + /// The Type to convert the value parameter to + /// the converted object + /// + /// + /// Converts the (which must be of the type supported + /// by this converter) to the specified.. + /// + /// + object ConvertTo(object source, Type targetType); + } } diff --git a/src/log4net/Util/TypeConverters/IPAddressConverter.cs b/src/log4net/Util/TypeConverters/IPAddressConverter.cs index 56e6b313..2c133a48 100644 --- a/src/log4net/Util/TypeConverters/IPAddressConverter.cs +++ b/src/log4net/Util/TypeConverters/IPAddressConverter.cs @@ -22,127 +22,127 @@ namespace log4net.Util.TypeConverters { - /// - /// Supports conversion from string to type. - /// - /// - /// - /// Supports conversion from string to type. - /// - /// - /// - /// - /// Nicko Cadell - internal class IPAddressConverter : IConvertFrom - { - #region Implementation of IConvertFrom + /// + /// Supports conversion from string to type. + /// + /// + /// + /// Supports conversion from string to type. + /// + /// + /// + /// + /// Nicko Cadell + internal class IPAddressConverter : IConvertFrom + { + #region Implementation of IConvertFrom - /// - /// Can the source type be converted to the type supported by this object - /// - /// the type to convert - /// true if the conversion is possible - /// - /// - /// Returns true if the is - /// the type. - /// - /// - public bool CanConvertFrom(Type sourceType) - { - return (sourceType == typeof(string)); - } + /// + /// Can the source type be converted to the type supported by this object + /// + /// the type to convert + /// true if the conversion is possible + /// + /// + /// Returns true if the is + /// the type. + /// + /// + public bool CanConvertFrom(Type sourceType) + { + return (sourceType == typeof(string)); + } - /// - /// Overrides the ConvertFrom method of IConvertFrom. - /// - /// the object to convert to an IPAddress - /// the IPAddress - /// - /// - /// Uses the method to convert the - /// argument to an . - /// If that fails then the string is resolved as a DNS hostname. - /// - /// - /// - /// The object cannot be converted to the - /// target type. To check for this condition use the - /// method. - /// - public object ConvertFrom(object source) - { - string str = source as string; - if (str != null && str.Length > 0) - { - try - { + /// + /// Overrides the ConvertFrom method of IConvertFrom. + /// + /// the object to convert to an IPAddress + /// the IPAddress + /// + /// + /// Uses the method to convert the + /// argument to an . + /// If that fails then the string is resolved as a DNS hostname. + /// + /// + /// + /// The object cannot be converted to the + /// target type. To check for this condition use the + /// method. + /// + public object ConvertFrom(object source) + { + string str = source as string; + if (str != null && str.Length > 0) + { + try + { #if NET_2_0 || NETCF_2_0 #if !NETCF_2_0 - // Try an explicit parse of string representation of an IPAddress (v4 or v6) - IPAddress result; - if (IPAddress.TryParse(str, out result)) - { - return result; - } + // Try an explicit parse of string representation of an IPAddress (v4 or v6) + IPAddress result; + if (IPAddress.TryParse(str, out result)) + { + return result; + } #endif - // Try to resolve via DNS. This is a blocking call. - // GetHostEntry works with either an IPAddress string or a host name - IPHostEntry host = Dns.GetHostEntry(str); - if (host != null && - host.AddressList != null && - host.AddressList.Length > 0 && - host.AddressList[0] != null) - { - return host.AddressList[0]; - } + // Try to resolve via DNS. This is a blocking call. + // GetHostEntry works with either an IPAddress string or a host name + IPHostEntry host = Dns.GetHostEntry(str); + if (host != null && + host.AddressList != null && + host.AddressList.Length > 0 && + host.AddressList[0] != null) + { + return host.AddressList[0]; + } #else - // Before .NET 2 we need to try to parse the IPAddress from the string first + // Before .NET 2 we need to try to parse the IPAddress from the string first - // Check if the string only contains IP address valid chars - if (str.Trim(validIpAddressChars).Length == 0) - { - try - { - // try to parse the string as an IP address - return IPAddress.Parse(str); - } - catch(FormatException) - { - // Ignore a FormatException, try to resolve via DNS - } - } + // Check if the string only contains IP address valid chars + if (str.Trim(validIpAddressChars).Length == 0) + { + try + { + // try to parse the string as an IP address + return IPAddress.Parse(str); + } + catch(FormatException) + { + // Ignore a FormatException, try to resolve via DNS + } + } - // Try to resolve via DNS. This is a blocking call. + // Try to resolve via DNS. This is a blocking call. #if NETSTANDARD - IPHostEntry host = Dns.GetHostEntryAsync(str).GetAwaiter().GetResult(); + IPHostEntry host = Dns.GetHostEntryAsync(str).GetAwaiter().GetResult(); #else - IPHostEntry host = Dns.GetHostByName(str); + IPHostEntry host = Dns.GetHostByName(str); #endif - if (host != null && - host.AddressList != null && - host.AddressList.Length > 0 && - host.AddressList[0] != null) - { - return host.AddressList[0]; - } + if (host != null && + host.AddressList != null && + host.AddressList.Length > 0 && + host.AddressList[0] != null) + { + return host.AddressList[0]; + } #endif - } - catch(Exception ex) - { - throw ConversionNotSupportedException.Create(typeof(IPAddress), source, ex); - } - } - throw ConversionNotSupportedException.Create(typeof(IPAddress), source); - } + } + catch(Exception ex) + { + throw ConversionNotSupportedException.Create(typeof(IPAddress), source, ex); + } + } + throw ConversionNotSupportedException.Create(typeof(IPAddress), source); + } - #endregion + #endregion - /// - /// Valid characters in an IPv4 or IPv6 address string. (Does not support subnets) - /// - private static readonly char[] validIpAddressChars = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','A','B','C','D','E','F','x','X','.',':','%'}; - } + /// + /// Valid characters in an IPv4 or IPv6 address string. (Does not support subnets) + /// + private static readonly char[] validIpAddressChars = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','A','B','C','D','E','F','x','X','.',':','%'}; + } } diff --git a/src/log4net/Util/TypeConverters/PatternLayoutConverter.cs b/src/log4net/Util/TypeConverters/PatternLayoutConverter.cs index c9942b2d..a3f594c7 100644 --- a/src/log4net/Util/TypeConverters/PatternLayoutConverter.cs +++ b/src/log4net/Util/TypeConverters/PatternLayoutConverter.cs @@ -24,69 +24,69 @@ namespace log4net.Util.TypeConverters { - /// - /// Supports conversion from string to type. - /// - /// - /// - /// Supports conversion from string to type. - /// - /// - /// The string is used as the - /// of the . - /// - /// - /// - /// - /// - /// Nicko Cadell - internal class PatternLayoutConverter : IConvertFrom - { - #region Implementation of IConvertFrom + /// + /// Supports conversion from string to type. + /// + /// + /// + /// Supports conversion from string to type. + /// + /// + /// The string is used as the + /// of the . + /// + /// + /// + /// + /// + /// Nicko Cadell + internal class PatternLayoutConverter : IConvertFrom + { + #region Implementation of IConvertFrom - /// - /// Can the source type be converted to the type supported by this object - /// - /// the type to convert - /// true if the conversion is possible - /// - /// - /// Returns true if the is - /// the type. - /// - /// - public bool CanConvertFrom(System.Type sourceType) - { - return (sourceType == typeof(string)); - } + /// + /// Can the source type be converted to the type supported by this object + /// + /// the type to convert + /// true if the conversion is possible + /// + /// + /// Returns true if the is + /// the type. + /// + /// + public bool CanConvertFrom(System.Type sourceType) + { + return (sourceType == typeof(string)); + } - /// - /// Overrides the ConvertFrom method of IConvertFrom. - /// - /// the object to convert to a PatternLayout - /// the PatternLayout - /// - /// - /// Creates and returns a new using - /// the as the - /// . - /// - /// - /// - /// The object cannot be converted to the - /// target type. To check for this condition use the - /// method. - /// - public object ConvertFrom(object source) - { - string str = source as string; - if (str != null) - { - return new PatternLayout(str); - } - throw ConversionNotSupportedException.Create(typeof(PatternLayout), source); - } + /// + /// Overrides the ConvertFrom method of IConvertFrom. + /// + /// the object to convert to a PatternLayout + /// the PatternLayout + /// + /// + /// Creates and returns a new using + /// the as the + /// . + /// + /// + /// + /// The object cannot be converted to the + /// target type. To check for this condition use the + /// method. + /// + public object ConvertFrom(object source) + { + string str = source as string; + if (str != null) + { + return new PatternLayout(str); + } + throw ConversionNotSupportedException.Create(typeof(PatternLayout), source); + } - #endregion - } + #endregion + } } diff --git a/src/log4net/Util/TypeConverters/PatternStringConverter.cs b/src/log4net/Util/TypeConverters/PatternStringConverter.cs index 82104d06..c414b636 100644 --- a/src/log4net/Util/TypeConverters/PatternStringConverter.cs +++ b/src/log4net/Util/TypeConverters/PatternStringConverter.cs @@ -21,117 +21,117 @@ namespace log4net.Util.TypeConverters { - /// - /// Convert between string and - /// - /// - /// - /// Supports conversion from string to type, - /// and from a type to a string. - /// - /// - /// The string is used as the - /// of the . - /// - /// - /// - /// - /// - /// Nicko Cadell - internal class PatternStringConverter : IConvertTo, IConvertFrom - { - #region Implementation of IConvertTo + /// + /// Convert between string and + /// + /// + /// + /// Supports conversion from string to type, + /// and from a type to a string. + /// + /// + /// The string is used as the + /// of the . + /// + /// + /// + /// + /// + /// Nicko Cadell + internal class PatternStringConverter : IConvertTo, IConvertFrom + { + #region Implementation of IConvertTo - /// - /// Can the target type be converted to the type supported by this object - /// - /// A that represents the type you want to convert to - /// true if the conversion is possible - /// - /// - /// Returns true if the is - /// assignable from a type. - /// - /// - public bool CanConvertTo(Type targetType) - { - return (typeof(string).IsAssignableFrom(targetType)); - } + /// + /// Can the target type be converted to the type supported by this object + /// + /// A that represents the type you want to convert to + /// true if the conversion is possible + /// + /// + /// Returns true if the is + /// assignable from a type. + /// + /// + public bool CanConvertTo(Type targetType) + { + return (typeof(string).IsAssignableFrom(targetType)); + } - /// - /// Converts the given value object to the specified type, using the arguments - /// - /// the object to convert - /// The Type to convert the value parameter to - /// the converted object - /// - /// - /// Uses the method to convert the - /// argument to a . - /// - /// - /// - /// The object cannot be converted to the - /// . To check for this condition use the - /// method. - /// - public object ConvertTo(object source, Type targetType) - { - PatternString patternString = source as PatternString; - if (patternString != null && CanConvertTo(targetType)) - { - return patternString.Format(); - } - throw ConversionNotSupportedException.Create(targetType, source); - } + /// + /// Converts the given value object to the specified type, using the arguments + /// + /// the object to convert + /// The Type to convert the value parameter to + /// the converted object + /// + /// + /// Uses the method to convert the + /// argument to a . + /// + /// + /// + /// The object cannot be converted to the + /// . To check for this condition use the + /// method. + /// + public object ConvertTo(object source, Type targetType) + { + PatternString patternString = source as PatternString; + if (patternString != null && CanConvertTo(targetType)) + { + return patternString.Format(); + } + throw ConversionNotSupportedException.Create(targetType, source); + } - #endregion + #endregion - #region Implementation of IConvertFrom + #region Implementation of IConvertFrom - /// - /// Can the source type be converted to the type supported by this object - /// - /// the type to convert - /// true if the conversion is possible - /// - /// - /// Returns true if the is - /// the type. - /// - /// - public bool CanConvertFrom(System.Type sourceType) - { - return (sourceType == typeof(string)); - } + /// + /// Can the source type be converted to the type supported by this object + /// + /// the type to convert + /// true if the conversion is possible + /// + /// + /// Returns true if the is + /// the type. + /// + /// + public bool CanConvertFrom(System.Type sourceType) + { + return (sourceType == typeof(string)); + } - /// - /// Overrides the ConvertFrom method of IConvertFrom. - /// - /// the object to convert to a PatternString - /// the PatternString - /// - /// - /// Creates and returns a new using - /// the as the - /// . - /// - /// - /// - /// The object cannot be converted to the - /// target type. To check for this condition use the - /// method. - /// - public object ConvertFrom(object source) - { - string str = source as string; - if (str != null) - { - return new PatternString(str); - } - throw ConversionNotSupportedException.Create(typeof(PatternString), source); - } + /// + /// Overrides the ConvertFrom method of IConvertFrom. + /// + /// the object to convert to a PatternString + /// the PatternString + /// + /// + /// Creates and returns a new using + /// the as the + /// . + /// + /// + /// + /// The object cannot be converted to the + /// target type. To check for this condition use the + /// method. + /// + public object ConvertFrom(object source) + { + string str = source as string; + if (str != null) + { + return new PatternString(str); + } + throw ConversionNotSupportedException.Create(typeof(PatternString), source); + } - #endregion - } + #endregion + } } diff --git a/src/log4net/Util/TypeConverters/TypeConverter.cs b/src/log4net/Util/TypeConverters/TypeConverter.cs index a4c7c5a0..606abf0c 100644 --- a/src/log4net/Util/TypeConverters/TypeConverter.cs +++ b/src/log4net/Util/TypeConverters/TypeConverter.cs @@ -24,70 +24,70 @@ namespace log4net.Util.TypeConverters { - /// - /// Supports conversion from string to type. - /// - /// - /// - /// Supports conversion from string to type. - /// - /// - /// - /// - /// - /// Nicko Cadell - internal class TypeConverter : IConvertFrom - { - #region Implementation of IConvertFrom + /// + /// Supports conversion from string to type. + /// + /// + /// + /// Supports conversion from string to type. + /// + /// + /// + /// + /// + /// Nicko Cadell + internal class TypeConverter : IConvertFrom + { + #region Implementation of IConvertFrom - /// - /// Can the source type be converted to the type supported by this object - /// - /// the type to convert - /// true if the conversion is possible - /// - /// - /// Returns true if the is - /// the type. - /// - /// - public bool CanConvertFrom(Type sourceType) - { - return (sourceType == typeof(string)); - } + /// + /// Can the source type be converted to the type supported by this object + /// + /// the type to convert + /// true if the conversion is possible + /// + /// + /// Returns true if the is + /// the type. + /// + /// + public bool CanConvertFrom(Type sourceType) + { + return (sourceType == typeof(string)); + } - /// - /// Overrides the ConvertFrom method of IConvertFrom. - /// - /// the object to convert to a Type - /// the Type - /// - /// - /// Uses the method to convert the - /// argument to a . - /// Additional effort is made to locate partially specified types - /// by searching the loaded assemblies. - /// - /// - /// - /// The object cannot be converted to the - /// target type. To check for this condition use the - /// method. - /// - public object ConvertFrom(object source) - { - string str = source as string; - if (str != null) - { + /// + /// Overrides the ConvertFrom method of IConvertFrom. + /// + /// the object to convert to a Type + /// the Type + /// + /// + /// Uses the method to convert the + /// argument to a . + /// Additional effort is made to locate partially specified types + /// by searching the loaded assemblies. + /// + /// + /// + /// The object cannot be converted to the + /// target type. To check for this condition use the + /// method. + /// + public object ConvertFrom(object source) + { + string str = source as string; + if (str != null) + { #if NETSTANDARD1_3 // TODO can we use ComponentModel here? - return SystemInfo.GetTypeFromString(GetType().GetTypeInfo().Assembly, str, true, true); + return SystemInfo.GetTypeFromString(GetType().GetTypeInfo().Assembly, str, true, true); #else - return SystemInfo.GetTypeFromString(str, true, true); + return SystemInfo.GetTypeFromString(str, true, true); #endif - } - throw ConversionNotSupportedException.Create(typeof(Type), source); - } + } + throw ConversionNotSupportedException.Create(typeof(Type), source); + } - #endregion - } + #endregion + } } diff --git a/src/log4net/Util/TypeConverters/TypeConverterAttribute.cs b/src/log4net/Util/TypeConverters/TypeConverterAttribute.cs index 196c5a81..d7f40fa0 100644 --- a/src/log4net/Util/TypeConverters/TypeConverterAttribute.cs +++ b/src/log4net/Util/TypeConverters/TypeConverterAttribute.cs @@ -21,96 +21,96 @@ namespace log4net.Util.TypeConverters { - /// - /// Attribute used to associate a type converter - /// - /// - /// - /// Class and Interface level attribute that specifies a type converter - /// to use with the associated type. - /// - /// - /// To associate a type converter with a target type apply a - /// TypeConverterAttribute to the target type. Specify the - /// type of the type converter on the attribute. - /// - /// - /// Nicko Cadell - /// Gert Driesen - [AttributeUsage(AttributeTargets.Class|AttributeTargets.Interface|AttributeTargets.Enum)] - public sealed class TypeConverterAttribute : Attribute - { - #region Member Variables + /// + /// Attribute used to associate a type converter + /// + /// + /// + /// Class and Interface level attribute that specifies a type converter + /// to use with the associated type. + /// + /// + /// To associate a type converter with a target type apply a + /// TypeConverterAttribute to the target type. Specify the + /// type of the type converter on the attribute. + /// + /// + /// Nicko Cadell + /// Gert Driesen + [AttributeUsage(AttributeTargets.Class|AttributeTargets.Interface|AttributeTargets.Enum)] + public sealed class TypeConverterAttribute : Attribute + { + #region Member Variables - /// - /// The string type name of the type converter - /// - private string m_typeName = null; + /// + /// The string type name of the type converter + /// + private string m_typeName = null; - #endregion + #endregion - #region Constructors + #region Constructors - /// - /// Default constructor - /// - /// - /// - /// Default constructor - /// - /// - public TypeConverterAttribute() - { - } + /// + /// Default constructor + /// + /// + /// + /// Default constructor + /// + /// + public TypeConverterAttribute() + { + } - /// - /// Create a new type converter attribute for the specified type name - /// - /// The string type name of the type converter - /// - /// - /// The type specified must implement the - /// or the interfaces. - /// - /// - public TypeConverterAttribute(string typeName) - { - m_typeName = typeName; - } + /// + /// Create a new type converter attribute for the specified type name + /// + /// The string type name of the type converter + /// + /// + /// The type specified must implement the + /// or the interfaces. + /// + /// + public TypeConverterAttribute(string typeName) + { + m_typeName = typeName; + } - /// - /// Create a new type converter attribute for the specified type - /// - /// The type of the type converter - /// - /// - /// The type specified must implement the - /// or the interfaces. - /// - /// - public TypeConverterAttribute(Type converterType) - { - m_typeName = log4net.Util.SystemInfo.AssemblyQualifiedName(converterType); - } + /// + /// Create a new type converter attribute for the specified type + /// + /// The type of the type converter + /// + /// + /// The type specified must implement the + /// or the interfaces. + /// + /// + public TypeConverterAttribute(Type converterType) + { + m_typeName = log4net.Util.SystemInfo.AssemblyQualifiedName(converterType); + } - #endregion + #endregion - /// - /// The string type name of the type converter - /// - /// - /// The string type name of the type converter - /// - /// - /// - /// The type specified must implement the - /// or the interfaces. - /// - /// - public string ConverterTypeName - { - get { return m_typeName; } - set { m_typeName = value ; } - } - } + /// + /// The string type name of the type converter + /// + /// + /// The string type name of the type converter + /// + /// + /// + /// The type specified must implement the + /// or the interfaces. + /// + /// + public string ConverterTypeName + { + get { return m_typeName; } + set { m_typeName = value ; } + } + } } diff --git a/src/log4net/Util/WindowsSecurityContext.cs b/src/log4net/Util/WindowsSecurityContext.cs index 6fac8ccb..d58f47f4 100644 --- a/src/log4net/Util/WindowsSecurityContext.cs +++ b/src/log4net/Util/WindowsSecurityContext.cs @@ -36,349 +36,349 @@ namespace log4net.Util { - /// - /// Impersonate a Windows Account - /// - /// - /// - /// This impersonates a Windows account. - /// - /// - /// How the impersonation is done depends on the value of . - /// This allows the context to either impersonate a set of user credentials specified - /// using username, domain name and password or to revert to the process credentials. - /// - /// - public class WindowsSecurityContext : SecurityContext, IOptionHandler - { - /// - /// The impersonation modes for the - /// - /// - /// - /// See the property for - /// details. - /// - /// - public enum ImpersonationMode - { - /// - /// Impersonate a user using the credentials supplied - /// - User, - - /// - /// Revert this the thread to the credentials of the process - /// - Process - } - - #region Member Variables - - private ImpersonationMode m_impersonationMode = ImpersonationMode.User; - private string m_userName; - private string m_domainName = Environment.MachineName; - private string m_password; - private WindowsIdentity m_identity; - - #endregion - - #region Constructor - - /// - /// Default constructor - /// - /// - /// - /// Default constructor - /// - /// - public WindowsSecurityContext() - { - } - - #endregion - - #region Public Properties - - /// - /// Gets or sets the impersonation mode for this security context - /// - /// - /// The impersonation mode for this security context - /// - /// - /// - /// Impersonate either a user with user credentials or - /// revert this thread to the credentials of the process. - /// The value is one of the - /// enum. - /// - /// - /// The default value is - /// - /// - /// When the mode is set to - /// the user's credentials are established using the - /// , and - /// values. - /// - /// - /// When the mode is set to - /// no other properties need to be set. If the calling thread is - /// impersonating then it will be reverted back to the process credentials. - /// - /// - public ImpersonationMode Credentials - { - get { return m_impersonationMode; } - set { m_impersonationMode = value; } - } - - /// - /// Gets or sets the Windows username for this security context - /// - /// - /// The Windows username for this security context - /// - /// - /// - /// This property must be set if - /// is set to (the default setting). - /// - /// - public string UserName - { - get { return m_userName; } - set { m_userName = value; } - } - - /// - /// Gets or sets the Windows domain name for this security context - /// - /// - /// The Windows domain name for this security context - /// - /// - /// - /// The default value for is the local machine name - /// taken from the property. - /// - /// - /// This property must be set if - /// is set to (the default setting). - /// - /// - public string DomainName - { - get { return m_domainName; } - set { m_domainName = value; } - } - - /// - /// Sets the password for the Windows account specified by the and properties. - /// - /// - /// The password for the Windows account specified by the and properties. - /// - /// - /// - /// This property must be set if - /// is set to (the default setting). - /// - /// - public string Password - { - set { m_password = value; } - } - - #endregion - - #region IOptionHandler Members - - /// - /// Initialize the SecurityContext based on the options set. - /// - /// - /// - /// This is part of the delayed object - /// activation scheme. The method must - /// be called on this object after the configuration properties have - /// been set. Until is called this - /// object is in an undefined state and must not be used. - /// - /// - /// If any of the configuration properties are modified then - /// must be called again. - /// - /// - /// The security context will try to Logon the specified user account and - /// capture a primary token for impersonation. - /// - /// - /// The required , - /// or properties were not specified. - public void ActivateOptions() - { - if (m_impersonationMode == ImpersonationMode.User) - { - if (m_userName == null) throw new ArgumentNullException("m_userName"); - if (m_domainName == null) throw new ArgumentNullException("m_domainName"); - if (m_password == null) throw new ArgumentNullException("m_password"); - - m_identity = LogonUser(m_userName, m_domainName, m_password); - } - } - - #endregion - - /// - /// Impersonate the Windows account specified by the and properties. - /// - /// caller provided state - /// - /// An instance that will revoke the impersonation of this SecurityContext - /// - /// - /// - /// Depending on the property either - /// impersonate a user using credentials supplied or revert - /// to the process credentials. - /// - /// - public override IDisposable Impersonate(object state) - { - if (m_impersonationMode == ImpersonationMode.User) - { - if (m_identity != null) - { - return new DisposableImpersonationContext(m_identity.Impersonate()); - } - } - else if (m_impersonationMode == ImpersonationMode.Process) - { - // Impersonate(0) will revert to the process credentials - return new DisposableImpersonationContext(WindowsIdentity.Impersonate(IntPtr.Zero)); - } - return null; - } - - /// - /// Create a given the userName, domainName and password. - /// - /// the user name - /// the domain name - /// the password - /// the for the account specified - /// - /// - /// Uses the Windows API call LogonUser to get a principal token for the account. This - /// token is used to initialize the WindowsIdentity. - /// - /// + /// + /// Impersonate a Windows Account + /// + /// + /// + /// This impersonates a Windows account. + /// + /// + /// How the impersonation is done depends on the value of . + /// This allows the context to either impersonate a set of user credentials specified + /// using username, domain name and password or to revert to the process credentials. + /// + /// + public class WindowsSecurityContext : SecurityContext, IOptionHandler + { + /// + /// The impersonation modes for the + /// + /// + /// + /// See the property for + /// details. + /// + /// + public enum ImpersonationMode + { + /// + /// Impersonate a user using the credentials supplied + /// + User, + + /// + /// Revert this the thread to the credentials of the process + /// + Process + } + + #region Member Variables + + private ImpersonationMode m_impersonationMode = ImpersonationMode.User; + private string m_userName; + private string m_domainName = Environment.MachineName; + private string m_password; + private WindowsIdentity m_identity; + + #endregion + + #region Constructor + + /// + /// Default constructor + /// + /// + /// + /// Default constructor + /// + /// + public WindowsSecurityContext() + { + } + + #endregion + + #region Public Properties + + /// + /// Gets or sets the impersonation mode for this security context + /// + /// + /// The impersonation mode for this security context + /// + /// + /// + /// Impersonate either a user with user credentials or + /// revert this thread to the credentials of the process. + /// The value is one of the + /// enum. + /// + /// + /// The default value is + /// + /// + /// When the mode is set to + /// the user's credentials are established using the + /// , and + /// values. + /// + /// + /// When the mode is set to + /// no other properties need to be set. If the calling thread is + /// impersonating then it will be reverted back to the process credentials. + /// + /// + public ImpersonationMode Credentials + { + get { return m_impersonationMode; } + set { m_impersonationMode = value; } + } + + /// + /// Gets or sets the Windows username for this security context + /// + /// + /// The Windows username for this security context + /// + /// + /// + /// This property must be set if + /// is set to (the default setting). + /// + /// + public string UserName + { + get { return m_userName; } + set { m_userName = value; } + } + + /// + /// Gets or sets the Windows domain name for this security context + /// + /// + /// The Windows domain name for this security context + /// + /// + /// + /// The default value for is the local machine name + /// taken from the property. + /// + /// + /// This property must be set if + /// is set to (the default setting). + /// + /// + public string DomainName + { + get { return m_domainName; } + set { m_domainName = value; } + } + + /// + /// Sets the password for the Windows account specified by the and properties. + /// + /// + /// The password for the Windows account specified by the and properties. + /// + /// + /// + /// This property must be set if + /// is set to (the default setting). + /// + /// + public string Password + { + set { m_password = value; } + } + + #endregion + + #region IOptionHandler Members + + /// + /// Initialize the SecurityContext based on the options set. + /// + /// + /// + /// This is part of the delayed object + /// activation scheme. The method must + /// be called on this object after the configuration properties have + /// been set. Until is called this + /// object is in an undefined state and must not be used. + /// + /// + /// If any of the configuration properties are modified then + /// must be called again. + /// + /// + /// The security context will try to Logon the specified user account and + /// capture a primary token for impersonation. + /// + /// + /// The required , + /// or properties were not specified. + public void ActivateOptions() + { + if (m_impersonationMode == ImpersonationMode.User) + { + if (m_userName == null) throw new ArgumentNullException("m_userName"); + if (m_domainName == null) throw new ArgumentNullException("m_domainName"); + if (m_password == null) throw new ArgumentNullException("m_password"); + + m_identity = LogonUser(m_userName, m_domainName, m_password); + } + } + + #endregion + + /// + /// Impersonate the Windows account specified by the and properties. + /// + /// caller provided state + /// + /// An instance that will revoke the impersonation of this SecurityContext + /// + /// + /// + /// Depending on the property either + /// impersonate a user using credentials supplied or revert + /// to the process credentials. + /// + /// + public override IDisposable Impersonate(object state) + { + if (m_impersonationMode == ImpersonationMode.User) + { + if (m_identity != null) + { + return new DisposableImpersonationContext(m_identity.Impersonate()); + } + } + else if (m_impersonationMode == ImpersonationMode.Process) + { + // Impersonate(0) will revert to the process credentials + return new DisposableImpersonationContext(WindowsIdentity.Impersonate(IntPtr.Zero)); + } + return null; + } + + /// + /// Create a given the userName, domainName and password. + /// + /// the user name + /// the domain name + /// the password + /// the for the account specified + /// + /// + /// Uses the Windows API call LogonUser to get a principal token for the account. This + /// token is used to initialize the WindowsIdentity. + /// + /// #if NET_4_0 || MONO_4_0 [System.Security.SecuritySafeCritical] #endif [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, UnmanagedCode = true)] private static WindowsIdentity LogonUser(string userName, string domainName, string password) - { - const int LOGON32_PROVIDER_DEFAULT = 0; - //This parameter causes LogonUser to create a primary token. - const int LOGON32_LOGON_INTERACTIVE = 2; - - // Call LogonUser to obtain a handle to an access token. - IntPtr tokenHandle = IntPtr.Zero; - if(!LogonUser(userName, domainName, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref tokenHandle)) - { - NativeError error = NativeError.GetLastError(); - throw new Exception("Failed to LogonUser ["+userName+"] in Domain ["+domainName+"]. Error: "+ error.ToString()); - } - - const int SecurityImpersonation = 2; - IntPtr dupeTokenHandle = IntPtr.Zero; - if(!DuplicateToken(tokenHandle, SecurityImpersonation, ref dupeTokenHandle)) - { - NativeError error = NativeError.GetLastError(); - if (tokenHandle != IntPtr.Zero) - { - CloseHandle(tokenHandle); - } - throw new Exception("Failed to DuplicateToken after LogonUser. Error: " + error.ToString()); - } - - WindowsIdentity identity = new WindowsIdentity(dupeTokenHandle); - - // Free the tokens. - if (dupeTokenHandle != IntPtr.Zero) - { - CloseHandle(dupeTokenHandle); - } - if (tokenHandle != IntPtr.Zero) - { - CloseHandle(tokenHandle); - } - - return identity; - } - - #region Native Method Stubs - - [DllImport("advapi32.dll", SetLastError=true)] - private static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken); - - [DllImport("kernel32.dll", CharSet=CharSet.Auto)] - private static extern bool CloseHandle(IntPtr handle); - - [DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)] - private static extern bool DuplicateToken(IntPtr ExistingTokenHandle, int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle); - - #endregion - - #region DisposableImpersonationContext class - - /// - /// Adds to - /// - /// - /// - /// Helper class to expose the - /// through the interface. - /// - /// - private sealed class DisposableImpersonationContext : IDisposable - { - private readonly WindowsImpersonationContext m_impersonationContext; - - /// - /// Constructor - /// - /// the impersonation context being wrapped - /// - /// - /// Constructor - /// - /// - public DisposableImpersonationContext(WindowsImpersonationContext impersonationContext) - { - m_impersonationContext = impersonationContext; - } - - /// - /// Revert the impersonation - /// - /// - /// - /// Revert the impersonation - /// - /// - public void Dispose() - { - m_impersonationContext.Undo(); - } - } - - #endregion - } + { + const int LOGON32_PROVIDER_DEFAULT = 0; + //This parameter causes LogonUser to create a primary token. + const int LOGON32_LOGON_INTERACTIVE = 2; + + // Call LogonUser to obtain a handle to an access token. + IntPtr tokenHandle = IntPtr.Zero; + if(!LogonUser(userName, domainName, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref tokenHandle)) + { + NativeError error = NativeError.GetLastError(); + throw new Exception("Failed to LogonUser ["+userName+"] in Domain ["+domainName+"]. Error: "+ error.ToString()); + } + + const int SecurityImpersonation = 2; + IntPtr dupeTokenHandle = IntPtr.Zero; + if(!DuplicateToken(tokenHandle, SecurityImpersonation, ref dupeTokenHandle)) + { + NativeError error = NativeError.GetLastError(); + if (tokenHandle != IntPtr.Zero) + { + CloseHandle(tokenHandle); + } + throw new Exception("Failed to DuplicateToken after LogonUser. Error: " + error.ToString()); + } + + WindowsIdentity identity = new WindowsIdentity(dupeTokenHandle); + + // Free the tokens. + if (dupeTokenHandle != IntPtr.Zero) + { + CloseHandle(dupeTokenHandle); + } + if (tokenHandle != IntPtr.Zero) + { + CloseHandle(tokenHandle); + } + + return identity; + } + + #region Native Method Stubs + + [DllImport("advapi32.dll", SetLastError=true)] + private static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken); + + [DllImport("kernel32.dll", CharSet=CharSet.Auto)] + private static extern bool CloseHandle(IntPtr handle); + + [DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)] + private static extern bool DuplicateToken(IntPtr ExistingTokenHandle, int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle); + + #endregion + + #region DisposableImpersonationContext class + + /// + /// Adds to + /// + /// + /// + /// Helper class to expose the + /// through the interface. + /// + /// + private sealed class DisposableImpersonationContext : IDisposable + { + private readonly WindowsImpersonationContext m_impersonationContext; + + /// + /// Constructor + /// + /// the impersonation context being wrapped + /// + /// + /// Constructor + /// + /// + public DisposableImpersonationContext(WindowsImpersonationContext impersonationContext) + { + m_impersonationContext = impersonationContext; + } + + /// + /// Revert the impersonation + /// + /// + /// + /// Revert the impersonation + /// + /// + public void Dispose() + { + m_impersonationContext.Undo(); + } + } + + #endregion + } } #endif // !CLI_1_0 From 223a9abf2c175ec0811f6493ea977019af49d199 Mon Sep 17 00:00:00 2001 From: Jan Friedrich Date: Tue, 5 Mar 2024 09:03:17 +0100 Subject: [PATCH 4/6] format documents #111 --- .../Appender/AnsiColorTerminalAppender.cs | 60 +- src/log4net/Appender/AppenderCollection.cs | 84 +- src/log4net/Appender/AppenderSkeleton.cs | 128 +- src/log4net/Appender/AspNetTraceAppender.cs | 72 +- .../Appender/BufferingAppenderSkeleton.cs | 52 +- .../Appender/BufferingForwardingAppender.cs | 34 +- .../Appender/ColoredConsoleAppender.cs | 72 +- src/log4net/Appender/ConsoleAppender.cs | 10 +- src/log4net/Appender/DebugAppender.cs | 116 +- src/log4net/Appender/EventLogAppender.cs | 338 +- src/log4net/Appender/FileAppender.cs | 2774 ++++++++-------- src/log4net/Appender/ForwardingAppender.cs | 44 +- src/log4net/Appender/IFlushable.cs | 66 +- src/log4net/Appender/LocalSyslogAppender.cs | 46 +- .../Appender/ManagedColoredConsoleAppender.cs | 46 +- src/log4net/Appender/MemoryAppender.cs | 68 +- src/log4net/Appender/NetSendAppender.cs | 32 +- .../Appender/OutputDebugStringAppender.cs | 4 +- src/log4net/Appender/RemotingAppender.cs | 10 +- src/log4net/Appender/RollingFileAppender.cs | 597 ++-- src/log4net/Appender/SmtpAppender.cs | 39 +- src/log4net/Appender/SmtpPickupDirAppender.cs | 34 +- src/log4net/Appender/TelnetAppender.cs | 72 +- src/log4net/Appender/TextWriterAppender.cs | 146 +- src/log4net/Appender/TraceAppender.cs | 84 +- src/log4net/Appender/UdpAppender.cs | 94 +- src/log4net/AssemblyInfo.cs | 4 +- src/log4net/Config/AliasDomainAttribute.cs | 2 +- .../Config/AliasRepositoryAttribute.cs | 4 +- src/log4net/Config/BasicConfigurator.cs | 220 +- src/log4net/Config/DOMConfigurator.cs | 12 +- src/log4net/Config/PluginAttribute.cs | 6 +- src/log4net/Config/RepositoryAttribute.cs | 4 +- .../SecurityContextProviderAttribute.cs | 26 +- src/log4net/Config/XmlConfigurator.cs | 24 +- .../Config/XmlConfiguratorAttribute.cs | 90 +- src/log4net/Core/CompactRepositorySelector.cs | 44 +- src/log4net/Core/DefaultRepositorySelector.cs | 140 +- src/log4net/Core/FixFlags.cs | 170 +- src/log4net/Core/IAppenderAttachable.cs | 4 +- src/log4net/Core/ILogger.cs | 2 +- src/log4net/Core/Level.cs | 36 +- src/log4net/Core/LevelCollection.cs | 86 +- src/log4net/Core/LevelEvaluator.cs | 6 +- src/log4net/Core/LevelMap.cs | 10 +- src/log4net/Core/LocationInfo.cs | 38 +- src/log4net/Core/LogException.cs | 10 +- src/log4net/Core/LogImpl.cs | 78 +- src/log4net/Core/LoggerManager.cs | 64 +- src/log4net/Core/LoggerWrapperImpl.cs | 6 +- src/log4net/Core/LoggingEvent.cs | 2892 ++++++++--------- src/log4net/Core/MethodItem.cs | 10 +- src/log4net/Core/StackFrameItem.cs | 262 +- src/log4net/Core/TimeEvaluator.cs | 210 +- src/log4net/Core/WrapperMap.cs | 12 +- .../AbsoluteTimeDateFormatter.cs | 110 +- .../DateFormatter/DateTimeDateFormatter.cs | 6 +- .../DateFormatter/Iso8601DateFormatter.cs | 2 +- src/log4net/Filter/DenyAllFilter.cs | 2 +- src/log4net/Filter/FilterDecision.cs | 2 +- src/log4net/Filter/FilterSkeleton.cs | 2 +- src/log4net/Filter/LevelMatchFilter.cs | 4 +- src/log4net/Filter/LevelRangeFilter.cs | 14 +- src/log4net/Filter/LoggerMatchFilter.cs | 8 +- src/log4net/Filter/PropertyFilter.cs | 18 +- src/log4net/Filter/StringMatchFilter.cs | 20 +- src/log4net/ILog.cs | 42 +- src/log4net/Layout/DynamicPatternLayout.cs | 6 +- src/log4net/Layout/ExceptionLayout.cs | 6 +- src/log4net/Layout/LayoutSkeleton.cs | 4 +- .../Pattern/AppDomainPatternConverter.cs | 2 +- .../Pattern/AspNetRequestPatternConverter.cs | 21 +- .../Layout/Pattern/DatePatternConverter.cs | 34 +- .../Pattern/ExceptionPatternConverter.cs | 4 +- .../Pattern/FileLocationPatternConverter.cs | 2 +- .../Pattern/FullLocationPatternConverter.cs | 4 +- .../Pattern/IdentityPatternConverter.cs | 2 +- .../Layout/Pattern/LevelPatternConverter.cs | 4 +- .../Pattern/LineLocationPatternConverter.cs | 2 +- .../Layout/Pattern/LoggerPatternConverter.cs | 4 +- .../Layout/Pattern/MessagePatternConverter.cs | 2 +- .../Pattern/MethodLocationPatternConverter.cs | 2 +- .../Layout/Pattern/NamedPatternConverter.cs | 72 +- .../Layout/Pattern/NdcPatternConverter.cs | 2 +- .../Layout/Pattern/PatternLayoutConverter.cs | 10 +- .../Pattern/PropertyPatternConverter.cs | 2 +- .../Pattern/RelativeTimePatternConverter.cs | 4 +- .../StackTraceDetailPatternConverter.cs | 100 +- .../Pattern/StackTracePatternConverter.cs | 58 +- .../Layout/Pattern/ThreadPatternConverter.cs | 2 +- .../Pattern/TypeNamePatternConverter.cs | 8 +- .../Pattern/UserNamePatternConverter.cs | 4 +- .../Layout/Pattern/UtcDatePatternConverter.cs | 24 +- src/log4net/Layout/PatternLayout.cs | 188 +- src/log4net/Layout/RawLayoutConverter.cs | 6 +- src/log4net/Layout/RawPropertyLayout.cs | 2 +- src/log4net/Layout/RawTimeStampLayout.cs | 2 +- src/log4net/Layout/RawUtcTimeStampLayout.cs | 2 +- src/log4net/Layout/SimpleLayout.cs | 6 +- src/log4net/Layout/XmlLayout.cs | 74 +- src/log4net/Layout/XmlLayoutBase.cs | 12 +- src/log4net/Layout/XmlLayoutSchemaLog4j.cs | 74 +- src/log4net/LogManager.cs | 100 +- src/log4net/NDC.cs | 16 +- src/log4net/ObjectRenderer/DefaultRenderer.cs | 12 +- src/log4net/ObjectRenderer/RendererMap.cs | 40 +- src/log4net/Plugin/PluginCollection.cs | 86 +- src/log4net/Plugin/PluginMap.cs | 10 +- src/log4net/Plugin/PluginSkeleton.cs | 8 +- .../Plugin/RemoteLoggingServerPlugin.cs | 38 +- .../ConfigurationChangedEventArgs.cs | 36 +- .../Hierarchy/DefaultLoggerFactory.cs | 2 +- src/log4net/Repository/Hierarchy/Hierarchy.cs | 219 +- src/log4net/Repository/Hierarchy/Logger.cs | 78 +- src/log4net/Repository/Hierarchy/LoggerKey.cs | 16 +- .../Repository/Hierarchy/RootLogger.cs | 28 +- .../Hierarchy/XmlHierarchyConfigurator.cs | 342 +- .../IBasicRepositoryConfigurator.cs | 24 +- src/log4net/Repository/ILoggerRepository.cs | 14 +- .../Repository/LoggerRepositorySkeleton.cs | 176 +- src/log4net/Util/AppenderAttachedImpl.cs | 84 +- src/log4net/Util/CompositeProperties.cs | 8 +- src/log4net/Util/ConverterInfo.cs | 114 +- src/log4net/Util/CountingQuietTextWriter.cs | 34 +- src/log4net/Util/CyclicBuffer.cs | 54 +- src/log4net/Util/EmptyCollection.cs | 6 +- src/log4net/Util/EmptyDictionary.cs | 8 +- src/log4net/Util/FormattingInfo.cs | 4 +- src/log4net/Util/GlobalContextProperties.cs | 10 +- src/log4net/Util/LevelMapping.cs | 10 +- src/log4net/Util/LevelMappingEntry.cs | 4 +- src/log4net/Util/LogLog.cs | 492 +-- .../Util/LogicalThreadContextProperties.cs | 52 +- src/log4net/Util/LogicalThreadContextStack.cs | 18 +- src/log4net/Util/NativeError.cs | 58 +- src/log4net/Util/NullDictionaryEnumerator.cs | 28 +- src/log4net/Util/NullEnumerator.cs | 14 +- src/log4net/Util/OnlyOnceErrorHandler.cs | 112 +- src/log4net/Util/OptionConverter.cs | 178 +- src/log4net/Util/PatternConverter.cs | 94 +- src/log4net/Util/PatternParser.cs | 56 +- src/log4net/Util/PatternString.cs | 52 +- .../AppDomainPatternConverter.cs | 6 +- .../AppSettingPatternConverter.cs | 134 +- .../DatePatternConverter.cs | 38 +- .../EnvironmentFolderPathPatternConverter.cs | 112 +- .../EnvironmentPatternConverter.cs | 48 +- .../IdentityPatternConverter.cs | 32 +- .../LiteralPatternConverter.cs | 6 +- .../ProcessIdPatternConverter.cs | 30 +- .../PropertyPatternConverter.cs | 4 +- .../RandomStringPatternConverter.cs | 34 +- .../UserNamePatternConverter.cs | 30 +- .../UtcDatePatternConverter.cs | 24 +- src/log4net/Util/PropertiesDictionary.cs | 2 +- src/log4net/Util/PropertyEntry.cs | 92 +- src/log4net/Util/QuietTextWriter.cs | 30 +- .../Util/ReadOnlyPropertiesDictionary.cs | 15 +- src/log4net/Util/ReaderWriterLock.cs | 2 +- src/log4net/Util/ReusableStringWriter.cs | 8 +- src/log4net/Util/SystemStringFormat.cs | 28 +- src/log4net/Util/TextWriterAdapter.cs | 26 +- src/log4net/Util/ThreadContextProperties.cs | 2 +- src/log4net/Util/ThreadContextStack.cs | 28 +- src/log4net/Util/ThreadContextStacks.cs | 24 +- src/log4net/Util/Transform.cs | 24 +- .../Util/TypeConverters/BooleanConverter.cs | 10 +- .../ConversionNotSupportedException.cs | 14 +- .../Util/TypeConverters/ConverterRegistry.cs | 32 +- .../Util/TypeConverters/EncodingConverter.cs | 8 +- .../Util/TypeConverters/IPAddressConverter.cs | 16 +- .../TypeConverters/PatternLayoutConverter.cs | 2 +- .../TypeConverters/PatternStringConverter.cs | 2 +- .../Util/TypeConverters/TypeConverter.cs | 6 +- .../TypeConverters/TypeConverterAttribute.cs | 4 +- src/log4net/Util/WindowsSecurityContext.cs | 18 +- 176 files changed, 7109 insertions(+), 7092 deletions(-) diff --git a/src/log4net/Appender/AnsiColorTerminalAppender.cs b/src/log4net/Appender/AnsiColorTerminalAppender.cs index 1331833a..da8cc088 100644 --- a/src/log4net/Appender/AnsiColorTerminalAppender.cs +++ b/src/log4net/Appender/AnsiColorTerminalAppender.cs @@ -121,16 +121,16 @@ public enum AnsiAttributes : int /// /// text is bright /// - Bright = 1, + Bright = 1, /// /// text is dim /// - Dim = 2, + Dim = 2, /// /// text is underlined /// - Underscore = 4, + Underscore = 4, /// /// text is blinking @@ -138,27 +138,27 @@ public enum AnsiAttributes : int /// /// Not all terminals support this attribute /// - Blink = 8, + Blink = 8, /// /// text and background colors are reversed /// - Reverse = 16, + Reverse = 16, /// /// text is hidden /// - Hidden = 32, + Hidden = 32, /// /// text is displayed with a strikethrough /// - Strikethrough = 64, + Strikethrough = 64, /// /// text color is light /// - Light = 128 + Light = 128 } /// @@ -176,42 +176,42 @@ public enum AnsiColor : int /// /// color is black /// - Black = 0, + Black = 0, /// /// color is red /// - Red = 1, + Red = 1, /// /// color is green /// - Green = 2, + Green = 2, /// /// color is yellow /// - Yellow = 3, + Yellow = 3, /// /// color is blue /// - Blue = 4, + Blue = 4, /// /// color is magenta /// - Magenta = 5, + Magenta = 5, /// /// color is cyan /// - Cyan = 6, + Cyan = 6, /// /// color is white /// - White = 7 + White = 7 } #endregion @@ -225,7 +225,7 @@ public enum AnsiColor : int /// The instance of the class is set up to write /// to the standard output stream. /// - public AnsiColorTerminalAppender() + public AnsiColorTerminalAppender() { } @@ -256,8 +256,8 @@ public virtual string Target if (SystemInfo.EqualsIgnoringCase(ConsoleError, trimmedTargetName)) { m_writeToErrorStream = true; - } - else + } + else { m_writeToErrorStream = false; } @@ -296,7 +296,7 @@ public void AddMapping(LevelColors mapping) /// The format of the output will depend on the appender's layout. /// /// - protected override void Append(log4net.Core.LoggingEvent loggingEvent) + protected override void Append(log4net.Core.LoggingEvent loggingEvent) { string loggingMessage = RenderLoggingEvent(loggingEvent); @@ -314,26 +314,26 @@ protected override void Append(log4net.Core.LoggingEvent loggingEvent) // are inserted afterwards. if (loggingMessage.Length > 1) { - if (loggingMessage.EndsWith("\r\n") || loggingMessage.EndsWith("\n\r")) + if (loggingMessage.EndsWith("\r\n") || loggingMessage.EndsWith("\n\r")) { loggingMessage = loggingMessage.Insert(loggingMessage.Length - 2, PostEventCodes); - } - else if (loggingMessage.EndsWith("\n") || loggingMessage.EndsWith("\r")) + } + else if (loggingMessage.EndsWith("\n") || loggingMessage.EndsWith("\r")) { loggingMessage = loggingMessage.Insert(loggingMessage.Length - 1, PostEventCodes); - } - else + } + else { loggingMessage = loggingMessage + PostEventCodes; } } else { - if (loggingMessage[0] == '\n' || loggingMessage[0] == '\r') + if (loggingMessage[0] == '\n' || loggingMessage[0] == '\r') { loggingMessage = PostEventCodes + loggingMessage; - } - else + } + else { loggingMessage = loggingMessage + PostEventCodes; } @@ -354,7 +354,7 @@ protected override void Append(log4net.Core.LoggingEvent loggingEvent) Console.Write(loggingMessage); } #endif - + } /// @@ -516,7 +516,7 @@ public override void ActivateOptions() buf.Append("\x1b[0;"); int lightAdjustment = ((m_attributes & AnsiAttributes.Light) > 0) ? 60 : 0; - + // set the foreground color buf.Append(30 + lightAdjustment + (int)m_foreColor); buf.Append(';'); diff --git a/src/log4net/Appender/AppenderCollection.cs b/src/log4net/Appender/AppenderCollection.cs index 97286610..768f3184 100644 --- a/src/log4net/Appender/AppenderCollection.cs +++ b/src/log4net/Appender/AppenderCollection.cs @@ -71,7 +71,7 @@ public interface IAppenderCollectionEnumerator private int m_version = 0; #endregion - + #region Static Wrappers /// @@ -83,7 +83,7 @@ public interface IAppenderCollectionEnumerator /// public static AppenderCollection ReadOnly(AppenderCollection list) { - if(list==null) throw new ArgumentNullException("list"); + if (list == null) throw new ArgumentNullException("list"); return new ReadOnlyAppenderCollection(list); } @@ -109,7 +109,7 @@ public AppenderCollection() { m_array = new IAppender[DEFAULT_CAPACITY]; } - + /// /// Initializes a new instance of the AppenderCollection class /// that has the specified initial capacity. @@ -143,7 +143,7 @@ public AppenderCollection(IAppender[] a) m_array = new IAppender[a.Length]; AddRange(a); } - + /// /// Initializes a new instance of the AppenderCollection class /// that contains elements copied from the specified collection. @@ -160,7 +160,7 @@ public AppenderCollection(ICollection col) /// Used to access protected constructor /// /// - protected internal enum Tag + protected internal enum Tag { /// /// A value @@ -179,7 +179,7 @@ protected internal AppenderCollection(Tag tag) } #endregion - + #region Operations (type-safe ICollection) /// @@ -212,8 +212,8 @@ public virtual void CopyTo(IAppender[] array, int start) { throw new System.ArgumentException("Destination array was not long enough."); } - - Array.Copy(m_array, 0, array, start, m_count); + + Array.Copy(m_array, 0, array, start, m_count); } /// @@ -234,7 +234,7 @@ public virtual object SyncRoot } #endregion - + #region Operations (type-safe IList) /// @@ -251,13 +251,13 @@ public virtual IAppender this[int index] get { ValidateIndex(index); // throws - return m_array[index]; + return m_array[index]; } set { ValidateIndex(index); // throws - ++m_version; - m_array[index] = value; + ++m_version; + m_array[index] = value; } } @@ -278,7 +278,7 @@ public virtual int Add(IAppender item) return m_count++; } - + /// /// Removes all elements from the AppenderCollection. /// @@ -288,7 +288,7 @@ public virtual void Clear() m_array = new IAppender[DEFAULT_CAPACITY]; m_count = 0; } - + /// /// Creates a shallow copy of the . /// @@ -310,7 +310,7 @@ public virtual object Clone() /// true if is found in the AppenderCollection; otherwise, false. public virtual bool Contains(IAppender item) { - for (int i=0; i != m_count; ++i) + for (int i = 0; i != m_count; ++i) { if (m_array[i].Equals(item)) { @@ -331,7 +331,7 @@ public virtual bool Contains(IAppender item) /// public virtual int IndexOf(IAppender item) { - for (int i=0; i != m_count; ++i) + for (int i = 0; i != m_count; ++i) { if (m_array[i].Equals(item)) { @@ -354,7 +354,7 @@ public virtual int IndexOf(IAppender item) public virtual void Insert(int index, IAppender item) { ValidateIndex(index, true); // throws - + if (m_count == m_array.Length) { EnsureCapacity(m_count + 1); @@ -378,13 +378,13 @@ public virtual void Insert(int index, IAppender item) /// The specified was not found in the AppenderCollection. /// public virtual void Remove(IAppender item) - { + { int i = IndexOf(item); if (i < 0) { throw new System.ArgumentException("Cannot remove the specified item because it was not found in the specified Collection."); } - + ++m_version; RemoveAt(i); } @@ -401,14 +401,14 @@ public virtual void Remove(IAppender item) public virtual void RemoveAt(int index) { ValidateIndex(index); // throws - + m_count--; if (index < m_count) { Array.Copy(m_array, index + 1, m_array, index, m_count - index); } - + // We can't set the deleted entry equal to null, because it might be a value type. // Instead, we'll create an empty single-element array of the right type and copy it // over the entry we want to erase. @@ -438,7 +438,7 @@ public virtual bool IsReadOnly #endregion #region Operations (type-safe IEnumerable) - + /// /// Returns an enumerator that can iterate through the AppenderCollection. /// @@ -451,15 +451,15 @@ public virtual IAppenderCollectionEnumerator GetEnumerator() #endregion #region Public helpers (just to mimic some nice features of ArrayList) - + /// /// Gets or sets the number of elements the AppenderCollection can contain. /// public virtual int Capacity { - get - { - return m_array.Length; + get + { + return m_array.Length; } set { @@ -495,7 +495,7 @@ public virtual int AddRange(AppenderCollection x) { EnsureCapacity(m_count + x.Count); } - + Array.Copy(x.m_array, 0, m_array, m_count, x.Count); m_count += x.Count; m_version++; @@ -521,7 +521,7 @@ public virtual int AddRange(IAppender[] x) return m_count; } - + /// /// Adds the elements of a collection to the current AppenderCollection. /// @@ -534,7 +534,7 @@ public virtual int AddRange(ICollection col) EnsureCapacity(m_count + col.Count); } - foreach(object item in col) + foreach (object item in col) { Add((IAppender)item); } @@ -585,7 +585,7 @@ private void ValidateIndex(int i) /// private void ValidateIndex(int i, bool allowEqualEnd) { - int max = (allowEqualEnd) ? (m_count) : (m_count-1); + int max = (allowEqualEnd) ? (m_count) : (m_count - 1); if (i < 0 || i > max) { throw log4net.Util.SystemInfo.CreateArgumentOutOfRangeException("i", (object)i, "Index was out of range. Must be non-negative and less than the size of the collection. [" + (object)i + "] Specified argument was out of the range of valid values."); @@ -604,7 +604,7 @@ private void EnsureCapacity(int min) } #endregion - + #region Implementation (ICollection) void ICollection.CopyTo(Array array, int start) @@ -675,15 +675,15 @@ IEnumerator IEnumerable.GetEnumerator() private sealed class Enumerator : IEnumerator, IAppenderCollectionEnumerator { #region Implementation (data) - + private readonly AppenderCollection m_collection; private int m_index; private int m_version; - + #endregion - + #region Construction - + /// /// Initializes a new instance of the Enumerator class. /// @@ -694,11 +694,11 @@ internal Enumerator(AppenderCollection tc) m_index = -1; m_version = tc.m_version; } - + #endregion - + #region Operations (type-safe IEnumerator) - + /// /// Gets the current element in the collection. /// @@ -736,14 +736,14 @@ public void Reset() m_index = -1; } #endregion - + #region Implementation (IEnumerator) - + object IEnumerator.Current { get { return this.Current; } } - + #endregion } @@ -778,7 +778,7 @@ public override void CopyTo(IAppender[] array) public override void CopyTo(IAppender[] array, int start) { - m_collection.CopyTo(array,start); + m_collection.CopyTo(array, start); } void ICollection.CopyTo(Array array, int start) diff --git a/src/log4net/Appender/AppenderSkeleton.cs b/src/log4net/Appender/AppenderSkeleton.cs index 0ababc3f..29354c9e 100644 --- a/src/log4net/Appender/AppenderSkeleton.cs +++ b/src/log4net/Appender/AppenderSkeleton.cs @@ -73,13 +73,13 @@ protected AppenderSkeleton() /// will call . /// /// - ~AppenderSkeleton() + ~AppenderSkeleton() { // An appender might be closed then garbage collected. // There is no point in closing twice. - if (!m_closed) + if (!m_closed) { - LogLog.Debug(declaringType, "Finalizing appender named ["+m_name+"]."); + LogLog.Debug(declaringType, "Finalizing appender named [" + m_name + "]."); Close(); } } @@ -105,7 +105,7 @@ protected AppenderSkeleton() /// string, such as "DEBUG", "INFO" and so on. /// /// - public Level Threshold + public Level Threshold { get { return m_threshold; } set { m_threshold = value; } @@ -121,20 +121,20 @@ public Level Threshold /// implementation for the property. /// /// - public virtual IErrorHandler ErrorHandler + public virtual IErrorHandler ErrorHandler { get { return this.m_errorHandler; } - set + set { - lock(this) + lock (this) { - if (value == null) + if (value == null) { // We do not throw exception here since the cause is probably a // bad config file. LogLog.Warn(declaringType, "You have tried to set a null error-handler."); - } - else + } + else { m_errorHandler = value; } @@ -167,7 +167,7 @@ public virtual IFilter FilterHead /// /// /// - public virtual ILayout Layout + public virtual ILayout Layout { get { return m_layout; } set { m_layout = value; } @@ -193,7 +193,7 @@ public virtual ILayout Layout /// must be called again. /// /// - public virtual void ActivateOptions() + public virtual void ActivateOptions() { } @@ -210,7 +210,7 @@ public virtual void ActivateOptions() /// The name uniquely identifies the appender. /// /// - public string Name + public string Name { get { return m_name; } set { m_name = value; } @@ -236,7 +236,7 @@ public string Name public void Close() { // This lock prevents the appender being closed while it is still appending - lock(this) + lock (this) { if (!m_closed) { @@ -287,18 +287,18 @@ public void Close() /// will be passed to the abstract method. /// /// - public void DoAppend(LoggingEvent loggingEvent) + public void DoAppend(LoggingEvent loggingEvent) { // This lock is absolutely critical for correct formatting // of the message in a multi-threaded environment. Without // this, the message may be broken up into elements from // multiple thread contexts (like get the wrong thread ID). - lock(this) + lock (this) { if (m_closed) { - ErrorHandler.Error("Attempted to append to closed appender named ["+m_name+"]."); + ErrorHandler.Error("Attempted to append to closed appender named [" + m_name + "]."); return; } @@ -317,7 +317,7 @@ public void DoAppend(LoggingEvent loggingEvent) this.Append(loggingEvent); } } - catch(Exception ex) + catch (Exception ex) { ErrorHandler.Error("Failed in DoAppend", ex); } @@ -384,18 +384,18 @@ public void DoAppend(LoggingEvent loggingEvent) /// will be passed to the method. /// /// - public void DoAppend(LoggingEvent[] loggingEvents) + public void DoAppend(LoggingEvent[] loggingEvents) { // This lock is absolutely critical for correct formatting // of the message in a multi-threaded environment. Without // this, the message may be broken up into elements from // multiple thread contexts (like get the wrong thread ID). - lock(this) + lock (this) { if (m_closed) { - ErrorHandler.Error("Attempted to append to closed appender named ["+m_name+"]."); + ErrorHandler.Error("Attempted to append to closed appender named [" + m_name + "]."); return; } @@ -411,7 +411,7 @@ public void DoAppend(LoggingEvent[] loggingEvents) ArrayList filteredEvents = new ArrayList(loggingEvents.Length); - foreach(LoggingEvent loggingEvent in loggingEvents) + foreach (LoggingEvent loggingEvent in loggingEvents) { if (FilterEvent(loggingEvent)) { @@ -424,7 +424,7 @@ public void DoAppend(LoggingEvent[] loggingEvents) this.Append((LoggingEvent[])filteredEvents.ToArray(typeof(LoggingEvent))); } } - catch(Exception ex) + catch (Exception ex) { ErrorHandler.Error("Failed in Bulk DoAppend", ex); } @@ -481,18 +481,18 @@ public void DoAppend(LoggingEvent[] loggingEvents) /// protected virtual bool FilterEvent(LoggingEvent loggingEvent) { - if (!IsAsSevereAsThreshold(loggingEvent.Level)) + if (!IsAsSevereAsThreshold(loggingEvent.Level)) { return false; } IFilter f = this.FilterHead; - while(f != null) + while (f != null) { - switch(f.Decide(loggingEvent)) + switch (f.Decide(loggingEvent)) { - case FilterDecision.Deny: + case FilterDecision.Deny: return false; // Return without appending case FilterDecision.Accept: @@ -530,14 +530,14 @@ public virtual void AddFilter(IFilter filter) throw new ArgumentNullException("filter param must not be null"); } - if (m_headFilter == null) + if (m_headFilter == null) { m_headFilter = m_tailFilter = filter; - } - else + } + else { m_tailFilter.Next = filter; - m_tailFilter = filter; + m_tailFilter = filter; } } @@ -571,7 +571,7 @@ public virtual void ClearFilters() /// true if the meets the /// requirements of this appender. /// - protected virtual bool IsAsSevereAsThreshold(Level level) + protected virtual bool IsAsSevereAsThreshold(Level level) { return ((m_threshold == null) || level >= m_threshold); } @@ -589,7 +589,7 @@ protected virtual bool IsAsSevereAsThreshold(Level level) /// It is a programming error to append to a closed appender. /// /// - protected virtual void OnClose() + protected virtual void OnClose() { // Do nothing by default } @@ -630,7 +630,7 @@ protected virtual void OnClose() /// protected virtual void Append(LoggingEvent[] loggingEvents) { - foreach(LoggingEvent loggingEvent in loggingEvents) + foreach (LoggingEvent loggingEvent in loggingEvents) { Append(loggingEvent); } @@ -658,7 +658,7 @@ protected virtual bool PreAppendCheck() { if ((m_layout == null) && RequiresLayout) { - ErrorHandler.Error("AppenderSkeleton: No layout set for the appender named ["+m_name+"]."); + ErrorHandler.Error("AppenderSkeleton: No layout set for the appender named [" + m_name + "]."); return false; } @@ -697,14 +697,14 @@ protected string RenderLoggingEvent(LoggingEvent loggingEvent) m_renderWriter = new ReusableStringWriter(System.Globalization.CultureInfo.InvariantCulture); } - lock (m_renderWriter) - { - // Reset the writer so we can reuse it - m_renderWriter.Reset(c_renderBufferMaxCapacity, c_renderBufferSize); + lock (m_renderWriter) + { + // Reset the writer so we can reuse it + m_renderWriter.Reset(c_renderBufferMaxCapacity, c_renderBufferSize); - RenderLoggingEvent(m_renderWriter, loggingEvent); - return m_renderWriter.ToString(); - } + RenderLoggingEvent(m_renderWriter, loggingEvent); + return m_renderWriter.ToString(); + } } /// @@ -732,27 +732,27 @@ protected string RenderLoggingEvent(LoggingEvent loggingEvent) /// protected void RenderLoggingEvent(TextWriter writer, LoggingEvent loggingEvent) { - if (m_layout == null) + if (m_layout == null) { throw new InvalidOperationException("A layout must be set"); } - if (m_layout.IgnoresException) + if (m_layout.IgnoresException) { string exceptionStr = loggingEvent.GetExceptionString(); - if (exceptionStr != null && exceptionStr.Length > 0) + if (exceptionStr != null && exceptionStr.Length > 0) { // render the event and the exception m_layout.Format(writer, loggingEvent); writer.WriteLine(exceptionStr); } - else + else { // there is no exception to render m_layout.Format(writer, loggingEvent); } } - else + else { // The layout will render the exception m_layout.Format(writer, loggingEvent); @@ -783,16 +783,16 @@ protected virtual bool RequiresLayout #endregion /// - /// Flushes any buffered log data. - /// + /// Flushes any buffered log data. + /// /// /// This implementation doesn't flush anything and always returns true /// - /// True if all logging events were flushed successfully, else false. - public virtual bool Flush(int millisecondsTimeout) - { - return true; - } + /// True if all logging events were flushed successfully, else false. + public virtual bool Flush(int millisecondsTimeout) + { + return true; + } #region Private Instance Fields @@ -893,17 +893,17 @@ public virtual bool Flush(int millisecondsTimeout) #endregion - #region Private Static Fields + #region Private Static Fields - /// - /// The fully qualified type of the AppenderSkeleton class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(AppenderSkeleton); + /// + /// The fully qualified type of the AppenderSkeleton class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(AppenderSkeleton); - #endregion Private Static Fields + #endregion Private Static Fields } } diff --git a/src/log4net/Appender/AspNetTraceAppender.cs b/src/log4net/Appender/AspNetTraceAppender.cs index addd4c14..c478a490 100644 --- a/src/log4net/Appender/AspNetTraceAppender.cs +++ b/src/log4net/Appender/AspNetTraceAppender.cs @@ -27,7 +27,7 @@ using log4net.Layout; using log4net.Core; -namespace log4net.Appender +namespace log4net.Appender { /// /// @@ -48,13 +48,13 @@ namespace log4net.Appender /// /// The logging event is passed to the or /// method depending on the level of the logging event. - /// The event's logger name is the default value for the category parameter of the Write/Warn method. + /// The event's logger name is the default value for the category parameter of the Write/Warn method. /// /// /// Nicko Cadell /// Gert Driesen /// Ron Grabowski - public class AspNetTraceAppender : AppenderSkeleton + public class AspNetTraceAppender : AppenderSkeleton { #region Public Instances Constructors @@ -66,7 +66,7 @@ public class AspNetTraceAppender : AppenderSkeleton /// Default constructor. /// /// - public AspNetTraceAppender() + public AspNetTraceAppender() { } @@ -85,21 +85,21 @@ public AspNetTraceAppender() /// (). /// /// - protected override void Append(LoggingEvent loggingEvent) + protected override void Append(LoggingEvent loggingEvent) { // check if log4net is running in the context of an ASP.NET application - if (HttpContext.Current != null) + if (HttpContext.Current != null) { // check if tracing is enabled for the current context - if (HttpContext.Current.Trace.IsEnabled) + if (HttpContext.Current.Trace.IsEnabled) { - if (loggingEvent.Level >= Level.Warn) + if (loggingEvent.Level >= Level.Warn) { - HttpContext.Current.Trace.Warn(m_category.Format(loggingEvent), RenderLoggingEvent(loggingEvent)); + HttpContext.Current.Trace.Warn(m_category.Format(loggingEvent), RenderLoggingEvent(loggingEvent)); } - else + else { - HttpContext.Current.Trace.Write(m_category.Format(loggingEvent), RenderLoggingEvent(loggingEvent)); + HttpContext.Current.Trace.Write(m_category.Format(loggingEvent), RenderLoggingEvent(loggingEvent)); } } } @@ -121,35 +121,35 @@ protected override bool RequiresLayout #endregion // Override implementation of AppenderSkeleton - #region Public Instance Properties - - /// - /// The category parameter sent to the Trace method. - /// - /// - /// - /// Defaults to %logger which will use the logger name of the current - /// as the category parameter. - /// - /// - /// - /// - public PatternLayout Category - { - get { return m_category; } - set { m_category = value; } - } + #region Public Instance Properties + + /// + /// The category parameter sent to the Trace method. + /// + /// + /// + /// Defaults to %logger which will use the logger name of the current + /// as the category parameter. + /// + /// + /// + /// + public PatternLayout Category + { + get { return m_category; } + set { m_category = value; } + } - #endregion + #endregion - #region Private Instance Fields + #region Private Instance Fields - /// - /// Defaults to %logger - /// - private PatternLayout m_category = new PatternLayout("%logger"); + /// + /// Defaults to %logger + /// + private PatternLayout m_category = new PatternLayout("%logger"); - #endregion + #endregion } } diff --git a/src/log4net/Appender/BufferingAppenderSkeleton.cs b/src/log4net/Appender/BufferingAppenderSkeleton.cs index e8f8e496..5af27c84 100644 --- a/src/log4net/Appender/BufferingAppenderSkeleton.cs +++ b/src/log4net/Appender/BufferingAppenderSkeleton.cs @@ -69,7 +69,7 @@ namespace log4net.Appender /// /// Nicko Cadell /// Gert Driesen - public abstract class BufferingAppenderSkeleton : AppenderSkeleton + public abstract class BufferingAppenderSkeleton : AppenderSkeleton { #region Protected Instance Constructors @@ -182,7 +182,7 @@ public int BufferSize public ITriggeringEventEvaluator Evaluator { get { return m_evaluator; } - set { m_evaluator = value; } + set { m_evaluator = value; } } /// @@ -201,7 +201,7 @@ public ITriggeringEventEvaluator Evaluator public ITriggeringEventEvaluator LossyEvaluator { get { return m_lossyEvaluator; } - set { m_lossyEvaluator = value; } + set { m_lossyEvaluator = value; } } /// @@ -225,8 +225,8 @@ public ITriggeringEventEvaluator LossyEvaluator public virtual bool OnlyFixPartialEventData { get { return (Fix == FixFlags.Partial); } - set - { + set + { if (value) { Fix = FixFlags.Partial; @@ -262,16 +262,16 @@ public virtual FixFlags Fix #region Public Methods - /// - /// Flushes any buffered log data. - /// - /// The maximum time to wait for logging events to be flushed. - /// True if all logging events were flushed successfully, else false. - public override bool Flush(int millisecondsTimeout) - { - Flush(); - return true; - } + /// + /// Flushes any buffered log data. + /// + /// The maximum time to wait for logging events to be flushed. + /// True if all logging events were flushed successfully, else false. + public override bool Flush(int millisecondsTimeout) + { + Flush(); + return true; + } /// /// Flush the currently buffered events @@ -316,7 +316,7 @@ public virtual void Flush(bool flushLossyBuffer) // This method will be called outside of the AppenderSkeleton DoAppend() method // therefore it needs to be protected by its own lock. This will block any // Appends while the buffer is flushed. - lock(this) + lock (this) { if (m_cb != null && m_cb.Length > 0) { @@ -331,7 +331,7 @@ public virtual void Flush(bool flushLossyBuffer) LoggingEvent[] bufferedEvents = m_cb.PopAll(); ArrayList filteredEvents = new ArrayList(bufferedEvents.Length); - foreach(LoggingEvent loggingEvent in bufferedEvents) + foreach (LoggingEvent loggingEvent in bufferedEvents) { if (m_lossyEvaluator.IsTriggeringEvent(loggingEvent)) { @@ -381,7 +381,7 @@ public virtual void Flush(bool flushLossyBuffer) /// must be called again. /// /// - public override void ActivateOptions() + public override void ActivateOptions() { base.ActivateOptions(); @@ -390,7 +390,7 @@ public override void ActivateOptions() // therefore check we have an evaluator. if (m_lossy && m_evaluator == null) { - ErrorHandler.Error("Appender ["+Name+"] is Lossy but has no Evaluator. The buffer will never be sent!"); + ErrorHandler.Error("Appender [" + Name + "] is Lossy but has no Evaluator. The buffer will never be sent!"); } if (m_bufferSize > 1) @@ -417,7 +417,7 @@ public override void ActivateOptions() /// the buffer must be sent when the appender is closed. /// /// - protected override void OnClose() + protected override void OnClose() { // Flush the buffer on close Flush(true); @@ -453,7 +453,7 @@ protected override void OnClose() /// is processed. /// /// - protected override void Append(LoggingEvent loggingEvent) + protected override void Append(LoggingEvent loggingEvent) { // If the buffer size is set to 1 or less then the buffer will be // sent immediately because there is not enough space in the buffer @@ -462,8 +462,8 @@ protected override void Append(LoggingEvent loggingEvent) if (m_cb == null || m_bufferSize <= 1) { // Only send the event if we are in non lossy mode or the event is a triggering event - if ((!m_lossy) || - (m_evaluator != null && m_evaluator.IsTriggeringEvent(loggingEvent)) || + if ((!m_lossy) || + (m_evaluator != null && m_evaluator.IsTriggeringEvent(loggingEvent)) || (m_lossyEvaluator != null && m_lossyEvaluator.IsTriggeringEvent(loggingEvent))) { if (m_eventMustBeFixed) @@ -473,7 +473,7 @@ protected override void Append(LoggingEvent loggingEvent) } // Not buffering events, send immediately - SendBuffer(new LoggingEvent[] { loggingEvent } ); + SendBuffer(new LoggingEvent[] { loggingEvent }); } } else @@ -511,7 +511,7 @@ protected override void Append(LoggingEvent loggingEvent) else if (discardedLoggingEvent != null) { // Just send the discarded event - SendBuffer(new LoggingEvent[] { discardedLoggingEvent } ); + SendBuffer(new LoggingEvent[] { discardedLoggingEvent }); } } } @@ -552,7 +552,7 @@ protected virtual void SendFromBuffer(LoggingEvent firstLoggingEvent, CyclicBuff } else if (bufferEvents.Length == 0) { - SendBuffer(new LoggingEvent[] { firstLoggingEvent } ); + SendBuffer(new LoggingEvent[] { firstLoggingEvent }); } else { diff --git a/src/log4net/Appender/BufferingForwardingAppender.cs b/src/log4net/Appender/BufferingForwardingAppender.cs index c228b223..360c8f9b 100644 --- a/src/log4net/Appender/BufferingForwardingAppender.cs +++ b/src/log4net/Appender/BufferingForwardingAppender.cs @@ -77,7 +77,7 @@ public BufferingForwardingAppender() protected override void OnClose() { // Remove all the attached appenders - lock(this) + lock (this) { // Delegate to base, which will flush buffers base.OnClose(); @@ -126,15 +126,15 @@ protected override void SendBuffer(LoggingEvent[] events) /// appenders, then it won't be added again. /// /// - public virtual void AddAppender(IAppender newAppender) + public virtual void AddAppender(IAppender newAppender) { if (newAppender == null) { throw new ArgumentNullException("newAppender"); } - lock(this) + lock (this) { - if (m_appenderAttachedImpl == null) + if (m_appenderAttachedImpl == null) { m_appenderAttachedImpl = new log4net.Util.AppenderAttachedImpl(); } @@ -157,13 +157,13 @@ public virtual AppenderCollection Appenders { get { - lock(this) + lock (this) { if (m_appenderAttachedImpl == null) { return AppenderCollection.EmptyCollection; } - else + else { return m_appenderAttachedImpl.Appenders; } @@ -183,9 +183,9 @@ public virtual AppenderCollection Appenders /// Get the named appender attached to this buffering appender. /// /// - public virtual IAppender GetAppender(string name) + public virtual IAppender GetAppender(string name) { - lock(this) + lock (this) { if (m_appenderAttachedImpl == null || name == null) { @@ -204,11 +204,11 @@ public virtual IAppender GetAppender(string name) /// This is useful when re-reading configuration information. /// /// - public virtual void RemoveAllAppenders() + public virtual void RemoveAllAppenders() { - lock(this) + lock (this) { - if (m_appenderAttachedImpl != null) + if (m_appenderAttachedImpl != null) { m_appenderAttachedImpl.RemoveAllAppenders(); m_appenderAttachedImpl = null; @@ -226,11 +226,11 @@ public virtual void RemoveAllAppenders() /// If you are discarding the appender you must call /// on the appender removed. /// - public virtual IAppender RemoveAppender(IAppender appender) + public virtual IAppender RemoveAppender(IAppender appender) { - lock(this) + lock (this) { - if (appender != null && m_appenderAttachedImpl != null) + if (appender != null && m_appenderAttachedImpl != null) { return m_appenderAttachedImpl.RemoveAppender(appender); } @@ -248,9 +248,9 @@ public virtual IAppender RemoveAppender(IAppender appender) /// If you are discarding the appender you must call /// on the appender removed. /// - public virtual IAppender RemoveAppender(string name) + public virtual IAppender RemoveAppender(string name) { - lock(this) + lock (this) { if (name != null && m_appenderAttachedImpl != null) { @@ -259,7 +259,7 @@ public virtual IAppender RemoveAppender(string name) } return null; } - + #endregion Implementation of IAppenderAttachable #region Private Instance Fields diff --git a/src/log4net/Appender/ColoredConsoleAppender.cs b/src/log4net/Appender/ColoredConsoleAppender.cs index c90cf5fb..00a07d2d 100644 --- a/src/log4net/Appender/ColoredConsoleAppender.cs +++ b/src/log4net/Appender/ColoredConsoleAppender.cs @@ -162,7 +162,7 @@ public enum Colors : int /// The instance of the class is set up to write /// to the standard output stream. /// - public ColoredConsoleAppender() + public ColoredConsoleAppender() { } @@ -192,7 +192,7 @@ public ColoredConsoleAppender(ILayout layout) : this(layout, false) /// output stream. /// [Obsolete("Instead use the default constructor and set the Layout & Target properties")] - public ColoredConsoleAppender(ILayout layout, bool writeToErrorStream) + public ColoredConsoleAppender(ILayout layout, bool writeToErrorStream) { Layout = layout; m_writeToErrorStream = writeToErrorStream; @@ -222,12 +222,12 @@ public virtual string Target set { string v = value.Trim(); - - if (string.Compare(ConsoleError, v, true, CultureInfo.InvariantCulture) == 0) + + if (string.Compare(ConsoleError, v, true, CultureInfo.InvariantCulture) == 0) { m_writeToErrorStream = true; - } - else + } + else { m_writeToErrorStream = false; } @@ -270,7 +270,7 @@ public void AddMapping(LevelColors mapping) [System.Security.SecuritySafeCritical] #endif [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, UnmanagedCode = true)] - protected override void Append(log4net.Core.LoggingEvent loggingEvent) + protected override void Append(log4net.Core.LoggingEvent loggingEvent) { if (m_consoleOutputWriter != null) { @@ -391,7 +391,7 @@ protected override void Append(log4net.Core.LoggingEvent loggingEvent) bool appendNewline = false; // Trim off last newline, if it exists - if (arrayLength > 1 && messageCharArray[arrayLength-2] == '\r' && messageCharArray[arrayLength-1] == '\n') + if (arrayLength > 1 && messageCharArray[arrayLength - 2] == '\r' && messageCharArray[arrayLength - 1] == '\n') { arrayLength -= 2; appendNewline = true; @@ -411,7 +411,7 @@ protected override void Append(log4net.Core.LoggingEvent loggingEvent) } } - private static readonly char[] s_windowsNewline = {'\r', '\n'}; + private static readonly char[] s_windowsNewline = { '\r', '\n' }; /// /// This appender requires a to be set. @@ -529,59 +529,59 @@ public override void ActivateOptions() #region Win32 Methods - [DllImport("Kernel32.dll", SetLastError=true, CharSet=CharSet.Auto)] + [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] private static extern int GetConsoleOutputCP(); - [DllImport("Kernel32.dll", SetLastError=true, CharSet=CharSet.Auto)] + [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] private static extern bool SetConsoleTextAttribute( IntPtr consoleHandle, ushort attributes); - [DllImport("Kernel32.dll", SetLastError=true, CharSet=CharSet.Auto)] + [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] private static extern bool GetConsoleScreenBufferInfo( IntPtr consoleHandle, out CONSOLE_SCREEN_BUFFER_INFO bufferInfo); -// [DllImport("Kernel32.dll", SetLastError=true, CharSet=CharSet.Unicode)] -// private static extern bool WriteConsoleW( -// IntPtr hConsoleHandle, -// [MarshalAs(UnmanagedType.LPWStr)] string strBuffer, -// UInt32 bufferLen, -// out UInt32 written, -// IntPtr reserved); + // [DllImport("Kernel32.dll", SetLastError=true, CharSet=CharSet.Unicode)] + // private static extern bool WriteConsoleW( + // IntPtr hConsoleHandle, + // [MarshalAs(UnmanagedType.LPWStr)] string strBuffer, + // UInt32 bufferLen, + // out UInt32 written, + // IntPtr reserved); //private const UInt32 STD_INPUT_HANDLE = unchecked((UInt32)(-10)); private const UInt32 STD_OUTPUT_HANDLE = unchecked((UInt32)(-11)); private const UInt32 STD_ERROR_HANDLE = unchecked((UInt32)(-12)); - [DllImport("Kernel32.dll", SetLastError=true, CharSet=CharSet.Auto)] + [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] private static extern IntPtr GetStdHandle( UInt32 type); [StructLayout(LayoutKind.Sequential)] - private struct COORD + private struct COORD { - public UInt16 x; - public UInt16 y; + public UInt16 x; + public UInt16 y; } [StructLayout(LayoutKind.Sequential)] - private struct SMALL_RECT + private struct SMALL_RECT { - public UInt16 Left; - public UInt16 Top; - public UInt16 Right; - public UInt16 Bottom; + public UInt16 Left; + public UInt16 Top; + public UInt16 Right; + public UInt16 Bottom; } [StructLayout(LayoutKind.Sequential)] - private struct CONSOLE_SCREEN_BUFFER_INFO - { - public COORD dwSize; - public COORD dwCursorPosition; - public ushort wAttributes; - public SMALL_RECT srWindow; - public COORD dwMaximumWindowSize; + private struct CONSOLE_SCREEN_BUFFER_INFO + { + public COORD dwSize; + public COORD dwCursorPosition; + public ushort wAttributes; + public SMALL_RECT srWindow; + public COORD dwMaximumWindowSize; } #endregion // Win32 Methods @@ -644,7 +644,7 @@ public Colors BackColor public override void ActivateOptions() { base.ActivateOptions(); - m_combinedColor = (ushort)( (int)m_foreColor + (((int)m_backColor) << 4) ); + m_combinedColor = (ushort)((int)m_foreColor + (((int)m_backColor) << 4)); } /// diff --git a/src/log4net/Appender/ConsoleAppender.cs b/src/log4net/Appender/ConsoleAppender.cs index 79643914..a7299eeb 100644 --- a/src/log4net/Appender/ConsoleAppender.cs +++ b/src/log4net/Appender/ConsoleAppender.cs @@ -61,7 +61,7 @@ public class ConsoleAppender : AppenderSkeleton /// The instance of the class is set up to write /// to the standard output stream. /// - public ConsoleAppender() + public ConsoleAppender() { } @@ -91,7 +91,7 @@ public ConsoleAppender(ILayout layout) : this(layout, false) /// output stream. /// [Obsolete("Instead use the default constructor and set the Layout & Target properties")] - public ConsoleAppender(ILayout layout, bool writeToErrorStream) + public ConsoleAppender(ILayout layout, bool writeToErrorStream) { Layout = layout; m_writeToErrorStream = writeToErrorStream; @@ -125,8 +125,8 @@ public virtual string Target if (SystemInfo.EqualsIgnoringCase(ConsoleError, v)) { m_writeToErrorStream = true; - } - else + } + else { m_writeToErrorStream = false; } @@ -149,7 +149,7 @@ public virtual string Target /// The format of the output will depend on the appender's layout. /// /// - protected override void Append(LoggingEvent loggingEvent) + protected override void Append(LoggingEvent loggingEvent) { #if NETCF_1_0 // Write to the output stream diff --git a/src/log4net/Appender/DebugAppender.cs b/src/log4net/Appender/DebugAppender.cs index 668d622c..9aa9e973 100644 --- a/src/log4net/Appender/DebugAppender.cs +++ b/src/log4net/Appender/DebugAppender.cs @@ -75,7 +75,7 @@ public DebugAppender(ILayout layout) #endregion Public Instance Constructors #region Public Instance Properties - + #if !NETSTANDARD1_3 // System.Diagnostics.Debug has no Flush() in netstandard1.3 /// /// Gets or sets a value that indicates whether the appender will @@ -102,45 +102,45 @@ public bool ImmediateFlush } #endif // !NETSTANDARD1_3 - /// - /// Formats the category parameter sent to the Debug method. - /// - /// - /// - /// Defaults to a with %logger as the pattern which will use the logger name of the current - /// as the category parameter. - /// - /// - /// - /// - public PatternLayout Category - { - get { return m_category; } - set { m_category = value; } - } - + /// + /// Formats the category parameter sent to the Debug method. + /// + /// + /// + /// Defaults to a with %logger as the pattern which will use the logger name of the current + /// as the category parameter. + /// + /// + /// + /// + public PatternLayout Category + { + get { return m_category; } + set { m_category = value; } + } + #endregion Public Instance Properties #if !NETSTANDARD1_3 - /// - /// Flushes any buffered log data. - /// - /// The maximum time to wait for logging events to be flushed. - /// True if all logging events were flushed successfully, else false. - public override bool Flush(int millisecondsTimeout) - { - // Nothing to do if ImmediateFlush is true - if (m_immediateFlush) return true; - - // System.Diagnostics.Debug is thread-safe, so no need for lock(this). - System.Diagnostics.Debug.Flush(); - - return true; - } + /// + /// Flushes any buffered log data. + /// + /// The maximum time to wait for logging events to be flushed. + /// True if all logging events were flushed successfully, else false. + public override bool Flush(int millisecondsTimeout) + { + // Nothing to do if ImmediateFlush is true + if (m_immediateFlush) return true; + + // System.Diagnostics.Debug is thread-safe, so no need for lock(this). + System.Diagnostics.Debug.Flush(); + + return true; + } #endif #region Override implementation of AppenderSkeleton - + #if NETSTANDARD1_3 /// /// Writes the logging event to the system. @@ -169,30 +169,30 @@ protected override void Append(LoggingEvent loggingEvent) // // Write the string to the Debug system // - if(m_category == null) - { - System.Diagnostics.Debug.Write(RenderLoggingEvent(loggingEvent)); - } - else - { - string category = m_category.Format(loggingEvent); - if (string.IsNullOrEmpty(category)) - { - System.Diagnostics.Debug.Write(RenderLoggingEvent(loggingEvent)); - } - else - { - System.Diagnostics.Debug.Write(RenderLoggingEvent(loggingEvent), category); - } - } + if (m_category == null) + { + System.Diagnostics.Debug.Write(RenderLoggingEvent(loggingEvent)); + } + else + { + string category = m_category.Format(loggingEvent); + if (string.IsNullOrEmpty(category)) + { + System.Diagnostics.Debug.Write(RenderLoggingEvent(loggingEvent)); + } + else + { + System.Diagnostics.Debug.Write(RenderLoggingEvent(loggingEvent), category); + } + } #if !NETSTANDARD1_3 // // Flush the Debug system if needed // - if (m_immediateFlush) + if (m_immediateFlush) { System.Diagnostics.Debug.Flush(); - } + } #endif } @@ -213,8 +213,8 @@ protected override bool RequiresLayout #endregion Override implementation of AppenderSkeleton #region Private Instance Fields - -#if !NETSTANDARD1_3 + +#if !NETSTANDARD1_3 /// /// Immediate flush means that the underlying writer or output stream /// will be flushed at the end of each append operation. @@ -233,10 +233,10 @@ protected override bool RequiresLayout private bool m_immediateFlush = true; #endif - /// - /// Defaults to a with %logger as the pattern. - /// - private PatternLayout m_category = new PatternLayout("%logger"); + /// + /// Defaults to a with %logger as the pattern. + /// + private PatternLayout m_category = new PatternLayout("%logger"); #endregion Private Instance Fields } diff --git a/src/log4net/Appender/EventLogAppender.cs b/src/log4net/Appender/EventLogAppender.cs index 2de708bd..f87a7bcf 100644 --- a/src/log4net/Appender/EventLogAppender.cs +++ b/src/log4net/Appender/EventLogAppender.cs @@ -40,17 +40,17 @@ namespace log4net.Appender /// Writes events to the system event log. /// /// - /// - /// The appender will fail if you try to write using an event source that doesn't exist unless it is running with local administrator privileges. - /// See also http://logging.apache.org/log4net/release/faq.html#trouble-EventLog - /// + /// + /// The appender will fail if you try to write using an event source that doesn't exist unless it is running with local administrator privileges. + /// See also http://logging.apache.org/log4net/release/faq.html#trouble-EventLog + /// /// /// The EventID of the event log entry can be /// set using the EventID property () /// on the . /// - /// - /// The Category of the event log entry can be + /// + /// The Category of the event log entry can be /// set using the Category property () /// on the . /// @@ -100,9 +100,9 @@ public class EventLogAppender : AppenderSkeleton /// public EventLogAppender() { - m_applicationName = System.Threading.Thread.GetDomain().FriendlyName; - m_logName = "Application"; // Defaults to application log - m_machineName = "."; // Only log on the local machine + m_applicationName = System.Threading.Thread.GetDomain().FriendlyName; + m_logName = "Application"; // Defaults to application log + m_machineName = "."; // Only log on the local machine } /// @@ -216,46 +216,47 @@ public void AddMapping(Level2EventLogEntryType mapping) /// of the current thread. /// /// - public SecurityContext SecurityContext + public SecurityContext SecurityContext { get { return m_securityContext; } set { m_securityContext = value; } } - /// - /// Gets or sets the EventId to use unless one is explicitly specified via the LoggingEvent's properties. - /// - /// - /// - /// The EventID of the event log entry will normally be - /// set using the EventID property () - /// on the . - /// This property provides the fallback value which defaults to 0. - /// - /// - public int EventId { - get { return m_eventId; } - set { m_eventId = value; } - } + /// + /// Gets or sets the EventId to use unless one is explicitly specified via the LoggingEvent's properties. + /// + /// + /// + /// The EventID of the event log entry will normally be + /// set using the EventID property () + /// on the . + /// This property provides the fallback value which defaults to 0. + /// + /// + public int EventId + { + get { return m_eventId; } + set { m_eventId = value; } + } - /// - /// Gets or sets the Category to use unless one is explicitly specified via the LoggingEvent's properties. - /// - /// - /// - /// The Category of the event log entry will normally be - /// set using the Category property () - /// on the . - /// This property provides the fallback value which defaults to 0. - /// - /// - public short Category - { - get { return m_category; } - set { m_category = value; } - } - #endregion // Public Instance Properties + /// + /// Gets or sets the Category to use unless one is explicitly specified via the LoggingEvent's properties. + /// + /// + /// + /// The Category of the event log entry will normally be + /// set using the Category property () + /// on the . + /// This property provides the fallback value which defaults to 0. + /// + /// + public short Category + { + get { return m_category; } + set { m_category = value; } + } + #endregion // Public Instance Properties #region Implementation of IOptionHandler @@ -275,73 +276,74 @@ public short Category /// must be called again. /// /// - public override void ActivateOptions() + public override void ActivateOptions() { - try - { - base.ActivateOptions(); - - if (m_securityContext == null) - { - m_securityContext = SecurityContextProvider.DefaultProvider.CreateSecurityContext(this); - } - - bool sourceAlreadyExists = false; - string currentLogName = null; - - using (SecurityContext.Impersonate(this)) - { - sourceAlreadyExists = EventLog.SourceExists(m_applicationName); - if (sourceAlreadyExists) { - currentLogName = EventLog.LogNameFromSourceName(m_applicationName, m_machineName); - } - } - - if (sourceAlreadyExists && currentLogName != m_logName) - { - LogLog.Debug(declaringType, "Changing event source [" + m_applicationName + "] from log [" + currentLogName + "] to log [" + m_logName + "]"); - } - else if (!sourceAlreadyExists) - { - LogLog.Debug(declaringType, "Creating event source Source [" + m_applicationName + "] in log " + m_logName + "]"); - } - - string registeredLogName = null; - - using (SecurityContext.Impersonate(this)) - { - if (sourceAlreadyExists && currentLogName != m_logName) - { - // - // Re-register this to the current application if the user has changed - // the application / logfile association - // - EventLog.DeleteEventSource(m_applicationName, m_machineName); - CreateEventSource(m_applicationName, m_logName, m_machineName); - - registeredLogName = EventLog.LogNameFromSourceName(m_applicationName, m_machineName); - } - else if (!sourceAlreadyExists) - { - CreateEventSource(m_applicationName, m_logName, m_machineName); - - registeredLogName = EventLog.LogNameFromSourceName(m_applicationName, m_machineName); - } - } - - m_levelMapping.ActivateOptions(); - - LogLog.Debug(declaringType, "Source [" + m_applicationName + "] is registered to log [" + registeredLogName + "]"); - } - catch (System.Security.SecurityException ex) - { - ErrorHandler.Error("Caught a SecurityException trying to access the EventLog. Most likely the event source " - + m_applicationName - + " doesn't exist and must be created by a local administrator. Will disable EventLogAppender." - + " See http://logging.apache.org/log4net/release/faq.html#trouble-EventLog", - ex); - Threshold = Level.Off; - } + try + { + base.ActivateOptions(); + + if (m_securityContext == null) + { + m_securityContext = SecurityContextProvider.DefaultProvider.CreateSecurityContext(this); + } + + bool sourceAlreadyExists = false; + string currentLogName = null; + + using (SecurityContext.Impersonate(this)) + { + sourceAlreadyExists = EventLog.SourceExists(m_applicationName); + if (sourceAlreadyExists) + { + currentLogName = EventLog.LogNameFromSourceName(m_applicationName, m_machineName); + } + } + + if (sourceAlreadyExists && currentLogName != m_logName) + { + LogLog.Debug(declaringType, "Changing event source [" + m_applicationName + "] from log [" + currentLogName + "] to log [" + m_logName + "]"); + } + else if (!sourceAlreadyExists) + { + LogLog.Debug(declaringType, "Creating event source Source [" + m_applicationName + "] in log " + m_logName + "]"); + } + + string registeredLogName = null; + + using (SecurityContext.Impersonate(this)) + { + if (sourceAlreadyExists && currentLogName != m_logName) + { + // + // Re-register this to the current application if the user has changed + // the application / logfile association + // + EventLog.DeleteEventSource(m_applicationName, m_machineName); + CreateEventSource(m_applicationName, m_logName, m_machineName); + + registeredLogName = EventLog.LogNameFromSourceName(m_applicationName, m_machineName); + } + else if (!sourceAlreadyExists) + { + CreateEventSource(m_applicationName, m_logName, m_machineName); + + registeredLogName = EventLog.LogNameFromSourceName(m_applicationName, m_machineName); + } + } + + m_levelMapping.ActivateOptions(); + + LogLog.Debug(declaringType, "Source [" + m_applicationName + "] is registered to log [" + registeredLogName + "]"); + } + catch (System.Security.SecurityException ex) + { + ErrorHandler.Error("Caught a SecurityException trying to access the EventLog. Most likely the event source " + + m_applicationName + + " doesn't exist and must be created by a local administrator. Will disable EventLogAppender." + + " See http://logging.apache.org/log4net/release/faq.html#trouble-EventLog", + ex); + Threshold = Level.Off; + } } #endregion // Implementation of IOptionHandler @@ -362,7 +364,7 @@ private static void CreateEventSource(string source, string logName, string mach EventLog.CreateEventSource(source, logName, machineName); #endif } - + #region Override implementation of AppenderSkeleton /// @@ -381,7 +383,7 @@ private static void CreateEventSource(string source, string logName, string mach /// There is a limit of 32K characters for an event log message /// /// - protected override void Append(LoggingEvent loggingEvent) + protected override void Append(LoggingEvent loggingEvent) { // // Write the resulting string to the event log system @@ -399,10 +401,10 @@ protected override void Append(LoggingEvent loggingEvent) else { string eventIDPropertyString = eventIDPropertyObj as string; - if (eventIDPropertyString == null) - { - eventIDPropertyString = eventIDPropertyObj.ToString(); - } + if (eventIDPropertyString == null) + { + eventIDPropertyString = eventIDPropertyObj.ToString(); + } if (eventIDPropertyString != null && eventIDPropertyString.Length > 0) { // Read the string property into a number @@ -419,37 +421,37 @@ protected override void Append(LoggingEvent loggingEvent) } } - short category = m_category; - // Look for the Category property - object categoryPropertyObj = loggingEvent.LookupProperty("Category"); - if (categoryPropertyObj != null) + short category = m_category; + // Look for the Category property + object categoryPropertyObj = loggingEvent.LookupProperty("Category"); + if (categoryPropertyObj != null) + { + if (categoryPropertyObj is short) + { + category = (short)categoryPropertyObj; + } + else + { + string categoryPropertyString = categoryPropertyObj as string; + if (categoryPropertyString == null) + { + categoryPropertyString = categoryPropertyObj.ToString(); + } + if (categoryPropertyString != null && categoryPropertyString.Length > 0) + { + // Read the string property into a number + short shortVal; + if (SystemInfo.TryParse(categoryPropertyString, out shortVal)) + { + category = shortVal; + } + else { - if (categoryPropertyObj is short) - { - category = (short) categoryPropertyObj; - } - else - { - string categoryPropertyString = categoryPropertyObj as string; - if (categoryPropertyString == null) - { - categoryPropertyString = categoryPropertyObj.ToString(); - } - if (categoryPropertyString != null && categoryPropertyString.Length > 0) - { - // Read the string property into a number - short shortVal; - if (SystemInfo.TryParse(categoryPropertyString, out shortVal)) - { - category = shortVal; - } - else - { - ErrorHandler.Error("Unable to parse event category property [" + categoryPropertyString + "]."); - } - } - } + ErrorHandler.Error("Unable to parse event category property [" + categoryPropertyString + "]."); } + } + } + } // Write to the event log try @@ -464,16 +466,16 @@ protected override void Append(LoggingEvent loggingEvent) EventLogEntryType entryType = GetEntryType(loggingEvent.Level); - using(SecurityContext.Impersonate(this)) + using (SecurityContext.Impersonate(this)) { EventLog.WriteEntry(m_applicationName, eventTxt, entryType, eventID, category); } } - catch(Exception ex) + catch (Exception ex) { ErrorHandler.Error("Unable to write to event log [" + m_logName + "] using source [" + m_applicationName + "]", ex); } - } + } /// /// This appender requires a to be set. @@ -515,14 +517,14 @@ protected virtual EventLogEntryType GetEntryType(Level level) // Use default behavior - if (level >= Level.Error) + if (level >= Level.Error) { return EventLogEntryType.Error; } - else if (level == Level.Warn) + else if (level == Level.Warn) { return EventLogEntryType.Warning; - } + } // Default setting return EventLogEntryType.Information; @@ -560,17 +562,17 @@ protected virtual EventLogEntryType GetEntryType(Level level) /// private SecurityContext m_securityContext; - /// - /// The event ID to use unless one is explicitly specified via the LoggingEvent's properties. - /// - private int m_eventId = 0; + /// + /// The event ID to use unless one is explicitly specified via the LoggingEvent's properties. + /// + private int m_eventId = 0; - /// - /// The event category to use unless one is explicitly specified via the LoggingEvent's properties. - /// - private short m_category = 0; + /// + /// The event category to use unless one is explicitly specified via the LoggingEvent's properties. + /// + private short m_category = 0; - #endregion // Private Instance Fields + #endregion // Private Instance Fields #region Level2EventLogEntryType LevelMapping Entry @@ -605,16 +607,16 @@ public EventLogEntryType EventLogEntryType #endregion // LevelColors LevelMapping Entry - #region Private Static Fields + #region Private Static Fields - /// - /// The fully qualified type of the EventLogAppender class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(EventLogAppender); + /// + /// The fully qualified type of the EventLogAppender class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(EventLogAppender); /// /// The maximum size supported by default. @@ -684,7 +686,7 @@ private static int GetMaxEventLogMessageSize() return MAX_EVENTLOG_MESSAGE_SIZE_DEFAULT; } - #endregion Private Static Fields + #endregion Private Static Fields } } diff --git a/src/log4net/Appender/FileAppender.cs b/src/log4net/Appender/FileAppender.cs index a9cce8e9..4179190d 100644 --- a/src/log4net/Appender/FileAppender.cs +++ b/src/log4net/Appender/FileAppender.cs @@ -36,54 +36,54 @@ namespace log4net.Appender { #if !NETCF - /// - /// Appends logging events to a file. - /// - /// - /// - /// Logging events are sent to the file specified by - /// the property. - /// - /// - /// The file can be opened in either append or overwrite mode - /// by specifying the property. - /// If the file path is relative it is taken as relative from - /// the application base directory. The file encoding can be - /// specified by setting the property. - /// - /// - /// The layout's and - /// values will be written each time the file is opened and closed - /// respectively. If the property is - /// then the file may contain multiple copies of the header and footer. - /// - /// - /// This appender will first try to open the file for writing when - /// is called. This will typically be during configuration. - /// If the file cannot be opened for writing the appender will attempt - /// to open the file again each time a message is logged to the appender. - /// If the file cannot be opened for writing when a message is logged then - /// the message will be discarded by this appender. - /// - /// - /// The supports pluggable file locking models via - /// the property. - /// The default behavior, implemented by - /// is to obtain an exclusive write lock on the file until this appender is closed. - /// The alternative models only hold a - /// write lock while the appender is writing a logging event () - /// or synchronize by using a named system wide Mutex (). - /// - /// - /// All locking strategies have issues and you should seriously consider using a different strategy that - /// avoids having multiple processes logging to the same file. - /// - /// - /// Nicko Cadell - /// Gert Driesen - /// Rodrigo B. de Oliveira - /// Douglas de la Torre - /// Niall Daley + /// + /// Appends logging events to a file. + /// + /// + /// + /// Logging events are sent to the file specified by + /// the property. + /// + /// + /// The file can be opened in either append or overwrite mode + /// by specifying the property. + /// If the file path is relative it is taken as relative from + /// the application base directory. The file encoding can be + /// specified by setting the property. + /// + /// + /// The layout's and + /// values will be written each time the file is opened and closed + /// respectively. If the property is + /// then the file may contain multiple copies of the header and footer. + /// + /// + /// This appender will first try to open the file for writing when + /// is called. This will typically be during configuration. + /// If the file cannot be opened for writing the appender will attempt + /// to open the file again each time a message is logged to the appender. + /// If the file cannot be opened for writing when a message is logged then + /// the message will be discarded by this appender. + /// + /// + /// The supports pluggable file locking models via + /// the property. + /// The default behavior, implemented by + /// is to obtain an exclusive write lock on the file until this appender is closed. + /// The alternative models only hold a + /// write lock while the appender is writing a logging event () + /// or synchronize by using a named system wide Mutex (). + /// + /// + /// All locking strategies have issues and you should seriously consider using a different strategy that + /// avoids having multiple processes logging to the same file. + /// + /// + /// Nicko Cadell + /// Gert Driesen + /// Rodrigo B. de Oliveira + /// Douglas de la Torre + /// Niall Daley #else /// /// Appends logging events to a file. @@ -133,57 +133,57 @@ namespace log4net.Appender /// Douglas de la Torre /// Niall Daley #endif - public class FileAppender : TextWriterAppender - { - #region LockingStream Inner Class + public class FileAppender : TextWriterAppender + { + #region LockingStream Inner Class - /// - /// Write only that uses the - /// to manage access to an underlying resource. - /// - private sealed class LockingStream : Stream, IDisposable - { + /// + /// Write only that uses the + /// to manage access to an underlying resource. + /// + private sealed class LockingStream : Stream, IDisposable + { #if !NETCR - [Serializable] + [Serializable] #endif - public sealed class LockStateException : LogException - { - public LockStateException(string message) - : base(message) - { - } + public sealed class LockStateException : LogException + { + public LockStateException(string message) + : base(message) + { + } - public LockStateException() - { - } + public LockStateException() + { + } - public LockStateException(string message, Exception innerException) : base(message, innerException) - { - } + public LockStateException(string message, Exception innerException) : base(message, innerException) + { + } #if !NETCR && !NETSTANDARD1_3 - private LockStateException(SerializationInfo info, StreamingContext context) : base(info, context) - { - } + private LockStateException(SerializationInfo info, StreamingContext context) : base(info, context) + { + } #endif - } + } - private Stream m_realStream = null; - private LockingModelBase m_lockingModel = null; - private int m_lockLevel = 0; + private Stream m_realStream = null; + private LockingModelBase m_lockingModel = null; + private int m_lockLevel = 0; - public LockingStream(LockingModelBase locking) - : base() - { - if (locking == null) - { - throw new ArgumentException("Locking model may not be null", "locking"); - } + public LockingStream(LockingModelBase locking) + : base() + { + if (locking == null) + { + throw new ArgumentException("Locking model may not be null", "locking"); + } - m_lockingModel = locking; - } + m_lockingModel = locking; + } - #region Override Implementation of Stream + #region Override Implementation of Stream #if NETSTANDARD protected override void Dispose(bool disposing) @@ -193,51 +193,51 @@ protected override void Dispose(bool disposing) } #else - private int m_readTotal = -1; + private int m_readTotal = -1; - // Methods - public override IAsyncResult BeginRead(byte[] buffer, - int offset, - int count, - AsyncCallback callback, - object state) - { - AssertLocked(); - IAsyncResult ret = m_realStream.BeginRead(buffer, offset, count, callback, state); - m_readTotal = EndRead(ret); - return ret; - } + // Methods + public override IAsyncResult BeginRead(byte[] buffer, + int offset, + int count, + AsyncCallback callback, + object state) + { + AssertLocked(); + IAsyncResult ret = m_realStream.BeginRead(buffer, offset, count, callback, state); + m_readTotal = EndRead(ret); + return ret; + } - /// - /// True asynchronous writes are not supported, the implementation forces a synchronous write. - /// - public override IAsyncResult BeginWrite(byte[] buffer, - int offset, - int count, - AsyncCallback callback, - object state) - { - AssertLocked(); - IAsyncResult ret = m_realStream.BeginWrite(buffer, offset, count, callback, state); - EndWrite(ret); - return ret; - } + /// + /// True asynchronous writes are not supported, the implementation forces a synchronous write. + /// + public override IAsyncResult BeginWrite(byte[] buffer, + int offset, + int count, + AsyncCallback callback, + object state) + { + AssertLocked(); + IAsyncResult ret = m_realStream.BeginWrite(buffer, offset, count, callback, state); + EndWrite(ret); + return ret; + } - public override void Close() - { - m_lockingModel.CloseFile(); - } + public override void Close() + { + m_lockingModel.CloseFile(); + } - public override int EndRead(IAsyncResult asyncResult) - { - AssertLocked(); - return m_readTotal; - } + public override int EndRead(IAsyncResult asyncResult) + { + AssertLocked(); + return m_readTotal; + } - public override void EndWrite(IAsyncResult asyncResult) - { - //No-op, it has already been handled - } + public override void EndWrite(IAsyncResult asyncResult) + { + //No-op, it has already been handled + } #endif #if NET_4_5 || NETSTANDARD @@ -254,928 +254,928 @@ public override Task WriteAsync(byte[] buffer, int offset, int count, Cancellati } #endif - public override void Flush() - { - AssertLocked(); - m_realStream.Flush(); - } + public override void Flush() + { + AssertLocked(); + m_realStream.Flush(); + } - public override int Read(byte[] buffer, int offset, int count) - { - return m_realStream.Read(buffer, offset, count); - } + public override int Read(byte[] buffer, int offset, int count) + { + return m_realStream.Read(buffer, offset, count); + } - public override int ReadByte() - { - return m_realStream.ReadByte(); - } + public override int ReadByte() + { + return m_realStream.ReadByte(); + } - public override long Seek(long offset, SeekOrigin origin) - { - AssertLocked(); - return m_realStream.Seek(offset, origin); - } + public override long Seek(long offset, SeekOrigin origin) + { + AssertLocked(); + return m_realStream.Seek(offset, origin); + } - public override void SetLength(long value) - { - AssertLocked(); - m_realStream.SetLength(value); - } + public override void SetLength(long value) + { + AssertLocked(); + m_realStream.SetLength(value); + } - void IDisposable.Dispose() - { + void IDisposable.Dispose() + { #if NETSTANDARD Dispose(true); #else - Close(); + Close(); #endif - } + } - public override void Write(byte[] buffer, int offset, int count) - { - AssertLocked(); - m_realStream.Write(buffer, offset, count); - } + public override void Write(byte[] buffer, int offset, int count) + { + AssertLocked(); + m_realStream.Write(buffer, offset, count); + } - public override void WriteByte(byte value) - { - AssertLocked(); - m_realStream.WriteByte(value); - } + public override void WriteByte(byte value) + { + AssertLocked(); + m_realStream.WriteByte(value); + } - // Properties - public override bool CanRead - { - get { return false; } - } + // Properties + public override bool CanRead + { + get { return false; } + } - public override bool CanSeek - { - get - { - AssertLocked(); - return m_realStream.CanSeek; - } - } + public override bool CanSeek + { + get + { + AssertLocked(); + return m_realStream.CanSeek; + } + } - public override bool CanWrite - { - get - { - AssertLocked(); - return m_realStream.CanWrite; - } - } + public override bool CanWrite + { + get + { + AssertLocked(); + return m_realStream.CanWrite; + } + } - public override long Length - { - get - { - AssertLocked(); - return m_realStream.Length; - } - } + public override long Length + { + get + { + AssertLocked(); + return m_realStream.Length; + } + } - public override long Position - { - get - { - AssertLocked(); - return m_realStream.Position; - } - set - { - AssertLocked(); - m_realStream.Position = value; - } - } + public override long Position + { + get + { + AssertLocked(); + return m_realStream.Position; + } + set + { + AssertLocked(); + m_realStream.Position = value; + } + } - #endregion Override Implementation of Stream + #endregion Override Implementation of Stream - #region Locking Methods + #region Locking Methods - private void AssertLocked() - { - if (m_realStream == null) - { - throw new LockStateException("The file is not currently locked"); - } - } + private void AssertLocked() + { + if (m_realStream == null) + { + throw new LockStateException("The file is not currently locked"); + } + } - public bool AcquireLock() - { - bool ret = false; - lock (this) - { - if (m_lockLevel == 0) - { - // If lock is already acquired, nop - m_realStream = m_lockingModel.AcquireLock(); - } - - if (m_realStream != null) - { - m_lockLevel++; - ret = true; - } - } - - return ret; - } + public bool AcquireLock() + { + bool ret = false; + lock (this) + { + if (m_lockLevel == 0) + { + // If lock is already acquired, nop + m_realStream = m_lockingModel.AcquireLock(); + } + + if (m_realStream != null) + { + m_lockLevel++; + ret = true; + } + } - public void ReleaseLock() - { - lock (this) - { - m_lockLevel--; - if (m_lockLevel == 0) - { - // If already unlocked, nop - m_lockingModel.ReleaseLock(); - m_realStream = null; - } - } - } + return ret; + } - #endregion Locking Methods + public void ReleaseLock() + { + lock (this) + { + m_lockLevel--; + if (m_lockLevel == 0) + { + // If already unlocked, nop + m_lockingModel.ReleaseLock(); + m_realStream = null; + } } + } - #endregion LockingStream Inner Class + #endregion Locking Methods + } - #region Locking Models + #endregion LockingStream Inner Class - /// - /// Locking model base class - /// - /// - /// - /// Base class for the locking models available to the derived loggers. - /// - /// - public abstract class LockingModelBase - { - private FileAppender m_appender = null; - - /// - /// Open the output file - /// - /// The filename to use - /// Whether to append to the file, or overwrite - /// The encoding to use - /// - /// - /// Open the file specified and prepare for logging. - /// No writes will be made until is called. - /// Must be called before any calls to , - /// and . - /// - /// - public abstract void OpenFile(string filename, bool append, Encoding encoding); - - /// - /// Close the file - /// - /// - /// - /// Close the file. No further writes will be made. - /// - /// - public abstract void CloseFile(); - - /// - /// Initializes all resources used by this locking model. - /// - public abstract void ActivateOptions(); - - /// - /// Disposes all resources that were initialized by this locking model. - /// - public abstract void OnClose(); - - /// - /// Acquire the lock on the file - /// - /// A stream that is ready to be written to. - /// - /// - /// Acquire the lock on the file in preparation for writing to it. - /// Return a stream pointing to the file. - /// must be called to release the lock on the output file. - /// - /// - public abstract Stream AcquireLock(); - - /// - /// Release the lock on the file - /// - /// - /// - /// Release the lock on the file. No further writes will be made to the - /// stream until is called again. - /// - /// - public abstract void ReleaseLock(); - - /// - /// Gets or sets the for this LockingModel - /// - /// - /// The for this LockingModel - /// - /// - /// - /// The file appender this locking model is attached to and working on - /// behalf of. - /// - /// - /// The file appender is used to locate the security context and the error handler to use. - /// - /// - /// The value of this property will be set before is - /// called. - /// - /// - public FileAppender CurrentAppender - { - get { return m_appender; } - set { m_appender = value; } - } + #region Locking Models - /// - /// Helper method that creates a FileStream under CurrentAppender's SecurityContext. - /// - /// - /// - /// Typically called during OpenFile or AcquireLock. - /// - /// - /// If the directory portion of the does not exist, it is created - /// via Directory.CreateDirecctory. - /// - /// - /// - /// - /// - /// - protected Stream CreateStream(string filename, bool append, FileShare fileShare) - { - filename = Environment.ExpandEnvironmentVariables(filename); - using (CurrentAppender.SecurityContext.Impersonate(this)) - { - // Ensure that the directory structure exists - string directoryFullName = Path.GetDirectoryName(filename); - - // Only create the directory if it does not exist - // doing this check here resolves some permissions failures - if (!Directory.Exists(directoryFullName)) - { - Directory.CreateDirectory(directoryFullName); - } - - FileMode fileOpenMode = append - ? FileMode.Append - : FileMode.Create; - return new FileStream(filename, fileOpenMode, FileAccess.Write, fileShare); - } - } + /// + /// Locking model base class + /// + /// + /// + /// Base class for the locking models available to the derived loggers. + /// + /// + public abstract class LockingModelBase + { + private FileAppender m_appender = null; + + /// + /// Open the output file + /// + /// The filename to use + /// Whether to append to the file, or overwrite + /// The encoding to use + /// + /// + /// Open the file specified and prepare for logging. + /// No writes will be made until is called. + /// Must be called before any calls to , + /// and . + /// + /// + public abstract void OpenFile(string filename, bool append, Encoding encoding); + + /// + /// Close the file + /// + /// + /// + /// Close the file. No further writes will be made. + /// + /// + public abstract void CloseFile(); + + /// + /// Initializes all resources used by this locking model. + /// + public abstract void ActivateOptions(); + + /// + /// Disposes all resources that were initialized by this locking model. + /// + public abstract void OnClose(); + + /// + /// Acquire the lock on the file + /// + /// A stream that is ready to be written to. + /// + /// + /// Acquire the lock on the file in preparation for writing to it. + /// Return a stream pointing to the file. + /// must be called to release the lock on the output file. + /// + /// + public abstract Stream AcquireLock(); + + /// + /// Release the lock on the file + /// + /// + /// + /// Release the lock on the file. No further writes will be made to the + /// stream until is called again. + /// + /// + public abstract void ReleaseLock(); + + /// + /// Gets or sets the for this LockingModel + /// + /// + /// The for this LockingModel + /// + /// + /// + /// The file appender this locking model is attached to and working on + /// behalf of. + /// + /// + /// The file appender is used to locate the security context and the error handler to use. + /// + /// + /// The value of this property will be set before is + /// called. + /// + /// + public FileAppender CurrentAppender + { + get { return m_appender; } + set { m_appender = value; } + } - /// - /// Helper method to close under CurrentAppender's SecurityContext. - /// - /// - /// Does not set to null. - /// - /// - protected void CloseStream(Stream stream) - { - using (CurrentAppender.SecurityContext.Impersonate(this)) - { - stream.Dispose(); - } - } + /// + /// Helper method that creates a FileStream under CurrentAppender's SecurityContext. + /// + /// + /// + /// Typically called during OpenFile or AcquireLock. + /// + /// + /// If the directory portion of the does not exist, it is created + /// via Directory.CreateDirecctory. + /// + /// + /// + /// + /// + /// + protected Stream CreateStream(string filename, bool append, FileShare fileShare) + { + filename = Environment.ExpandEnvironmentVariables(filename); + using (CurrentAppender.SecurityContext.Impersonate(this)) + { + // Ensure that the directory structure exists + string directoryFullName = Path.GetDirectoryName(filename); + + // Only create the directory if it does not exist + // doing this check here resolves some permissions failures + if (!Directory.Exists(directoryFullName)) + { + Directory.CreateDirectory(directoryFullName); + } + + FileMode fileOpenMode = append + ? FileMode.Append + : FileMode.Create; + return new FileStream(filename, fileOpenMode, FileAccess.Write, fileShare); } + } - /// - /// Hold an exclusive lock on the output file - /// - /// - /// - /// Open the file once for writing and hold it open until is called. - /// Maintains an exclusive lock on the file during this time. - /// - /// - public class ExclusiveLock : LockingModelBase + /// + /// Helper method to close under CurrentAppender's SecurityContext. + /// + /// + /// Does not set to null. + /// + /// + protected void CloseStream(Stream stream) + { + using (CurrentAppender.SecurityContext.Impersonate(this)) { - private Stream m_stream = null; - - /// - /// Open the file specified and prepare for logging. - /// - /// The filename to use - /// Whether to append to the file, or overwrite - /// The encoding to use - /// - /// - /// Open the file specified and prepare for logging. - /// No writes will be made until is called. - /// Must be called before any calls to , - /// and . - /// - /// - public override void OpenFile(string filename, bool append, Encoding encoding) - { - try - { - m_stream = CreateStream(filename, append, FileShare.Read); - } - catch (Exception e1) - { - CurrentAppender.ErrorHandler.Error("Unable to acquire lock on file " + filename + ". " + - e1.Message); - } - } + stream.Dispose(); + } + } + } - /// - /// Close the file - /// - /// - /// - /// Close the file. No further writes will be made. - /// - /// - public override void CloseFile() - { - CloseStream(m_stream); - m_stream = null; - } + /// + /// Hold an exclusive lock on the output file + /// + /// + /// + /// Open the file once for writing and hold it open until is called. + /// Maintains an exclusive lock on the file during this time. + /// + /// + public class ExclusiveLock : LockingModelBase + { + private Stream m_stream = null; + + /// + /// Open the file specified and prepare for logging. + /// + /// The filename to use + /// Whether to append to the file, or overwrite + /// The encoding to use + /// + /// + /// Open the file specified and prepare for logging. + /// No writes will be made until is called. + /// Must be called before any calls to , + /// and . + /// + /// + public override void OpenFile(string filename, bool append, Encoding encoding) + { + try + { + m_stream = CreateStream(filename, append, FileShare.Read); + } + catch (Exception e1) + { + CurrentAppender.ErrorHandler.Error("Unable to acquire lock on file " + filename + ". " + + e1.Message); + } + } - /// - /// Acquire the lock on the file - /// - /// A stream that is ready to be written to. - /// - /// - /// Does nothing. The lock is already taken - /// - /// - public override Stream AcquireLock() - { - return m_stream; - } + /// + /// Close the file + /// + /// + /// + /// Close the file. No further writes will be made. + /// + /// + public override void CloseFile() + { + CloseStream(m_stream); + m_stream = null; + } - /// - /// Release the lock on the file - /// - /// - /// - /// Does nothing. The lock will be released when the file is closed. - /// - /// - public override void ReleaseLock() - { - //NOP - } + /// + /// Acquire the lock on the file + /// + /// A stream that is ready to be written to. + /// + /// + /// Does nothing. The lock is already taken + /// + /// + public override Stream AcquireLock() + { + return m_stream; + } - /// - /// Initializes all resources used by this locking model. - /// - public override void ActivateOptions() - { - //NOP - } + /// + /// Release the lock on the file + /// + /// + /// + /// Does nothing. The lock will be released when the file is closed. + /// + /// + public override void ReleaseLock() + { + //NOP + } - /// - /// Disposes all resources that were initialized by this locking model. - /// - public override void OnClose() - { - //NOP - } - } + /// + /// Initializes all resources used by this locking model. + /// + public override void ActivateOptions() + { + //NOP + } - /// - /// Acquires the file lock for each write - /// - /// - /// - /// Opens the file once for each / cycle, - /// thus holding the lock for the minimal amount of time. This method of locking - /// is considerably slower than but allows - /// other processes to move/delete the log file whilst logging continues. - /// - /// - public class MinimalLock : LockingModelBase - { - private string m_filename; - private bool m_append; - private Stream m_stream = null; - - /// - /// Prepares to open the file when the first message is logged. - /// - /// The filename to use - /// Whether to append to the file, or overwrite - /// The encoding to use - /// - /// - /// Open the file specified and prepare for logging. - /// No writes will be made until is called. - /// Must be called before any calls to , - /// and . - /// - /// - public override void OpenFile(string filename, bool append, Encoding encoding) - { - m_filename = filename; - m_append = append; - } + /// + /// Disposes all resources that were initialized by this locking model. + /// + public override void OnClose() + { + //NOP + } + } - /// - /// Close the file - /// - /// - /// - /// Close the file. No further writes will be made. - /// - /// - public override void CloseFile() - { - // NOP - } - - /// - /// Acquire the lock on the file - /// - /// A stream that is ready to be written to. - /// - /// - /// Acquire the lock on the file in preparation for writing to it. - /// Return a stream pointing to the file. - /// must be called to release the lock on the output file. - /// - /// - public override Stream AcquireLock() - { - if (m_stream == null) - { - try - { - m_stream = CreateStream(m_filename, m_append, FileShare.Read); - m_append = true; - } - catch (Exception e1) - { - CurrentAppender.ErrorHandler.Error("Unable to acquire lock on file " + m_filename + ". " + - e1.Message); - } - } - - return m_stream; - } - - /// - /// Release the lock on the file - /// - /// - /// - /// Release the lock on the file. No further writes will be made to the - /// stream until is called again. - /// - /// - public override void ReleaseLock() - { - CloseStream(m_stream); - m_stream = null; - } - - /// - /// Initializes all resources used by this locking model. - /// - public override void ActivateOptions() - { - //NOP - } + /// + /// Acquires the file lock for each write + /// + /// + /// + /// Opens the file once for each / cycle, + /// thus holding the lock for the minimal amount of time. This method of locking + /// is considerably slower than but allows + /// other processes to move/delete the log file whilst logging continues. + /// + /// + public class MinimalLock : LockingModelBase + { + private string m_filename; + private bool m_append; + private Stream m_stream = null; + + /// + /// Prepares to open the file when the first message is logged. + /// + /// The filename to use + /// Whether to append to the file, or overwrite + /// The encoding to use + /// + /// + /// Open the file specified and prepare for logging. + /// No writes will be made until is called. + /// Must be called before any calls to , + /// and . + /// + /// + public override void OpenFile(string filename, bool append, Encoding encoding) + { + m_filename = filename; + m_append = append; + } - /// - /// Disposes all resources that were initialized by this locking model. - /// - public override void OnClose() - { - //NOP - } - } + /// + /// Close the file + /// + /// + /// + /// Close the file. No further writes will be made. + /// + /// + public override void CloseFile() + { + // NOP + } -#if !NETCF - /// - /// Provides cross-process file locking. - /// - /// Ron Grabowski - /// Steve Wranovsky - public class InterProcessLock : LockingModelBase + /// + /// Acquire the lock on the file + /// + /// A stream that is ready to be written to. + /// + /// + /// Acquire the lock on the file in preparation for writing to it. + /// Return a stream pointing to the file. + /// must be called to release the lock on the output file. + /// + /// + public override Stream AcquireLock() + { + if (m_stream == null) { - private Mutex m_mutex = null; - private Stream m_stream = null; - private int m_recursiveWatch = 0; - - /// - /// Open the file specified and prepare for logging. - /// - /// The filename to use - /// Whether to append to the file, or overwrite - /// The encoding to use - /// - /// - /// Open the file specified and prepare for logging. - /// No writes will be made until is called. - /// Must be called before any calls to , - /// - and . - /// - /// -#if NET_4_0 || MONO_4_0 || NETSTANDARD - [System.Security.SecuritySafeCritical] -#endif - public override void OpenFile(string filename, bool append, Encoding encoding) - { - try - { - m_stream = CreateStream(filename, append, FileShare.ReadWrite); - } - catch (Exception e1) - { - CurrentAppender.ErrorHandler.Error("Unable to acquire lock on file " + filename + ". " + - e1.Message); - } - } + try + { + m_stream = CreateStream(m_filename, m_append, FileShare.Read); + m_append = true; + } + catch (Exception e1) + { + CurrentAppender.ErrorHandler.Error("Unable to acquire lock on file " + m_filename + ". " + + e1.Message); + } + } - /// - /// Close the file - /// - /// - /// - /// Close the file. No further writes will be made. - /// - /// - public override void CloseFile() - { - try - { - CloseStream(m_stream); - m_stream = null; - } - finally - { - ReleaseLock(); - } - } + return m_stream; + } - /// - /// Acquire the lock on the file - /// - /// A stream that is ready to be written to. - /// - /// - /// Does nothing. The lock is already taken - /// - /// - public override Stream AcquireLock() - { - if (m_mutex != null) - { - // TODO: add timeout? - m_mutex.WaitOne(); - - // increment recursive watch - m_recursiveWatch++; - - // should always be true (and fast) for FileStream - if (m_stream != null) - { - if (m_stream.CanSeek) - { - m_stream.Seek(0, SeekOrigin.End); - } - } - else - { - // this can happen when the file appender cannot open a file for writing - } - } - else - { - CurrentAppender.ErrorHandler.Error( - "Programming error, no mutex available to acquire lock! From here on things will be dangerous!"); - } - - return m_stream; - } + /// + /// Release the lock on the file + /// + /// + /// + /// Release the lock on the file. No further writes will be made to the + /// stream until is called again. + /// + /// + public override void ReleaseLock() + { + CloseStream(m_stream); + m_stream = null; + } - /// - /// Releases the lock and allows others to acquire a lock. - /// - public override void ReleaseLock() - { - if (m_mutex != null) - { - if (m_recursiveWatch > 0) - { - m_recursiveWatch--; - m_mutex.ReleaseMutex(); - } - } - else - { - CurrentAppender.ErrorHandler.Error("Programming error, no mutex available to release the lock!"); - } - } + /// + /// Initializes all resources used by this locking model. + /// + public override void ActivateOptions() + { + //NOP + } - /// - /// Initializes all resources used by this locking model. - /// - public override void ActivateOptions() - { - if (m_mutex == null) - { - string mutexFriendlyFilename = CurrentAppender.File - .Replace("\\", "_") - .Replace(":", "_") - .Replace("/", "_"); - - m_mutex = new Mutex(false, mutexFriendlyFilename); - } - else - { - CurrentAppender.ErrorHandler.Error("Programming error, mutex already initialized!"); - } - } + /// + /// Disposes all resources that were initialized by this locking model. + /// + public override void OnClose() + { + //NOP + } + } - /// - /// Disposes all resources that were initialized by this locking model. - /// - public override void OnClose() - { - if (m_mutex != null) - { +#if !NETCF + /// + /// Provides cross-process file locking. + /// + /// Ron Grabowski + /// Steve Wranovsky + public class InterProcessLock : LockingModelBase + { + private Mutex m_mutex = null; + private Stream m_stream = null; + private int m_recursiveWatch = 0; + + /// + /// Open the file specified and prepare for logging. + /// + /// The filename to use + /// Whether to append to the file, or overwrite + /// The encoding to use + /// + /// + /// Open the file specified and prepare for logging. + /// No writes will be made until is called. + /// Must be called before any calls to , + /// - and . + /// + /// #if NET_4_0 || MONO_4_0 || NETSTANDARD - m_mutex.Dispose(); -#else - m_mutex.Close(); + [System.Security.SecuritySafeCritical] #endif - m_mutex = null; - } - else - { - CurrentAppender.ErrorHandler.Error("Programming error, mutex not initialized!"); - } - } + public override void OpenFile(string filename, bool append, Encoding encoding) + { + try + { + m_stream = CreateStream(filename, append, FileShare.ReadWrite); } -#endif - - /// - /// Hold no lock on the output file - /// - /// - /// - /// Open the file once and hold it open until is called. - /// Maintains no lock on the file during this time. - /// - /// - public class NoLock : LockingModelBase + catch (Exception e1) { - private Stream m_stream = null; - - /// - /// Open the file specified and prepare for logging. - /// - /// The filename to use - /// Whether to append to the file, or overwrite - /// The encoding to use - /// - /// - /// Open the file specified and prepare for logging. - /// No writes will be made until is called. - /// Must be called before any calls to , - /// and . - /// - /// - public override void OpenFile(string filename, bool append, Encoding encoding) - { - try - { - // no lock - m_stream = CreateStream(filename, append, FileShare.ReadWrite); - } - catch (Exception e1) - { - CurrentAppender.ErrorHandler.Error( - $"Unable to acquire lock on file {filename}. {e1.Message}" - ); - } - } - - /// - /// Close the file - /// - /// - /// - /// Close the file. No further writes will be made. - /// - /// - public override void CloseFile() - { - CloseStream(m_stream); - m_stream = null; - } + CurrentAppender.ErrorHandler.Error("Unable to acquire lock on file " + filename + ". " + + e1.Message); + } + } - /// - /// Acquire the lock on the file - /// - /// A stream that is ready to be written to. - /// - /// - /// Does nothing. The lock is already taken - /// - /// - public override Stream AcquireLock() - { - return m_stream; - } + /// + /// Close the file + /// + /// + /// + /// Close the file. No further writes will be made. + /// + /// + public override void CloseFile() + { + try + { + CloseStream(m_stream); + m_stream = null; + } + finally + { + ReleaseLock(); + } + } - /// - /// Release the lock on the file - /// - /// - /// - /// Does nothing. The lock will be released when the file is closed. - /// - /// - public override void ReleaseLock() - { - // NOP - } + /// + /// Acquire the lock on the file + /// + /// A stream that is ready to be written to. + /// + /// + /// Does nothing. The lock is already taken + /// + /// + public override Stream AcquireLock() + { + if (m_mutex != null) + { + // TODO: add timeout? + m_mutex.WaitOne(); - /// - /// Initializes all resources used by this locking model. - /// - public override void ActivateOptions() - { - // NOP - } + // increment recursive watch + m_recursiveWatch++; - /// - /// Disposes all resources that were initialized by this locking model. - /// - public override void OnClose() + // should always be true (and fast) for FileStream + if (m_stream != null) + { + if (m_stream.CanSeek) { - // NOP + m_stream.Seek(0, SeekOrigin.End); } + } + else + { + // this can happen when the file appender cannot open a file for writing + } } - - /// - /// Default locking model (when no locking model was configured) - /// - private static Type defaultLockingModelType = typeof(ExclusiveLock); - - /// - /// Specify default locking model - /// - /// Type of LockingModel - public static void SetDefaultLockingModelType() where TLockingModel : LockingModelBase + else { - defaultLockingModelType = typeof(TLockingModel); + CurrentAppender.ErrorHandler.Error( + "Programming error, no mutex available to acquire lock! From here on things will be dangerous!"); } - #endregion Locking Models - - #region Public Instance Constructors + return m_stream; + } - /// - /// Default constructor - /// - /// - /// - /// Default constructor - /// - /// - public FileAppender() + /// + /// Releases the lock and allows others to acquire a lock. + /// + public override void ReleaseLock() + { + if (m_mutex != null) { + if (m_recursiveWatch > 0) + { + m_recursiveWatch--; + m_mutex.ReleaseMutex(); + } } - - /// - /// Construct a new appender using the layout, file and append mode. - /// - /// the layout to use with this appender - /// the full path to the file to write to - /// flag to indicate if the file should be appended to - /// - /// - /// Obsolete constructor. - /// - /// - [Obsolete("Instead use the default constructor and set the Layout, File & AppendToFile properties")] - public FileAppender(ILayout layout, string filename, bool append) + else { - Layout = layout; - File = filename; - AppendToFile = append; - ActivateOptions(); + CurrentAppender.ErrorHandler.Error("Programming error, no mutex available to release the lock!"); } + } - /// - /// Construct a new appender using the layout and file specified. - /// The file will be appended to. - /// - /// the layout to use with this appender - /// the full path to the file to write to - /// - /// - /// Obsolete constructor. - /// - /// - [Obsolete("Instead use the default constructor and set the Layout & File properties")] - public FileAppender(ILayout layout, string filename) - : this(layout, filename, true) + /// + /// Initializes all resources used by this locking model. + /// + public override void ActivateOptions() + { + if (m_mutex == null) { - } + string mutexFriendlyFilename = CurrentAppender.File + .Replace("\\", "_") + .Replace(":", "_") + .Replace("/", "_"); - #endregion Public Instance Constructors - - #region Public Instance Properties - - /// - /// Gets or sets the path to the file that logging will be written to. - /// - /// - /// The path to the file that logging will be written to. - /// - /// - /// - /// If the path is relative it is taken as relative from - /// the application base directory. - /// - /// - public virtual string File + m_mutex = new Mutex(false, mutexFriendlyFilename); + } + else { - get { return m_fileName; } - set { m_fileName = value; } + CurrentAppender.ErrorHandler.Error("Programming error, mutex already initialized!"); } + } - /// - /// Gets or sets a flag that indicates whether the file should be - /// appended to or overwritten. - /// - /// - /// Indicates whether the file should be appended to or overwritten. - /// - /// - /// - /// If the value is set to false then the file will be overwritten, if - /// it is set to true then the file will be appended to. - /// - /// The default value is true. - /// - public bool AppendToFile + /// + /// Disposes all resources that were initialized by this locking model. + /// + public override void OnClose() + { + if (m_mutex != null) { - get { return m_appendToFile; } - set { m_appendToFile = value; } +#if NET_4_0 || MONO_4_0 || NETSTANDARD + m_mutex.Dispose(); +#else + m_mutex.Close(); +#endif + m_mutex = null; } - - /// - /// Gets or sets used to write to the file. - /// - /// - /// The used to write to the file. - /// - /// - /// - /// The default encoding set is - /// which is the encoding for the system's current ANSI code page. - /// - /// - public Encoding Encoding + else { - get { return m_encoding; } - set { m_encoding = value; } + CurrentAppender.ErrorHandler.Error("Programming error, mutex not initialized!"); } + } + } +#endif - /// - /// Gets or sets the used to write to the file. - /// - /// - /// The used to write to the file. - /// - /// - /// - /// Unless a specified here for this appender - /// the is queried for the - /// security context to use. The default behavior is to use the security context - /// of the current thread. - /// - /// - public SecurityContext SecurityContext + /// + /// Hold no lock on the output file + /// + /// + /// + /// Open the file once and hold it open until is called. + /// Maintains no lock on the file during this time. + /// + /// + public class NoLock : LockingModelBase + { + private Stream m_stream = null; + + /// + /// Open the file specified and prepare for logging. + /// + /// The filename to use + /// Whether to append to the file, or overwrite + /// The encoding to use + /// + /// + /// Open the file specified and prepare for logging. + /// No writes will be made until is called. + /// Must be called before any calls to , + /// and . + /// + /// + public override void OpenFile(string filename, bool append, Encoding encoding) + { + try + { + // no lock + m_stream = CreateStream(filename, append, FileShare.ReadWrite); + } + catch (Exception e1) { - get { return m_securityContext; } - set { m_securityContext = value; } + CurrentAppender.ErrorHandler.Error( + $"Unable to acquire lock on file {filename}. {e1.Message}" + ); } + } + + /// + /// Close the file + /// + /// + /// + /// Close the file. No further writes will be made. + /// + /// + public override void CloseFile() + { + CloseStream(m_stream); + m_stream = null; + } + + /// + /// Acquire the lock on the file + /// + /// A stream that is ready to be written to. + /// + /// + /// Does nothing. The lock is already taken + /// + /// + public override Stream AcquireLock() + { + return m_stream; + } + + /// + /// Release the lock on the file + /// + /// + /// + /// Does nothing. The lock will be released when the file is closed. + /// + /// + public override void ReleaseLock() + { + // NOP + } + + /// + /// Initializes all resources used by this locking model. + /// + public override void ActivateOptions() + { + // NOP + } + + /// + /// Disposes all resources that were initialized by this locking model. + /// + public override void OnClose() + { + // NOP + } + } + + /// + /// Default locking model (when no locking model was configured) + /// + private static Type defaultLockingModelType = typeof(ExclusiveLock); + + /// + /// Specify default locking model + /// + /// Type of LockingModel + public static void SetDefaultLockingModelType() where TLockingModel : LockingModelBase + { + defaultLockingModelType = typeof(TLockingModel); + } + + #endregion Locking Models + + #region Public Instance Constructors + + /// + /// Default constructor + /// + /// + /// + /// Default constructor + /// + /// + public FileAppender() + { + } + + /// + /// Construct a new appender using the layout, file and append mode. + /// + /// the layout to use with this appender + /// the full path to the file to write to + /// flag to indicate if the file should be appended to + /// + /// + /// Obsolete constructor. + /// + /// + [Obsolete("Instead use the default constructor and set the Layout, File & AppendToFile properties")] + public FileAppender(ILayout layout, string filename, bool append) + { + Layout = layout; + File = filename; + AppendToFile = append; + ActivateOptions(); + } + + /// + /// Construct a new appender using the layout and file specified. + /// The file will be appended to. + /// + /// the layout to use with this appender + /// the full path to the file to write to + /// + /// + /// Obsolete constructor. + /// + /// + [Obsolete("Instead use the default constructor and set the Layout & File properties")] + public FileAppender(ILayout layout, string filename) + : this(layout, filename, true) + { + } + + #endregion Public Instance Constructors + + #region Public Instance Properties + + /// + /// Gets or sets the path to the file that logging will be written to. + /// + /// + /// The path to the file that logging will be written to. + /// + /// + /// + /// If the path is relative it is taken as relative from + /// the application base directory. + /// + /// + public virtual string File + { + get { return m_fileName; } + set { m_fileName = value; } + } + + /// + /// Gets or sets a flag that indicates whether the file should be + /// appended to or overwritten. + /// + /// + /// Indicates whether the file should be appended to or overwritten. + /// + /// + /// + /// If the value is set to false then the file will be overwritten, if + /// it is set to true then the file will be appended to. + /// + /// The default value is true. + /// + public bool AppendToFile + { + get { return m_appendToFile; } + set { m_appendToFile = value; } + } + + /// + /// Gets or sets used to write to the file. + /// + /// + /// The used to write to the file. + /// + /// + /// + /// The default encoding set is + /// which is the encoding for the system's current ANSI code page. + /// + /// + public Encoding Encoding + { + get { return m_encoding; } + set { m_encoding = value; } + } + + /// + /// Gets or sets the used to write to the file. + /// + /// + /// The used to write to the file. + /// + /// + /// + /// Unless a specified here for this appender + /// the is queried for the + /// security context to use. The default behavior is to use the security context + /// of the current thread. + /// + /// + public SecurityContext SecurityContext + { + get { return m_securityContext; } + set { m_securityContext = value; } + } #if NETCF /// @@ -1199,479 +1199,479 @@ public SecurityContext SecurityContext /// /// #else - /// - /// Gets or sets the used to handle locking of the file. - /// - /// - /// The used to lock the file. - /// - /// - /// - /// Gets or sets the used to handle locking of the file. - /// - /// - /// There are three built in locking models, , and . - /// The first locks the file from the start of logging to the end, the - /// second locks only for the minimal amount of time when logging each message - /// and the last synchronizes processes using a named system wide Mutex. - /// - /// - /// The default locking model is the . - /// - /// + /// + /// Gets or sets the used to handle locking of the file. + /// + /// + /// The used to lock the file. + /// + /// + /// + /// Gets or sets the used to handle locking of the file. + /// + /// + /// There are three built in locking models, , and . + /// The first locks the file from the start of logging to the end, the + /// second locks only for the minimal amount of time when logging each message + /// and the last synchronizes processes using a named system wide Mutex. + /// + /// + /// The default locking model is the . + /// + /// #endif - public FileAppender.LockingModelBase LockingModel - { - get { return m_lockingModel; } - set { m_lockingModel = value; } - } + public FileAppender.LockingModelBase LockingModel + { + get { return m_lockingModel; } + set { m_lockingModel = value; } + } - #endregion Public Instance Properties - - #region Override implementation of AppenderSkeleton - - /// - /// Activate the options on the file appender. - /// - /// - /// - /// This is part of the delayed object - /// activation scheme. The method must - /// be called on this object after the configuration properties have - /// been set. Until is called this - /// object is in an undefined state and must not be used. - /// - /// - /// If any of the configuration properties are modified then - /// must be called again. - /// - /// - /// This will cause the file to be opened. - /// - /// - public override void ActivateOptions() - { - base.ActivateOptions(); + #endregion Public Instance Properties - if (m_securityContext == null) - { - m_securityContext = SecurityContextProvider.DefaultProvider.CreateSecurityContext(this); - } + #region Override implementation of AppenderSkeleton - if (m_lockingModel == null) - { - m_lockingModel = (LockingModelBase) Activator.CreateInstance(defaultLockingModelType); - } + /// + /// Activate the options on the file appender. + /// + /// + /// + /// This is part of the delayed object + /// activation scheme. The method must + /// be called on this object after the configuration properties have + /// been set. Until is called this + /// object is in an undefined state and must not be used. + /// + /// + /// If any of the configuration properties are modified then + /// must be called again. + /// + /// + /// This will cause the file to be opened. + /// + /// + public override void ActivateOptions() + { + base.ActivateOptions(); - m_lockingModel.CurrentAppender = this; - m_lockingModel.ActivateOptions(); + if (m_securityContext == null) + { + m_securityContext = SecurityContextProvider.DefaultProvider.CreateSecurityContext(this); + } - if (m_fileName != null) - { - using (SecurityContext.Impersonate(this)) - { - m_fileName = ConvertToFullPath(m_fileName.Trim()); - } + if (m_lockingModel == null) + { + m_lockingModel = (LockingModelBase)Activator.CreateInstance(defaultLockingModelType); + } - SafeOpenFile(m_fileName, m_appendToFile); - } - else - { - LogLog.Warn(declaringType, "FileAppender: File option not set for appender [" + Name + "]."); - LogLog.Warn(declaringType, "FileAppender: Are you using FileAppender instead of ConsoleAppender?"); - } + m_lockingModel.CurrentAppender = this; + m_lockingModel.ActivateOptions(); + + if (m_fileName != null) + { + using (SecurityContext.Impersonate(this)) + { + m_fileName = ConvertToFullPath(m_fileName.Trim()); } - #endregion Override implementation of AppenderSkeleton + SafeOpenFile(m_fileName, m_appendToFile); + } + else + { + LogLog.Warn(declaringType, "FileAppender: File option not set for appender [" + Name + "]."); + LogLog.Warn(declaringType, "FileAppender: Are you using FileAppender instead of ConsoleAppender?"); + } + } + + #endregion Override implementation of AppenderSkeleton - #region Override implementation of TextWriterAppender + #region Override implementation of TextWriterAppender - /// - /// Closes any previously opened file and calls the parent's . - /// - /// - /// - /// Resets the filename and the file stream. - /// - /// - protected override void Reset() + /// + /// Closes any previously opened file and calls the parent's . + /// + /// + /// + /// Resets the filename and the file stream. + /// + /// + protected override void Reset() + { + base.Reset(); + m_fileName = null; + } + + /// + /// Close this appender instance. The underlying stream or writer is also closed. + /// + protected override void OnClose() + { + base.OnClose(); + m_lockingModel.OnClose(); + } + + /// + /// Called to initialize the file writer + /// + /// + /// + /// Will be called for each logged message until the file is + /// successfully opened. + /// + /// + protected override void PrepareWriter() + { + SafeOpenFile(m_fileName, m_appendToFile); + } + + /// + /// This method is called by the + /// method. + /// + /// The event to log. + /// + /// + /// Writes a log statement to the output stream if the output stream exists + /// and is writable. + /// + /// + /// The format of the output will depend on the appender's layout. + /// + /// + protected override void Append(LoggingEvent loggingEvent) + { + if (m_stream.AcquireLock()) + { + try { - base.Reset(); - m_fileName = null; + base.Append(loggingEvent); } - - /// - /// Close this appender instance. The underlying stream or writer is also closed. - /// - protected override void OnClose() + finally { - base.OnClose(); - m_lockingModel.OnClose(); + m_stream.ReleaseLock(); } + } + } - /// - /// Called to initialize the file writer - /// - /// - /// - /// Will be called for each logged message until the file is - /// successfully opened. - /// - /// - protected override void PrepareWriter() + /// + /// This method is called by the + /// method. + /// + /// The array of events to log. + /// + /// + /// Acquires the output file locks once before writing all the events to + /// the stream. + /// + /// + protected override void Append(LoggingEvent[] loggingEvents) + { + if (m_stream.AcquireLock()) + { + try { - SafeOpenFile(m_fileName, m_appendToFile); + base.Append(loggingEvents); } - - /// - /// This method is called by the - /// method. - /// - /// The event to log. - /// - /// - /// Writes a log statement to the output stream if the output stream exists - /// and is writable. - /// - /// - /// The format of the output will depend on the appender's layout. - /// - /// - protected override void Append(LoggingEvent loggingEvent) + finally { - if (m_stream.AcquireLock()) - { - try - { - base.Append(loggingEvent); - } - finally - { - m_stream.ReleaseLock(); - } - } + m_stream.ReleaseLock(); } + } + } - /// - /// This method is called by the - /// method. - /// - /// The array of events to log. - /// - /// - /// Acquires the output file locks once before writing all the events to - /// the stream. - /// - /// - protected override void Append(LoggingEvent[] loggingEvents) + /// + /// Writes a footer as produced by the embedded layout's property. + /// + /// + /// + /// Writes a footer as produced by the embedded layout's property. + /// + /// + protected override void WriteFooter() + { + if (m_stream != null) + { + //WriteFooter can be called even before a file is opened + m_stream.AcquireLock(); + try { - if (m_stream.AcquireLock()) - { - try - { - base.Append(loggingEvents); - } - finally - { - m_stream.ReleaseLock(); - } - } + base.WriteFooter(); } - - /// - /// Writes a footer as produced by the embedded layout's property. - /// - /// - /// - /// Writes a footer as produced by the embedded layout's property. - /// - /// - protected override void WriteFooter() + finally { - if (m_stream != null) - { - //WriteFooter can be called even before a file is opened - m_stream.AcquireLock(); - try - { - base.WriteFooter(); - } - finally - { - m_stream.ReleaseLock(); - } - } + m_stream.ReleaseLock(); } + } + } - /// - /// Writes a header produced by the embedded layout's property. - /// - /// - /// - /// Writes a header produced by the embedded layout's property. - /// - /// - protected override void WriteHeader() + /// + /// Writes a header produced by the embedded layout's property. + /// + /// + /// + /// Writes a header produced by the embedded layout's property. + /// + /// + protected override void WriteHeader() + { + if (m_stream != null) + { + if (m_stream.AcquireLock()) { - if (m_stream != null) - { - if (m_stream.AcquireLock()) - { - try - { - base.WriteHeader(); - } - finally - { - m_stream.ReleaseLock(); - } - } - } + try + { + base.WriteHeader(); + } + finally + { + m_stream.ReleaseLock(); + } } + } + } - /// - /// Closes the underlying . - /// - /// - /// - /// Closes the underlying . - /// - /// - protected override void CloseWriter() + /// + /// Closes the underlying . + /// + /// + /// + /// Closes the underlying . + /// + /// + protected override void CloseWriter() + { + if (m_stream != null) + { + m_stream.AcquireLock(); + try { - if (m_stream != null) - { - m_stream.AcquireLock(); - try - { - base.CloseWriter(); - } - finally - { - m_stream.ReleaseLock(); - } - } + base.CloseWriter(); } + finally + { + m_stream.ReleaseLock(); + } + } + } - #endregion Override implementation of TextWriterAppender + #endregion Override implementation of TextWriterAppender - #region Public Instance Methods + #region Public Instance Methods + + /// + /// Closes the previously opened file. + /// + /// + /// + /// Writes the to the file and then + /// closes the file. + /// + /// + protected void CloseFile() + { + WriteFooterAndCloseWriter(); + } + + #endregion Public Instance Methods + + #region Protected Instance Methods + + /// + /// Sets and opens the file where the log output will go. The specified file must be writable. + /// + /// The path to the log file. Must be a fully qualified path. + /// If true will append to fileName. Otherwise will truncate fileName + /// + /// + /// Calls but guarantees not to throw an exception. + /// Errors are passed to the . + /// + /// + protected virtual void SafeOpenFile(string fileName, bool append) + { + try + { + OpenFile(fileName, append); + } + catch (Exception e) + { + ErrorHandler.Error("OpenFile(" + fileName + "," + append + ") call failed.", e, + ErrorCode.FileOpenFailure); + } + } - /// - /// Closes the previously opened file. - /// - /// - /// - /// Writes the to the file and then - /// closes the file. - /// - /// - protected void CloseFile() + /// + /// Sets and opens the file where the log output will go. The specified file must be writable. + /// + /// The path to the log file. Must be a fully qualified path. + /// If true will append to fileName. Otherwise will truncate fileName + /// + /// + /// If there was already an opened file, then the previous file + /// is closed first. + /// + /// + /// This method will ensure that the directory structure + /// for the specified exists. + /// + /// + protected virtual void OpenFile(string fileName, bool append) + { + if (LogLog.IsErrorEnabled) + { + // Internal check that the fileName passed in is a rooted path + bool isPathRooted = false; + using (SecurityContext.Impersonate(this)) { - WriteFooterAndCloseWriter(); + isPathRooted = Path.IsPathRooted(fileName); } - #endregion Public Instance Methods - - #region Protected Instance Methods - - /// - /// Sets and opens the file where the log output will go. The specified file must be writable. - /// - /// The path to the log file. Must be a fully qualified path. - /// If true will append to fileName. Otherwise will truncate fileName - /// - /// - /// Calls but guarantees not to throw an exception. - /// Errors are passed to the . - /// - /// - protected virtual void SafeOpenFile(string fileName, bool append) + if (!isPathRooted) { - try - { - OpenFile(fileName, append); - } - catch (Exception e) - { - ErrorHandler.Error("OpenFile(" + fileName + "," + append + ") call failed.", e, - ErrorCode.FileOpenFailure); - } + LogLog.Error(declaringType, + "INTERNAL ERROR. OpenFile(" + fileName + "): File name is not fully qualified."); } + } - /// - /// Sets and opens the file where the log output will go. The specified file must be writable. - /// - /// The path to the log file. Must be a fully qualified path. - /// If true will append to fileName. Otherwise will truncate fileName - /// - /// - /// If there was already an opened file, then the previous file - /// is closed first. - /// - /// - /// This method will ensure that the directory structure - /// for the specified exists. - /// - /// - protected virtual void OpenFile(string fileName, bool append) - { - if (LogLog.IsErrorEnabled) - { - // Internal check that the fileName passed in is a rooted path - bool isPathRooted = false; - using (SecurityContext.Impersonate(this)) - { - isPathRooted = Path.IsPathRooted(fileName); - } - - if (!isPathRooted) - { - LogLog.Error(declaringType, - "INTERNAL ERROR. OpenFile(" + fileName + "): File name is not fully qualified."); - } - } + lock (this) + { + Reset(); - lock (this) - { - Reset(); - - LogLog.Debug(declaringType, "Opening file for writing [" + fileName + "] append [" + append + "]"); - - // Save these for later, allowing retries if file open fails - m_fileName = fileName; - m_appendToFile = append; - - LockingModel.CurrentAppender = this; - LockingModel.OpenFile(fileName, append, m_encoding); - m_stream = new LockingStream(LockingModel); - - if (m_stream != null) - { - m_stream.AcquireLock(); - try - { - SetQWForFiles(m_stream); - } - finally - { - m_stream.ReleaseLock(); - } - } - - WriteHeader(); - } - } + LogLog.Debug(declaringType, "Opening file for writing [" + fileName + "] append [" + append + "]"); - /// - /// Sets the quiet writer used for file output - /// - /// the file stream that has been opened for writing - /// - /// - /// This implementation of creates a - /// over the and passes it to the - /// method. - /// - /// - /// This method can be overridden by sub classes that want to wrap the - /// in some way, for example to encrypt the output - /// data using a System.Security.Cryptography.CryptoStream. - /// - /// - protected virtual void SetQWForFiles(Stream fileStream) + // Save these for later, allowing retries if file open fails + m_fileName = fileName; + m_appendToFile = append; + + LockingModel.CurrentAppender = this; + LockingModel.OpenFile(fileName, append, m_encoding); + m_stream = new LockingStream(LockingModel); + + if (m_stream != null) { + m_stream.AcquireLock(); + try + { + SetQWForFiles(m_stream); + } + finally + { + m_stream.ReleaseLock(); + } + } + + WriteHeader(); + } + } + + /// + /// Sets the quiet writer used for file output + /// + /// the file stream that has been opened for writing + /// + /// + /// This implementation of creates a + /// over the and passes it to the + /// method. + /// + /// + /// This method can be overridden by sub classes that want to wrap the + /// in some way, for example to encrypt the output + /// data using a System.Security.Cryptography.CryptoStream. + /// + /// + protected virtual void SetQWForFiles(Stream fileStream) + { #pragma warning disable CA2000 // Dispose objects before losing scope - StreamWriter writer = new StreamWriter(fileStream, m_encoding); + StreamWriter writer = new StreamWriter(fileStream, m_encoding); #pragma warning restore CA2000 // Dispose objects before losing scope - SetQWForFiles(writer); - } + SetQWForFiles(writer); + } - /// - /// Sets the quiet writer being used. - /// - /// the writer over the file stream that has been opened for writing - /// - /// - /// This method can be overridden by sub classes that want to - /// wrap the in some way. - /// - /// - protected virtual void SetQWForFiles(TextWriter writer) - { - QuietWriter = new QuietTextWriter(writer, ErrorHandler); - } + /// + /// Sets the quiet writer being used. + /// + /// the writer over the file stream that has been opened for writing + /// + /// + /// This method can be overridden by sub classes that want to + /// wrap the in some way. + /// + /// + protected virtual void SetQWForFiles(TextWriter writer) + { + QuietWriter = new QuietTextWriter(writer, ErrorHandler); + } - #endregion Protected Instance Methods - - #region Protected Static Methods - - /// - /// Convert a path into a fully qualified path. - /// - /// The path to convert. - /// The fully qualified path. - /// - /// - /// Converts the path specified to a fully - /// qualified path. If the path is relative it is - /// taken as relative from the application base - /// directory. - /// - /// - protected static string ConvertToFullPath(string path) - { - return SystemInfo.ConvertToFullPath(path); - } + #endregion Protected Instance Methods + + #region Protected Static Methods + + /// + /// Convert a path into a fully qualified path. + /// + /// The path to convert. + /// The fully qualified path. + /// + /// + /// Converts the path specified to a fully + /// qualified path. If the path is relative it is + /// taken as relative from the application base + /// directory. + /// + /// + protected static string ConvertToFullPath(string path) + { + return SystemInfo.ConvertToFullPath(path); + } - #endregion Protected Static Methods + #endregion Protected Static Methods - #region Private Instance Fields + #region Private Instance Fields - /// - /// Flag to indicate if we should append to the file - /// or overwrite the file. The default is to append. - /// - private bool m_appendToFile = true; + /// + /// Flag to indicate if we should append to the file + /// or overwrite the file. The default is to append. + /// + private bool m_appendToFile = true; - /// - /// The name of the log file. - /// - private string m_fileName = null; + /// + /// The name of the log file. + /// + private string m_fileName = null; - /// - /// The encoding to use for the file stream. - /// - private Encoding m_encoding = Encoding.GetEncoding(0); + /// + /// The encoding to use for the file stream. + /// + private Encoding m_encoding = Encoding.GetEncoding(0); - /// - /// The security context to use for privileged calls - /// - private SecurityContext m_securityContext; + /// + /// The security context to use for privileged calls + /// + private SecurityContext m_securityContext; - /// - /// The stream to log to. Has added locking semantics - /// - private FileAppender.LockingStream m_stream = null; + /// + /// The stream to log to. Has added locking semantics + /// + private FileAppender.LockingStream m_stream = null; - /// - /// The locking model to use - /// - private FileAppender.LockingModelBase m_lockingModel; + /// + /// The locking model to use + /// + private FileAppender.LockingModelBase m_lockingModel; - #endregion Private Instance Fields + #endregion Private Instance Fields - #region Private Static Fields + #region Private Static Fields - /// - /// The fully qualified type of the FileAppender class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(FileAppender); + /// + /// The fully qualified type of the FileAppender class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(FileAppender); - #endregion Private Static Fields - } + #endregion Private Static Fields + } } \ No newline at end of file diff --git a/src/log4net/Appender/ForwardingAppender.cs b/src/log4net/Appender/ForwardingAppender.cs index f1a13964..57d29078 100644 --- a/src/log4net/Appender/ForwardingAppender.cs +++ b/src/log4net/Appender/ForwardingAppender.cs @@ -71,7 +71,7 @@ public ForwardingAppender() protected override void OnClose() { // Remove all the attached appenders - lock(this) + lock (this) { if (m_appenderAttachedImpl != null) { @@ -89,14 +89,14 @@ protected override void OnClose() /// Delivers the logging event to all the attached appenders. /// /// - protected override void Append(LoggingEvent loggingEvent) + protected override void Append(LoggingEvent loggingEvent) { // Pass the logging event on the the attached appenders if (m_appenderAttachedImpl != null) { m_appenderAttachedImpl.AppendLoopOnAppenders(loggingEvent); } - } + } /// /// Forward the logging events to the attached appenders @@ -107,14 +107,14 @@ protected override void Append(LoggingEvent loggingEvent) /// Delivers the logging events to all the attached appenders. /// /// - protected override void Append(LoggingEvent[] loggingEvents) + protected override void Append(LoggingEvent[] loggingEvents) { // Pass the logging event on the the attached appenders if (m_appenderAttachedImpl != null) { m_appenderAttachedImpl.AppendLoopOnAppenders(loggingEvents); } - } + } #endregion Override implementation of AppenderSkeleton @@ -131,15 +131,15 @@ protected override void Append(LoggingEvent[] loggingEvents) /// appenders, then it won't be added again. /// /// - public virtual void AddAppender(IAppender newAppender) + public virtual void AddAppender(IAppender newAppender) { if (newAppender == null) { throw new ArgumentNullException("newAppender"); } - lock(this) + lock (this) { - if (m_appenderAttachedImpl == null) + if (m_appenderAttachedImpl == null) { m_appenderAttachedImpl = new log4net.Util.AppenderAttachedImpl(); } @@ -158,17 +158,17 @@ public virtual void AddAppender(IAppender newAppender) /// /// A collection of the appenders in this appender. /// - public virtual AppenderCollection Appenders + public virtual AppenderCollection Appenders { get { - lock(this) + lock (this) { if (m_appenderAttachedImpl == null) { return AppenderCollection.EmptyCollection; } - else + else { return m_appenderAttachedImpl.Appenders; } @@ -188,9 +188,9 @@ public virtual AppenderCollection Appenders /// Get the named appender attached to this appender. /// /// - public virtual IAppender GetAppender(string name) + public virtual IAppender GetAppender(string name) { - lock(this) + lock (this) { if (m_appenderAttachedImpl == null || name == null) { @@ -209,11 +209,11 @@ public virtual IAppender GetAppender(string name) /// This is useful when re-reading configuration information. /// /// - public virtual void RemoveAllAppenders() + public virtual void RemoveAllAppenders() { - lock(this) + lock (this) { - if (m_appenderAttachedImpl != null) + if (m_appenderAttachedImpl != null) { m_appenderAttachedImpl.RemoveAllAppenders(); m_appenderAttachedImpl = null; @@ -231,11 +231,11 @@ public virtual void RemoveAllAppenders() /// If you are discarding the appender you must call /// on the appender removed. /// - public virtual IAppender RemoveAppender(IAppender appender) + public virtual IAppender RemoveAppender(IAppender appender) { - lock(this) + lock (this) { - if (appender != null && m_appenderAttachedImpl != null) + if (appender != null && m_appenderAttachedImpl != null) { return m_appenderAttachedImpl.RemoveAppender(appender); } @@ -253,9 +253,9 @@ public virtual IAppender RemoveAppender(IAppender appender) /// If you are discarding the appender you must call /// on the appender removed. /// - public virtual IAppender RemoveAppender(string name) + public virtual IAppender RemoveAppender(string name) { - lock(this) + lock (this) { if (name != null && m_appenderAttachedImpl != null) { @@ -264,7 +264,7 @@ public virtual IAppender RemoveAppender(string name) } return null; } - + #endregion Implementation of IAppenderAttachable #region Private Instance Fields diff --git a/src/log4net/Appender/IFlushable.cs b/src/log4net/Appender/IFlushable.cs index 2cb7ae3f..65c7bbf1 100644 --- a/src/log4net/Appender/IFlushable.cs +++ b/src/log4net/Appender/IFlushable.cs @@ -21,39 +21,39 @@ namespace log4net.Appender { + /// + /// Interface that can be implemented by Appenders that buffer logging data and expose a method. + /// + public interface IFlushable + { /// - /// Interface that can be implemented by Appenders that buffer logging data and expose a method. + /// Flushes any buffered log data. /// - public interface IFlushable - { - /// - /// Flushes any buffered log data. - /// - /// - /// Appenders that implement the method must do so in a thread-safe manner: it can be called concurrently with - /// the method. - /// - /// Typically this is done by locking on the Appender instance, e.g.: - /// - /// - /// - /// - /// - /// The parameter is only relevant for appenders that process logging events asynchronously, - /// such as . - /// - /// - /// The maximum time to wait for logging events to be flushed. - /// True if all logging events were flushed successfully, else false. - bool Flush(int millisecondsTimeout); - } + /// + /// Appenders that implement the method must do so in a thread-safe manner: it can be called concurrently with + /// the method. + /// + /// Typically this is done by locking on the Appender instance, e.g.: + /// + /// + /// + /// + /// + /// The parameter is only relevant for appenders that process logging events asynchronously, + /// such as . + /// + /// + /// The maximum time to wait for logging events to be flushed. + /// True if all logging events were flushed successfully, else false. + bool Flush(int millisecondsTimeout); + } } diff --git a/src/log4net/Appender/LocalSyslogAppender.cs b/src/log4net/Appender/LocalSyslogAppender.cs index 3cd0c16d..549d2ee1 100644 --- a/src/log4net/Appender/LocalSyslogAppender.cs +++ b/src/log4net/Appender/LocalSyslogAppender.cs @@ -27,7 +27,7 @@ using log4net.Core; using log4net.Util; -namespace log4net.Appender +namespace log4net.Appender { /// /// Logs events to a local syslog service. @@ -62,7 +62,7 @@ namespace log4net.Appender /// /// Rob Lyon /// Nicko Cadell - public class LocalSyslogAppender : AppenderSkeleton + public class LocalSyslogAppender : AppenderSkeleton { #region Enumerations @@ -262,14 +262,14 @@ public enum SyslogFacility /// This instance of the class is set up to write /// to a local syslog service. /// - public LocalSyslogAppender() + public LocalSyslogAppender() { } #endregion // Public Instance Constructors #region Public Instance Properties - + /// /// Message identity /// @@ -300,7 +300,7 @@ public SyslogFacility Facility get { return m_facility; } set { m_facility = value; } } - + #endregion // Public Instance Properties /// @@ -341,7 +341,7 @@ public void AddMapping(LevelSeverity mapping) public override void ActivateOptions() { base.ActivateOptions(); - + m_levelMapping.ActivateOptions(); string identString = m_identity; @@ -382,7 +382,7 @@ public override void ActivateOptions() #if !NETSTANDARD1_3 [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, UnmanagedCode = true)] #endif - protected override void Append(LoggingEvent loggingEvent) + protected override void Append(LoggingEvent loggingEvent) { int priority = GeneratePriority(m_facility, GetSeverity(loggingEvent.Level)); string message = RenderLoggingEvent(loggingEvent); @@ -412,11 +412,11 @@ protected override void OnClose() // close syslog closelog(); } - catch(DllNotFoundException) + catch (DllNotFoundException) { // Ignore dll not found at this point } - + if (m_handleToIdentity != IntPtr.Zero) { // free global ident @@ -464,30 +464,30 @@ protected virtual SyslogSeverity GetSeverity(Level level) // Fallback to sensible default values // - if (level >= Level.Alert) + if (level >= Level.Alert) { return SyslogSeverity.Alert; - } - else if (level >= Level.Critical) + } + else if (level >= Level.Critical) { return SyslogSeverity.Critical; - } - else if (level >= Level.Error) + } + else if (level >= Level.Error) { return SyslogSeverity.Error; - } - else if (level >= Level.Warn) + } + else if (level >= Level.Warn) { return SyslogSeverity.Warning; - } - else if (level >= Level.Notice) + } + else if (level >= Level.Notice) { return SyslogSeverity.Notice; - } - else if (level >= Level.Info) + } + else if (level >= Level.Info) { return SyslogSeverity.Informational; - } + } // Default setting return SyslogSeverity.Debug; } @@ -536,7 +536,7 @@ private static int GeneratePriority(SyslogFacility facility, SyslogSeverity seve #endregion // Private Instances Fields #region External Members - + /// /// Open connection to system logger. /// @@ -555,7 +555,7 @@ private static int GeneratePriority(SyslogFacility facility, SyslogSeverity seve /// string to "%s". /// /// - [DllImport("libc", CharSet=CharSet.Ansi, CallingConvention=CallingConvention.Cdecl)] + [DllImport("libc", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] private static extern void syslog(int priority, string format, string message); /// diff --git a/src/log4net/Appender/ManagedColoredConsoleAppender.cs b/src/log4net/Appender/ManagedColoredConsoleAppender.cs index ecc69490..263ce17a 100644 --- a/src/log4net/Appender/ManagedColoredConsoleAppender.cs +++ b/src/log4net/Appender/ManagedColoredConsoleAppender.cs @@ -98,7 +98,7 @@ namespace log4net.Appender /// Rick Hobbs /// Nicko Cadell /// Pavlos Touboulidis - public class ManagedColoredConsoleAppender: AppenderSkeleton + public class ManagedColoredConsoleAppender : AppenderSkeleton { /// /// Initializes a new instance of the class. @@ -107,10 +107,10 @@ public class ManagedColoredConsoleAppender: AppenderSkeleton /// The instance of the class is set up to write /// to the standard output stream. /// - public ManagedColoredConsoleAppender() + public ManagedColoredConsoleAppender() { } - + #region Public Instance Properties /// /// Target is the value of the console output stream. @@ -136,8 +136,8 @@ public virtual string Target if (SystemInfo.EqualsIgnoringCase(ConsoleError, v)) { m_writeToErrorStream = true; - } - else + } + else { m_writeToErrorStream = false; } @@ -174,18 +174,18 @@ public void AddMapping(LevelColors mapping) /// The format of the output will depend on the appender's layout. /// /// - protected override void Append(log4net.Core.LoggingEvent loggingEvent) + protected override void Append(log4net.Core.LoggingEvent loggingEvent) { System.IO.TextWriter writer; - + if (m_writeToErrorStream) writer = Console.Error; else writer = Console.Out; - + // Reset color Console.ResetColor(); - + // see if there is a specified lookup LevelColors levelColors = m_levelMapping.Lookup(loggingEvent.Level) as LevelColors; if (levelColors != null) @@ -197,7 +197,7 @@ protected override void Append(log4net.Core.LoggingEvent loggingEvent) if (levelColors.HasForeColor) Console.ForegroundColor = levelColors.ForeColor; } - + // Render the event to a string string strLoggingMessage = RenderLoggingEvent(loggingEvent); // and write it @@ -304,11 +304,13 @@ public ConsoleColor ForeColor } private ConsoleColor foreColor; private bool hasForeColor; - internal bool HasForeColor { - get { - return hasForeColor; - } - } + internal bool HasForeColor + { + get + { + return hasForeColor; + } + } /// /// The mapped background color for the specified level @@ -327,12 +329,14 @@ public ConsoleColor BackColor set { this.backColor = value; this.hasBackColor = true; } } private ConsoleColor backColor; - private bool hasBackColor; - internal bool HasBackColor { - get { - return hasBackColor; - } - } + private bool hasBackColor; + internal bool HasBackColor + { + get + { + return hasBackColor; + } + } } #endregion // LevelColors LevelMapping Entry } diff --git a/src/log4net/Appender/MemoryAppender.cs b/src/log4net/Appender/MemoryAppender.cs index 5c30c2ba..486a4106 100644 --- a/src/log4net/Appender/MemoryAppender.cs +++ b/src/log4net/Appender/MemoryAppender.cs @@ -86,10 +86,10 @@ public MemoryAppender() : base() /// public virtual LoggingEvent[] GetEvents() { - lock (m_eventsList.SyncRoot) - { - return (LoggingEvent[]) m_eventsList.ToArray(typeof(LoggingEvent)); - } + lock (m_eventsList.SyncRoot) + { + return (LoggingEvent[])m_eventsList.ToArray(typeof(LoggingEvent)); + } } /// @@ -113,8 +113,8 @@ public virtual LoggingEvent[] GetEvents() public virtual bool OnlyFixPartialEventData { get { return (Fix == FixFlags.Partial); } - set - { + set + { if (value) { Fix = FixFlags.Partial; @@ -153,18 +153,18 @@ public virtual FixFlags Fix /// /// Stores the in the events list. /// - protected override void Append(LoggingEvent loggingEvent) + protected override void Append(LoggingEvent loggingEvent) { // Because we are caching the LoggingEvent beyond the // lifetime of the Append() method we must fix any // volatile data in the event. loggingEvent.Fix = this.Fix; - lock (m_eventsList.SyncRoot) - { - m_eventsList.Add(loggingEvent); - } - } + lock (m_eventsList.SyncRoot) + { + m_eventsList.Add(loggingEvent); + } + } #endregion Override implementation of AppenderSkeleton @@ -178,30 +178,30 @@ protected override void Append(LoggingEvent loggingEvent) /// public virtual void Clear() { - lock (m_eventsList.SyncRoot) - { - m_eventsList.Clear(); - } + lock (m_eventsList.SyncRoot) + { + m_eventsList.Clear(); + } } - /// - /// Gets the events that have been logged and clears the list of events. - /// - /// The events that have been logged - /// - /// - /// Gets the events that have been logged and clears the list of events. - /// - /// - public virtual LoggingEvent[] PopAllEvents() - { - lock (m_eventsList.SyncRoot) - { - LoggingEvent[] tmp = (LoggingEvent[]) m_eventsList.ToArray(typeof (LoggingEvent)); - m_eventsList.Clear(); - return tmp; - } - } + /// + /// Gets the events that have been logged and clears the list of events. + /// + /// The events that have been logged + /// + /// + /// Gets the events that have been logged and clears the list of events. + /// + /// + public virtual LoggingEvent[] PopAllEvents() + { + lock (m_eventsList.SyncRoot) + { + LoggingEvent[] tmp = (LoggingEvent[])m_eventsList.ToArray(typeof(LoggingEvent)); + m_eventsList.Clear(); + return tmp; + } + } #endregion Public Instance Methods diff --git a/src/log4net/Appender/NetSendAppender.cs b/src/log4net/Appender/NetSendAppender.cs index f6fdbb55..1c0d0aea 100644 --- a/src/log4net/Appender/NetSendAppender.cs +++ b/src/log4net/Appender/NetSendAppender.cs @@ -35,7 +35,7 @@ using log4net.Core; -namespace log4net.Appender +namespace log4net.Appender { /// /// Logs entries by sending network messages using the @@ -138,7 +138,7 @@ namespace log4net.Appender /// /// Nicko Cadell /// Gert Driesen - public class NetSendAppender : AppenderSkeleton + public class NetSendAppender : AppenderSkeleton { #region Member Variables @@ -172,7 +172,7 @@ public class NetSendAppender : AppenderSkeleton /// /// The default constructor initializes all fields to their default values. /// - public NetSendAppender() + public NetSendAppender() { } @@ -189,7 +189,7 @@ public NetSendAppender() /// /// If this property is not specified, the message is sent from the local computer. /// - public string Sender + public string Sender { get { return m_sender; } set { m_sender = value; } @@ -204,12 +204,12 @@ public string Sender /// /// This property should always be specified in order to send a message. /// - public string Recipient + public string Recipient { get { return m_recipient; } set { m_recipient = value; } } - + /// /// Gets or sets the DNS or NetBIOS name of the remote server on which the function is to execute. /// @@ -224,7 +224,7 @@ public string Recipient /// If this property is not specified, the local computer is used. /// /// - public string Server + public string Server { get { return m_server; } set { m_server = value; } @@ -244,7 +244,7 @@ public string Server /// of the current thread. /// /// - public SecurityContext SecurityContext + public SecurityContext SecurityContext { get { return m_securityContext; } set { m_securityContext = value; } @@ -277,8 +277,8 @@ public SecurityContext SecurityContext public override void ActivateOptions() { base.ActivateOptions(); - - if (this.Recipient == null) + + if (this.Recipient == null) { throw new ArgumentNullException("Recipient", "The required property 'Recipient' was not specified."); } @@ -308,20 +308,20 @@ public override void ActivateOptions() #if !NETSTANDARD1_3 [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, UnmanagedCode = true)] #endif - protected override void Append(LoggingEvent loggingEvent) + protected override void Append(LoggingEvent loggingEvent) { NativeError nativeError = null; // Render the event in the callers security context string renderedLoggingEvent = RenderLoggingEvent(loggingEvent); - using(m_securityContext.Impersonate(this)) + using (m_securityContext.Impersonate(this)) { // Send the message - int returnValue = NetMessageBufferSend(this.Server, this.Recipient, this.Sender, renderedLoggingEvent, renderedLoggingEvent.Length * Marshal.SystemDefaultCharSize); + int returnValue = NetMessageBufferSend(this.Server, this.Recipient, this.Sender, renderedLoggingEvent, renderedLoggingEvent.Length * Marshal.SystemDefaultCharSize); // Log the error if the message could not be sent - if (returnValue != 0) + if (returnValue != 0) { // Lookup the native error nativeError = NativeError.GetError(returnValue); @@ -407,8 +407,8 @@ protected override bool RequiresLayout /// If the function succeeds, the return value is zero. /// /// - [DllImport("netapi32.dll", SetLastError=true)] - protected static extern int NetMessageBufferSend( + [DllImport("netapi32.dll", SetLastError = true)] + protected static extern int NetMessageBufferSend( [MarshalAs(UnmanagedType.LPWStr)] string serverName, [MarshalAs(UnmanagedType.LPWStr)] string msgName, [MarshalAs(UnmanagedType.LPWStr)] string fromName, diff --git a/src/log4net/Appender/OutputDebugStringAppender.cs b/src/log4net/Appender/OutputDebugStringAppender.cs index 7a074f0e..5580532b 100644 --- a/src/log4net/Appender/OutputDebugStringAppender.cs +++ b/src/log4net/Appender/OutputDebugStringAppender.cs @@ -80,7 +80,7 @@ public OutputDebugStringAppender() #if !NETCF && !NETSTANDARD1_3 [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, UnmanagedCode = true)] #endif - protected override void Append(LoggingEvent loggingEvent) + protected override void Append(LoggingEvent loggingEvent) { #if NETSTANDARD if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) @@ -90,7 +90,7 @@ protected override void Append(LoggingEvent loggingEvent) #endif OutputDebugString(RenderLoggingEvent(loggingEvent)); - } + } /// /// This appender requires a to be set. diff --git a/src/log4net/Appender/RemotingAppender.cs b/src/log4net/Appender/RemotingAppender.cs index 7a9fd773..69a0b6b7 100644 --- a/src/log4net/Appender/RemotingAppender.cs +++ b/src/log4net/Appender/RemotingAppender.cs @@ -141,11 +141,11 @@ public string Sink #if NET_4_0 || MONO_4_0 [System.Security.SecuritySafeCritical] #endif - public override void ActivateOptions() + public override void ActivateOptions() { base.ActivateOptions(); - IDictionary channelProperties = new Hashtable(); + IDictionary channelProperties = new Hashtable(); channelProperties["typeFilterLevel"] = "Full"; m_sinkObj = (IRemoteLoggingSink)Activator.GetObject(typeof(IRemoteLoggingSink), m_sinkUrl, channelProperties); @@ -184,7 +184,7 @@ protected override void SendBuffer(LoggingEvent[] events) // Cancel the async send EndAsyncSend(); - ErrorHandler.Error("RemotingAppender ["+Name+"] failed to ThreadPool.QueueUserWorkItem logging events in SendBuffer."); + ErrorHandler.Error("RemotingAppender [" + Name + "] failed to ThreadPool.QueueUserWorkItem logging events in SendBuffer."); } } @@ -214,7 +214,7 @@ protected override void OnClose() // Wait for the work queue to become empty before closing, timeout 30 seconds if (!m_workQueueEmptyEvent.WaitOne(30 * 1000, false)) { - ErrorHandler.Error("RemotingAppender ["+Name+"] failed to send all queued events before close, in OnClose."); + ErrorHandler.Error("RemotingAppender [" + Name + "] failed to send all queued events before close, in OnClose."); } } @@ -274,7 +274,7 @@ private void SendBufferCallback(object state) // Send the events m_sinkObj.LogEvents(events); } - catch(Exception ex) + catch (Exception ex) { ErrorHandler.Error("Failed in SendBufferCallback", ex); } diff --git a/src/log4net/Appender/RollingFileAppender.cs b/src/log4net/Appender/RollingFileAppender.cs index b1943d70..aaf0b330 100644 --- a/src/log4net/Appender/RollingFileAppender.cs +++ b/src/log4net/Appender/RollingFileAppender.cs @@ -124,10 +124,10 @@ namespace log4net.Appender /// Douglas de la Torre /// Edward Smit public class RollingFileAppender : FileAppender - { - #region Public Enums + { + #region Public Enums - /// + /// /// Style of rolling to use /// /// @@ -152,22 +152,22 @@ public enum RollingMode /// this appender would just be a normal file appender. /// /// - Once = 0, + Once = 0, /// /// Roll files based only on the size of the file /// - Size = 1, + Size = 1, /// /// Roll files based only on the date /// - Date = 2, + Date = 2, /// /// Roll files based on both the size and date of the file /// - Composite = 3 + Composite = 3 } #endregion @@ -187,37 +187,37 @@ protected enum RollPoint /// /// Roll the log not based on the date /// - InvalidRollPoint =-1, + InvalidRollPoint = -1, /// /// Roll the log for each minute /// - TopOfMinute = 0, + TopOfMinute = 0, /// /// Roll the log for each hour /// - TopOfHour = 1, + TopOfHour = 1, /// /// Roll the log twice a day (midday and midnight) /// - HalfDay = 2, + HalfDay = 2, /// /// Roll the log each day (midnight) /// - TopOfDay = 3, + TopOfDay = 3, /// /// Roll the log each week /// - TopOfWeek = 4, + TopOfWeek = 4, /// /// Roll the log each month /// - TopOfMonth = 5 + TopOfMonth = 5 } #endregion Protected Enums @@ -232,7 +232,7 @@ protected enum RollPoint /// Default constructor. /// /// - public RollingFileAppender() + public RollingFileAppender() { } @@ -259,7 +259,7 @@ public RollingFileAppender() #region Public Instance Properties #if !NET_1_0 && !CLI_1_0 && !NETCF - /// + /// /// Gets or sets the strategy for determining the current date and time. The default /// implementation is to use LocalDateTime which internally calls through to DateTime.Now. /// DateTime.UtcNow may be used on frameworks newer than .NET 1.0 by specifying @@ -272,12 +272,12 @@ public RollingFileAppender() /// /// Gets or sets the used to return the current date and time. /// - /// - /// There are two built strategies for determining the current date and time, + /// + /// There are two built strategies for determining the current date and time, /// - /// and . - /// - /// + /// and . + /// + /// /// The default strategy is . /// /// @@ -298,7 +298,7 @@ public RollingFileAppender() /// /// #endif - public IDateTime DateTimeStrategy + public IDateTime DateTimeStrategy { get { return m_dateTime; } set { m_dateTime = value; } @@ -327,7 +327,7 @@ public string DatePattern get { return m_datePattern; } set { m_datePattern = value; } } - + /// /// Gets or sets the maximum number of backup files that are kept before /// the oldest is erased. @@ -356,7 +356,7 @@ public int MaxSizeRollBackups get { return m_maxSizeRollBackups; } set { m_maxSizeRollBackups = value; } } - + /// /// Gets or sets the maximum size that the output file is allowed to reach /// before being rolled over to backup files. @@ -381,7 +381,7 @@ public long MaxFileSize get { return m_maxFileSize; } set { m_maxFileSize = value; } } - + /// /// Gets or sets the maximum size that the output file is allowed to reach /// before being rolled over to backup files. @@ -442,7 +442,7 @@ public int CountDirection get { return m_countDirection; } set { m_countDirection = value; } } - + /// /// Gets or sets the rolling style. /// @@ -464,7 +464,7 @@ public RollingMode RollingStyle set { m_rollingStyle = value; - switch (m_rollingStyle) + switch (m_rollingStyle) { case RollingMode.Once: m_rollDate = false; @@ -486,30 +486,30 @@ public RollingMode RollingStyle case RollingMode.Composite: m_rollDate = true; m_rollSize = true; - break; + break; } } } - /// - /// Gets or sets a value indicating whether to preserve the file name extension when rolling. - /// - /// - /// true if the file name extension should be preserved. - /// - /// - /// - /// By default file.log is rolled to file.log.yyyy-MM-dd or file.log.curSizeRollBackup. - /// However, under Windows the new file name will loose any program associations as the - /// extension is changed. Optionally file.log can be renamed to file.yyyy-MM-dd.log or - /// file.curSizeRollBackup.log to maintain any program associations. - /// - /// - public bool PreserveLogFileNameExtension - { - get { return m_preserveLogFileNameExtension; } - set { m_preserveLogFileNameExtension = value; } - } + /// + /// Gets or sets a value indicating whether to preserve the file name extension when rolling. + /// + /// + /// true if the file name extension should be preserved. + /// + /// + /// + /// By default file.log is rolled to file.log.yyyy-MM-dd or file.log.curSizeRollBackup. + /// However, under Windows the new file name will loose any program associations as the + /// extension is changed. Optionally file.log can be renamed to file.yyyy-MM-dd.log or + /// file.curSizeRollBackup.log to maintain any program associations. + /// + /// + public bool PreserveLogFileNameExtension + { + get { return m_preserveLogFileNameExtension; } + set { m_preserveLogFileNameExtension = value; } + } /// /// Gets or sets a value indicating whether to always log to @@ -538,21 +538,21 @@ public bool StaticLogFileName #endregion Public Instance Properties - #region Private Static Fields + #region Private Static Fields - /// - /// The fully qualified type of the RollingFileAppender class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(RollingFileAppender); + /// + /// The fully qualified type of the RollingFileAppender class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(RollingFileAppender); - #endregion Private Static Fields + #endregion Private Static Fields #region Override implementation of FileAppender - + /// /// Sets the quiet writer being used. /// @@ -560,7 +560,7 @@ public bool StaticLogFileName /// This method can be overridden by sub classes. /// /// the writer to set - protected override void SetQWForFiles(TextWriter writer) + protected override void SetQWForFiles(TextWriter writer) { QuietWriter = new CountingQuietTextWriter(writer, ErrorHandler); } @@ -576,13 +576,13 @@ protected override void SetQWForFiles(TextWriter writer) /// is need and then appends to the file last. /// /// - protected override void Append(LoggingEvent loggingEvent) + protected override void Append(LoggingEvent loggingEvent) { AdjustFileBeforeAppend(); base.Append(loggingEvent); } - - /// + + /// /// Write out an array of logging events. /// /// the events to write to file. @@ -593,7 +593,7 @@ protected override void Append(LoggingEvent loggingEvent) /// is need and then appends to the file last. /// /// - protected override void Append(LoggingEvent[] loggingEvents) + protected override void Append(LoggingEvent[] loggingEvents) { AdjustFileBeforeAppend(); base.Append(loggingEvents); @@ -665,15 +665,15 @@ protected virtual void AdjustFileBeforeAppend() /// protected override void OpenFile(string fileName, bool append) { - lock(this) + lock (this) { fileName = GetNextOutputFileName(fileName); // Calculate the current size of the file long currentCount = 0; - if (append) + if (append) { - using(SecurityContext.Impersonate(this)) + using (SecurityContext.Impersonate(this)) { if (System.IO.File.Exists(fileName)) { @@ -691,12 +691,12 @@ protected override void OpenFile(string fileName, bool append) // The only exception is if we are not allowed to roll the existing file away. if (m_maxSizeRollBackups != 0 && FileExists(fileName)) { - LogLog.Error(declaringType, "RollingFileAppender: INTERNAL ERROR. Append is False but OutputFile ["+fileName+"] already exists."); + LogLog.Error(declaringType, "RollingFileAppender: INTERNAL ERROR. Append is False but OutputFile [" + fileName + "] already exists."); } } } - if (!m_staticLogFileName) + if (!m_staticLogFileName) { m_scheduledFilename = fileName; } @@ -723,18 +723,18 @@ protected override void OpenFile(string fileName, bool append) /// protected string GetNextOutputFileName(string fileName) { - if (!m_staticLogFileName) + if (!m_staticLogFileName) { fileName = fileName.Trim(); if (m_rollDate) { - fileName = CombinePath(fileName, m_now.ToString(m_datePattern, DateTimeFormatInfo.InvariantInfo)); + fileName = CombinePath(fileName, m_now.ToString(m_datePattern, DateTimeFormatInfo.InvariantInfo)); } - if (m_countDirection >= 0) + if (m_countDirection >= 0) { - fileName = CombinePath(fileName, "." + m_curSizeRollBackups); + fileName = CombinePath(fileName, "." + m_curSizeRollBackups); } } @@ -751,11 +751,11 @@ protected string GetNextOutputFileName(string fileName) private void DetermineCurSizeRollBackups() { m_curSizeRollBackups = 0; - + string fullPath = null; string fileName = null; - using(SecurityContext.Impersonate(this)) + using (SecurityContext.Impersonate(this)) { fullPath = Path.GetFullPath(m_baseFileName); fileName = Path.GetFileName(fullPath); @@ -764,7 +764,7 @@ private void DetermineCurSizeRollBackups() var arrayFiles = GetExistingFiles(fullPath); InitializeRollBackups(fileName, arrayFiles); - LogLog.Debug(declaringType, "curSizeRollBackups starts at ["+m_curSizeRollBackups+"]"); + LogLog.Debug(declaringType, "curSizeRollBackups starts at [" + m_curSizeRollBackups + "]"); } /// @@ -775,14 +775,14 @@ private void DetermineCurSizeRollBackups() /// private string GetWildcardPatternForFile(string baseFileName) { - if (m_preserveLogFileNameExtension) - { - return Path.GetFileNameWithoutExtension(baseFileName) + "*" + Path.GetExtension(baseFileName); - } - else - { - return baseFileName + '*'; - } + if (m_preserveLogFileNameExtension) + { + return Path.GetFileNameWithoutExtension(baseFileName) + "*" + Path.GetExtension(baseFileName); + } + else + { + return baseFileName + '*'; + } } /// @@ -797,7 +797,7 @@ private ArrayList GetExistingFiles(string baseFilePath) string directory = null; - using(SecurityContext.Impersonate(this)) + using (SecurityContext.Impersonate(this)) { var fullPath = Path.GetFullPath(baseFilePath); @@ -807,10 +807,10 @@ private ArrayList GetExistingFiles(string baseFilePath) var baseFileName = Path.GetFileName(fullPath); var files = Directory.GetFiles(directory, GetWildcardPatternForFile(baseFileName)); - + if (files != null) { - for (var i = 0; i < files.Length; i++) + for (var i = 0; i < files.Length; i++) { var curFileName = Path.GetFileName(files[i]); if (curFileName.StartsWith(Path.GetFileNameWithoutExtension(baseFileName))) @@ -821,7 +821,7 @@ private ArrayList GetExistingFiles(string baseFilePath) } } } - LogLog.Debug(declaringType, "Searched for existing files in ["+directory+"]"); + LogLog.Debug(declaringType, "Searched for existing files in [" + directory + "]"); return alFiles; } @@ -830,14 +830,15 @@ private ArrayList GetExistingFiles(string baseFilePath) /// private void RollOverIfDateBoundaryCrossing() { - if (m_staticLogFileName && m_rollDate) + if (m_staticLogFileName && m_rollDate) { - if (FileExists(m_baseFileName)) + if (FileExists(m_baseFileName)) { DateTime last; - using(SecurityContext.Impersonate(this)) { + using (SecurityContext.Impersonate(this)) + { #if !NET_1_0 && !CLI_1_0 && !NETCF - if (DateTimeStrategy is UniversalDateTime) + if (DateTimeStrategy is UniversalDateTime) { last = System.IO.File.GetLastWriteTimeUtc(m_baseFileName); } @@ -846,17 +847,17 @@ private void RollOverIfDateBoundaryCrossing() #endif last = System.IO.File.GetLastWriteTime(m_baseFileName); #if !NET_1_0 && !CLI_1_0 && !NETCF - } + } #endif - } - LogLog.Debug(declaringType, "["+last.ToString(m_datePattern,DateTimeFormatInfo.InvariantInfo)+"] vs. ["+m_now.ToString(m_datePattern,DateTimeFormatInfo.InvariantInfo)+"]"); + } + LogLog.Debug(declaringType, "[" + last.ToString(m_datePattern, DateTimeFormatInfo.InvariantInfo) + "] vs. [" + m_now.ToString(m_datePattern, DateTimeFormatInfo.InvariantInfo) + "]"); - if (!(last.ToString(m_datePattern,DateTimeFormatInfo.InvariantInfo).Equals(m_now.ToString(m_datePattern, DateTimeFormatInfo.InvariantInfo)))) + if (!(last.ToString(m_datePattern, DateTimeFormatInfo.InvariantInfo).Equals(m_now.ToString(m_datePattern, DateTimeFormatInfo.InvariantInfo)))) { m_scheduledFilename = CombinePath(m_baseFileName, last.ToString(m_datePattern, DateTimeFormatInfo.InvariantInfo)); - LogLog.Debug(declaringType, "Initial roll over to ["+m_scheduledFilename+"]"); + LogLog.Debug(declaringType, "Initial roll over to [" + m_scheduledFilename + "]"); RollOverTime(false); - LogLog.Debug(declaringType, "curSizeRollBackups after rollOver at ["+m_curSizeRollBackups+"]"); + LogLog.Debug(declaringType, "curSizeRollBackups after rollOver at [" + m_curSizeRollBackups + "]"); } } } @@ -875,7 +876,7 @@ private void RollOverIfDateBoundaryCrossing() /// /// /// - protected void ExistingInit() + protected void ExistingInit() { DetermineCurSizeRollBackups(); RollOverIfDateBoundaryCrossing(); @@ -889,7 +890,7 @@ protected void ExistingInit() bool fileExists; var fileName = GetNextOutputFileName(m_baseFileName); - using(SecurityContext.Impersonate(this)) + using (SecurityContext.Impersonate(this)) { fileExists = System.IO.File.Exists(fileName); } @@ -901,11 +902,11 @@ protected void ExistingInit() if (m_maxSizeRollBackups == 0) { - LogLog.Debug(declaringType, "Output file ["+fileName+"] already exists. MaxSizeRollBackups is 0; cannot roll. Overwriting existing file."); + LogLog.Debug(declaringType, "Output file [" + fileName + "] already exists. MaxSizeRollBackups is 0; cannot roll. Overwriting existing file."); } else { - LogLog.Debug(declaringType, "Output file ["+fileName+"] already exists. Not appending to file. Rolling existing file out of the way."); + LogLog.Debug(declaringType, "Output file [" + fileName + "] already exists. Not appending to file. Rolling existing file out of the way."); RollOverRenameFiles(fileName); } @@ -924,113 +925,113 @@ private void InitializeFromOneFile(string baseFile, string curFileName) { curFileName = curFileName.ToLower(); baseFile = baseFile.ToLower(); - if (curFileName.StartsWith(Path.GetFileNameWithoutExtension(baseFile)) == false) + if (curFileName.StartsWith(Path.GetFileNameWithoutExtension(baseFile)) == false) { // This is not a log file, so ignore return; } - if (curFileName.Equals(baseFile)) + if (curFileName.Equals(baseFile)) { // Base log file is not an incremented logfile (.1 or .2, etc) return; } - + // Only look for files in the current roll point if (m_rollDate && !m_staticLogFileName) { var date = m_dateTime.Now.ToString(m_datePattern, DateTimeFormatInfo.InvariantInfo).ToLower(); - var prefix = (m_preserveLogFileNameExtension - ? Path.GetFileNameWithoutExtension(baseFile) + date + var prefix = (m_preserveLogFileNameExtension + ? Path.GetFileNameWithoutExtension(baseFile) + date : baseFile + date).ToLower(); - var suffix = m_preserveLogFileNameExtension + var suffix = m_preserveLogFileNameExtension ? Path.GetExtension(baseFile).ToLower() : ""; if (!curFileName.StartsWith(prefix) || !curFileName.EndsWith(suffix)) { - LogLog.Debug(declaringType, "Ignoring file ["+curFileName+"] because it is from a different date period"); + LogLog.Debug(declaringType, "Ignoring file [" + curFileName + "] because it is from a different date period"); return; } } - - try + + try { // Bump the counter up to the highest count seen so far - var backup = GetBackUpIndex(curFileName); - - // caution: we might get a false positive when certain - // date patterns such as yyyyMMdd are used...those are - // valid number but aren't the kind of back up index - // we're looking for - if (backup > m_curSizeRollBackups) - { - if (0 == m_maxSizeRollBackups) - { - // Stay at zero when zero backups are desired - } - else if (-1 == m_maxSizeRollBackups) - { - // Infinite backups, so go as high as the highest value - m_curSizeRollBackups = backup; - } - else - { - // Backups limited to a finite number - if (m_countDirection >= 0) - { - // Go with the highest file when counting up - m_curSizeRollBackups = backup; - } - else - { - // Clip to the limit when counting down - if (backup <= m_maxSizeRollBackups) - { - m_curSizeRollBackups = backup; - } - } - } - LogLog.Debug(declaringType, "File name [" + curFileName + "] moves current count to [" + m_curSizeRollBackups + "]"); - } - } - catch(FormatException) + var backup = GetBackUpIndex(curFileName); + + // caution: we might get a false positive when certain + // date patterns such as yyyyMMdd are used...those are + // valid number but aren't the kind of back up index + // we're looking for + if (backup > m_curSizeRollBackups) + { + if (0 == m_maxSizeRollBackups) + { + // Stay at zero when zero backups are desired + } + else if (-1 == m_maxSizeRollBackups) + { + // Infinite backups, so go as high as the highest value + m_curSizeRollBackups = backup; + } + else + { + // Backups limited to a finite number + if (m_countDirection >= 0) + { + // Go with the highest file when counting up + m_curSizeRollBackups = backup; + } + else + { + // Clip to the limit when counting down + if (backup <= m_maxSizeRollBackups) + { + m_curSizeRollBackups = backup; + } + } + } + LogLog.Debug(declaringType, "File name [" + curFileName + "] moves current count to [" + m_curSizeRollBackups + "]"); + } + } + catch (FormatException) { //this happens when file.log -> file.log.yyyy-MM-dd which is normal //when staticLogFileName == false - LogLog.Debug(declaringType, "Encountered a backup file not ending in .x ["+curFileName+"]"); + LogLog.Debug(declaringType, "Encountered a backup file not ending in .x [" + curFileName + "]"); } } - /// - /// Attempts to extract a number from the end of the file name that indicates - /// the number of the times the file has been rolled over. - /// - /// - /// Certain date pattern extensions like yyyyMMdd will be parsed as valid backup indexes. - /// - /// - /// - private int GetBackUpIndex(string curFileName) - { - var backUpIndex = -1; - var fileName = curFileName; + /// + /// Attempts to extract a number from the end of the file name that indicates + /// the number of the times the file has been rolled over. + /// + /// + /// Certain date pattern extensions like yyyyMMdd will be parsed as valid backup indexes. + /// + /// + /// + private int GetBackUpIndex(string curFileName) + { + var backUpIndex = -1; + var fileName = curFileName; - if (m_preserveLogFileNameExtension) - { - fileName = Path.GetFileNameWithoutExtension(fileName); - } - - var index = fileName.LastIndexOf("."); - if (index > 0) - { - // if the "yyyy-MM-dd" component of file.log.yyyy-MM-dd is passed to TryParse - // it will gracefully fail and return backUpIndex will be 0 - SystemInfo.TryParse(fileName.Substring(index + 1), out backUpIndex); - } + if (m_preserveLogFileNameExtension) + { + fileName = Path.GetFileNameWithoutExtension(fileName); + } - return backUpIndex; + var index = fileName.LastIndexOf("."); + if (index > 0) + { + // if the "yyyy-MM-dd" component of file.log.yyyy-MM-dd is passed to TryParse + // it will gracefully fail and return backUpIndex will be 0 + SystemInfo.TryParse(fileName.Substring(index + 1), out backUpIndex); } - /// + return backUpIndex; + } + + /// /// Takes a list of files and a base file name, and looks for /// 'incremented' versions of the base file. Bumps the max /// count up to the highest count seen. @@ -1043,7 +1044,7 @@ private void InitializeRollBackups(string baseFile, ArrayList arrayFiles) { var baseFileLower = baseFile.ToLowerInvariant(); - foreach(string curFileName in arrayFiles) + foreach (string curFileName in arrayFiles) { InitializeFromOneFile(baseFileLower, curFileName.ToLowerInvariant()); } @@ -1063,7 +1064,7 @@ private void InitializeRollBackups(string baseFile, ArrayList arrayFiles) /// and hour then the smallest roll point that can be detected would be /// and hourly roll point as minutes could not be detected. /// - private RollPoint ComputeCheckPeriod(string datePattern) + private RollPoint ComputeCheckPeriod(string datePattern) { // s_date1970 is 1970-01-01 00:00:00 this is UniversalSortableDateTimePattern // (based on ISO 8601) using universal time. This date is used for reference @@ -1073,15 +1074,15 @@ private RollPoint ComputeCheckPeriod(string datePattern) var r0 = s_date1970.ToString(datePattern, DateTimeFormatInfo.InvariantInfo); // Check each type of rolling mode starting with the smallest increment. - for(var i = (int)RollPoint.TopOfMinute; i <= (int)RollPoint.TopOfMonth; i++) + for (var i = (int)RollPoint.TopOfMinute; i <= (int)RollPoint.TopOfMonth; i++) { // Get string representation of next pattern var r1 = NextCheckDate(s_date1970, (RollPoint)i).ToString(datePattern, DateTimeFormatInfo.InvariantInfo); - LogLog.Debug(declaringType, "Type = ["+i+"], r0 = ["+r0+"], r1 = ["+r1+"]"); + LogLog.Debug(declaringType, "Type = [" + i + "], r0 = [" + r0 + "], r1 = [" + r1 + "]"); // Check if the string representations are different - if (r0 != null && r1 != null && !r0.Equals(r1)) + if (r0 != null && r1 != null && !r0.Equals(r1)) { // Found highest precision roll point return (RollPoint)i; @@ -1112,31 +1113,31 @@ private RollPoint ComputeCheckPeriod(string datePattern) /// the current number of backups. /// /// - public override void ActivateOptions() + public override void ActivateOptions() { if (m_dateTime == null) { m_dateTime = new LocalDateTime(); } - if (m_rollDate && m_datePattern != null) + if (m_rollDate && m_datePattern != null) { m_now = m_dateTime.Now; m_rollPoint = ComputeCheckPeriod(m_datePattern); if (m_rollPoint == RollPoint.InvalidRollPoint) { - throw new ArgumentException("Invalid RollPoint, unable to parse ["+m_datePattern+"]"); + throw new ArgumentException("Invalid RollPoint, unable to parse [" + m_datePattern + "]"); } // next line added as this removes the name check in rollOver m_nextCheck = NextCheckDate(m_now, m_rollPoint); - } - else + } + else { if (m_rollDate) { - ErrorHandler.Error("Either DatePattern or rollingStyle options are not set for ["+Name+"]."); + ErrorHandler.Error("Either DatePattern or rollingStyle options are not set for [" + Name + "]."); } } @@ -1145,7 +1146,7 @@ public override void ActivateOptions() SecurityContext = SecurityContextProvider.DefaultProvider.CreateSecurityContext(this); } - using(SecurityContext.Impersonate(this)) + using (SecurityContext.Impersonate(this)) { // Must convert the FileAppender's m_filePath to an absolute path before we // call ExistingInit(). This will be done by the base.ActivateOptions() but @@ -1167,36 +1168,36 @@ public override void ActivateOptions() if (m_rollDate && File != null && m_scheduledFilename == null) { - m_scheduledFilename = CombinePath(File, m_now.ToString(m_datePattern, DateTimeFormatInfo.InvariantInfo)); + m_scheduledFilename = CombinePath(File, m_now.ToString(m_datePattern, DateTimeFormatInfo.InvariantInfo)); } ExistingInit(); - + base.ActivateOptions(); } #endregion - + #region Roll File - /// - /// - /// - /// - /// .1, .2, .3, etc. - /// - private string CombinePath(string path1, string path2) - { - var extension = Path.GetExtension(path1); - if (m_preserveLogFileNameExtension && extension.Length > 0) - { - return Path.Combine(Path.GetDirectoryName(path1), Path.GetFileNameWithoutExtension(path1) + path2 + extension); - } - else - { - return path1 + path2; - } - } + /// + /// + /// + /// + /// .1, .2, .3, etc. + /// + private string CombinePath(string path1, string path2) + { + var extension = Path.GetExtension(path1); + if (m_preserveLogFileNameExtension && extension.Length > 0) + { + return Path.Combine(Path.GetDirectoryName(path1), Path.GetFileNameWithoutExtension(path1) + path2 + extension); + } + else + { + return path1 + path2; + } + } /// /// Rollover the file(s) to date/time tagged file(s). @@ -1209,49 +1210,49 @@ private string CombinePath(string path1, string path2) /// If fileIsOpen is set then the new file is opened (through SafeOpenFile). /// /// - protected void RollOverTime(bool fileIsOpen) + protected void RollOverTime(bool fileIsOpen) { - if (m_staticLogFileName) + if (m_staticLogFileName) { // Compute filename, but only if datePattern is specified - if (m_datePattern == null) + if (m_datePattern == null) { ErrorHandler.Error("Missing DatePattern option in rollOver()."); return; } - + //is the new file name equivalent to the 'current' one //something has gone wrong if we hit this -- we should only //roll over if the new file will be different from the old var dateFormat = m_now.ToString(m_datePattern, DateTimeFormatInfo.InvariantInfo); - if (m_scheduledFilename.Equals(CombinePath(File, dateFormat))) + if (m_scheduledFilename.Equals(CombinePath(File, dateFormat))) { - ErrorHandler.Error("Compare " + m_scheduledFilename + " : " + CombinePath(File, dateFormat)); + ErrorHandler.Error("Compare " + m_scheduledFilename + " : " + CombinePath(File, dateFormat)); return; } - + if (fileIsOpen) { // close current file, and rename it to datedFilename CloseFile(); } - + //we may have to roll over a large number of backups here - for (var i = 1; i <= m_curSizeRollBackups; i++) + for (var i = 1; i <= m_curSizeRollBackups; i++) { - var from = CombinePath(File, "." + i); - var to = CombinePath(m_scheduledFilename, "." + i); + var from = CombinePath(File, "." + i); + var to = CombinePath(m_scheduledFilename, "." + i); RollFile(from, to); } - + RollFile(File, m_scheduledFilename); } - + //We've cleared out the old date and are ready for the new - m_curSizeRollBackups = 0; - + m_curSizeRollBackups = 0; + //new scheduled name - m_scheduledFilename = CombinePath(File, m_now.ToString(m_datePattern, DateTimeFormatInfo.InvariantInfo)); + m_scheduledFilename = CombinePath(File, m_now.ToString(m_datePattern, DateTimeFormatInfo.InvariantInfo)); if (fileIsOpen) { @@ -1259,7 +1260,7 @@ protected void RollOverTime(bool fileIsOpen) SafeOpenFile(m_baseFileName, false); } } - + /// /// Renames file to file . /// @@ -1271,7 +1272,7 @@ protected void RollOverTime(bool fileIsOpen) /// also checks for existence of target file and deletes if it does. /// /// - protected void RollFile(string fromFile, string toFile) + protected void RollFile(string fromFile, string toFile) { if (FileExists(fromFile)) { @@ -1282,12 +1283,12 @@ protected void RollFile(string fromFile, string toFile) try { LogLog.Debug(declaringType, "Moving [" + fromFile + "] -> [" + toFile + "]"); - using(SecurityContext.Impersonate(this)) + using (SecurityContext.Impersonate(this)) { System.IO.File.Move(fromFile, toFile); } } - catch(Exception moveEx) + catch (Exception moveEx) { ErrorHandler.Error("Exception while rolling file [" + fromFile + "] -> [" + toFile + "]", moveEx, ErrorCode.GenericFailure); } @@ -1310,12 +1311,12 @@ protected void RollFile(string fromFile, string toFile) /// protected bool FileExists(string path) { - using(SecurityContext.Impersonate(this)) + using (SecurityContext.Impersonate(this)) { return System.IO.File.Exists(path); } } - + /// /// Deletes the specified file if it exists. /// @@ -1328,9 +1329,9 @@ protected bool FileExists(string path) /// be deleted, but it still can be moved. /// /// - protected void DeleteFile(string fileName) + protected void DeleteFile(string fileName) { - if (FileExists(fileName)) + if (FileExists(fileName)) { // We may not have permission to delete the file, or the file may be locked @@ -1341,13 +1342,13 @@ protected void DeleteFile(string fileName) var tempFileName = fileName + "." + Environment.TickCount + ".DeletePending"; try { - using(SecurityContext.Impersonate(this)) + using (SecurityContext.Impersonate(this)) { System.IO.File.Move(fileName, tempFileName); } fileToDelete = tempFileName; } - catch(Exception moveEx) + catch (Exception moveEx) { LogLog.Debug(declaringType, "Exception while moving file to be deleted [" + fileName + "] -> [" + tempFileName + "]", moveEx); } @@ -1355,13 +1356,13 @@ protected void DeleteFile(string fileName) // Try to delete the file (either the original or the moved file) try { - using(SecurityContext.Impersonate(this)) + using (SecurityContext.Impersonate(this)) { System.IO.File.Delete(fileToDelete); } LogLog.Debug(declaringType, "Deleted file [" + fileName + "]"); } - catch(Exception deleteEx) + catch (Exception deleteEx) { if (fileToDelete == fileName) { @@ -1377,7 +1378,7 @@ protected void DeleteFile(string fileName) } } } - + /// /// Implements file roll base on file size. /// @@ -1404,18 +1405,18 @@ protected void DeleteFile(string fileName) /// renamed if needed and no files are deleted. /// /// - protected void RollOverSize() + protected void RollOverSize() { CloseFile(); // keep windows happy. - - LogLog.Debug(declaringType, "rolling over count ["+((CountingQuietTextWriter)QuietWriter).Count+"]"); - LogLog.Debug(declaringType, "maxSizeRollBackups ["+m_maxSizeRollBackups+"]"); - LogLog.Debug(declaringType, "curSizeRollBackups ["+m_curSizeRollBackups+"]"); - LogLog.Debug(declaringType, "countDirection ["+m_countDirection+"]"); + + LogLog.Debug(declaringType, "rolling over count [" + ((CountingQuietTextWriter)QuietWriter).Count + "]"); + LogLog.Debug(declaringType, "maxSizeRollBackups [" + m_maxSizeRollBackups + "]"); + LogLog.Debug(declaringType, "curSizeRollBackups [" + m_curSizeRollBackups + "]"); + LogLog.Debug(declaringType, "countDirection [" + m_countDirection + "]"); RollOverRenameFiles(File); - - if (!m_staticLogFileName && m_countDirection >= 0) + + if (!m_staticLogFileName && m_countDirection >= 0) { m_curSizeRollBackups++; } @@ -1450,35 +1451,35 @@ protected void RollOverSize() /// This is called by to rename the files. /// /// - protected void RollOverRenameFiles(string baseFileName) + protected void RollOverRenameFiles(string baseFileName) { // If maxBackups <= 0, then there is no file renaming to be done. - if (m_maxSizeRollBackups != 0) + if (m_maxSizeRollBackups != 0) { - if (m_countDirection < 0) + if (m_countDirection < 0) { // Delete the oldest file, to keep Windows happy. - if (m_curSizeRollBackups == m_maxSizeRollBackups) + if (m_curSizeRollBackups == m_maxSizeRollBackups) { - DeleteFile(CombinePath(baseFileName, "." + m_maxSizeRollBackups)); + DeleteFile(CombinePath(baseFileName, "." + m_maxSizeRollBackups)); m_curSizeRollBackups--; } - + // Map {(maxBackupIndex - 1), ..., 2, 1} to {maxBackupIndex, ..., 3, 2} - for (var i = m_curSizeRollBackups; i >= 1; i--) + for (var i = m_curSizeRollBackups; i >= 1; i--) { - RollFile((CombinePath(baseFileName, "." + i)), (CombinePath(baseFileName, "." + (i + 1)))); + RollFile((CombinePath(baseFileName, "." + i)), (CombinePath(baseFileName, "." + (i + 1)))); } - + m_curSizeRollBackups++; // Rename fileName to fileName.1 - RollFile(baseFileName, CombinePath(baseFileName, ".1")); - } - else + RollFile(baseFileName, CombinePath(baseFileName, ".1")); + } + else { //countDirection >= 0 - if (m_curSizeRollBackups >= m_maxSizeRollBackups && m_maxSizeRollBackups > 0) + if (m_curSizeRollBackups >= m_maxSizeRollBackups && m_maxSizeRollBackups > 0) { //delete the first and keep counting up. var oldestFileIndex = m_curSizeRollBackups - m_maxSizeRollBackups; @@ -1495,34 +1496,34 @@ protected void RollOverRenameFiles(string baseFileName) var archiveFileBaseName = baseFileName; if (!m_staticLogFileName) { - if (m_preserveLogFileNameExtension) - { - var extension = Path.GetExtension(archiveFileBaseName); - var baseName = Path.GetFileNameWithoutExtension(archiveFileBaseName); - var lastDotIndex = baseName.LastIndexOf("."); - if (lastDotIndex >= 0) + if (m_preserveLogFileNameExtension) { - archiveFileBaseName = baseName.Substring(0, lastDotIndex) + extension; + var extension = Path.GetExtension(archiveFileBaseName); + var baseName = Path.GetFileNameWithoutExtension(archiveFileBaseName); + var lastDotIndex = baseName.LastIndexOf("."); + if (lastDotIndex >= 0) + { + archiveFileBaseName = baseName.Substring(0, lastDotIndex) + extension; + } } - } - else - { - var lastDotIndex = archiveFileBaseName.LastIndexOf("."); - if (lastDotIndex >= 0) + else { - archiveFileBaseName = archiveFileBaseName.Substring(0, lastDotIndex); + var lastDotIndex = archiveFileBaseName.LastIndexOf("."); + if (lastDotIndex >= 0) + { + archiveFileBaseName = archiveFileBaseName.Substring(0, lastDotIndex); + } } - } } // Delete the archive file - DeleteFile(CombinePath(archiveFileBaseName, "." + oldestFileIndex)); + DeleteFile(CombinePath(archiveFileBaseName, "." + oldestFileIndex)); } - - if (m_staticLogFileName) + + if (m_staticLogFileName) { m_curSizeRollBackups++; - RollFile(baseFileName, CombinePath(baseFileName, "." + m_curSizeRollBackups)); + RollFile(baseFileName, CombinePath(baseFileName, "." + m_curSizeRollBackups)); } } } @@ -1549,13 +1550,13 @@ protected void RollOverRenameFiles(string baseFileName) /// worth of time and get the start time of the next window for the rollpoint. /// /// - protected DateTime NextCheckDate(DateTime currentDateTime, RollPoint rollPoint) + protected DateTime NextCheckDate(DateTime currentDateTime, RollPoint rollPoint) { // Local variable to work on (this does not look very efficient) var current = currentDateTime; // Do slightly different things depending on what the type of roll point we want. - switch(rollPoint) + switch (rollPoint) { case RollPoint.TopOfMinute: current = current.AddMilliseconds(-current.Millisecond); @@ -1575,11 +1576,11 @@ protected DateTime NextCheckDate(DateTime currentDateTime, RollPoint rollPoint) current = current.AddSeconds(-current.Second); current = current.AddMinutes(-current.Minute); - if (current.Hour < 12) + if (current.Hour < 12) { current = current.AddHours(12 - current.Hour); - } - else + } + else { current = current.AddHours(-current.Hour); current = current.AddDays(1); @@ -1610,7 +1611,7 @@ protected DateTime NextCheckDate(DateTime currentDateTime, RollPoint rollPoint) current = current.AddDays(1 - current.Day); /* first day of month is 1 not 0 */ current = current.AddMonths(1); break; - } + } return current; } @@ -1630,49 +1631,49 @@ protected DateTime NextCheckDate(DateTime currentDateTime, RollPoint rollPoint) /// meaning daily rollover. /// private string m_datePattern = ".yyyy-MM-dd"; - + /// /// The actual formatted filename that is currently being written to /// or will be the file transferred to on roll over /// (based on staticLogFileName). /// private string m_scheduledFilename = null; - + /// /// The timestamp when we shall next recompute the filename. /// private DateTime m_nextCheck = DateTime.MaxValue; - + /// /// Holds date of last roll over /// private DateTime m_now; - + /// /// The type of rolling done /// private RollPoint m_rollPoint; - + /// /// The default maximum file size is 10MB /// - private long m_maxFileSize = 10*1024*1024; - + private long m_maxFileSize = 10 * 1024 * 1024; + /// /// There is zero backup files by default /// - private int m_maxSizeRollBackups = 0; + private int m_maxSizeRollBackups = 0; /// /// How many sized based backups have been made so far /// private int m_curSizeRollBackups = 0; - + /// /// The rolling file count direction. /// private int m_countDirection = -1; - + /// /// The rolling mode used in this appender. /// @@ -1687,13 +1688,13 @@ protected DateTime NextCheckDate(DateTime currentDateTime, RollPoint rollPoint) /// Cache flag set if we are rolling by size. /// private bool m_rollSize = true; - + /// /// Value indicating whether to always log to the same file. /// private bool m_staticLogFileName = true; - - /// + + /// /// Value indicating whether to preserve the file name extension when rolling. /// private bool m_preserveLogFileNameExtension = false; @@ -1767,7 +1768,7 @@ public DateTime Now } #if !NET_1_0 && !CLI_1_0 && !NETCF - /// + /// /// Implementation of that returns the current time as the coordinated universal time (UTC). /// private class UniversalDateTime : IDateTime @@ -1788,6 +1789,6 @@ public DateTime Now } #endif - #endregion DateTime + #endregion DateTime } } diff --git a/src/log4net/Appender/SmtpAppender.cs b/src/log4net/Appender/SmtpAppender.cs index c0d12462..58f822bd 100644 --- a/src/log4net/Appender/SmtpAppender.cs +++ b/src/log4net/Appender/SmtpAppender.cs @@ -81,7 +81,7 @@ public class SmtpAppender : BufferingAppenderSkeleton /// /// public SmtpAppender() - { + { } #endregion // Public Instance Constructors @@ -168,7 +168,7 @@ public string Bcc /// The e-mail address of the sender. /// /// - public string From + public string From { get { return m_from; } set { m_from = value; } @@ -185,12 +185,12 @@ public string From /// The subject line of the e-mail message. /// /// - public string Subject + public string Subject { get { return m_subject; } set { m_subject = value; } } - + /// /// Gets or sets the name of the SMTP relay mail server to use to send /// the e-mail messages. @@ -226,7 +226,7 @@ public string SmtpHost public bool LocationInfo { get { return false; } - set { ; } + set {; } } /// @@ -381,12 +381,12 @@ public Encoding BodyEncoding /// Sends the contents of the cyclic buffer as an e-mail message. /// /// The logging events to send. - protected override void SendBuffer(LoggingEvent[] events) + protected override void SendBuffer(LoggingEvent[] events) { // Note: this code already owns the monitor for this // appender. This frees us from needing to synchronize again. - try - { + try + { using StringWriter writer = new StringWriter(System.Globalization.CultureInfo.InvariantCulture); string t = Layout.Header; @@ -395,7 +395,7 @@ protected override void SendBuffer(LoggingEvent[] events) writer.Write(t); } - for(int i = 0; i < events.Length; i++) + for (int i = 0; i < events.Length; i++) { // Render the event and append the text to the buffer RenderLoggingEvent(writer, events[i]); @@ -408,8 +408,8 @@ protected override void SendBuffer(LoggingEvent[] events) } SendEmail(writer.ToString()); - } - catch(Exception e) + } + catch (Exception e) { ErrorHandler.Error("Error occurred while sending e-mail notification.", e); } @@ -650,19 +650,20 @@ public enum SmtpAuthentication #endregion // SmtpAuthentication Enum - private static readonly char[] ADDRESS_DELIMITERS = new char[] { ',', ';' }; - - /// - /// trims leading and trailing commas or semicolons - /// - private static string MaybeTrimSeparators(string s) { + private static readonly char[] ADDRESS_DELIMITERS = new char[] { ',', ';' }; + + /// + /// trims leading and trailing commas or semicolons + /// + private static string MaybeTrimSeparators(string s) + { #if NET_2_0 || MONO_2_0 || NETSTANDARD2_0 - return string.IsNullOrEmpty(s) ? s : s.Trim(ADDRESS_DELIMITERS); + return string.IsNullOrEmpty(s) ? s : s.Trim(ADDRESS_DELIMITERS); #else return s != null && s.Length > 0 ? s : s.Trim(ADDRESS_DELIMITERS); #endif - } } + } } #endif // !NETCF && !SSCLI diff --git a/src/log4net/Appender/SmtpPickupDirAppender.cs b/src/log4net/Appender/SmtpPickupDirAppender.cs index f3f3aa05..8a0fab04 100644 --- a/src/log4net/Appender/SmtpPickupDirAppender.cs +++ b/src/log4net/Appender/SmtpPickupDirAppender.cs @@ -80,7 +80,7 @@ public SmtpPickupDirAppender() /// A semicolon-delimited list of e-mail addresses. /// /// - public string To + public string To { get { return m_to; } set { m_to = value; } @@ -97,7 +97,7 @@ public string To /// The e-mail address of the sender. /// /// - public string From + public string From { get { return m_from; } set { m_from = value; } @@ -114,12 +114,12 @@ public string From /// The subject line of the e-mail message. /// /// - public string Subject + public string Subject { get { return m_subject; } set { m_subject = value; } } - + /// /// Gets or sets the path to write the messages to. /// @@ -135,7 +135,7 @@ public string PickupDir set { m_pickupDir = value; } } - /// + /// /// Gets or sets the file extension for the generated files /// /// @@ -182,7 +182,7 @@ public string FileExtension /// of the current thread. /// /// - public SecurityContext SecurityContext + public SecurityContext SecurityContext { get { return m_securityContext; } set { m_securityContext = value; } @@ -201,17 +201,17 @@ public SecurityContext SecurityContext /// Sends the contents of the cyclic buffer as an e-mail message. /// /// - protected override void SendBuffer(LoggingEvent[] events) + protected override void SendBuffer(LoggingEvent[] events) { // Note: this code already owns the monitor for this // appender. This frees us from needing to synchronize again. - try + try { string filePath = null; StreamWriter writer = null; // Impersonate to open the file - using(SecurityContext.Impersonate(this)) + using (SecurityContext.Impersonate(this)) { filePath = Path.Combine(m_pickupDir, SystemInfo.NewGuid().ToString("N") + m_fileExtension); writer = File.CreateText(filePath); @@ -219,11 +219,11 @@ protected override void SendBuffer(LoggingEvent[] events) if (writer == null) { - ErrorHandler.Error("Failed to create output file for writing ["+filePath+"]", null, ErrorCode.FileOpenFailure); + ErrorHandler.Error("Failed to create output file for writing [" + filePath + "]", null, ErrorCode.FileOpenFailure); } else { - using(writer) + using (writer) { writer.WriteLine("To: " + m_to); writer.WriteLine("From: " + m_from); @@ -237,7 +237,7 @@ protected override void SendBuffer(LoggingEvent[] events) writer.Write(t); } - for(int i = 0; i < events.Length; i++) + for (int i = 0; i < events.Length; i++) { // Render the event and append the text to the buffer RenderLoggingEvent(writer, events[i]); @@ -253,8 +253,8 @@ protected override void SendBuffer(LoggingEvent[] events) writer.WriteLine("."); } } - } - catch(Exception e) + } + catch (Exception e) { ErrorHandler.Error("Error occurred while sending e-mail notification.", e); } @@ -280,8 +280,8 @@ protected override void SendBuffer(LoggingEvent[] events) /// must be called again. /// /// - public override void ActivateOptions() - { + public override void ActivateOptions() + { base.ActivateOptions(); if (m_securityContext == null) @@ -289,7 +289,7 @@ public override void ActivateOptions() m_securityContext = SecurityContextProvider.DefaultProvider.CreateSecurityContext(this); } - using(SecurityContext.Impersonate(this)) + using (SecurityContext.Impersonate(this)) { m_pickupDir = ConvertToFullPath(m_pickupDir.Trim()); } diff --git a/src/log4net/Appender/TelnetAppender.cs b/src/log4net/Appender/TelnetAppender.cs index 9aa503e0..b0e21307 100644 --- a/src/log4net/Appender/TelnetAppender.cs +++ b/src/log4net/Appender/TelnetAppender.cs @@ -30,7 +30,7 @@ using log4net.Core; using log4net.Util; -namespace log4net.Appender +namespace log4net.Appender { /// /// Appender that allows clients to connect via Telnet to receive log messages @@ -49,7 +49,7 @@ namespace log4net.Appender /// /// Keith Long /// Nicko Cadell - public class TelnetAppender : AppenderSkeleton + public class TelnetAppender : AppenderSkeleton { private SocketHandler m_handler; private int m_listeningPort = 23; @@ -70,18 +70,18 @@ public TelnetAppender() #endregion - #region Private Static Fields + #region Private Static Fields - /// - /// The fully qualified type of the TelnetAppender class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(TelnetAppender); + /// + /// The fully qualified type of the TelnetAppender class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(TelnetAppender); - #endregion Private Static Fields + #endregion Private Static Fields /// /// Gets or sets the TCP port number on which this will listen for connections. @@ -108,9 +108,9 @@ public int Port if (value < IPEndPoint.MinPort || value > IPEndPoint.MaxPort) { throw log4net.Util.SystemInfo.CreateArgumentOutOfRangeException("value", (object)value, - "The value specified for Port is less than " + - IPEndPoint.MinPort.ToString(NumberFormatInfo.InvariantInfo) + - " or greater than " + + "The value specified for Port is less than " + + IPEndPoint.MinPort.ToString(NumberFormatInfo.InvariantInfo) + + " or greater than " + IPEndPoint.MaxPort.ToString(NumberFormatInfo.InvariantInfo) + "."); } else @@ -130,7 +130,7 @@ public int Port /// Closes all the outstanding connections. /// /// - protected override void OnClose() + protected override void OnClose() { base.OnClose(); @@ -174,15 +174,15 @@ protected override bool RequiresLayout /// Create the socket handler and wait for connections /// /// - public override void ActivateOptions() + public override void ActivateOptions() { base.ActivateOptions(); - try + try { - LogLog.Debug(declaringType, "Creating SocketHandler to listen on port ["+m_listeningPort+"]"); + LogLog.Debug(declaringType, "Creating SocketHandler to listen on port [" + m_listeningPort + "]"); m_handler = new SocketHandler(m_listeningPort); } - catch(Exception ex) + catch (Exception ex) { LogLog.Error(declaringType, "Failed to create SocketHandler", ex); throw; @@ -198,7 +198,7 @@ public override void ActivateOptions() /// Writes the logging event to each connected client. /// /// - protected override void Append(LoggingEvent loggingEvent) + protected override void Append(LoggingEvent loggingEvent) { if (m_handler != null && m_handler.HasConnections) { @@ -221,7 +221,7 @@ protected override void Append(LoggingEvent loggingEvent) /// /// protected class SocketHandler : IDisposable - { + { private const int MAX_CONNECTIONS = 20; private Socket m_serverSocket; @@ -325,7 +325,7 @@ public void Dispose() #endregion } - + /// /// Opens a new server port on /// @@ -387,7 +387,7 @@ public void Send(String message) /// client to add private void AddClient(SocketClient client) { - lock(this) + lock (this) { ArrayList clientsCopy = (ArrayList)m_clients.Clone(); clientsCopy.Add(client); @@ -401,7 +401,7 @@ private void AddClient(SocketClient client) /// client to remove private void RemoveClient(SocketClient client) { - lock(this) + lock (this) { ArrayList clientsCopy = (ArrayList)m_clients.Clone(); clientsCopy.Remove(client); @@ -431,7 +431,7 @@ public bool HasConnections return (localClients != null && localClients.Count > 0); } } - + #if NETSTANDARD private void OnConnect(Task acceptTask) @@ -457,11 +457,11 @@ private void OnConnect(IAsyncResult asyncResult) // Block until a client connects Socket socket = m_serverSocket.EndAccept(asyncResult); #endif - LogLog.Debug(declaringType, "Accepting connection from ["+socket.RemoteEndPoint.ToString()+"]"); + LogLog.Debug(declaringType, "Accepting connection from [" + socket.RemoteEndPoint.ToString() + "]"); SocketClient client = new SocketClient(socket); int currentActiveConnectionsCount = m_clients.Count; - if (currentActiveConnectionsCount < MAX_CONNECTIONS) + if (currentActiveConnectionsCount < MAX_CONNECTIONS) { try { @@ -473,7 +473,7 @@ private void OnConnect(IAsyncResult asyncResult) client.Dispose(); } } - else + else { client.Send("Sorry - Too many connections.\r\n"); client.Dispose(); @@ -513,12 +513,12 @@ public void Dispose() Socket localSocket = m_serverSocket; m_serverSocket = null; - try + try { localSocket.Shutdown(SocketShutdown.Both); - } - catch - { + } + catch + { } try @@ -529,9 +529,9 @@ public void Dispose() localSocket.Dispose(); #endif } - catch - { - } + catch + { + } } #endregion diff --git a/src/log4net/Appender/TextWriterAppender.cs b/src/log4net/Appender/TextWriterAppender.cs index b047be2a..41b9dc57 100644 --- a/src/log4net/Appender/TextWriterAppender.cs +++ b/src/log4net/Appender/TextWriterAppender.cs @@ -42,7 +42,7 @@ namespace log4net.Appender /// Nicko Cadell /// Gert Driesen /// Douglas de la Torre - public class TextWriterAppender : AppenderSkeleton + public class TextWriterAppender : AppenderSkeleton { #region Public Instance Constructors @@ -54,7 +54,7 @@ public class TextWriterAppender : AppenderSkeleton /// Default constructor. /// /// - public TextWriterAppender() + public TextWriterAppender() { } @@ -90,7 +90,7 @@ public TextWriterAppender() /// /// [Obsolete("Instead use the default constructor and set the Layout & Writer properties")] - public TextWriterAppender(ILayout layout, TextWriter writer) + public TextWriterAppender(ILayout layout, TextWriter writer) { Layout = layout; Writer = writer; @@ -123,7 +123,7 @@ public TextWriterAppender(ILayout layout, TextWriter writer) /// be recorded on disk when the application exits. This is a high /// price to pay even for a 20% performance gain. /// - public bool ImmediateFlush + public bool ImmediateFlush { get { return m_immediateFlush; } set { m_immediateFlush = value; } @@ -144,12 +144,12 @@ public bool ImmediateFlush /// Note: Logging to an unopened will fail. /// /// - public virtual TextWriter Writer + public virtual TextWriter Writer { get { return m_qtw; } - set + set { - lock(this) + lock (this) { Reset(); if (value != null) @@ -175,27 +175,27 @@ public virtual TextWriter Writer /// /// /// false if any of the preconditions fail. - protected override bool PreAppendCheck() + protected override bool PreAppendCheck() { - if (!base.PreAppendCheck()) + if (!base.PreAppendCheck()) { return false; } - if (m_qtw == null) + if (m_qtw == null) { // Allow subclass to lazily create the writer PrepareWriter(); - if (m_qtw == null) + if (m_qtw == null) { - ErrorHandler.Error("No output stream or file set for the appender named ["+ Name +"]."); + ErrorHandler.Error("No output stream or file set for the appender named [" + Name + "]."); return false; } } - if (m_qtw.Closed) + if (m_qtw.Closed) { - ErrorHandler.Error("Output stream for appender named ["+ Name +"] has been closed."); + ErrorHandler.Error("Output stream for appender named [" + Name + "] has been closed."); return false; } @@ -216,14 +216,14 @@ protected override bool PreAppendCheck() /// The format of the output will depend on the appender's layout. /// /// - protected override void Append(LoggingEvent loggingEvent) + protected override void Append(LoggingEvent loggingEvent) { RenderLoggingEvent(m_qtw, loggingEvent); - if (m_immediateFlush) + if (m_immediateFlush) { m_qtw.Flush(); - } + } } /// @@ -237,17 +237,17 @@ protected override void Append(LoggingEvent loggingEvent) /// before flushing the stream. /// /// - protected override void Append(LoggingEvent[] loggingEvents) + protected override void Append(LoggingEvent[] loggingEvents) { - foreach(LoggingEvent loggingEvent in loggingEvents) + foreach (LoggingEvent loggingEvent in loggingEvents) { RenderLoggingEvent(m_qtw, loggingEvent); } - if (m_immediateFlush) + if (m_immediateFlush) { m_qtw.Flush(); - } + } } /// @@ -256,9 +256,9 @@ protected override void Append(LoggingEvent[] loggingEvents) /// /// Closed appenders cannot be reused. /// - protected override void OnClose() + protected override void OnClose() { - lock(this) + lock (this) { Reset(); } @@ -276,20 +276,20 @@ public override IErrorHandler ErrorHandler get { return base.ErrorHandler; } set { - lock(this) + lock (this) { - if (value == null) + if (value == null) { LogLog.Warn(declaringType, "TextWriterAppender: You have tried to set a null error-handler."); - } - else + } + else { base.ErrorHandler = value; - if (m_qtw != null) + if (m_qtw != null) { m_qtw.ErrorHandler = value; } - } + } } } } @@ -334,17 +334,17 @@ protected virtual void WriteFooterAndCloseWriter() /// Closes the underlying . /// /// - protected virtual void CloseWriter() + protected virtual void CloseWriter() { - if (m_qtw != null) + if (m_qtw != null) { - try + try { m_qtw.Close(); - } - catch(Exception e) + } + catch (Exception e) { - ErrorHandler.Error("Could not close writer ["+m_qtw+"]", e); + ErrorHandler.Error("Could not close writer [" + m_qtw + "]", e); // do need to invoke an error handler // at this late stage } @@ -360,7 +360,7 @@ protected virtual void CloseWriter() /// Subclasses can override this method for an alternate closing behavior. /// /// - protected virtual void Reset() + protected virtual void Reset() { WriteFooterAndCloseWriter(); m_qtw = null; @@ -374,9 +374,9 @@ protected virtual void Reset() /// Writes a footer as produced by the embedded layout's property. /// /// - protected virtual void WriteFooter() + protected virtual void WriteFooter() { - if (Layout != null && m_qtw != null && !m_qtw.Closed) + if (Layout != null && m_qtw != null && !m_qtw.Closed) { string f = Layout.Footer; if (f != null) @@ -394,9 +394,9 @@ protected virtual void WriteFooter() /// Writes a header produced by the embedded layout's property. /// /// - protected virtual void WriteHeader() + protected virtual void WriteHeader() { - if (Layout != null && m_qtw != null && !m_qtw.Closed) + if (Layout != null && m_qtw != null && !m_qtw.Closed) { string h = Layout.Header; if (h != null) @@ -437,13 +437,13 @@ protected QuietTextWriter QuietWriter { get { return m_qtw; } set { m_qtw = value; } - } + } - #endregion Protected Instance Methods + #endregion Protected Instance Methods - #region Private Instance Fields + #region Private Instance Fields - /// + /// /// This is the where logging events /// will be written to. /// @@ -469,36 +469,36 @@ protected QuietTextWriter QuietWriter #endregion Private Instance Fields - #region Private Static Fields - - /// - /// The fully qualified type of the TextWriterAppender class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(TextWriterAppender); - - #endregion Private Static Fields - - /// - /// Flushes any buffered log data. - /// - /// The maximum time to wait for logging events to be flushed. - /// True if all logging events were flushed successfully, else false. - public override bool Flush(int millisecondsTimeout) - { - // Nothing to do if ImmediateFlush is true - if (m_immediateFlush) return true; + #region Private Static Fields + + /// + /// The fully qualified type of the TextWriterAppender class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(TextWriterAppender); - // lock(this) will block any Appends while the buffer is flushed. - lock (this) - { - m_qtw.Flush(); - } + #endregion Private Static Fields - return true; - } + /// + /// Flushes any buffered log data. + /// + /// The maximum time to wait for logging events to be flushed. + /// True if all logging events were flushed successfully, else false. + public override bool Flush(int millisecondsTimeout) + { + // Nothing to do if ImmediateFlush is true + if (m_immediateFlush) return true; + + // lock(this) will block any Appends while the buffer is flushed. + lock (this) + { + m_qtw.Flush(); + } + + return true; + } } } diff --git a/src/log4net/Appender/TraceAppender.cs b/src/log4net/Appender/TraceAppender.cs index e266f4b8..e495336e 100644 --- a/src/log4net/Appender/TraceAppender.cs +++ b/src/log4net/Appender/TraceAppender.cs @@ -37,7 +37,7 @@ namespace log4net.Appender /// /// Events are written using the System.Diagnostics.Trace.Write(string,string) /// method. The event's logger name is the default value for the category parameter - /// of the Write method. + /// of the Write method. /// /// /// Compact Framework
@@ -50,7 +50,7 @@ namespace log4net.Appender /// Douglas de la Torre /// Nicko Cadell /// Gert Driesen - /// Ron Grabowski + /// Ron Grabowski public class TraceAppender : AppenderSkeleton { #region Public Instance Constructors @@ -111,24 +111,24 @@ public bool ImmediateFlush set { m_immediateFlush = value; } } - /// - /// The category parameter sent to the Trace method. - /// - /// - /// - /// Defaults to %logger which will use the logger name of the current - /// as the category parameter. - /// - /// - /// - /// - public PatternLayout Category - { - get { return m_category; } - set { m_category = value; } - } + /// + /// The category parameter sent to the Trace method. + /// + /// + /// + /// Defaults to %logger which will use the logger name of the current + /// as the category parameter. + /// + /// + /// + /// + public PatternLayout Category + { + get { return m_category; } + set { m_category = value; } + } - #endregion Public Instance Properties + #endregion Public Instance Properties #region Override implementation of AppenderSkeleton @@ -141,7 +141,7 @@ public PatternLayout Category /// Writes the logging event to the system. ///
/// - protected override void Append(LoggingEvent loggingEvent) + protected override void Append(LoggingEvent loggingEvent) { // // Write the string to the Trace system @@ -149,20 +149,20 @@ protected override void Append(LoggingEvent loggingEvent) #if NETCF System.Diagnostics.Debug.Write(RenderLoggingEvent(loggingEvent), m_category.Format(loggingEvent)); #else - System.Diagnostics.Trace.Write(RenderLoggingEvent(loggingEvent), m_category.Format(loggingEvent)); + System.Diagnostics.Trace.Write(RenderLoggingEvent(loggingEvent), m_category.Format(loggingEvent)); #endif - + // // Flush the Trace system if needed // - if (m_immediateFlush) + if (m_immediateFlush) { #if NETCF System.Diagnostics.Debug.Flush(); #else System.Diagnostics.Trace.Flush(); #endif - } + } } /// @@ -200,30 +200,30 @@ protected override bool RequiresLayout /// private bool m_immediateFlush = true; - /// - /// Defaults to %logger - /// - private PatternLayout m_category = new PatternLayout("%logger"); + /// + /// Defaults to %logger + /// + private PatternLayout m_category = new PatternLayout("%logger"); #endregion Private Instance Fields - /// - /// Flushes any buffered log data. - /// - /// The maximum time to wait for logging events to be flushed. - /// True if all logging events were flushed successfully, else false. - public override bool Flush(int millisecondsTimeout) - { - // Nothing to do if ImmediateFlush is true - if (m_immediateFlush) return true; - - // System.Diagnostics.Trace and System.Diagnostics.Debug are thread-safe, so no need for lock(this). + /// + /// Flushes any buffered log data. + /// + /// The maximum time to wait for logging events to be flushed. + /// True if all logging events were flushed successfully, else false. + public override bool Flush(int millisecondsTimeout) + { + // Nothing to do if ImmediateFlush is true + if (m_immediateFlush) return true; + + // System.Diagnostics.Trace and System.Diagnostics.Debug are thread-safe, so no need for lock(this). #if NETCF System.Diagnostics.Debug.Flush(); #else - System.Diagnostics.Trace.Flush(); + System.Diagnostics.Trace.Flush(); #endif - return true; - } + return true; } + } } diff --git a/src/log4net/Appender/UdpAppender.cs b/src/log4net/Appender/UdpAppender.cs index 70acff03..b0d4f68d 100644 --- a/src/log4net/Appender/UdpAppender.cs +++ b/src/log4net/Appender/UdpAppender.cs @@ -25,7 +25,7 @@ using log4net.Core; -namespace log4net.Appender +namespace log4net.Appender { /// /// Sends logging events as connectionless UDP datagrams to a remote host or a @@ -114,7 +114,7 @@ public class UdpAppender : AppenderSkeleton /// /// The default constructor initializes all fields to their default values. /// - public UdpAppender() + public UdpAppender() { } @@ -212,17 +212,17 @@ public IPAddress RemoteAddress public int RemotePort { get { return m_remotePort; } - set + set { - if (value < IPEndPoint.MinPort || value > IPEndPoint.MaxPort) + if (value < IPEndPoint.MinPort || value > IPEndPoint.MaxPort) { throw log4net.Util.SystemInfo.CreateArgumentOutOfRangeException("value", (object)value, - "The value specified is less than " + - IPEndPoint.MinPort.ToString(NumberFormatInfo.InvariantInfo) + - " or greater than " + + "The value specified is less than " + + IPEndPoint.MinPort.ToString(NumberFormatInfo.InvariantInfo) + + " or greater than " + IPEndPoint.MaxPort.ToString(NumberFormatInfo.InvariantInfo) + "."); - } - else + } + else { m_remotePort = value; } @@ -249,17 +249,17 @@ public int RemotePort public int LocalPort { get { return m_localPort; } - set + set { if (value != 0 && (value < IPEndPoint.MinPort || value > IPEndPoint.MaxPort)) { throw log4net.Util.SystemInfo.CreateArgumentOutOfRangeException("value", (object)value, - "The value specified is less than " + - IPEndPoint.MinPort.ToString(NumberFormatInfo.InvariantInfo) + - " or greater than " + + "The value specified is less than " + + IPEndPoint.MinPort.ToString(NumberFormatInfo.InvariantInfo) + + " or greater than " + IPEndPoint.MaxPort.ToString(NumberFormatInfo.InvariantInfo) + "."); - } - else + } + else { m_localPort = value; } @@ -353,27 +353,27 @@ public override void ActivateOptions() { base.ActivateOptions(); - if (this.RemoteAddress == null) + if (this.RemoteAddress == null) { throw new ArgumentNullException("The required property 'Address' was not specified."); - } - else if (this.RemotePort < IPEndPoint.MinPort || this.RemotePort > IPEndPoint.MaxPort) + } + else if (this.RemotePort < IPEndPoint.MinPort || this.RemotePort > IPEndPoint.MaxPort) { throw log4net.Util.SystemInfo.CreateArgumentOutOfRangeException("this.RemotePort", (object)this.RemotePort, - "The RemotePort is less than " + - IPEndPoint.MinPort.ToString(NumberFormatInfo.InvariantInfo) + - " or greater than " + + "The RemotePort is less than " + + IPEndPoint.MinPort.ToString(NumberFormatInfo.InvariantInfo) + + " or greater than " + IPEndPoint.MaxPort.ToString(NumberFormatInfo.InvariantInfo) + "."); - } + } else if (this.LocalPort != 0 && (this.LocalPort < IPEndPoint.MinPort || this.LocalPort > IPEndPoint.MaxPort)) { throw log4net.Util.SystemInfo.CreateArgumentOutOfRangeException("this.LocalPort", (object)this.LocalPort, - "The LocalPort is less than " + - IPEndPoint.MinPort.ToString(NumberFormatInfo.InvariantInfo) + - " or greater than " + + "The LocalPort is less than " + + IPEndPoint.MinPort.ToString(NumberFormatInfo.InvariantInfo) + + " or greater than " + IPEndPoint.MaxPort.ToString(NumberFormatInfo.InvariantInfo) + "."); - } - else + } + else { this.RemoteEndPoint = new IPEndPoint(this.RemoteAddress, this.RemotePort); this.InitializeClientConnection(); @@ -396,25 +396,25 @@ public override void ActivateOptions() /// Exceptions are passed to the . /// /// - protected override void Append(LoggingEvent loggingEvent) + protected override void Append(LoggingEvent loggingEvent) { - try + try { - Byte [] buffer = m_encoding.GetBytes(RenderLoggingEvent(loggingEvent).ToCharArray()); + Byte[] buffer = m_encoding.GetBytes(RenderLoggingEvent(loggingEvent).ToCharArray()); #if NETSTANDARD Client.SendAsync(buffer, buffer.Length, RemoteEndPoint).Wait(); #else this.Client.Send(buffer, buffer.Length, this.RemoteEndPoint); #endif - } - catch (Exception ex) + } + catch (Exception ex) { ErrorHandler.Error( - "Unable to send logging event to remote host " + - this.RemoteAddress.ToString() + - " on port " + - this.RemotePort + ".", - ex, + "Unable to send logging event to remote host " + + this.RemoteAddress.ToString() + + " on port " + + this.RemotePort + ".", + ex, ErrorCode.WriteFailure); } } @@ -443,11 +443,11 @@ protected override bool RequiresLayout /// and unmanaged resources associated with the . /// /// - protected override void OnClose() + protected override void OnClose() { base.OnClose(); - if (this.Client != null) + if (this.Client != null) { this.Client.Close(); } @@ -469,9 +469,9 @@ protected override void OnClose() /// Exceptions are passed to the . /// /// - protected virtual void InitializeClientConnection() + protected virtual void InitializeClientConnection() { - try + try { if (this.LocalPort == 0) { @@ -489,13 +489,13 @@ protected virtual void InitializeClientConnection() this.Client = new UdpClient(this.LocalPort, RemoteAddress.AddressFamily); #endif } - } - catch (Exception ex) + } + catch (Exception ex) { ErrorHandler.Error( - "Could not initialize the UdpClient connection on port " + - this.LocalPort.ToString(NumberFormatInfo.InvariantInfo) + ".", - ex, + "Could not initialize the UdpClient connection on port " + + this.LocalPort.ToString(NumberFormatInfo.InvariantInfo) + ".", + ex, ErrorCode.GenericFailure); this.Client = null; @@ -511,7 +511,7 @@ protected virtual void InitializeClientConnection() /// the logging event will be sent. /// private IPAddress m_remoteAddress; - + /// /// The TCP port number of the remote host or multicast group to /// which the logging event will be sent. diff --git a/src/log4net/AssemblyInfo.cs b/src/log4net/AssemblyInfo.cs index 19772bc6..3c55f6bc 100644 --- a/src/log4net/AssemblyInfo.cs +++ b/src/log4net/AssemblyInfo.cs @@ -137,8 +137,8 @@ [assembly: AssemblyProduct("log4net")] [assembly: AssemblyDefaultAlias("log4net")] -[assembly: AssemblyCulture("")] - +[assembly: AssemblyCulture("")] + // // In order to sign your assembly you must specify a key to use. Refer to the // Microsoft .NET Framework documentation for more information on assembly signing. diff --git a/src/log4net/Config/AliasDomainAttribute.cs b/src/log4net/Config/AliasDomainAttribute.cs index dc1af1f5..c1da9995 100644 --- a/src/log4net/Config/AliasDomainAttribute.cs +++ b/src/log4net/Config/AliasDomainAttribute.cs @@ -46,7 +46,7 @@ namespace log4net.Config /// /// Nicko Cadell /// Gert Driesen - [AttributeUsage(AttributeTargets.Assembly,AllowMultiple=true)] + [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] [Serializable] [Obsolete("Use AliasRepositoryAttribute instead of AliasDomainAttribute")] public sealed class AliasDomainAttribute : AliasRepositoryAttribute diff --git a/src/log4net/Config/AliasRepositoryAttribute.cs b/src/log4net/Config/AliasRepositoryAttribute.cs index 1b6021fe..29b4a8f9 100644 --- a/src/log4net/Config/AliasRepositoryAttribute.cs +++ b/src/log4net/Config/AliasRepositoryAttribute.cs @@ -43,7 +43,7 @@ namespace log4net.Config /// /// Nicko Cadell /// Gert Driesen - [AttributeUsage(AttributeTargets.Assembly,AllowMultiple=true)] + [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] [Serializable] public /*sealed*/ class AliasRepositoryAttribute : Attribute { @@ -87,7 +87,7 @@ public AliasRepositoryAttribute(string name) public string Name { get { return m_name; } - set { m_name = value ; } + set { m_name = value; } } #endregion Public Instance Properties diff --git a/src/log4net/Config/BasicConfigurator.cs b/src/log4net/Config/BasicConfigurator.cs index 8e5a6b23..53afeaeb 100644 --- a/src/log4net/Config/BasicConfigurator.cs +++ b/src/log4net/Config/BasicConfigurator.cs @@ -52,23 +52,23 @@ namespace log4net.Config /// Nicko Cadell /// Gert Driesen public sealed class BasicConfigurator - { - #region Private Static Fields + { + #region Private Static Fields - /// - /// The fully qualified type of the BasicConfigurator class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(BasicConfigurator); + /// + /// The fully qualified type of the BasicConfigurator class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(BasicConfigurator); - #endregion Private Static Fields + #endregion Private Static Fields - #region Private Instance Constructors + #region Private Instance Constructors - /// + /// /// Initializes a new instance of the class. /// /// @@ -97,37 +97,37 @@ private BasicConfigurator() /// layout style. /// /// - public static ICollection Configure() + public static ICollection Configure() { - return BasicConfigurator.Configure(LogManager.GetRepository(Assembly.GetCallingAssembly())); - } - - /// - /// Initializes the log4net system using the specified appenders. - /// - /// The appenders to use to log all logging events. - /// - /// - /// Initializes the log4net system using the specified appenders. - /// - /// - public static ICollection Configure(params IAppender[] appenders) - { - ArrayList configurationMessages = new ArrayList(); - - ILoggerRepository repository = LogManager.GetRepository(Assembly.GetCallingAssembly()); - - using (new LogLog.LogReceivedAdapter(configurationMessages)) - { - InternalConfigure(repository, appenders); - } - - repository.ConfigurationMessages = configurationMessages; - - return configurationMessages; - } - - /// + return BasicConfigurator.Configure(LogManager.GetRepository(Assembly.GetCallingAssembly())); + } + + /// + /// Initializes the log4net system using the specified appenders. + /// + /// The appenders to use to log all logging events. + /// + /// + /// Initializes the log4net system using the specified appenders. + /// + /// + public static ICollection Configure(params IAppender[] appenders) + { + ArrayList configurationMessages = new ArrayList(); + + ILoggerRepository repository = LogManager.GetRepository(Assembly.GetCallingAssembly()); + + using (new LogLog.LogReceivedAdapter(configurationMessages)) + { + InternalConfigure(repository, appenders); + } + + repository.ConfigurationMessages = configurationMessages; + + return configurationMessages; + } + + /// /// Initializes the log4net system using the specified appender. /// /// The appender to use to log all logging events. @@ -136,9 +136,9 @@ public static ICollection Configure(params IAppender[] appenders) /// Initializes the log4net system using the specified appender. /// /// - public static ICollection Configure(IAppender appender) + public static ICollection Configure(IAppender appender) { - return Configure(new IAppender[] { appender }); + return Configure(new IAppender[] { appender }); } #endif // !NETSTANDARD1_3 @@ -155,80 +155,80 @@ public static ICollection Configure(IAppender appender) /// layout style. /// /// - public static ICollection Configure(ILoggerRepository repository) + public static ICollection Configure(ILoggerRepository repository) { - ArrayList configurationMessages = new ArrayList(); + ArrayList configurationMessages = new ArrayList(); + + using (new LogLog.LogReceivedAdapter(configurationMessages)) + { + // Create the layout + PatternLayout layout = new PatternLayout(); + layout.ConversionPattern = PatternLayout.DetailConversionPattern; + layout.ActivateOptions(); - using (new LogLog.LogReceivedAdapter(configurationMessages)) - { - // Create the layout - PatternLayout layout = new PatternLayout(); - layout.ConversionPattern = PatternLayout.DetailConversionPattern; - layout.ActivateOptions(); + // Create the appender + ConsoleAppender appender = new ConsoleAppender(); + appender.Layout = layout; + appender.ActivateOptions(); - // Create the appender - ConsoleAppender appender = new ConsoleAppender(); - appender.Layout = layout; - appender.ActivateOptions(); + InternalConfigure(repository, appender); + } + + repository.ConfigurationMessages = configurationMessages; + + return configurationMessages; + } + + /// + /// Initializes the using the specified appender. + /// + /// The repository to configure. + /// The appender to use to log all logging events. + /// + /// + /// Initializes the using the specified appender. + /// + /// + public static ICollection Configure(ILoggerRepository repository, IAppender appender) + { + return Configure(repository, new IAppender[] { appender }); + } + + /// + /// Initializes the using the specified appenders. + /// + /// The repository to configure. + /// The appenders to use to log all logging events. + /// + /// + /// Initializes the using the specified appender. + /// + /// + public static ICollection Configure(ILoggerRepository repository, params IAppender[] appenders) + { + ArrayList configurationMessages = new ArrayList(); - InternalConfigure(repository, appender); - } + using (new LogLog.LogReceivedAdapter(configurationMessages)) + { + InternalConfigure(repository, appenders); + } - repository.ConfigurationMessages = configurationMessages; + repository.ConfigurationMessages = configurationMessages; - return configurationMessages; + return configurationMessages; } - /// - /// Initializes the using the specified appender. - /// - /// The repository to configure. - /// The appender to use to log all logging events. - /// - /// - /// Initializes the using the specified appender. - /// - /// - public static ICollection Configure(ILoggerRepository repository, IAppender appender) - { - return Configure(repository, new IAppender[] { appender }); - } - - /// - /// Initializes the using the specified appenders. - /// - /// The repository to configure. - /// The appenders to use to log all logging events. - /// - /// - /// Initializes the using the specified appender. - /// - /// - public static ICollection Configure(ILoggerRepository repository, params IAppender[] appenders) - { - ArrayList configurationMessages = new ArrayList(); - - using (new LogLog.LogReceivedAdapter(configurationMessages)) - { - InternalConfigure(repository, appenders); - } - - repository.ConfigurationMessages = configurationMessages; - - return configurationMessages; - } - - private static void InternalConfigure(ILoggerRepository repository, params IAppender[] appenders) + private static void InternalConfigure(ILoggerRepository repository, params IAppender[] appenders) { - IBasicRepositoryConfigurator configurableRepository = repository as IBasicRepositoryConfigurator; - if (configurableRepository != null) - { - configurableRepository.Configure(appenders); - } - else - { - LogLog.Warn(declaringType, "BasicConfigurator: Repository [" + repository + "] does not support the BasicConfigurator"); - } + IBasicRepositoryConfigurator configurableRepository = repository as IBasicRepositoryConfigurator; + if (configurableRepository != null) + { + configurableRepository.Configure(appenders); + } + else + { + LogLog.Warn(declaringType, "BasicConfigurator: Repository [" + repository + "] does not support the BasicConfigurator"); + } } #endregion Public Static Methods diff --git a/src/log4net/Config/DOMConfigurator.cs b/src/log4net/Config/DOMConfigurator.cs index 0486edfc..b7c15637 100644 --- a/src/log4net/Config/DOMConfigurator.cs +++ b/src/log4net/Config/DOMConfigurator.cs @@ -52,8 +52,8 @@ public sealed class DOMConfigurator /// /// Private constructor /// - private DOMConfigurator() - { + private DOMConfigurator() + { } #endregion Protected Instance Constructors @@ -75,7 +75,7 @@ private DOMConfigurator() /// log4net that contains the configuration data. /// [Obsolete("Use XmlConfigurator.Configure instead of DOMConfigurator.Configure")] - public static void Configure() + public static void Configure() { XmlConfigurator.Configure(LogManager.GetRepository(Assembly.GetCallingAssembly())); } @@ -96,7 +96,7 @@ public static void Configure() /// /// The repository to configure. [Obsolete("Use XmlConfigurator.Configure instead of DOMConfigurator.Configure")] - public static void Configure(ILoggerRepository repository) + public static void Configure(ILoggerRepository repository) { XmlConfigurator.Configure(repository); } @@ -113,7 +113,7 @@ public static void Configure(ILoggerRepository repository) /// /// The element to parse. [Obsolete("Use XmlConfigurator.Configure instead of DOMConfigurator.Configure")] - public static void Configure(XmlElement element) + public static void Configure(XmlElement element) { XmlConfigurator.Configure(LogManager.GetRepository(Assembly.GetCallingAssembly()), element); } @@ -132,7 +132,7 @@ public static void Configure(XmlElement element) /// The repository to configure. /// The element to parse. [Obsolete("Use XmlConfigurator.Configure instead of DOMConfigurator.Configure")] - public static void Configure(ILoggerRepository repository, XmlElement element) + public static void Configure(ILoggerRepository repository, XmlElement element) { XmlConfigurator.Configure(repository, element); } diff --git a/src/log4net/Config/PluginAttribute.cs b/src/log4net/Config/PluginAttribute.cs index 229dad9b..21bbad7a 100644 --- a/src/log4net/Config/PluginAttribute.cs +++ b/src/log4net/Config/PluginAttribute.cs @@ -43,7 +43,7 @@ namespace log4net.Config /// /// Nicko Cadell /// Gert Driesen - [AttributeUsage(AttributeTargets.Assembly,AllowMultiple=true)] + [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] [Serializable] public sealed class PluginAttribute : Attribute, IPluginFactory { @@ -102,7 +102,7 @@ public PluginAttribute(Type type) public Type Type { get { return m_type; } - set { m_type = value ; } + set { m_type = value; } } /// @@ -122,7 +122,7 @@ public Type Type public string TypeName { get { return m_typeName; } - set { m_typeName = value ; } + set { m_typeName = value; } } #endregion Public Instance Properties diff --git a/src/log4net/Config/RepositoryAttribute.cs b/src/log4net/Config/RepositoryAttribute.cs index 2bacd532..9f3b7238 100644 --- a/src/log4net/Config/RepositoryAttribute.cs +++ b/src/log4net/Config/RepositoryAttribute.cs @@ -101,7 +101,7 @@ public RepositoryAttribute(string name) public string Name { get { return m_name; } - set { m_name = value ; } + set { m_name = value; } } /// @@ -127,7 +127,7 @@ public string Name public Type RepositoryType { get { return m_repositoryType; } - set { m_repositoryType = value ; } + set { m_repositoryType = value; } } #endregion Public Instance Properties diff --git a/src/log4net/Config/SecurityContextProviderAttribute.cs b/src/log4net/Config/SecurityContextProviderAttribute.cs index c85c15f8..5e76c1fe 100644 --- a/src/log4net/Config/SecurityContextProviderAttribute.cs +++ b/src/log4net/Config/SecurityContextProviderAttribute.cs @@ -106,17 +106,17 @@ public override void Configure(Assembly sourceAssembly, ILoggerRepository target { if (m_providerType == null) { - LogLog.Error(declaringType, "Attribute specified on assembly ["+sourceAssembly.FullName+"] with null ProviderType."); + LogLog.Error(declaringType, "Attribute specified on assembly [" + sourceAssembly.FullName + "] with null ProviderType."); } else { - LogLog.Debug(declaringType, "Creating provider of type ["+ m_providerType.FullName +"]"); + LogLog.Debug(declaringType, "Creating provider of type [" + m_providerType.FullName + "]"); SecurityContextProvider provider = Activator.CreateInstance(m_providerType) as SecurityContextProvider; if (provider == null) { - LogLog.Error(declaringType, "Failed to create SecurityContextProvider instance of type ["+m_providerType.Name+"]."); + LogLog.Error(declaringType, "Failed to create SecurityContextProvider instance of type [" + m_providerType.Name + "]."); } else { @@ -133,18 +133,18 @@ public override void Configure(Assembly sourceAssembly, ILoggerRepository target #endregion Private Instance Fields - #region Private Static Fields + #region Private Static Fields - /// - /// The fully qualified type of the SecurityContextProviderAttribute class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(SecurityContextProviderAttribute); + /// + /// The fully qualified type of the SecurityContextProviderAttribute class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(SecurityContextProviderAttribute); - #endregion Private Static Fields + #endregion Private Static Fields } } diff --git a/src/log4net/Config/XmlConfigurator.cs b/src/log4net/Config/XmlConfigurator.cs index e854e75f..b11cda02 100644 --- a/src/log4net/Config/XmlConfigurator.cs +++ b/src/log4net/Config/XmlConfigurator.cs @@ -140,7 +140,7 @@ private static void InternalConfigure(ILoggerRepository repository) InternalConfigureFromXml(repository, configElement); } } - catch(System.Configuration.ConfigurationException confEx) + catch (System.Configuration.ConfigurationException confEx) { if (confEx.BareMessage.IndexOf("Unrecognized element") >= 0) { @@ -532,14 +532,14 @@ private static void InternalConfigure(ILoggerRepository repository, FileInfo con FileStream fs = null; // Try hard to open the file - for(int retry = 5; --retry >= 0; ) + for (int retry = 5; --retry >= 0;) { try { fs = configFile.Open(FileMode.Open, FileAccess.Read, FileShare.Read); break; } - catch(IOException ex) + catch (IOException ex) { if (retry == 0) { @@ -605,7 +605,7 @@ public static ICollection Configure(ILoggerRepository repository, Uri configUri) private static void InternalConfigure(ILoggerRepository repository, Uri configUri) { - LogLog.Debug(declaringType, "configuring repository [" + repository.Name + "] using URI ["+configUri+"]"); + LogLog.Debug(declaringType, "configuring repository [" + repository.Name + "] using URI [" + configUri + "]"); if (configUri == null) { @@ -627,9 +627,9 @@ private static void InternalConfigure(ILoggerRepository repository, Uri configUr { configRequest = WebRequest.Create(configUri); } - catch(Exception ex) + catch (Exception ex) { - LogLog.Error(declaringType, "Failed to create WebRequest for URI ["+configUri+"]", ex); + LogLog.Error(declaringType, "Failed to create WebRequest for URI [" + configUri + "]", ex); } if (configRequest != null) @@ -658,9 +658,9 @@ private static void InternalConfigure(ILoggerRepository repository, Uri configUr InternalConfigure(repository, configStream); } } - catch(Exception ex) + catch (Exception ex) { - LogLog.Error(declaringType, "Failed to request config from URI ["+configUri+"]", ex); + LogLog.Error(declaringType, "Failed to request config from URI [" + configUri + "]", ex); } } } @@ -746,7 +746,7 @@ private static void InternalConfigure(ILoggerRepository repository, Stream confi // load the data into the document doc.Load(xmlReader); } - catch(Exception ex) + catch (Exception ex) { LogLog.Error(declaringType, "Error while loading XML configuration", ex); @@ -890,9 +890,9 @@ private static void InternalConfigureAndWatch(ILoggerRepository repository, File m_repositoryName2ConfigAndWatchHandler[configFile.FullName] = handler; } } - catch(Exception ex) + catch (Exception ex) { - LogLog.Error(declaringType, "Failed to initialize configuration file watcher for file ["+configFile.FullName+"]", ex); + LogLog.Error(declaringType, "Failed to initialize configuration file watcher for file [" + configFile.FullName + "]", ex); } } } @@ -1001,7 +1001,7 @@ public ConfigureAndWatchHandler(ILoggerRepository repository, FileInfo configFil /// private void ConfigureAndWatchHandler_OnChanged(object source, FileSystemEventArgs e) { - LogLog.Debug(declaringType, "ConfigureAndWatchHandler: "+e.ChangeType+" [" + m_configFile.FullName + "]"); + LogLog.Debug(declaringType, "ConfigureAndWatchHandler: " + e.ChangeType + " [" + m_configFile.FullName + "]"); // Deliver the event in TimeoutMillis time // timer will fire only once diff --git a/src/log4net/Config/XmlConfiguratorAttribute.cs b/src/log4net/Config/XmlConfiguratorAttribute.cs index 4fa93fa6..bdc79a10 100644 --- a/src/log4net/Config/XmlConfiguratorAttribute.cs +++ b/src/log4net/Config/XmlConfiguratorAttribute.cs @@ -195,35 +195,35 @@ public bool Watch /// configure it. /// /// - /// The does not extend . + /// The does not extend . public override void Configure(Assembly sourceAssembly, ILoggerRepository targetRepository) { - IList configurationMessages = new ArrayList(); + IList configurationMessages = new ArrayList(); - using (new LogLog.LogReceivedAdapter(configurationMessages)) - { - string applicationBaseDirectory = null; - try - { - applicationBaseDirectory = SystemInfo.ApplicationBaseDirectory; - } - catch - { - // Ignore this exception because it is only thrown when ApplicationBaseDirectory is a file - // and the application does not have PathDiscovery permission - } - - if (applicationBaseDirectory == null || (new Uri(applicationBaseDirectory)).IsFile) - { - ConfigureFromFile(sourceAssembly, targetRepository); - } - else - { - ConfigureFromUri(sourceAssembly, targetRepository); - } - } + using (new LogLog.LogReceivedAdapter(configurationMessages)) + { + string applicationBaseDirectory = null; + try + { + applicationBaseDirectory = SystemInfo.ApplicationBaseDirectory; + } + catch + { + // Ignore this exception because it is only thrown when ApplicationBaseDirectory is a file + // and the application does not have PathDiscovery permission + } - targetRepository.ConfigurationMessages = configurationMessages; + if (applicationBaseDirectory == null || (new Uri(applicationBaseDirectory)).IsFile) + { + ConfigureFromFile(sourceAssembly, targetRepository); + } + else + { + ConfigureFromUri(sourceAssembly, targetRepository); + } + } + + targetRepository.ConfigurationMessages = configurationMessages; } #endregion @@ -237,7 +237,7 @@ private void ConfigureFromFile(Assembly sourceAssembly, ILoggerRepository target { // Work out the full path to the config file string fullPath2ConfigFile = null; - + // Select the config file if (m_configFile == null || m_configFile.Length == 0) { @@ -248,7 +248,7 @@ private void ConfigureFromFile(Assembly sourceAssembly, ILoggerRepository target { fullPath2ConfigFile = SystemInfo.ConfigurationFileLocation; } - catch(Exception ex) + catch (Exception ex) { LogLog.Error(declaringType, "XmlConfiguratorAttribute: Exception getting ConfigurationFileLocation. Must be able to resolve ConfigurationFileLocation when ConfigFile and ConfigFileExtension properties are not set.", ex); } @@ -266,7 +266,7 @@ private void ConfigureFromFile(Assembly sourceAssembly, ILoggerRepository target { applicationBaseDirectory = SystemInfo.ApplicationBaseDirectory; } - catch(Exception ex) + catch (Exception ex) { LogLog.Error(declaringType, "Exception getting ApplicationBaseDirectory. Must be able to resolve ApplicationBaseDirectory and AssemblyFileName when ConfigFileExtension property is set.", ex); } @@ -284,9 +284,9 @@ private void ConfigureFromFile(Assembly sourceAssembly, ILoggerRepository target { applicationBaseDirectory = SystemInfo.ApplicationBaseDirectory; } - catch(Exception ex) + catch (Exception ex) { - LogLog.Warn(declaringType, "Exception getting ApplicationBaseDirectory. ConfigFile property path ["+m_configFile+"] will be treated as an absolute path.", ex); + LogLog.Warn(declaringType, "Exception getting ApplicationBaseDirectory. ConfigFile property path [" + m_configFile + "] will be treated as an absolute path.", ex); } if (applicationBaseDirectory != null) @@ -341,7 +341,7 @@ private void ConfigureFromUri(Assembly sourceAssembly, ILoggerRepository targetR { // Work out the full path to the config file Uri fullPath2ConfigFile = null; - + // Select the config file if (m_configFile == null || m_configFile.Length == 0) { @@ -352,7 +352,7 @@ private void ConfigureFromUri(Assembly sourceAssembly, ILoggerRepository targetR { systemConfigFilePath = SystemInfo.ConfigurationFileLocation; } - catch(Exception ex) + catch (Exception ex) { LogLog.Error(declaringType, "XmlConfiguratorAttribute: Exception getting ConfigurationFileLocation. Must be able to resolve ConfigurationFileLocation when ConfigFile and ConfigFileExtension properties are not set.", ex); } @@ -378,7 +378,7 @@ private void ConfigureFromUri(Assembly sourceAssembly, ILoggerRepository targetR { systemConfigFilePath = SystemInfo.ConfigurationFileLocation; } - catch(Exception ex) + catch (Exception ex) { LogLog.Error(declaringType, "XmlConfiguratorAttribute: Exception getting ConfigurationFileLocation. Must be able to resolve ConfigurationFileLocation when the ConfigFile property are not set.", ex); } @@ -408,9 +408,9 @@ private void ConfigureFromUri(Assembly sourceAssembly, ILoggerRepository targetR { applicationBaseDirectory = SystemInfo.ApplicationBaseDirectory; } - catch(Exception ex) + catch (Exception ex) { - LogLog.Warn(declaringType, "Exception getting ApplicationBaseDirectory. ConfigFile property path ["+m_configFile+"] will be treated as an absolute URI.", ex); + LogLog.Warn(declaringType, "Exception getting ApplicationBaseDirectory. ConfigFile property path [" + m_configFile + "] will be treated as an absolute URI.", ex); } if (applicationBaseDirectory != null) @@ -451,18 +451,18 @@ private void ConfigureFromUri(Assembly sourceAssembly, ILoggerRepository targetR #endregion Private Instance Fields - #region Private Static Fields + #region Private Static Fields - /// - /// The fully qualified type of the XmlConfiguratorAttribute class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(XmlConfiguratorAttribute); + /// + /// The fully qualified type of the XmlConfiguratorAttribute class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(XmlConfiguratorAttribute); - #endregion Private Static Fields + #endregion Private Static Fields } } diff --git a/src/log4net/Core/CompactRepositorySelector.cs b/src/log4net/Core/CompactRepositorySelector.cs index f97f1071..6034315d 100644 --- a/src/log4net/Core/CompactRepositorySelector.cs +++ b/src/log4net/Core/CompactRepositorySelector.cs @@ -81,14 +81,14 @@ public CompactRepositorySelector(Type defaultRepositoryType) } // Check that the type is a repository - if (! (typeof(ILoggerRepository).IsAssignableFrom(defaultRepositoryType)) ) + if (!(typeof(ILoggerRepository).IsAssignableFrom(defaultRepositoryType))) { - throw log4net.Util.SystemInfo.CreateArgumentOutOfRangeException("defaultRepositoryType", (object)defaultRepositoryType, "Parameter: defaultRepositoryType, Value: ["+defaultRepositoryType+"] out of range. Argument must implement the ILoggerRepository interface"); + throw log4net.Util.SystemInfo.CreateArgumentOutOfRangeException("defaultRepositoryType", (object)defaultRepositoryType, "Parameter: defaultRepositoryType, Value: [" + defaultRepositoryType + "] out of range. Argument must implement the ILoggerRepository interface"); } m_defaultRepositoryType = defaultRepositoryType; - LogLog.Debug(declaringType, "defaultRepositoryType ["+m_defaultRepositoryType+"]"); + LogLog.Debug(declaringType, "defaultRepositoryType [" + m_defaultRepositoryType + "]"); } #endregion @@ -137,13 +137,13 @@ public ILoggerRepository GetRepository(string repositoryName) throw new ArgumentNullException("repositoryName"); } - lock(this) + lock (this) { // Lookup in map ILoggerRepository rep = m_name2repositoryMap[repositoryName] as ILoggerRepository; if (rep == null) { - throw new LogException("Repository ["+repositoryName+"] is NOT defined."); + throw new LogException("Repository [" + repositoryName + "] is NOT defined."); } return rep; } @@ -177,7 +177,7 @@ public ILoggerRepository CreateRepository(Assembly assembly, Type repositoryType repositoryType = m_defaultRepositoryType; } - lock(this) + lock (this) { // This method should not throw if the default repository already exists. @@ -190,7 +190,7 @@ public ILoggerRepository CreateRepository(Assembly assembly, Type repositoryType } return rep; - } + } } /// @@ -229,7 +229,7 @@ public ILoggerRepository CreateRepository(string repositoryName, Type repository repositoryType = m_defaultRepositoryType; } - lock(this) + lock (this) { ILoggerRepository rep = null; @@ -237,11 +237,11 @@ public ILoggerRepository CreateRepository(string repositoryName, Type repository rep = m_name2repositoryMap[repositoryName] as ILoggerRepository; if (rep != null) { - throw new LogException("Repository ["+repositoryName+"] is already defined. Repositories cannot be redefined."); + throw new LogException("Repository [" + repositoryName + "] is already defined. Repositories cannot be redefined."); } else { - LogLog.Debug(declaringType, "Creating repository ["+repositoryName+"] using type ["+repositoryType+"]"); + LogLog.Debug(declaringType, "Creating repository [" + repositoryName + "] using type [" + repositoryType + "]"); // Call the no arg constructor for the repositoryType rep = (ILoggerRepository)Activator.CreateInstance(repositoryType); @@ -274,7 +274,7 @@ public ILoggerRepository CreateRepository(string repositoryName, Type repository /// public bool ExistsRepository(string repositoryName) { - lock(this) + lock (this) { return m_name2repositoryMap.ContainsKey(repositoryName); } @@ -291,7 +291,7 @@ public bool ExistsRepository(string repositoryName) /// public ILoggerRepository[] GetAllRepositories() { - lock(this) + lock (this) { ICollection reps = m_name2repositoryMap.Values; ILoggerRepository[] all = new ILoggerRepository[reps.Count]; @@ -302,18 +302,18 @@ public ILoggerRepository[] GetAllRepositories() #endregion - #region Private Static Fields + #region Private Static Fields - /// - /// The fully qualified type of the CompactRepositorySelector class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(CompactRepositorySelector); + /// + /// The fully qualified type of the CompactRepositorySelector class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(CompactRepositorySelector); - #endregion Private Static Fields + #endregion Private Static Fields /// /// Event to notify that a logger repository has been created. diff --git a/src/log4net/Core/DefaultRepositorySelector.cs b/src/log4net/Core/DefaultRepositorySelector.cs index 32408134..913bfc85 100644 --- a/src/log4net/Core/DefaultRepositorySelector.cs +++ b/src/log4net/Core/DefaultRepositorySelector.cs @@ -66,7 +66,7 @@ public class DefaultRepositorySelector : IRepositorySelector /// holds the newly created . /// /// - public event LoggerRepositoryCreationEventHandler LoggerRepositoryCreatedEvent + public event LoggerRepositoryCreationEventHandler LoggerRepositoryCreatedEvent { add { m_loggerRepositoryCreatedEvent += value; } remove { m_loggerRepositoryCreatedEvent -= value; } @@ -97,7 +97,7 @@ public DefaultRepositorySelector(Type defaultRepositoryType) } // Check that the type is a repository - if (! (typeof(ILoggerRepository).IsAssignableFrom(defaultRepositoryType)) ) + if (!(typeof(ILoggerRepository).IsAssignableFrom(defaultRepositoryType))) { throw log4net.Util.SystemInfo.CreateArgumentOutOfRangeException("defaultRepositoryType", defaultRepositoryType, "Parameter: defaultRepositoryType, Value: [" + defaultRepositoryType + "] out of range. Argument must implement the ILoggerRepository interface"); } @@ -167,7 +167,7 @@ public ILoggerRepository GetRepository(string repositoryName) throw new ArgumentNullException("repositoryName"); } - lock(this) + lock (this) { // Lookup in map ILoggerRepository rep = m_name2repositoryMap[repositoryName] as ILoggerRepository; @@ -271,7 +271,7 @@ public ILoggerRepository CreateRepository(Assembly repositoryAssembly, Type repo repositoryType = m_defaultRepositoryType; } - lock(this) + lock (this) { // Lookup in map ILoggerRepository rep = m_assembly2repositoryMap[repositoryAssembly] as ILoggerRepository; @@ -370,7 +370,7 @@ public ILoggerRepository CreateRepository(string repositoryName, Type repository repositoryType = m_defaultRepositoryType; } - lock(this) + lock (this) { ILoggerRepository rep = null; @@ -401,7 +401,7 @@ public ILoggerRepository CreateRepository(string repositoryName, Type repository else { // Invalid repository type for alias - LogLog.Error(declaringType, "Failed to alias repository [" + repositoryName + "] to existing repository ["+aliasedRepository.Name+"]. Requested repository type ["+repositoryType.FullName+"] is not compatible with existing type [" + aliasedRepository.GetType().FullName + "]"); + LogLog.Error(declaringType, "Failed to alias repository [" + repositoryName + "] to existing repository [" + aliasedRepository.Name + "]. Requested repository type [" + repositoryType.FullName + "] is not compatible with existing type [" + aliasedRepository.GetType().FullName + "]"); // We now drop through to create the repository without aliasing } @@ -444,7 +444,7 @@ public ILoggerRepository CreateRepository(string repositoryName, Type repository /// public bool ExistsRepository(string repositoryName) { - lock(this) + lock (this) { return m_name2repositoryMap.ContainsKey(repositoryName); } @@ -461,7 +461,7 @@ public bool ExistsRepository(string repositoryName) /// public ILoggerRepository[] GetAllRepositories() { - lock(this) + lock (this) { ICollection reps = m_name2repositoryMap.Values; ILoggerRepository[] all = new ILoggerRepository[reps.Count]; @@ -494,40 +494,40 @@ public ILoggerRepository[] GetAllRepositories() /// -or- /// is . /// - public void AliasRepository(string repositoryAlias, ILoggerRepository repositoryTarget) + public void AliasRepository(string repositoryAlias, ILoggerRepository repositoryTarget) { - if (repositoryAlias == null) + if (repositoryAlias == null) { throw new ArgumentNullException("repositoryAlias"); } - if (repositoryTarget == null) + if (repositoryTarget == null) { throw new ArgumentNullException("repositoryTarget"); } - lock(this) + lock (this) { // Check if the alias is already set - if (m_alias2repositoryMap.Contains(repositoryAlias)) + if (m_alias2repositoryMap.Contains(repositoryAlias)) { // Check if this is a duplicate of the current alias - if (repositoryTarget != ((ILoggerRepository)m_alias2repositoryMap[repositoryAlias])) + if (repositoryTarget != ((ILoggerRepository)m_alias2repositoryMap[repositoryAlias])) { // Cannot redefine existing alias throw new InvalidOperationException("Repository [" + repositoryAlias + "] is already aliased to repository [" + ((ILoggerRepository)m_alias2repositoryMap[repositoryAlias]).Name + "]. Aliases cannot be redefined."); } } - // Check if the alias is already mapped to a repository - else if (m_name2repositoryMap.Contains(repositoryAlias)) + // Check if the alias is already mapped to a repository + else if (m_name2repositoryMap.Contains(repositoryAlias)) { // Check if this is a duplicate of the current mapping - if ( repositoryTarget != ((ILoggerRepository)m_name2repositoryMap[repositoryAlias]) ) + if (repositoryTarget != ((ILoggerRepository)m_name2repositoryMap[repositoryAlias])) { // Cannot define alias for already mapped repository throw new InvalidOperationException("Repository [" + repositoryAlias + "] already exists and cannot be aliased to repository [" + repositoryTarget.Name + "]."); } } - else + else { // Set the alias m_alias2repositoryMap[repositoryAlias] = repositoryTarget; @@ -548,10 +548,10 @@ public void AliasRepository(string repositoryAlias, ILoggerRepository repository /// Raises the event. /// /// - protected virtual void OnLoggerRepositoryCreatedEvent(ILoggerRepository repository) + protected virtual void OnLoggerRepositoryCreatedEvent(ILoggerRepository repository) { LoggerRepositoryCreationEventHandler handler = m_loggerRepositoryCreatedEvent; - if (handler != null) + if (handler != null) { handler(this, new LoggerRepositoryCreationEventArgs(repository)); } @@ -674,7 +674,7 @@ private void ConfigureRepository(Assembly assembly, ILoggerRepository repository Array.Sort(configAttributes); // Delegate to the attribute the job of configuring the repository - foreach(log4net.Config.ConfiguratorAttribute configAttr in configAttributes) + foreach (log4net.Config.ConfiguratorAttribute configAttr in configAttributes) { if (configAttr != null) { @@ -684,7 +684,7 @@ private void ConfigureRepository(Assembly assembly, ILoggerRepository repository } catch (Exception ex) { - LogLog.Error(declaringType, "Exception calling ["+configAttr.GetType().FullName+"] .Configure method.", ex); + LogLog.Error(declaringType, "Exception calling [" + configAttr.GetType().FullName + "] .Configure method.", ex); } } } @@ -704,21 +704,21 @@ private void ConfigureRepository(Assembly assembly, ILoggerRepository repository { applicationBaseDirectory = SystemInfo.ApplicationBaseDirectory; } - catch(Exception ex) + catch (Exception ex) { - LogLog.Warn(declaringType, "Exception getting ApplicationBaseDirectory. appSettings log4net.Config path ["+repositoryConfigFile+"] will be treated as an absolute URI", ex); + LogLog.Warn(declaringType, "Exception getting ApplicationBaseDirectory. appSettings log4net.Config path [" + repositoryConfigFile + "] will be treated as an absolute URI", ex); } - string repositoryConfigFilePath = repositoryConfigFile; - if (applicationBaseDirectory != null) - { - repositoryConfigFilePath = Path.Combine(applicationBaseDirectory, repositoryConfigFile); - } + string repositoryConfigFilePath = repositoryConfigFile; + if (applicationBaseDirectory != null) + { + repositoryConfigFilePath = Path.Combine(applicationBaseDirectory, repositoryConfigFile); + } - // Determine whether to watch the file or not based on an app setting value: - bool watchRepositoryConfigFile = false; + // Determine whether to watch the file or not based on an app setting value: + bool watchRepositoryConfigFile = false; #if NET_2_0 || MONO_2_0 || MONO_3_5 || MONO_4_0 || NETSTANDARD - Boolean.TryParse(SystemInfo.GetAppSetting("log4net.Config.Watch"), out watchRepositoryConfigFile); + Boolean.TryParse(SystemInfo.GetAppSetting("log4net.Config.Watch"), out watchRepositoryConfigFile); #else { string watch = SystemInfo.GetAppSetting("log4net.Config.Watch"); @@ -738,8 +738,8 @@ private void ConfigureRepository(Assembly assembly, ILoggerRepository repository if (watchRepositoryConfigFile) { - // As we are going to watch the config file it is required to resolve it as a - // physical file system path pass that in a FileInfo object to the Configurator + // As we are going to watch the config file it is required to resolve it as a + // physical file system path pass that in a FileInfo object to the Configurator FileInfo repositoryConfigFileInfo = null; try { @@ -747,48 +747,48 @@ private void ConfigureRepository(Assembly assembly, ILoggerRepository repository } catch (Exception ex) { - LogLog.Error(declaringType, "DefaultRepositorySelector: Exception while parsing log4net.Config file physical path [" + repositoryConfigFilePath + "]", ex); + LogLog.Error(declaringType, "DefaultRepositorySelector: Exception while parsing log4net.Config file physical path [" + repositoryConfigFilePath + "]", ex); } try { - LogLog.Debug(declaringType, "Loading and watching configuration for default repository from AppSettings specified Config path [" + repositoryConfigFilePath + "]"); + LogLog.Debug(declaringType, "Loading and watching configuration for default repository from AppSettings specified Config path [" + repositoryConfigFilePath + "]"); - XmlConfigurator.ConfigureAndWatch(repository, repositoryConfigFileInfo); + XmlConfigurator.ConfigureAndWatch(repository, repositoryConfigFileInfo); } catch (Exception ex) { - LogLog.Error(declaringType, "DefaultRepositorySelector: Exception calling XmlConfigurator.ConfigureAndWatch method with ConfigFilePath [" + repositoryConfigFilePath + "]", ex); + LogLog.Error(declaringType, "DefaultRepositorySelector: Exception calling XmlConfigurator.ConfigureAndWatch method with ConfigFilePath [" + repositoryConfigFilePath + "]", ex); } } else { - // As we are not going to watch the config file it is easiest to just resolve it as a - // URI and pass that to the Configurator - Uri repositoryConfigUri = null; - try - { - repositoryConfigUri = new Uri(repositoryConfigFilePath); - } - catch(Exception ex) - { - LogLog.Error(declaringType, "Exception while parsing log4net.Config file path ["+repositoryConfigFile+"]", ex); - } - - if (repositoryConfigUri != null) - { - LogLog.Debug(declaringType, "Loading configuration for default repository from AppSettings specified Config URI ["+repositoryConfigUri.ToString()+"]"); - + // As we are not going to watch the config file it is easiest to just resolve it as a + // URI and pass that to the Configurator + Uri repositoryConfigUri = null; try { - // TODO: Support other types of configurator - XmlConfigurator.Configure(repository, repositoryConfigUri); + repositoryConfigUri = new Uri(repositoryConfigFilePath); } catch (Exception ex) { - LogLog.Error(declaringType, "Exception calling XmlConfigurator.Configure method with ConfigUri ["+repositoryConfigUri+"]", ex); + LogLog.Error(declaringType, "Exception while parsing log4net.Config file path [" + repositoryConfigFile + "]", ex); + } + + if (repositoryConfigUri != null) + { + LogLog.Debug(declaringType, "Loading configuration for default repository from AppSettings specified Config URI [" + repositoryConfigUri.ToString() + "]"); + + try + { + // TODO: Support other types of configurator + XmlConfigurator.Configure(repository, repositoryConfigUri); + } + catch (Exception ex) + { + LogLog.Error(declaringType, "Exception calling XmlConfigurator.Configure method with ConfigUri [" + repositoryConfigUri + "]", ex); + } } } - } } } } @@ -822,14 +822,14 @@ private void LoadPlugins(Assembly assembly, ILoggerRepository repository) #endif if (configAttributes != null && configAttributes.Length > 0) { - foreach(log4net.Plugin.IPluginFactory configAttr in configAttributes) + foreach (log4net.Plugin.IPluginFactory configAttr in configAttributes) { try { // Create the plugin and add it to the repository repository.PluginMap.Add(configAttr.CreatePlugin()); } - catch(Exception ex) + catch (Exception ex) { LogLog.Error(declaringType, "Failed to create plugin. Attribute [" + configAttr.ToString() + "]", ex); } @@ -866,13 +866,13 @@ private void LoadAliases(Assembly assembly, ILoggerRepository repository) #endif if (configAttributes != null && configAttributes.Length > 0) { - foreach(log4net.Config.AliasRepositoryAttribute configAttr in configAttributes) + foreach (log4net.Config.AliasRepositoryAttribute configAttr in configAttributes) { try { AliasRepository(configAttr.Name, repository); } - catch(Exception ex) + catch (Exception ex) { LogLog.Error(declaringType, "Failed to alias repository [" + configAttr.Name + "]", ex); } @@ -884,14 +884,14 @@ private void LoadAliases(Assembly assembly, ILoggerRepository repository) #region Private Static Fields - /// - /// The fully qualified type of the DefaultRepositorySelector class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(DefaultRepositorySelector); + /// + /// The fully qualified type of the DefaultRepositorySelector class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(DefaultRepositorySelector); private const string DefaultRepositoryName = "log4net-default-repository"; diff --git a/src/log4net/Core/FixFlags.cs b/src/log4net/Core/FixFlags.cs index b2e94454..1853f44c 100644 --- a/src/log4net/Core/FixFlags.cs +++ b/src/log4net/Core/FixFlags.cs @@ -2,103 +2,103 @@ namespace log4net.Core { + /// + /// Flags passed to the property + /// + /// + /// + /// Flags passed to the property + /// + /// + /// Nicko Cadell + [Flags] + public enum FixFlags + { /// - /// Flags passed to the property + /// Fix the MDC /// - /// - /// - /// Flags passed to the property - /// - /// - /// Nicko Cadell - [Flags] - public enum FixFlags - { - /// - /// Fix the MDC - /// - [Obsolete("Replaced by composite Properties")] - Mdc = 0x01, + [Obsolete("Replaced by composite Properties")] + Mdc = 0x01, - /// - /// Fix the NDC - /// - Ndc = 0x02, + /// + /// Fix the NDC + /// + Ndc = 0x02, - /// - /// Fix the rendered message - /// - Message = 0x04, + /// + /// Fix the rendered message + /// + Message = 0x04, - /// - /// Fix the thread name - /// - ThreadName = 0x08, + /// + /// Fix the thread name + /// + ThreadName = 0x08, - /// - /// Fix the callers location information - /// - /// - /// CAUTION: Very slow to generate - /// - LocationInfo = 0x10, + /// + /// Fix the callers location information + /// + /// + /// CAUTION: Very slow to generate + /// + LocationInfo = 0x10, - /// - /// Fix the callers windows user name - /// - /// - /// CAUTION: Slow to generate - /// - UserName = 0x20, + /// + /// Fix the callers windows user name + /// + /// + /// CAUTION: Slow to generate + /// + UserName = 0x20, - /// - /// Fix the domain friendly name - /// - Domain = 0x40, + /// + /// Fix the domain friendly name + /// + Domain = 0x40, - /// - /// Fix the callers principal name - /// - /// - /// CAUTION: May be slow to generate - /// - Identity = 0x80, + /// + /// Fix the callers principal name + /// + /// + /// CAUTION: May be slow to generate + /// + Identity = 0x80, - /// - /// Fix the exception text - /// - Exception = 0x100, + /// + /// Fix the exception text + /// + Exception = 0x100, - /// - /// Fix the event properties. Active properties must implement in order to be eligible for fixing. - /// - Properties = 0x200, + /// + /// Fix the event properties. Active properties must implement in order to be eligible for fixing. + /// + Properties = 0x200, - /// - /// No fields fixed - /// - None = 0x0, + /// + /// No fields fixed + /// + None = 0x0, - /// - /// All fields fixed - /// - All = 0xFFFFFFF, + /// + /// All fields fixed + /// + All = 0xFFFFFFF, - /// - /// Partial fields fixed - /// - /// - /// - /// This set of partial fields gives good performance. The following fields are fixed: - /// - /// - /// - /// - /// - /// - /// - /// - /// - Partial = Message | ThreadName | Exception | Domain | Properties, - } + /// + /// Partial fields fixed + /// + /// + /// + /// This set of partial fields gives good performance. The following fields are fixed: + /// + /// + /// + /// + /// + /// + /// + /// + /// + Partial = Message | ThreadName | Exception | Domain | Properties, + } } \ No newline at end of file diff --git a/src/log4net/Core/IAppenderAttachable.cs b/src/log4net/Core/IAppenderAttachable.cs index 43b50c11..3632765a 100644 --- a/src/log4net/Core/IAppenderAttachable.cs +++ b/src/log4net/Core/IAppenderAttachable.cs @@ -61,7 +61,7 @@ public interface IAppenderAttachable /// collection rather than null. /// /// - AppenderCollection Appenders {get;} + AppenderCollection Appenders { get; } /// /// Gets an attached appender with the specified name. @@ -116,6 +116,6 @@ public interface IAppenderAttachable /// on the appender removed. /// /// - IAppender RemoveAppender(string name); + IAppender RemoveAppender(string name); } } diff --git a/src/log4net/Core/ILogger.cs b/src/log4net/Core/ILogger.cs index b7e45142..289a33f9 100644 --- a/src/log4net/Core/ILogger.cs +++ b/src/log4net/Core/ILogger.cs @@ -70,7 +70,7 @@ public interface ILogger /// /// void Log(Type callerStackBoundaryDeclaringType, Level level, object message, Exception exception); - + /// /// This is the most generic printing method that is intended to be used /// by wrappers. diff --git a/src/log4net/Core/Level.cs b/src/log4net/Core/Level.cs index ced11f8d..a200e2a6 100644 --- a/src/log4net/Core/Level.cs +++ b/src/log4net/Core/Level.cs @@ -99,7 +99,7 @@ public sealed class Level : IComparable /// the specified level name and value. /// /// - public Level(int level, string levelName, string displayName) + public Level(int level, string levelName, string displayName) { if (levelName == null) { @@ -202,7 +202,7 @@ public string DisplayName /// Returns the level . /// /// - public override string ToString() + public override string ToString() { return m_levelName; } @@ -321,7 +321,7 @@ public int CompareTo(object r) /// Compares two levels. /// /// - public static bool operator > (Level l, Level r) + public static bool operator >(Level l, Level r) { return l.m_levelValue > r.m_levelValue; } @@ -341,7 +341,7 @@ public int CompareTo(object r) /// Compares two levels. /// /// - public static bool operator < (Level l, Level r) + public static bool operator <(Level l, Level r) { return l.m_levelValue < r.m_levelValue; } @@ -361,7 +361,7 @@ public int CompareTo(object r) /// Compares two levels. /// /// - public static bool operator >= (Level l, Level r) + public static bool operator >=(Level l, Level r) { return l.m_levelValue >= r.m_levelValue; } @@ -381,7 +381,7 @@ public int CompareTo(object r) /// Compares two levels. /// /// - public static bool operator <= (Level l, Level r) + public static bool operator <=(Level l, Level r) { return l.m_levelValue <= r.m_levelValue; } @@ -401,7 +401,7 @@ public int CompareTo(object r) /// Compares two levels. /// /// - public static bool operator == (Level l, Level r) + public static bool operator ==(Level l, Level r) { if (((object)l) != null && ((object)r) != null) { @@ -409,7 +409,7 @@ public int CompareTo(object r) } else { - return ((object) l) == ((object) r); + return ((object)l) == ((object)r); } } @@ -428,9 +428,9 @@ public int CompareTo(object r) /// Compares two levels. /// /// - public static bool operator != (Level l, Level r) + public static bool operator !=(Level l, Level r) { - return !(l==r); + return !(l == r); } #endregion Operators @@ -502,11 +502,11 @@ public static int Compare(Level l, Level r) /// public static readonly Level Off = new Level(int.MaxValue, "OFF"); - /// - /// The level designates very severe error events. - /// System unusable, emergencies. - /// - public static readonly Level Log4Net_Debug = new Level(120000, "log4net:DEBUG"); + /// + /// The level designates very severe error events. + /// System unusable, emergencies. + /// + public static readonly Level Log4Net_Debug = new Level(120000, "log4net:DEBUG"); /// /// The level designates very severe error events. @@ -547,19 +547,19 @@ public static int Compare(Level l, Level r) /// The level designates potentially harmful /// situations. /// - public static readonly Level Warn = new Level(60000, "WARN"); + public static readonly Level Warn = new Level(60000, "WARN"); /// /// The level designates informational messages /// that highlight the progress of the application at the highest level. /// - public static readonly Level Notice = new Level(50000, "NOTICE"); + public static readonly Level Notice = new Level(50000, "NOTICE"); /// /// The level designates informational messages that /// highlight the progress of the application at coarse-grained level. /// - public static readonly Level Info = new Level(40000, "INFO"); + public static readonly Level Info = new Level(40000, "INFO"); /// /// The level designates fine-grained informational diff --git a/src/log4net/Core/LevelCollection.cs b/src/log4net/Core/LevelCollection.cs index 649eeca7..4f358828 100644 --- a/src/log4net/Core/LevelCollection.cs +++ b/src/log4net/Core/LevelCollection.cs @@ -72,7 +72,7 @@ public interface ILevelCollectionEnumerator private int m_version = 0; #endregion - + #region Static Wrappers /// @@ -84,7 +84,7 @@ public interface ILevelCollectionEnumerator /// public static LevelCollection ReadOnly(LevelCollection list) { - if(list==null) throw new ArgumentNullException("list"); + if (list == null) throw new ArgumentNullException("list"); return new ReadOnlyLevelCollection(list); } @@ -101,7 +101,7 @@ public LevelCollection() { m_array = new Level[DEFAULT_CAPACITY]; } - + /// /// Initializes a new instance of the LevelCollection class /// that has the specified initial capacity. @@ -146,12 +146,12 @@ public LevelCollection(ICollection col) m_array = new Level[col.Count]; AddRange(col); } - + /// /// Type visible only to our subclasses /// Used to access protected constructor /// - protected internal enum Tag + protected internal enum Tag { /// /// A value @@ -168,7 +168,7 @@ protected internal LevelCollection(Tag tag) m_array = null; } #endregion - + #region Operations (type-safe ICollection) /// @@ -201,8 +201,8 @@ public virtual void CopyTo(Level[] array, int start) { throw new System.ArgumentException("Destination array was not long enough."); } - - Array.Copy(m_array, 0, array, start, m_count); + + Array.Copy(m_array, 0, array, start, m_count); } /// @@ -223,7 +223,7 @@ public virtual object SyncRoot } #endregion - + #region Operations (type-safe IList) /// @@ -240,13 +240,13 @@ public virtual Level this[int index] get { ValidateIndex(index); // throws - return m_array[index]; + return m_array[index]; } set { ValidateIndex(index); // throws - ++m_version; - m_array[index] = value; + ++m_version; + m_array[index] = value; } } @@ -267,7 +267,7 @@ public virtual int Add(Level item) return m_count++; } - + /// /// Removes all elements from the LevelCollection. /// @@ -277,7 +277,7 @@ public virtual void Clear() m_array = new Level[DEFAULT_CAPACITY]; m_count = 0; } - + /// /// Creates a shallow copy of the . /// @@ -299,7 +299,7 @@ public virtual object Clone() /// true if is found in the LevelCollection; otherwise, false. public virtual bool Contains(Level item) { - for (int i=0; i != m_count; ++i) + for (int i = 0; i != m_count; ++i) { if (m_array[i].Equals(item)) { @@ -320,7 +320,7 @@ public virtual bool Contains(Level item) /// public virtual int IndexOf(Level item) { - for (int i=0; i != m_count; ++i) + for (int i = 0; i != m_count; ++i) { if (m_array[i].Equals(item)) { @@ -343,7 +343,7 @@ public virtual int IndexOf(Level item) public virtual void Insert(int index, Level item) { ValidateIndex(index, true); // throws - + if (m_count == m_array.Length) { EnsureCapacity(m_count + 1); @@ -367,13 +367,13 @@ public virtual void Insert(int index, Level item) /// The specified was not found in the LevelCollection. /// public virtual void Remove(Level item) - { + { int i = IndexOf(item); if (i < 0) { throw new System.ArgumentException("Cannot remove the specified item because it was not found in the specified Collection."); } - + ++m_version; RemoveAt(i); } @@ -390,14 +390,14 @@ public virtual void Remove(Level item) public virtual void RemoveAt(int index) { ValidateIndex(index); // throws - + m_count--; if (index < m_count) { Array.Copy(m_array, index + 1, m_array, index, m_count - index); } - + // We can't set the deleted entry equal to null, because it might be a value type. // Instead, we'll create an empty single-element array of the right type and copy it // over the entry we want to erase. @@ -427,7 +427,7 @@ public virtual bool IsReadOnly #endregion #region Operations (type-safe IEnumerable) - + /// /// Returns an enumerator that can iterate through the LevelCollection. /// @@ -440,15 +440,15 @@ public virtual ILevelCollectionEnumerator GetEnumerator() #endregion #region Public helpers (just to mimic some nice features of ArrayList) - + /// /// Gets or sets the number of elements the LevelCollection can contain. /// public virtual int Capacity { - get - { - return m_array.Length; + get + { + return m_array.Length; } set { @@ -484,7 +484,7 @@ public virtual int AddRange(LevelCollection x) { EnsureCapacity(m_count + x.Count); } - + Array.Copy(x.m_array, 0, m_array, m_count, x.Count); m_count += x.Count; m_version++; @@ -523,14 +523,14 @@ public virtual int AddRange(ICollection col) EnsureCapacity(m_count + col.Count); } - foreach(object item in col) + foreach (object item in col) { Add((Level)item); } return m_count; } - + /// /// Sets the capacity to the actual number of elements. /// @@ -560,7 +560,7 @@ private void ValidateIndex(int i) /// private void ValidateIndex(int i, bool allowEqualEnd) { - int max = (allowEqualEnd) ? (m_count) : (m_count-1); + int max = (allowEqualEnd) ? (m_count) : (m_count - 1); if (i < 0 || i > max) { throw log4net.Util.SystemInfo.CreateArgumentOutOfRangeException("i", (object)i, "Index was out of range. Must be non-negative and less than the size of the collection. [" + (object)i + "] Specified argument was out of the range of valid values."); @@ -579,7 +579,7 @@ private void EnsureCapacity(int min) } #endregion - + #region Implementation (ICollection) void ICollection.CopyTo(Array array, int start) @@ -646,15 +646,15 @@ IEnumerator IEnumerable.GetEnumerator() private sealed class Enumerator : IEnumerator, ILevelCollectionEnumerator { #region Implementation (data) - + private readonly LevelCollection m_collection; private int m_index; private int m_version; - + #endregion - + #region Construction - + /// /// Initializes a new instance of the Enumerator class. /// @@ -665,11 +665,11 @@ internal Enumerator(LevelCollection tc) m_index = -1; m_version = tc.m_version; } - + #endregion - + #region Operations (type-safe IEnumerator) - + /// /// Gets the current element in the collection. /// @@ -708,14 +708,14 @@ public void Reset() } #endregion - + #region Implementation (IEnumerator) - + object IEnumerator.Current { get { return this.Current; } } - + #endregion } @@ -749,7 +749,7 @@ public override void CopyTo(Level[] array) public override void CopyTo(Level[] array, int start) { - m_collection.CopyTo(array,start); + m_collection.CopyTo(array, start); } public override int Count { @@ -802,7 +802,7 @@ public override void Insert(int pos, Level x) } public override void Remove(Level x) - { + { throw new NotSupportedException("This is a Read Only Collection and can not be modified"); } diff --git a/src/log4net/Core/LevelEvaluator.cs b/src/log4net/Core/LevelEvaluator.cs index d058cee9..eac2d4e4 100644 --- a/src/log4net/Core/LevelEvaluator.cs +++ b/src/log4net/Core/LevelEvaluator.cs @@ -35,7 +35,7 @@ namespace log4net.Core /// /// /// Nicko Cadell - public class LevelEvaluator : ITriggeringEventEvaluator + public class LevelEvaluator : ITriggeringEventEvaluator { /// /// The threshold for triggering @@ -120,14 +120,14 @@ public Level Threshold /// level. /// /// - public bool IsTriggeringEvent(LoggingEvent loggingEvent) + public bool IsTriggeringEvent(LoggingEvent loggingEvent) { if (loggingEvent == null) { throw new ArgumentNullException("loggingEvent"); } - return (loggingEvent.Level >= m_threshold); + return (loggingEvent.Level >= m_threshold); } } } diff --git a/src/log4net/Core/LevelMap.cs b/src/log4net/Core/LevelMap.cs index 7558d1ac..75a2abbf 100644 --- a/src/log4net/Core/LevelMap.cs +++ b/src/log4net/Core/LevelMap.cs @@ -95,7 +95,7 @@ public Level this[string name] throw new ArgumentNullException("name"); } - lock(this) + lock (this) { return (Level)m_mapName2Level[name]; } @@ -137,7 +137,7 @@ public void Add(string name, int value, string displayName) } if (name.Length == 0) { - throw log4net.Util.SystemInfo.CreateArgumentOutOfRangeException("name", name, "Parameter: name, Value: ["+name+"] out of range. Level name must not be empty"); + throw log4net.Util.SystemInfo.CreateArgumentOutOfRangeException("name", name, "Parameter: name, Value: [" + name + "] out of range. Level name must not be empty"); } if (displayName == null || displayName.Length == 0) @@ -163,7 +163,7 @@ public void Add(Level level) { throw new ArgumentNullException("level"); } - lock(this) + lock (this) { m_mapName2Level[level.Name] = level; } @@ -182,7 +182,7 @@ public LevelCollection AllLevels { get { - lock(this) + lock (this) { return new LevelCollection(m_mapName2Level.Values); } @@ -214,7 +214,7 @@ public Level LookupWithDefault(Level defaultLevel) throw new ArgumentNullException("defaultLevel"); } - lock(this) + lock (this) { Level level = (Level)m_mapName2Level[defaultLevel.Name]; if (level == null) diff --git a/src/log4net/Core/LocationInfo.cs b/src/log4net/Core/LocationInfo.cs index b2403385..a3633fd9 100644 --- a/src/log4net/Core/LocationInfo.cs +++ b/src/log4net/Core/LocationInfo.cs @@ -76,7 +76,7 @@ public class LocationInfo /// class based on the current thread. /// /// - public LocationInfo(Type callerStackBoundaryDeclaringType) + public LocationInfo(Type callerStackBoundaryDeclaringType) { // Initialize all fields m_className = NA; @@ -92,7 +92,7 @@ public LocationInfo(Type callerStackBoundaryDeclaringType) { StackTrace st = new StackTrace(true); int frameIndex = 0; - + // skip frames not from fqnOfCallingClass while (frameIndex < st.FrameCount) { @@ -119,15 +119,15 @@ public LocationInfo(Type callerStackBoundaryDeclaringType) { // take into account the frames we skip above int adjustedFrameCount = st.FrameCount - frameIndex; - ArrayList stackFramesList = new ArrayList(adjustedFrameCount); + ArrayList stackFramesList = new ArrayList(adjustedFrameCount); m_stackFrames = new StackFrameItem[adjustedFrameCount]; - for (int i=frameIndex; i < st.FrameCount; i++) + for (int i = frameIndex; i < st.FrameCount; i++) { stackFramesList.Add(new StackFrameItem(st.GetFrame(i))); } - + stackFramesList.CopyTo(m_stackFrames, 0); - + // now frameIndex is the first 'user' caller frame StackFrame locationFrame = st.GetFrame(frameIndex); @@ -137,7 +137,7 @@ public LocationInfo(Type callerStackBoundaryDeclaringType) if (method != null) { - m_methodName = method.Name; + m_methodName = method.Name; if (method.DeclaringType != null) { m_className = method.DeclaringType.FullName; @@ -147,11 +147,11 @@ public LocationInfo(Type callerStackBoundaryDeclaringType) m_lineNumber = locationFrame.GetFileLineNumber().ToString(System.Globalization.NumberFormatInfo.InvariantInfo); // Combine all location info - m_fullInfo = m_className + '.' + m_methodName + '(' + m_fileName + ':' + m_lineNumber + ')'; + m_fullInfo = m_className + '.' + m_methodName + '(' + m_fileName + ':' + m_lineNumber + ')'; } } } - catch(System.Security.SecurityException) + catch (System.Security.SecurityException) { // This security exception will occur if the caller does not have // some undefined set of SecurityPermission flags. @@ -180,7 +180,7 @@ public LocationInfo(string className, string methodName, string fileName, string m_fileName = fileName; m_lineNumber = lineNumber; m_methodName = methodName; - m_fullInfo = m_className + '.' + m_methodName + '(' + m_fileName + + m_fullInfo = m_className + '.' + m_methodName + '(' + m_fileName + ':' + m_lineNumber + ')'; } @@ -272,7 +272,7 @@ public string FullInfo { get { return m_fullInfo; } } - + #if !NETCF && !NETSTANDARD1_3 /// /// Gets the stack frames from the stack trace of the caller making the log request @@ -300,14 +300,14 @@ public StackFrameItem[] StackFrames #region Private Static Fields - /// - /// The fully qualified type of the LocationInfo class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(LocationInfo); + /// + /// The fully qualified type of the LocationInfo class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(LocationInfo); /// /// When location information is not available the constant diff --git a/src/log4net/Core/LogException.cs b/src/log4net/Core/LogException.cs index 88243895..f9b8e25b 100644 --- a/src/log4net/Core/LogException.cs +++ b/src/log4net/Core/LogException.cs @@ -42,7 +42,7 @@ namespace log4net.Core #if NETSTANDARD1_3 public class LogException : Exception #else - public class LogException : ApplicationException + public class LogException : ApplicationException #endif { #region Public Instance Constructors @@ -69,10 +69,10 @@ public LogException() /// the specified message. /// /// - public LogException(String message) : base(message) + public LogException(String message) : base(message) { } - + /// /// Constructor /// @@ -84,7 +84,7 @@ public LogException(String message) : base(message) /// with the specified message and inner exception. /// /// - public LogException(String message, Exception innerException) : base(message, innerException) + public LogException(String message, Exception innerException) : base(message, innerException) { } @@ -104,7 +104,7 @@ public LogException(String message, Exception innerException) : base(message, in /// with serialized data. /// /// - protected LogException(SerializationInfo info, StreamingContext context) : base(info, context) + protected LogException(SerializationInfo info, StreamingContext context) : base(info, context) { } #endif diff --git a/src/log4net/Core/LogImpl.cs b/src/log4net/Core/LogImpl.cs index 965b5aaf..6eae4fa5 100644 --- a/src/log4net/Core/LogImpl.cs +++ b/src/log4net/Core/LogImpl.cs @@ -165,7 +165,7 @@ protected virtual void ReloadLevels(ILoggerRepository repository) /// form instead. /// /// - public virtual void Debug(object message) + public virtual void Debug(object message) { Logger.Log(ThisDeclaringType, m_levelDebug, message, null); } @@ -186,7 +186,7 @@ public virtual void Debug(object message) /// /// /// - public virtual void Debug(object message, Exception exception) + public virtual void Debug(object message, Exception exception) { Logger.Log(ThisDeclaringType, m_levelDebug, message, exception); } @@ -213,7 +213,7 @@ public virtual void Debug(object message, Exception exception) /// methods instead. /// /// - public virtual void DebugFormat(string format, params object[] args) + public virtual void DebugFormat(string format, params object[] args) { if (IsDebugEnabled) { @@ -243,7 +243,7 @@ public virtual void DebugFormat(string format, params object[] args) /// methods instead. /// /// - public virtual void DebugFormat(string format, object arg0) + public virtual void DebugFormat(string format, object arg0) { if (IsDebugEnabled) { @@ -274,7 +274,7 @@ public virtual void DebugFormat(string format, object arg0) /// methods instead. /// /// - public virtual void DebugFormat(string format, object arg0, object arg1) + public virtual void DebugFormat(string format, object arg0, object arg1) { if (IsDebugEnabled) { @@ -306,7 +306,7 @@ public virtual void DebugFormat(string format, object arg0, object arg1) /// methods instead. /// /// - public virtual void DebugFormat(string format, object arg0, object arg1, object arg2) + public virtual void DebugFormat(string format, object arg0, object arg1, object arg2) { if (IsDebugEnabled) { @@ -332,7 +332,7 @@ public virtual void DebugFormat(string format, object arg0, object arg1, object /// methods instead. /// /// - public virtual void DebugFormat(IFormatProvider provider, string format, params object[] args) + public virtual void DebugFormat(IFormatProvider provider, string format, params object[] args) { if (IsDebugEnabled) { @@ -363,11 +363,11 @@ public virtual void DebugFormat(IFormatProvider provider, string format, params /// form instead. /// /// - public virtual void Info(object message) + public virtual void Info(object message) { Logger.Log(ThisDeclaringType, m_levelInfo, message, null); } - + /// /// Logs a message object with the INFO level. /// @@ -384,7 +384,7 @@ public virtual void Info(object message) /// /// /// - public virtual void Info(object message, Exception exception) + public virtual void Info(object message, Exception exception) { Logger.Log(ThisDeclaringType, m_levelInfo, message, exception); } @@ -411,7 +411,7 @@ public virtual void Info(object message, Exception exception) /// methods instead. /// /// - public virtual void InfoFormat(string format, params object[] args) + public virtual void InfoFormat(string format, params object[] args) { if (IsInfoEnabled) { @@ -441,7 +441,7 @@ public virtual void InfoFormat(string format, params object[] args) /// methods instead. /// /// - public virtual void InfoFormat(string format, object arg0) + public virtual void InfoFormat(string format, object arg0) { if (IsInfoEnabled) { @@ -472,7 +472,7 @@ public virtual void InfoFormat(string format, object arg0) /// methods instead. /// /// - public virtual void InfoFormat(string format, object arg0, object arg1) + public virtual void InfoFormat(string format, object arg0, object arg1) { if (IsInfoEnabled) { @@ -504,7 +504,7 @@ public virtual void InfoFormat(string format, object arg0, object arg1) /// methods instead. /// /// - public virtual void InfoFormat(string format, object arg0, object arg1, object arg2) + public virtual void InfoFormat(string format, object arg0, object arg1, object arg2) { if (IsInfoEnabled) { @@ -530,7 +530,7 @@ public virtual void InfoFormat(string format, object arg0, object arg1, object a /// methods instead. /// /// - public virtual void InfoFormat(IFormatProvider provider, string format, params object[] args) + public virtual void InfoFormat(IFormatProvider provider, string format, params object[] args) { if (IsInfoEnabled) { @@ -561,11 +561,11 @@ public virtual void InfoFormat(IFormatProvider provider, string format, params o /// form instead. /// /// - public virtual void Warn(object message) + public virtual void Warn(object message) { Logger.Log(ThisDeclaringType, m_levelWarn, message, null); } - + /// /// Logs a message object with the WARN level /// @@ -582,7 +582,7 @@ public virtual void Warn(object message) /// /// /// - public virtual void Warn(object message, Exception exception) + public virtual void Warn(object message, Exception exception) { Logger.Log(ThisDeclaringType, m_levelWarn, message, exception); } @@ -609,7 +609,7 @@ public virtual void Warn(object message, Exception exception) /// methods instead. /// /// - public virtual void WarnFormat(string format, params object[] args) + public virtual void WarnFormat(string format, params object[] args) { if (IsWarnEnabled) { @@ -639,7 +639,7 @@ public virtual void WarnFormat(string format, params object[] args) /// methods instead. /// /// - public virtual void WarnFormat(string format, object arg0) + public virtual void WarnFormat(string format, object arg0) { if (IsWarnEnabled) { @@ -670,7 +670,7 @@ public virtual void WarnFormat(string format, object arg0) /// methods instead. /// /// - public virtual void WarnFormat(string format, object arg0, object arg1) + public virtual void WarnFormat(string format, object arg0, object arg1) { if (IsWarnEnabled) { @@ -702,7 +702,7 @@ public virtual void WarnFormat(string format, object arg0, object arg1) /// methods instead. /// /// - public virtual void WarnFormat(string format, object arg0, object arg1, object arg2) + public virtual void WarnFormat(string format, object arg0, object arg1, object arg2) { if (IsWarnEnabled) { @@ -728,7 +728,7 @@ public virtual void WarnFormat(string format, object arg0, object arg1, object a /// methods instead. /// /// - public virtual void WarnFormat(IFormatProvider provider, string format, params object[] args) + public virtual void WarnFormat(IFormatProvider provider, string format, params object[] args) { if (IsWarnEnabled) { @@ -759,7 +759,7 @@ public virtual void WarnFormat(IFormatProvider provider, string format, params o /// form instead. /// /// - public virtual void Error(object message) + public virtual void Error(object message) { Logger.Log(ThisDeclaringType, m_levelError, message, null); } @@ -780,7 +780,7 @@ public virtual void Error(object message) /// /// /// - public virtual void Error(object message, Exception exception) + public virtual void Error(object message, Exception exception) { Logger.Log(ThisDeclaringType, m_levelError, message, exception); } @@ -807,7 +807,7 @@ public virtual void Error(object message, Exception exception) /// methods instead. /// /// - public virtual void ErrorFormat(string format, params object[] args) + public virtual void ErrorFormat(string format, params object[] args) { if (IsErrorEnabled) { @@ -837,7 +837,7 @@ public virtual void ErrorFormat(string format, params object[] args) /// methods instead. /// /// - public virtual void ErrorFormat(string format, object arg0) + public virtual void ErrorFormat(string format, object arg0) { if (IsErrorEnabled) { @@ -868,7 +868,7 @@ public virtual void ErrorFormat(string format, object arg0) /// methods instead. /// /// - public virtual void ErrorFormat(string format, object arg0, object arg1) + public virtual void ErrorFormat(string format, object arg0, object arg1) { if (IsErrorEnabled) { @@ -900,7 +900,7 @@ public virtual void ErrorFormat(string format, object arg0, object arg1) /// methods instead. /// /// - public virtual void ErrorFormat(string format, object arg0, object arg1, object arg2) + public virtual void ErrorFormat(string format, object arg0, object arg1, object arg2) { if (IsErrorEnabled) { @@ -926,7 +926,7 @@ public virtual void ErrorFormat(string format, object arg0, object arg1, object /// methods instead. /// /// - public virtual void ErrorFormat(IFormatProvider provider, string format, params object[] args) + public virtual void ErrorFormat(IFormatProvider provider, string format, params object[] args) { if (IsErrorEnabled) { @@ -957,11 +957,11 @@ public virtual void ErrorFormat(IFormatProvider provider, string format, params /// form instead. /// /// - public virtual void Fatal(object message) + public virtual void Fatal(object message) { Logger.Log(ThisDeclaringType, m_levelFatal, message, null); } - + /// /// Logs a message object with the FATAL level /// @@ -978,7 +978,7 @@ public virtual void Fatal(object message) /// /// /// - public virtual void Fatal(object message, Exception exception) + public virtual void Fatal(object message, Exception exception) { Logger.Log(ThisDeclaringType, m_levelFatal, message, exception); } @@ -1005,7 +1005,7 @@ public virtual void Fatal(object message, Exception exception) /// methods instead. /// /// - public virtual void FatalFormat(string format, params object[] args) + public virtual void FatalFormat(string format, params object[] args) { if (IsFatalEnabled) { @@ -1035,7 +1035,7 @@ public virtual void FatalFormat(string format, params object[] args) /// methods instead. /// /// - public virtual void FatalFormat(string format, object arg0) + public virtual void FatalFormat(string format, object arg0) { if (IsFatalEnabled) { @@ -1066,7 +1066,7 @@ public virtual void FatalFormat(string format, object arg0) /// methods instead. /// /// - public virtual void FatalFormat(string format, object arg0, object arg1) + public virtual void FatalFormat(string format, object arg0, object arg1) { if (IsFatalEnabled) { @@ -1098,7 +1098,7 @@ public virtual void FatalFormat(string format, object arg0, object arg1) /// methods instead. /// /// - public virtual void FatalFormat(string format, object arg0, object arg1, object arg2) + public virtual void FatalFormat(string format, object arg0, object arg1, object arg2) { if (IsFatalEnabled) { @@ -1124,7 +1124,7 @@ public virtual void FatalFormat(string format, object arg0, object arg1, object /// methods instead. /// /// - public virtual void FatalFormat(IFormatProvider provider, string format, params object[] args) + public virtual void FatalFormat(IFormatProvider provider, string format, params object[] args) { if (IsFatalEnabled) { @@ -1179,7 +1179,7 @@ public virtual bool IsDebugEnabled { get { return Logger.IsEnabledFor(m_levelDebug); } } - + /// /// Checks if this logger is enabled for the INFO level. /// diff --git a/src/log4net/Core/LoggerManager.cs b/src/log4net/Core/LoggerManager.cs index 8fb38c8c..565cd6aa 100644 --- a/src/log4net/Core/LoggerManager.cs +++ b/src/log4net/Core/LoggerManager.cs @@ -61,7 +61,7 @@ public sealed class LoggerManager /// Private constructor to prevent instances. Only static methods should be used. /// /// - private LoggerManager() + private LoggerManager() { } @@ -88,16 +88,16 @@ static LoggerManager() // makes a LinkDemand which throws the exception during the JIT phase. RegisterAppDomainEvents(); } - catch(System.Security.SecurityException) + catch (System.Security.SecurityException) { - LogLog.Debug(declaringType, "Security Exception (ControlAppDomain LinkDemand) while trying "+ - "to register Shutdown handler with the AppDomain. LoggerManager.Shutdown() "+ - "will not be called automatically when the AppDomain exits. It must be called "+ + LogLog.Debug(declaringType, "Security Exception (ControlAppDomain LinkDemand) while trying " + + "to register Shutdown handler with the AppDomain. LoggerManager.Shutdown() " + + "will not be called automatically when the AppDomain exits. It must be called " + "programmatically."); } // Dump out our assembly version into the log if debug is enabled - LogLog.Debug(declaringType, GetVersionInfo()); + LogLog.Debug(declaringType, GetVersionInfo()); // Set the default repository selector #if NETCF @@ -114,9 +114,9 @@ static LoggerManager() { appRepositorySelectorType = SystemInfo.GetTypeFromString(appRepositorySelectorTypeName, false, true); } - catch(Exception ex) + catch (Exception ex) { - LogLog.Error(declaringType, "Exception while resolving RepositorySelector Type ["+appRepositorySelectorTypeName+"]", ex); + LogLog.Error(declaringType, "Exception while resolving RepositorySelector Type [" + appRepositorySelectorTypeName + "]", ex); } if (appRepositorySelectorType != null) @@ -127,9 +127,9 @@ static LoggerManager() { appRepositorySelectorObj = Activator.CreateInstance(appRepositorySelectorType); } - catch(Exception ex) + catch (Exception ex) { - LogLog.Error(declaringType, "Exception while creating RepositorySelector ["+appRepositorySelectorType.FullName+"]", ex); + LogLog.Error(declaringType, "Exception while creating RepositorySelector [" + appRepositorySelectorType.FullName + "]", ex); } if (appRepositorySelectorObj != null && appRepositorySelectorObj is IRepositorySelector) @@ -138,7 +138,7 @@ static LoggerManager() } else { - LogLog.Error(declaringType, "RepositorySelector Type ["+appRepositorySelectorType.FullName+"] is not an IRepositorySelector"); + LogLog.Error(declaringType, "RepositorySelector Type [" + appRepositorySelectorType.FullName + "] is not an IRepositorySelector"); } } } @@ -260,7 +260,7 @@ public static ILoggerRepository GetRepository(Assembly repositoryAssembly) /// null. /// /// - public static ILogger Exists(string repository, string name) + public static ILogger Exists(string repository, string name) { if (repository == null) { @@ -289,7 +289,7 @@ public static ILogger Exists(string repository, string name) /// null. /// /// - public static ILogger Exists(Assembly repositoryAssembly, string name) + public static ILogger Exists(Assembly repositoryAssembly, string name) { if (repositoryAssembly == null) { @@ -402,7 +402,7 @@ public static ILogger GetLogger(Assembly repositoryAssembly, string name) throw new ArgumentNullException("name"); } return RepositorySelector.GetRepository(repositoryAssembly).GetLogger(name); - } + } /// /// Shorthand for . @@ -415,7 +415,7 @@ public static ILogger GetLogger(Assembly repositoryAssembly, string name) /// Gets the logger for the fully qualified name of the type specified. /// /// - public static ILogger GetLogger(string repository, Type type) + public static ILogger GetLogger(string repository, Type type) { if (repository == null) { @@ -439,7 +439,7 @@ public static ILogger GetLogger(string repository, Type type) /// Gets the logger for the fully qualified name of the type specified. /// /// - public static ILogger GetLogger(Assembly repositoryAssembly, Type type) + public static ILogger GetLogger(Assembly repositoryAssembly, Type type) { if (repositoryAssembly == null) { @@ -450,7 +450,7 @@ public static ILogger GetLogger(Assembly repositoryAssembly, Type type) throw new ArgumentNullException("type"); } return RepositorySelector.GetRepository(repositoryAssembly).GetLogger(type.FullName); - } + } /// /// Shuts down the log4net system. @@ -472,9 +472,9 @@ public static ILogger GetLogger(Assembly repositoryAssembly, Type type) /// and again to a nested appender. /// /// - public static void Shutdown() + public static void Shutdown() { - foreach(ILoggerRepository repository in GetAllRepositories()) + foreach (ILoggerRepository repository in GetAllRepositories()) { repository.Shutdown(); } @@ -501,7 +501,7 @@ public static void Shutdown() /// and again to a nested appender. /// /// - public static void ShutdownRepository(string repository) + public static void ShutdownRepository(string repository) { if (repository == null) { @@ -532,7 +532,7 @@ public static void ShutdownRepository(string repository) /// and again to a nested appender. /// /// - public static void ShutdownRepository(Assembly repositoryAssembly) + public static void ShutdownRepository(Assembly repositoryAssembly) { if (repositoryAssembly == null) { @@ -555,7 +555,7 @@ public static void ShutdownRepository(Assembly repositoryAssembly) /// message disabling is set its default "off" value. /// /// - public static void ResetConfiguration(string repository) + public static void ResetConfiguration(string repository) { if (repository == null) { @@ -578,7 +578,7 @@ public static void ResetConfiguration(string repository) /// message disabling is set its default "off" value. /// /// - public static void ResetConfiguration(Assembly repositoryAssembly) + public static void ResetConfiguration(Assembly repositoryAssembly) { if (repositoryAssembly == null) { @@ -810,7 +810,7 @@ private static string GetVersionInfo() sb.Append("Loaded from [").Append(SystemInfo.AssemblyLocationInfo(myAssembly)).Append("]. "); sb.Append("(.NET Runtime [").Append(Environment.Version.ToString()).Append("]"); #if (!SSCLI) - sb.Append(" on ").Append(Environment.OSVersion.ToString()); + sb.Append(" on ").Append(Environment.OSVersion.ToString()); #endif #endif // NETSTANDARD1_3 sb.Append(")"); @@ -859,14 +859,14 @@ private static void OnProcessExit(object sender, EventArgs e) #region Private Static Fields - /// - /// The fully qualified type of the LoggerManager class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(LoggerManager); + /// + /// The fully qualified type of the LoggerManager class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(LoggerManager); /// /// Initialize the default repository selector diff --git a/src/log4net/Core/LoggerWrapperImpl.cs b/src/log4net/Core/LoggerWrapperImpl.cs index fbc49a49..61e19ebf 100644 --- a/src/log4net/Core/LoggerWrapperImpl.cs +++ b/src/log4net/Core/LoggerWrapperImpl.cs @@ -42,7 +42,7 @@ public abstract class LoggerWrapperImpl : ILoggerWrapper /// Constructs a new wrapper for the specified logger. /// /// - protected LoggerWrapperImpl(ILogger logger) + protected LoggerWrapperImpl(ILogger logger) { m_logger = logger; } @@ -79,8 +79,8 @@ public virtual ILogger Logger /// /// The logger that this object is wrapping /// - private readonly ILogger m_logger; - + private readonly ILogger m_logger; + #endregion Private Instance Fields } } diff --git a/src/log4net/Core/LoggingEvent.cs b/src/log4net/Core/LoggingEvent.cs index 4d73ddb0..b4d2a00f 100644 --- a/src/log4net/Core/LoggingEvent.cs +++ b/src/log4net/Core/LoggingEvent.cs @@ -32,185 +32,1186 @@ namespace log4net.Core { + /// + /// Portable data structure used by + /// + /// + /// + /// Portable data structure used by + /// + /// + /// Nicko Cadell + public struct LoggingEventData + { + #region Public Instance Fields + /// - /// Portable data structure used by + /// The logger name. /// /// /// - /// Portable data structure used by + /// The logger name. + /// + /// + public string LoggerName; + + /// + /// Level of logging event. + /// + /// + /// + /// Level of logging event. Level cannot be Serializable + /// because it is a flyweight. Due to its special serialization it + /// cannot be declared final either. + /// + /// + public Level Level; + + /// + /// The application supplied message. + /// + /// + /// + /// The application supplied message of logging event. + /// + /// + public string Message; + + /// + /// The name of thread + /// + /// + /// + /// The name of thread in which this logging event was generated + /// + /// + public string ThreadName; + + /// + /// Gets or sets the local time the event was logged + /// + /// + /// + /// Prefer using the setter, since local time can be ambiguous. + /// + /// + [Obsolete( + "Prefer using TimeStampUtc, since local time can be ambiguous in time zones with daylight savings time.")] + public DateTime TimeStamp; + + /// + /// Gets or sets the UTC time the event was logged + /// + /// + /// + /// The TimeStamp is stored in the UTC time zone. /// /// - /// Nicko Cadell - public struct LoggingEventData - { - #region Public Instance Fields - - /// - /// The logger name. - /// - /// - /// - /// The logger name. - /// - /// - public string LoggerName; - - /// - /// Level of logging event. - /// - /// - /// - /// Level of logging event. Level cannot be Serializable - /// because it is a flyweight. Due to its special serialization it - /// cannot be declared final either. - /// - /// - public Level Level; - - /// - /// The application supplied message. - /// - /// - /// - /// The application supplied message of logging event. - /// - /// - public string Message; - - /// - /// The name of thread - /// - /// - /// - /// The name of thread in which this logging event was generated - /// - /// - public string ThreadName; - - /// - /// Gets or sets the local time the event was logged - /// - /// - /// - /// Prefer using the setter, since local time can be ambiguous. - /// - /// - [Obsolete( - "Prefer using TimeStampUtc, since local time can be ambiguous in time zones with daylight savings time.")] - public DateTime TimeStamp; - - /// - /// Gets or sets the UTC time the event was logged - /// - /// - /// - /// The TimeStamp is stored in the UTC time zone. - /// - /// #pragma warning disable 618 // Suppress warnings that TimeStamp field is obsolete - public DateTime TimeStampUtc + public DateTime TimeStampUtc + { + get + { + if (TimeStamp != default(DateTime) && + _timeStampUtc == default(DateTime)) { - get + // TimeStamp field has been set explicitly but TimeStampUtc hasn't + // => use TimeStamp + return TimeStamp.ToUniversalTime(); + } + + return _timeStampUtc; + } + set + { + _timeStampUtc = value; + // For backwards compatibility + TimeStamp = _timeStampUtc.ToLocalTime(); + } + } + + private DateTime _timeStampUtc; +#pragma warning restore 618 + + /// + /// Location information for the caller. + /// + /// + /// + /// Location information for the caller. + /// + /// + public LocationInfo LocationInfo; + + /// + /// String representation of the user + /// + /// + /// + /// String representation of the user's windows name, + /// like DOMAIN\username + /// + /// + public string UserName; + + /// + /// String representation of the identity. + /// + /// + /// + /// String representation of the current thread's principal identity. + /// + /// + public string Identity; + + /// + /// The string representation of the exception + /// + /// + /// + /// The string representation of the exception + /// + /// + public string ExceptionString; + + /// + /// String representation of the AppDomain. + /// + /// + /// + /// String representation of the AppDomain. + /// + /// + public string Domain; + + /// + /// Additional event specific properties + /// + /// + /// + /// A logger or an appender may attach additional + /// properties to specific events. These properties + /// have a string key and an object value. + /// + /// + public PropertiesDictionary Properties; + + #endregion Public Instance Fields + } + + /// + /// The internal representation of logging events. + /// + /// + /// + /// When an affirmative decision is made to log then a + /// instance is created. This instance + /// is passed around to the different log4net components. + /// + /// + /// This class is of concern to those wishing to extend log4net. + /// + /// + /// Some of the values in instances of + /// are considered volatile, that is the values are correct at the + /// time the event is delivered to appenders, but will not be consistent + /// at any time afterwards. If an event is to be stored and then processed + /// at a later time these volatile values must be fixed by calling + /// . There is a performance penalty + /// for incurred by calling but it + /// is essential to maintaining data consistency. + /// + /// + /// Nicko Cadell + /// Gert Driesen + /// Douglas de la Torre + /// Daniel Cazzulino +#if !NETCF + [Serializable] +#endif + public class LoggingEvent +#if !NETCF + : ISerializable +#endif + { + private static readonly Type declaringType = typeof(LoggingEvent); + + #region Public Instance Constructors + + /// + /// Initializes a new instance of the class + /// from the supplied parameters. + /// + /// The declaring type of the method that is + /// the stack boundary into the logging system for this call. + /// The repository this event is logged in. + /// The name of the logger of this event. + /// The level of this event. + /// The message of this event. + /// The exception for this event. + /// + /// + /// Except , and , + /// all fields of LoggingEvent are filled when actually needed. Call + /// to cache all data locally + /// to prevent inconsistencies. + /// + /// This method is called by the log4net framework + /// to create a logging event. + /// + /// + public LoggingEvent(Type callerStackBoundaryDeclaringType, + log4net.Repository.ILoggerRepository repository, + string loggerName, + Level level, + object message, + Exception exception) + { + m_callerStackBoundaryDeclaringType = callerStackBoundaryDeclaringType; + m_message = message; + m_repository = repository; + m_thrownException = exception; + + m_data.LoggerName = loggerName; + m_data.Level = level; + + // Store the event creation time + m_data.TimeStampUtc = DateTime.UtcNow; + } + + /// + /// Initializes a new instance of the class + /// using specific data. + /// + /// The declaring type of the method that is + /// the stack boundary into the logging system for this call. + /// The repository this event is logged in. + /// Data used to initialize the logging event. + /// The fields in the struct that have already been fixed. + /// + /// + /// This constructor is provided to allow a + /// to be created independently of the log4net framework. This can + /// be useful if you require a custom serialization scheme. + /// + /// + /// Use the method to obtain an + /// instance of the class. + /// + /// + /// The parameter should be used to specify which fields in the + /// struct have been preset. Fields not specified in the + /// will be captured from the environment if requested or fixed. + /// + /// + public LoggingEvent(Type callerStackBoundaryDeclaringType, + log4net.Repository.ILoggerRepository repository, + LoggingEventData data, + FixFlags fixedData) + { + m_callerStackBoundaryDeclaringType = callerStackBoundaryDeclaringType; + m_repository = repository; + + m_data = data; + m_fixFlags = fixedData; + } + + /// + /// Initializes a new instance of the class + /// using specific data. + /// + /// The declaring type of the method that is + /// the stack boundary into the logging system for this call. + /// The repository this event is logged in. + /// Data used to initialize the logging event. + /// + /// + /// This constructor is provided to allow a + /// to be created independently of the log4net framework. This can + /// be useful if you require a custom serialization scheme. + /// + /// + /// Use the method to obtain an + /// instance of the class. + /// + /// + /// This constructor sets this objects flags to , + /// this assumes that all the data relating to this event is passed in via the + /// parameter and no other data should be captured from the environment. + /// + /// + public LoggingEvent(Type callerStackBoundaryDeclaringType, + log4net.Repository.ILoggerRepository repository, + LoggingEventData data) : this(callerStackBoundaryDeclaringType, repository, data, FixFlags.All) + { + } + + /// + /// Initializes a new instance of the class + /// using specific data. + /// + /// Data used to initialize the logging event. + /// + /// + /// This constructor is provided to allow a + /// to be created independently of the log4net framework. This can + /// be useful if you require a custom serialization scheme. + /// + /// + /// Use the method to obtain an + /// instance of the class. + /// + /// + /// This constructor sets this objects flags to , + /// this assumes that all the data relating to this event is passed in via the + /// parameter and no other data should be captured from the environment. + /// + /// + public LoggingEvent(LoggingEventData data) : this(null, null, data) + { + } + + #endregion Public Instance Constructors + + #region Protected Instance Constructors + +#if !NETCF + + /// + /// Serialization constructor + /// + /// The that holds the serialized object data. + /// The that contains contextual information about the source or destination. + /// + /// + /// Initializes a new instance of the class + /// with serialized data. + /// + /// + protected LoggingEvent(SerializationInfo info, StreamingContext context) + { + m_data.LoggerName = info.GetString("LoggerName"); + + // Note we are deserializing the whole level object. That is the + // name and the value. This value is correct for the source + // hierarchy but may not be for the target hierarchy that this + // event may be re-logged into. If it is to be re-logged it may + // be necessary to re-lookup the level based only on the name. + m_data.Level = (Level)info.GetValue("Level", typeof(Level)); + + m_data.Message = info.GetString("Message"); + m_data.ThreadName = info.GetString("ThreadName"); + m_data.TimeStampUtc = info.GetDateTime("TimeStamp").ToUniversalTime(); + m_data.LocationInfo = (LocationInfo)info.GetValue("LocationInfo", typeof(LocationInfo)); + m_data.UserName = info.GetString("UserName"); + m_data.ExceptionString = info.GetString("ExceptionString"); + m_data.Properties = (PropertiesDictionary)info.GetValue("Properties", typeof(PropertiesDictionary)); + m_data.Domain = info.GetString("Domain"); + m_data.Identity = info.GetString("Identity"); + + // We have restored all the values of this instance, i.e. all the values are fixed + // Set the fix flags otherwise the data values may be overwritten from the current environment. + m_fixFlags = FixFlags.All; + } + +#endif + + #endregion Protected Instance Constructors + + #region Public Instance Properties + + /// + /// Gets the time when the current process started. + /// + /// + /// This is the time when this process started. + /// + /// + /// + /// The TimeStamp is stored internally in UTC and converted to the local time zone for this computer. + /// + /// + /// Tries to get the start time for the current process. + /// Failing that it returns the time of the first call to + /// this property. + /// + /// + /// Note that AppDomains may be loaded and unloaded within the + /// same process without the process terminating and therefore + /// without the process start time being reset. + /// + /// + public static DateTime StartTime + { + get { return SystemInfo.ProcessStartTimeUtc.ToLocalTime(); } + } + + /// + /// Gets the UTC time when the current process started. + /// + /// + /// This is the UTC time when this process started. + /// + /// + /// + /// Tries to get the start time for the current process. + /// Failing that it returns the time of the first call to + /// this property. + /// + /// + /// Note that AppDomains may be loaded and unloaded within the + /// same process without the process terminating and therefore + /// without the process start time being reset. + /// + /// + public static DateTime StartTimeUtc + { + get { return SystemInfo.ProcessStartTimeUtc; } + } + + /// + /// Gets the of the logging event. + /// + /// + /// The of the logging event. + /// + /// + /// + /// Gets the of the logging event. + /// + /// + public Level Level + { + get { return m_data.Level; } + } + + /// + /// Gets the time of the logging event. + /// + /// + /// The time of the logging event. + /// + /// + /// + /// The TimeStamp is stored in UTC and converted to the local time zone for this computer. + /// + /// + public DateTime TimeStamp + { + get { return m_data.TimeStampUtc.ToLocalTime(); } + } + + /// + /// Gets UTC the time of the logging event. + /// + /// + /// The UTC time of the logging event. + /// + public DateTime TimeStampUtc + { + get { return m_data.TimeStampUtc; } + } + + /// + /// Gets the name of the logger that logged the event. + /// + /// + /// The name of the logger that logged the event. + /// + /// + /// + /// Gets the name of the logger that logged the event. + /// + /// + public string LoggerName + { + get { return m_data.LoggerName; } + } + + /// + /// Gets the location information for this logging event. + /// + /// + /// The location information for this logging event. + /// + /// + /// + /// The collected information is cached for future use. + /// + /// + /// See the class for more information on + /// supported frameworks and the different behavior in Debug and + /// Release builds. + /// + /// + public LocationInfo LocationInformation + { + get + { + if (m_data.LocationInfo == null && this.m_cacheUpdatable) + { + m_data.LocationInfo = new LocationInfo(m_callerStackBoundaryDeclaringType); + } + + return m_data.LocationInfo; + } + } + + /// + /// Gets the message object used to initialize this event. + /// + /// + /// The message object used to initialize this event. + /// + /// + /// + /// Gets the message object used to initialize this event. + /// Note that this event may not have a valid message object. + /// If the event is serialized the message object will not + /// be transferred. To get the text of the message the + /// property must be used + /// not this property. + /// + /// + /// If there is no defined message object for this event then + /// null will be returned. + /// + /// + public object MessageObject + { + get { return m_message; } + protected set { m_message = value; } + } + + /// + /// Gets the exception object used to initialize this event. + /// + /// + /// The exception object used to initialize this event. + /// + /// + /// + /// Gets the exception object used to initialize this event. + /// Note that this event may not have a valid exception object. + /// If the event is serialized the exception object will not + /// be transferred. To get the text of the exception the + /// method must be used + /// not this property. + /// + /// + /// If there is no defined exception object for this event then + /// null will be returned. + /// + /// + public Exception ExceptionObject + { + get { return m_thrownException; } + } + + /// + /// The that this event was created in. + /// + /// + /// + /// The that this event was created in. + /// + /// + public ILoggerRepository Repository + { + get { return m_repository; } + } + + /// + /// Ensure that the repository is set. + /// + /// the value for the repository + internal void EnsureRepository(ILoggerRepository repository) + { + if (repository != null) + { + m_repository = repository; + } + } + + /// + /// Gets the message, rendered through the . + /// + /// + /// The message rendered through the . + /// + /// + /// + /// The collected information is cached for future use. + /// + /// + public virtual string RenderedMessage + { + get + { + if (m_data.Message == null && this.m_cacheUpdatable) + { + if (m_message == null) + { + m_data.Message = ""; + } + else if (m_message is string) + { + m_data.Message = (m_message as string); + } + else if (m_repository != null) + { + m_data.Message = m_repository.RendererMap.FindAndRender(m_message); + } + else + { + // Very last resort + m_data.Message = m_message.ToString(); + } + } + + return m_data.Message; + } + } + + /// + /// Write the rendered message to a TextWriter + /// + /// the writer to write the message to + /// + /// + /// Unlike the property this method + /// does store the message data in the internal cache. Therefore + /// if called only once this method should be faster than the + /// property, however if the message is + /// to be accessed multiple times then the property will be more efficient. + /// + /// + public virtual void WriteRenderedMessage(TextWriter writer) + { + if (m_data.Message != null) + { + writer.Write(m_data.Message); + } + else + { + if (m_message != null) + { + if (m_message is string) + { + writer.Write(m_message as string); + } + else if (m_repository != null) + { + m_repository.RendererMap.FindAndRender(m_message, writer); + } + else + { + // Very last resort + writer.Write(m_message.ToString()); + } + } + } + } + + /// + /// Gets the name of the current thread. + /// + /// + /// The name of the current thread, or the thread ID when + /// the name is not available. + /// + /// + /// + /// The collected information is cached for future use. + /// + /// + public string ThreadName + { + get + { + if (m_data.ThreadName == null && this.m_cacheUpdatable) + { +#if NETCF + // Get thread ID only + m_data.ThreadName = + SystemInfo.CurrentThreadId.ToString(System.Globalization.NumberFormatInfo.InvariantInfo); +#else + // '.NET ThreadPool Worker' appears as a default thread name in the .NET 6-7 thread pool. + // '.NET TP Worker' is the default thread name in the .NET 8+ thread pool. + // Prefer the numeric thread ID instead. + string threadName = System.Threading.Thread.CurrentThread.Name; + if (!string.IsNullOrEmpty(threadName) && threadName != ".NET TP Worker" && threadName != ".NET ThreadPool Worker") + { + m_data.ThreadName = threadName; + } + else + { + // The thread name is not available or unsuitable. Therefore we + // go to the AppDomain to get the ID of the + // current thread. (Why don't Threads know their own ID?) + try + { + m_data.ThreadName = + SystemInfo.CurrentThreadId.ToString(System.Globalization.NumberFormatInfo + .InvariantInfo); + } + catch (SecurityException) + { + // This security exception will occur if the caller does not have + // some undefined set of SecurityPermission flags. + LogLog.Debug(declaringType, + "Security exception while trying to get current thread ID. Error Ignored. Empty thread name."); + + // As a last resort use the hash code of the Thread object + m_data.ThreadName = System.Threading.Thread.CurrentThread.GetHashCode() + .ToString(System.Globalization.CultureInfo.InvariantCulture); + } + } +#endif + } + + return m_data.ThreadName; + } + } + + /// + /// Gets the name of the current user. + /// + /// + /// The name of the current user, or NOT AVAILABLE when the + /// underlying runtime has no support for retrieving the name of the + /// current user. + /// + /// + /// + /// Calls WindowsIdentity.GetCurrent().Name to get the name of + /// the current windows user. + /// + /// + /// To improve performance, we could cache the string representation of + /// the name, and reuse that as long as the identity stayed constant. + /// Once the identity changed, we would need to re-assign and re-render + /// the string. + /// + /// + /// However, the WindowsIdentity.GetCurrent() call seems to + /// return different objects every time, so the current implementation + /// doesn't do this type of caching. + /// + /// + /// Timing for these operations: + /// + /// + /// + /// Method + /// Results + /// + /// + /// WindowsIdentity.GetCurrent() + /// 10000 loops, 00:00:00.2031250 seconds + /// + /// + /// WindowsIdentity.GetCurrent().Name + /// 10000 loops, 00:00:08.0468750 seconds + /// + /// + /// + /// This means we could speed things up almost 40 times by caching the + /// value of the WindowsIdentity.GetCurrent().Name property, since + /// this takes (8.04-0.20) = 7.84375 seconds. + /// + /// + public string UserName => + m_data.UserName ??= TryGetCurrentUserName() ?? SystemInfo.NotAvailableText; + + private string TryGetCurrentUserName() + { +#if (NETCF || SSCLI || NETSTANDARD1_3) + // On compact framework there's no notion of current Windows user + return SystemInfo.NotAvailableText; +#else + if (_platformDoesNotSupportWindowsIdentity) + { + // we've already received one PlatformNotSupportedException + // and it's highly unlikely that will change + return Environment.UserName; + } + + try + { + return _cachedWindowsIdentityUserName ??= + TryReadWindowsIdentityUserName(); + } + catch (PlatformNotSupportedException) + { + _platformDoesNotSupportWindowsIdentity = true; + return Environment.UserName; + } + catch (SecurityException) + { + // This security exception will occur if the caller does not have + // some undefined set of SecurityPermission flags. + LogLog.Debug( + declaringType, + "Security exception while trying to get current windows identity. Error Ignored." + ); + return Environment.UserName; + } + catch + { + return null; + } +#endif + } + +#if (NETCF || SSCLI || NETSTANDARD1_3) +#else + private string _cachedWindowsIdentityUserName; + private static string TryReadWindowsIdentityUserName() + { + using var identity = WindowsIdentity.GetCurrent(); + return identity?.Name ?? ""; + } +#endif + +#if (NETCF || SSCLI || NETSTANDARD1_3) +#else + private static bool _platformDoesNotSupportWindowsIdentity; +#endif + + /// + /// Gets the identity of the current thread principal. + /// + /// + /// The string name of the identity of the current thread principal. + /// + /// + /// + /// Calls System.Threading.Thread.CurrentPrincipal.Identity.Name to get + /// the name of the current thread principal. + /// + /// + public string Identity + { + get + { + if (m_data.Identity == null && this.m_cacheUpdatable) + { +#if (NETCF || SSCLI || NETSTANDARD1_3) + // On compact framework there's no notion of current thread principals + m_data.Identity = SystemInfo.NotAvailableText; +#else + try + { + if (System.Threading.Thread.CurrentPrincipal != null && + System.Threading.Thread.CurrentPrincipal.Identity != null && + System.Threading.Thread.CurrentPrincipal.Identity.Name != null) { - if (TimeStamp != default(DateTime) && - _timeStampUtc == default(DateTime)) - { - // TimeStamp field has been set explicitly but TimeStampUtc hasn't - // => use TimeStamp - return TimeStamp.ToUniversalTime(); - } - - return _timeStampUtc; + m_data.Identity = System.Threading.Thread.CurrentPrincipal.Identity.Name; } - set + else { - _timeStampUtc = value; - // For backwards compatibility - TimeStamp = _timeStampUtc.ToLocalTime(); + m_data.Identity = ""; } + } + catch (ObjectDisposedException) + { + // This exception will occur if System.Threading.Thread.CurrentPrincipal.Identity is not null but + // the getter of the property Name tries to access disposed objects. + // Seen to happen on IIS 7 or greater with windows authentication. + LogLog.Debug(declaringType, + "Object disposed exception while trying to get current thread principal. Error Ignored. Empty identity name."); + + m_data.Identity = ""; + } + catch (System.Security.SecurityException) + { + // This security exception will occur if the caller does not have + // some undefined set of SecurityPermission flags. + LogLog.Debug(declaringType, + "Security exception while trying to get current thread principal. Error Ignored. Empty identity name."); + + m_data.Identity = ""; + } +#endif + } + + return m_data.Identity; + } + } + + /// + /// Gets the AppDomain friendly name. + /// + /// + /// The AppDomain friendly name. + /// + /// + /// + /// Gets the AppDomain friendly name. + /// + /// + public string Domain + { + get + { + if (m_data.Domain == null && this.m_cacheUpdatable) + { + m_data.Domain = SystemInfo.ApplicationFriendlyName; + } + + return m_data.Domain; + } + } + + /// + /// Additional event specific properties. + /// + /// + /// Additional event specific properties. + /// + /// + /// + /// A logger or an appender may attach additional + /// properties to specific events. These properties + /// have a string key and an object value. + /// + /// + /// 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 + /// and . + /// + /// + /// Once the properties have been fixed this property + /// returns the combined cached properties. This ensures that updates to + /// this property are always reflected in the underlying storage. When + /// returning the combined properties there may be more keys in the + /// Dictionary than expected. + /// + /// + public PropertiesDictionary Properties + { + get + { + // If we have cached properties then return that otherwise changes will be lost + if (m_data.Properties != null) + { + return m_data.Properties; + } + + if (m_eventProperties == null) + { + m_eventProperties = new PropertiesDictionary(); + } + + return m_eventProperties; + } + } + + /// + /// The fixed fields in this event + /// + /// + /// The set of fields that are fixed in this event + /// + /// + /// + /// Fields will not be fixed if they have previously been fixed. + /// It is not possible to 'unfix' a field. + /// + /// + public FixFlags Fix + { + get { return m_fixFlags; } + set { this.FixVolatileData(value); } + } + + #endregion Public Instance Properties + + #region Implementation of ISerializable + +#if !NETCF + + /// + /// Serializes this object into the provided. + /// + /// The to populate with data. + /// The destination for this serialization. + /// + /// + /// The data in this event must be fixed before it can be serialized. + /// + /// + /// The method must be called during the + /// method call if this event + /// is to be used outside that method. + /// + /// +#if NET_4_0 || MONO_4_0 || NETSTANDARD + [System.Security.SecurityCritical] +#endif +#if !NETCF && !NETSTANDARD1_3 + [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, + SerializationFormatter = true)] +#endif + public virtual void GetObjectData(SerializationInfo info, StreamingContext context) + { + // The caller must call FixVolatileData before this object + // can be serialized. + + info.AddValue("LoggerName", m_data.LoggerName); + info.AddValue("Level", m_data.Level); + info.AddValue("Message", m_data.Message); + info.AddValue("ThreadName", m_data.ThreadName); + // TODO: consider serializing UTC rather than local time. Not implemented here because it + // would give an unexpected result if client and server have different versions of this class. + // info.AddValue("TimeStamp", m_data.TimeStampUtc); +#pragma warning disable 618 + info.AddValue("TimeStamp", m_data.TimeStamp); +#pragma warning restore 618 + info.AddValue("LocationInfo", m_data.LocationInfo); + info.AddValue("UserName", m_data.UserName); + info.AddValue("ExceptionString", m_data.ExceptionString); + info.AddValue("Properties", m_data.Properties); + info.AddValue("Domain", m_data.Domain); + info.AddValue("Identity", m_data.Identity); + } + +#endif + + #endregion Implementation of ISerializable + + #region Public Instance Methods + + /// + /// Gets the portable data for this . + /// + /// The for this event. + /// + /// + /// A new can be constructed using a + /// instance. + /// + /// + /// Does a fix of the data + /// in the logging event before returning the event data. + /// + /// + public LoggingEventData GetLoggingEventData() + { + return GetLoggingEventData(FixFlags.Partial); + } + + /// + /// Gets the portable data for this . + /// + /// The set of data to ensure is fixed in the LoggingEventData + /// The for this event. + /// + /// + /// A new can be constructed using a + /// instance. + /// + /// + public LoggingEventData GetLoggingEventData(FixFlags fixFlags) + { + Fix = fixFlags; + return m_data; + } + + /// + /// Returns this event's exception's rendered using the + /// . + /// + /// + /// This event's exception's rendered using the . + /// + /// + /// + /// Obsolete. Use instead. + /// + /// + [Obsolete("Use GetExceptionString instead")] + public string GetExceptionStrRep() + { + return GetExceptionString(); + } + + /// + /// Returns this event's exception's rendered using the + /// . + /// + /// + /// This event's exception's rendered using the . + /// + /// + /// + /// Returns this event's exception's rendered using the + /// . + /// + /// + public string GetExceptionString() + { + if (m_data.ExceptionString == null && this.m_cacheUpdatable) + { + if (m_thrownException != null) + { + if (m_repository != null) + { + // Render exception using the repositories renderer map + m_data.ExceptionString = m_repository.RendererMap.FindAndRender(m_thrownException); + } + else + { + // Very last resort + m_data.ExceptionString = m_thrownException.ToString(); + } + } + else + { + m_data.ExceptionString = ""; } + } - private DateTime _timeStampUtc; -#pragma warning restore 618 - - /// - /// Location information for the caller. - /// - /// - /// - /// Location information for the caller. - /// - /// - public LocationInfo LocationInfo; - - /// - /// String representation of the user - /// - /// - /// - /// String representation of the user's windows name, - /// like DOMAIN\username - /// - /// - public string UserName; - - /// - /// String representation of the identity. - /// - /// - /// - /// String representation of the current thread's principal identity. - /// - /// - public string Identity; - - /// - /// The string representation of the exception - /// - /// - /// - /// The string representation of the exception - /// - /// - public string ExceptionString; - - /// - /// String representation of the AppDomain. - /// - /// - /// - /// String representation of the AppDomain. - /// - /// - public string Domain; - - /// - /// Additional event specific properties - /// - /// - /// - /// A logger or an appender may attach additional - /// properties to specific events. These properties - /// have a string key and an object value. - /// - /// - public PropertiesDictionary Properties; - - #endregion Public Instance Fields + return m_data.ExceptionString; } /// - /// The internal representation of logging events. + /// Fix instance fields that hold volatile data. /// /// /// - /// When an affirmative decision is made to log then a - /// instance is created. This instance - /// is passed around to the different log4net components. + /// Some of the values in instances of + /// are considered volatile, that is the values are correct at the + /// time the event is delivered to appenders, but will not be consistent + /// at any time afterwards. If an event is to be stored and then processed + /// at a later time these volatile values must be fixed by calling + /// . There is a performance penalty + /// incurred by calling but it + /// is essential to maintaining data consistency. + /// + /// + /// Calling is equivalent to + /// calling passing the parameter + /// false. /// /// - /// This class is of concern to those wishing to extend log4net. + /// See for more + /// information. /// + /// + [Obsolete("Use Fix property")] + public void FixVolatileData() + { + Fix = FixFlags.All; + } + + /// + /// Fixes instance fields that hold volatile data. + /// + /// Set to true to not fix data that takes a long time to fix. + /// /// /// Some of the values in instances of /// are considered volatile, that is the values are correct at the @@ -221,1384 +1222,383 @@ public DateTime TimeStampUtc /// for incurred by calling but it /// is essential to maintaining data consistency. /// + /// + /// The param controls the data that + /// is fixed. Some of the data that can be fixed takes a long time to + /// generate, therefore if you do not require those settings to be fixed + /// they can be ignored by setting the param + /// to true. This setting will ignore the + /// and settings. + /// + /// + /// Set to false to ensure that all + /// settings are fixed. + /// /// - /// Nicko Cadell - /// Gert Driesen - /// Douglas de la Torre - /// Daniel Cazzulino -#if !NETCF - [Serializable] -#endif - public class LoggingEvent -#if !NETCF - : ISerializable -#endif + [Obsolete("Use Fix property")] + public void FixVolatileData(bool fastButLoose) { - private static readonly Type declaringType = typeof(LoggingEvent); - - #region Public Instance Constructors - - /// - /// Initializes a new instance of the class - /// from the supplied parameters. - /// - /// The declaring type of the method that is - /// the stack boundary into the logging system for this call. - /// The repository this event is logged in. - /// The name of the logger of this event. - /// The level of this event. - /// The message of this event. - /// The exception for this event. - /// - /// - /// Except , and , - /// all fields of LoggingEvent are filled when actually needed. Call - /// to cache all data locally - /// to prevent inconsistencies. - /// - /// This method is called by the log4net framework - /// to create a logging event. - /// - /// - public LoggingEvent(Type callerStackBoundaryDeclaringType, - log4net.Repository.ILoggerRepository repository, - string loggerName, - Level level, - object message, - Exception exception) - { - m_callerStackBoundaryDeclaringType = callerStackBoundaryDeclaringType; - m_message = message; - m_repository = repository; - m_thrownException = exception; - - m_data.LoggerName = loggerName; - m_data.Level = level; - - // Store the event creation time - m_data.TimeStampUtc = DateTime.UtcNow; - } + if (fastButLoose) + { + Fix = FixFlags.Partial; + } + else + { + Fix = FixFlags.All; + } + } - /// - /// Initializes a new instance of the class - /// using specific data. - /// - /// The declaring type of the method that is - /// the stack boundary into the logging system for this call. - /// The repository this event is logged in. - /// Data used to initialize the logging event. - /// The fields in the struct that have already been fixed. - /// - /// - /// This constructor is provided to allow a - /// to be created independently of the log4net framework. This can - /// be useful if you require a custom serialization scheme. - /// - /// - /// Use the method to obtain an - /// instance of the class. - /// - /// - /// The parameter should be used to specify which fields in the - /// struct have been preset. Fields not specified in the - /// will be captured from the environment if requested or fixed. - /// - /// - public LoggingEvent(Type callerStackBoundaryDeclaringType, - log4net.Repository.ILoggerRepository repository, - LoggingEventData data, - FixFlags fixedData) - { - m_callerStackBoundaryDeclaringType = callerStackBoundaryDeclaringType; - m_repository = repository; + /// + /// Fix the fields specified by the parameter + /// + /// the fields to fix + /// + /// + /// Only fields specified in the will be fixed. + /// Fields will not be fixed if they have previously been fixed. + /// It is not possible to 'unfix' a field. + /// + /// + protected virtual void FixVolatileData(FixFlags flags) + { + object forceCreation = null; - m_data = data; - m_fixFlags = fixedData; - } + //Unlock the cache so that new values can be stored + //This may not be ideal if we are no longer in the correct context + //and someone calls fix. + m_cacheUpdatable = true; - /// - /// Initializes a new instance of the class - /// using specific data. - /// - /// The declaring type of the method that is - /// the stack boundary into the logging system for this call. - /// The repository this event is logged in. - /// Data used to initialize the logging event. - /// - /// - /// This constructor is provided to allow a - /// to be created independently of the log4net framework. This can - /// be useful if you require a custom serialization scheme. - /// - /// - /// Use the method to obtain an - /// instance of the class. - /// - /// - /// This constructor sets this objects flags to , - /// this assumes that all the data relating to this event is passed in via the - /// parameter and no other data should be captured from the environment. - /// - /// - public LoggingEvent(Type callerStackBoundaryDeclaringType, - log4net.Repository.ILoggerRepository repository, - LoggingEventData data) : this(callerStackBoundaryDeclaringType, repository, data, FixFlags.All) - { - } + // determine the flags that we are actually fixing + var updateFlags = (FixFlags)((flags ^ m_fixFlags) & flags); - /// - /// Initializes a new instance of the class - /// using specific data. - /// - /// Data used to initialize the logging event. - /// - /// - /// This constructor is provided to allow a - /// to be created independently of the log4net framework. This can - /// be useful if you require a custom serialization scheme. - /// - /// - /// Use the method to obtain an - /// instance of the class. - /// - /// - /// This constructor sets this objects flags to , - /// this assumes that all the data relating to this event is passed in via the - /// parameter and no other data should be captured from the environment. - /// - /// - public LoggingEvent(LoggingEventData data) : this(null, null, data) + if (updateFlags > 0) + { + if ((updateFlags & FixFlags.Message) != 0) { - } - - #endregion Public Instance Constructors + // Force the message to be rendered + forceCreation = this.RenderedMessage; - #region Protected Instance Constructors - -#if !NETCF - - /// - /// Serialization constructor - /// - /// The that holds the serialized object data. - /// The that contains contextual information about the source or destination. - /// - /// - /// Initializes a new instance of the class - /// with serialized data. - /// - /// - protected LoggingEvent(SerializationInfo info, StreamingContext context) - { - m_data.LoggerName = info.GetString("LoggerName"); - - // Note we are deserializing the whole level object. That is the - // name and the value. This value is correct for the source - // hierarchy but may not be for the target hierarchy that this - // event may be re-logged into. If it is to be re-logged it may - // be necessary to re-lookup the level based only on the name. - m_data.Level = (Level)info.GetValue("Level", typeof(Level)); - - m_data.Message = info.GetString("Message"); - m_data.ThreadName = info.GetString("ThreadName"); - m_data.TimeStampUtc = info.GetDateTime("TimeStamp").ToUniversalTime(); - m_data.LocationInfo = (LocationInfo)info.GetValue("LocationInfo", typeof(LocationInfo)); - m_data.UserName = info.GetString("UserName"); - m_data.ExceptionString = info.GetString("ExceptionString"); - m_data.Properties = (PropertiesDictionary)info.GetValue("Properties", typeof(PropertiesDictionary)); - m_data.Domain = info.GetString("Domain"); - m_data.Identity = info.GetString("Identity"); - - // We have restored all the values of this instance, i.e. all the values are fixed - // Set the fix flags otherwise the data values may be overwritten from the current environment. - m_fixFlags = FixFlags.All; + m_fixFlags |= FixFlags.Message; } -#endif - - #endregion Protected Instance Constructors - - #region Public Instance Properties - - /// - /// Gets the time when the current process started. - /// - /// - /// This is the time when this process started. - /// - /// - /// - /// The TimeStamp is stored internally in UTC and converted to the local time zone for this computer. - /// - /// - /// Tries to get the start time for the current process. - /// Failing that it returns the time of the first call to - /// this property. - /// - /// - /// Note that AppDomains may be loaded and unloaded within the - /// same process without the process terminating and therefore - /// without the process start time being reset. - /// - /// - public static DateTime StartTime + if ((updateFlags & FixFlags.ThreadName) != 0) { - get { return SystemInfo.ProcessStartTimeUtc.ToLocalTime(); } - } + // Grab the thread name + forceCreation = this.ThreadName; - /// - /// Gets the UTC time when the current process started. - /// - /// - /// This is the UTC time when this process started. - /// - /// - /// - /// Tries to get the start time for the current process. - /// Failing that it returns the time of the first call to - /// this property. - /// - /// - /// Note that AppDomains may be loaded and unloaded within the - /// same process without the process terminating and therefore - /// without the process start time being reset. - /// - /// - public static DateTime StartTimeUtc - { - get { return SystemInfo.ProcessStartTimeUtc; } + m_fixFlags |= FixFlags.ThreadName; } - /// - /// Gets the of the logging event. - /// - /// - /// The of the logging event. - /// - /// - /// - /// Gets the of the logging event. - /// - /// - public Level Level + if ((updateFlags & FixFlags.LocationInfo) != 0) { - get { return m_data.Level; } - } + // Force the location information to be loaded + forceCreation = this.LocationInformation; - /// - /// Gets the time of the logging event. - /// - /// - /// The time of the logging event. - /// - /// - /// - /// The TimeStamp is stored in UTC and converted to the local time zone for this computer. - /// - /// - public DateTime TimeStamp - { - get { return m_data.TimeStampUtc.ToLocalTime(); } + m_fixFlags |= FixFlags.LocationInfo; } - /// - /// Gets UTC the time of the logging event. - /// - /// - /// The UTC time of the logging event. - /// - public DateTime TimeStampUtc + if ((updateFlags & FixFlags.UserName) != 0) { - get { return m_data.TimeStampUtc; } - } + // Grab the user name + forceCreation = this.UserName; - /// - /// Gets the name of the logger that logged the event. - /// - /// - /// The name of the logger that logged the event. - /// - /// - /// - /// Gets the name of the logger that logged the event. - /// - /// - public string LoggerName - { - get { return m_data.LoggerName; } + m_fixFlags |= FixFlags.UserName; } - /// - /// Gets the location information for this logging event. - /// - /// - /// The location information for this logging event. - /// - /// - /// - /// The collected information is cached for future use. - /// - /// - /// See the class for more information on - /// supported frameworks and the different behavior in Debug and - /// Release builds. - /// - /// - public LocationInfo LocationInformation + if ((updateFlags & FixFlags.Domain) != 0) { - get - { - if (m_data.LocationInfo == null && this.m_cacheUpdatable) - { - m_data.LocationInfo = new LocationInfo(m_callerStackBoundaryDeclaringType); - } + // Grab the domain name + forceCreation = this.Domain; - return m_data.LocationInfo; - } + m_fixFlags |= FixFlags.Domain; } - /// - /// Gets the message object used to initialize this event. - /// - /// - /// The message object used to initialize this event. - /// - /// - /// - /// Gets the message object used to initialize this event. - /// Note that this event may not have a valid message object. - /// If the event is serialized the message object will not - /// be transferred. To get the text of the message the - /// property must be used - /// not this property. - /// - /// - /// If there is no defined message object for this event then - /// null will be returned. - /// - /// - public object MessageObject + if ((updateFlags & FixFlags.Identity) != 0) { - get { return m_message; } - protected set { m_message = value; } - } + // Grab the identity + forceCreation = this.Identity; - /// - /// Gets the exception object used to initialize this event. - /// - /// - /// The exception object used to initialize this event. - /// - /// - /// - /// Gets the exception object used to initialize this event. - /// Note that this event may not have a valid exception object. - /// If the event is serialized the exception object will not - /// be transferred. To get the text of the exception the - /// method must be used - /// not this property. - /// - /// - /// If there is no defined exception object for this event then - /// null will be returned. - /// - /// - public Exception ExceptionObject - { - get { return m_thrownException; } + m_fixFlags |= FixFlags.Identity; } - /// - /// The that this event was created in. - /// - /// - /// - /// The that this event was created in. - /// - /// - public ILoggerRepository Repository + if ((updateFlags & FixFlags.Exception) != 0) { - get { return m_repository; } - } + // Force the exception text to be loaded + forceCreation = GetExceptionString(); - /// - /// Ensure that the repository is set. - /// - /// the value for the repository - internal void EnsureRepository(ILoggerRepository repository) - { - if (repository != null) - { - m_repository = repository; - } + m_fixFlags |= FixFlags.Exception; } - /// - /// Gets the message, rendered through the . - /// - /// - /// The message rendered through the . - /// - /// - /// - /// The collected information is cached for future use. - /// - /// - public virtual string RenderedMessage + if ((updateFlags & FixFlags.Properties) != 0) { - get - { - if (m_data.Message == null && this.m_cacheUpdatable) - { - if (m_message == null) - { - m_data.Message = ""; - } - else if (m_message is string) - { - m_data.Message = (m_message as string); - } - else if (m_repository != null) - { - m_data.Message = m_repository.RendererMap.FindAndRender(m_message); - } - else - { - // Very last resort - m_data.Message = m_message.ToString(); - } - } - - return m_data.Message; - } - } + CacheProperties(); - /// - /// Write the rendered message to a TextWriter - /// - /// the writer to write the message to - /// - /// - /// Unlike the property this method - /// does store the message data in the internal cache. Therefore - /// if called only once this method should be faster than the - /// property, however if the message is - /// to be accessed multiple times then the property will be more efficient. - /// - /// - public virtual void WriteRenderedMessage(TextWriter writer) - { - if (m_data.Message != null) - { - writer.Write(m_data.Message); - } - else - { - if (m_message != null) - { - if (m_message is string) - { - writer.Write(m_message as string); - } - else if (m_repository != null) - { - m_repository.RendererMap.FindAndRender(m_message, writer); - } - else - { - // Very last resort - writer.Write(m_message.ToString()); - } - } - } + m_fixFlags |= FixFlags.Properties; } + } - /// - /// Gets the name of the current thread. - /// - /// - /// The name of the current thread, or the thread ID when - /// the name is not available. - /// - /// - /// - /// The collected information is cached for future use. - /// - /// - public string ThreadName - { - get - { - if (m_data.ThreadName == null && this.m_cacheUpdatable) - { -#if NETCF - // Get thread ID only - m_data.ThreadName = - SystemInfo.CurrentThreadId.ToString(System.Globalization.NumberFormatInfo.InvariantInfo); -#else - // '.NET ThreadPool Worker' appears as a default thread name in the .NET 6-7 thread pool. - // '.NET TP Worker' is the default thread name in the .NET 8+ thread pool. - // Prefer the numeric thread ID instead. - string threadName = System.Threading.Thread.CurrentThread.Name; - if (!string.IsNullOrEmpty(threadName) && threadName != ".NET TP Worker" && threadName != ".NET ThreadPool Worker") - { - m_data.ThreadName = threadName; - } - else - { - // The thread name is not available or unsuitable. Therefore we - // go to the AppDomain to get the ID of the - // current thread. (Why don't Threads know their own ID?) - try - { - m_data.ThreadName = - SystemInfo.CurrentThreadId.ToString(System.Globalization.NumberFormatInfo - .InvariantInfo); - } - catch (SecurityException) - { - // This security exception will occur if the caller does not have - // some undefined set of SecurityPermission flags. - LogLog.Debug(declaringType, - "Security exception while trying to get current thread ID. Error Ignored. Empty thread name."); - - // As a last resort use the hash code of the Thread object - m_data.ThreadName = System.Threading.Thread.CurrentThread.GetHashCode() - .ToString(System.Globalization.CultureInfo.InvariantCulture); - } - } -#endif - } + // avoid warning CS0219 + if (forceCreation != null) + { + } - return m_data.ThreadName; - } - } + //Finaly lock everything we've cached. + m_cacheUpdatable = false; + } - /// - /// Gets the name of the current user. - /// - /// - /// The name of the current user, or NOT AVAILABLE when the - /// underlying runtime has no support for retrieving the name of the - /// current user. - /// - /// - /// - /// Calls WindowsIdentity.GetCurrent().Name to get the name of - /// the current windows user. - /// - /// - /// To improve performance, we could cache the string representation of - /// the name, and reuse that as long as the identity stayed constant. - /// Once the identity changed, we would need to re-assign and re-render - /// the string. - /// - /// - /// However, the WindowsIdentity.GetCurrent() call seems to - /// return different objects every time, so the current implementation - /// doesn't do this type of caching. - /// - /// - /// Timing for these operations: - /// - /// - /// - /// Method - /// Results - /// - /// - /// WindowsIdentity.GetCurrent() - /// 10000 loops, 00:00:00.2031250 seconds - /// - /// - /// WindowsIdentity.GetCurrent().Name - /// 10000 loops, 00:00:08.0468750 seconds - /// - /// - /// - /// This means we could speed things up almost 40 times by caching the - /// value of the WindowsIdentity.GetCurrent().Name property, since - /// this takes (8.04-0.20) = 7.84375 seconds. - /// - /// - public string UserName => - m_data.UserName ??= TryGetCurrentUserName() ?? SystemInfo.NotAvailableText; - - private string TryGetCurrentUserName() - { -#if (NETCF || SSCLI || NETSTANDARD1_3) - // On compact framework there's no notion of current Windows user - return SystemInfo.NotAvailableText; -#else - if (_platformDoesNotSupportWindowsIdentity) - { - // we've already received one PlatformNotSupportedException - // and it's highly unlikely that will change - return Environment.UserName; - } + #endregion Public Instance Methods - try - { - return _cachedWindowsIdentityUserName ??= - TryReadWindowsIdentityUserName(); - } - catch (PlatformNotSupportedException) - { - _platformDoesNotSupportWindowsIdentity = true; - return Environment.UserName; - } - catch (SecurityException) - { - // This security exception will occur if the caller does not have - // some undefined set of SecurityPermission flags. - LogLog.Debug( - declaringType, - "Security exception while trying to get current windows identity. Error Ignored." - ); - return Environment.UserName; - } - catch - { - return null; - } -#endif - } - -#if (NETCF || SSCLI || NETSTANDARD1_3) -#else - private string _cachedWindowsIdentityUserName; - private static string TryReadWindowsIdentityUserName() - { - using var identity = WindowsIdentity.GetCurrent(); - return identity?.Name ?? ""; - } -#endif + #region Protected Instance Methods -#if (NETCF || SSCLI || NETSTANDARD1_3) -#else - private static bool _platformDoesNotSupportWindowsIdentity; -#endif + private void CreateCompositeProperties() + { + var compositeProperties = new CompositeProperties(); - /// - /// Gets the identity of the current thread principal. - /// - /// - /// The string name of the identity of the current thread principal. - /// - /// - /// - /// Calls System.Threading.Thread.CurrentPrincipal.Identity.Name to get - /// the name of the current thread principal. - /// - /// - public string Identity - { - get - { - if (m_data.Identity == null && this.m_cacheUpdatable) - { -#if (NETCF || SSCLI || NETSTANDARD1_3) - // On compact framework there's no notion of current thread principals - m_data.Identity = SystemInfo.NotAvailableText; -#else - try - { - if (System.Threading.Thread.CurrentPrincipal != null && - System.Threading.Thread.CurrentPrincipal.Identity != null && - System.Threading.Thread.CurrentPrincipal.Identity.Name != null) - { - m_data.Identity = System.Threading.Thread.CurrentPrincipal.Identity.Name; - } - else - { - m_data.Identity = ""; - } - } - catch (ObjectDisposedException) - { - // This exception will occur if System.Threading.Thread.CurrentPrincipal.Identity is not null but - // the getter of the property Name tries to access disposed objects. - // Seen to happen on IIS 7 or greater with windows authentication. - LogLog.Debug(declaringType, - "Object disposed exception while trying to get current thread principal. Error Ignored. Empty identity name."); - - m_data.Identity = ""; - } - catch (System.Security.SecurityException) - { - // This security exception will occur if the caller does not have - // some undefined set of SecurityPermission flags. - LogLog.Debug(declaringType, - "Security exception while trying to get current thread principal. Error Ignored. Empty identity name."); - - m_data.Identity = ""; - } + if (m_eventProperties != null) + { + compositeProperties.Add(m_eventProperties); + } +#if !NETCF + var logicalThreadProperties = LogicalThreadContext.Properties.GetProperties(false); + if (logicalThreadProperties != null) + { + compositeProperties.Add(logicalThreadProperties); + } #endif - } - - return m_data.Identity; - } - } - - /// - /// Gets the AppDomain friendly name. - /// - /// - /// The AppDomain friendly name. - /// - /// - /// - /// Gets the AppDomain friendly name. - /// - /// - public string Domain - { - get - { - if (m_data.Domain == null && this.m_cacheUpdatable) - { - m_data.Domain = SystemInfo.ApplicationFriendlyName; - } - - return m_data.Domain; - } - } - - /// - /// Additional event specific properties. - /// - /// - /// Additional event specific properties. - /// - /// - /// - /// A logger or an appender may attach additional - /// properties to specific events. These properties - /// have a string key and an object value. - /// - /// - /// 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 - /// and . - /// - /// - /// Once the properties have been fixed this property - /// returns the combined cached properties. This ensures that updates to - /// this property are always reflected in the underlying storage. When - /// returning the combined properties there may be more keys in the - /// Dictionary than expected. - /// - /// - public PropertiesDictionary Properties + var threadProperties = ThreadContext.Properties.GetProperties(false); + if (threadProperties != null) + { + compositeProperties.Add(threadProperties); + } + + // TODO: Add Repository Properties + + // event properties + var shouldFixUserName = (m_fixFlags & FixFlags.UserName) != 0; + var shouldFixIdentity = (m_fixFlags & FixFlags.Identity) != 0; + if (shouldFixIdentity || shouldFixUserName) + { + var eventProperties = new PropertiesDictionary(); + if (shouldFixUserName) { - get - { - // If we have cached properties then return that otherwise changes will be lost - if (m_data.Properties != null) - { - return m_data.Properties; - } - - if (m_eventProperties == null) - { - m_eventProperties = new PropertiesDictionary(); - } - - return m_eventProperties; - } + eventProperties[UserNameProperty] = UserName; } - /// - /// The fixed fields in this event - /// - /// - /// The set of fields that are fixed in this event - /// - /// - /// - /// Fields will not be fixed if they have previously been fixed. - /// It is not possible to 'unfix' a field. - /// - /// - public FixFlags Fix + if (shouldFixIdentity) { - get { return m_fixFlags; } - set { this.FixVolatileData(value); } + eventProperties[IdentityProperty] = Identity; } - #endregion Public Instance Properties - - #region Implementation of ISerializable + compositeProperties.Add(eventProperties); + } -#if !NETCF + compositeProperties.Add(GlobalContext.Properties.GetReadOnlyProperties()); + m_compositeProperties = compositeProperties; + } - /// - /// Serializes this object into the provided. - /// - /// The to populate with data. - /// The destination for this serialization. - /// - /// - /// The data in this event must be fixed before it can be serialized. - /// - /// - /// The method must be called during the - /// method call if this event - /// is to be used outside that method. - /// - /// -#if NET_4_0 || MONO_4_0 || NETSTANDARD - [System.Security.SecurityCritical] -#endif -#if !NETCF && !NETSTANDARD1_3 - [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, - SerializationFormatter = true)] -#endif - public virtual void GetObjectData(SerializationInfo info, StreamingContext context) + private void CacheProperties() + { + if (m_data.Properties == null && this.m_cacheUpdatable) + { + if (m_compositeProperties == null) { - // The caller must call FixVolatileData before this object - // can be serialized. - - info.AddValue("LoggerName", m_data.LoggerName); - info.AddValue("Level", m_data.Level); - info.AddValue("Message", m_data.Message); - info.AddValue("ThreadName", m_data.ThreadName); - // TODO: consider serializing UTC rather than local time. Not implemented here because it - // would give an unexpected result if client and server have different versions of this class. - // info.AddValue("TimeStamp", m_data.TimeStampUtc); -#pragma warning disable 618 - info.AddValue("TimeStamp", m_data.TimeStamp); -#pragma warning restore 618 - info.AddValue("LocationInfo", m_data.LocationInfo); - info.AddValue("UserName", m_data.UserName); - info.AddValue("ExceptionString", m_data.ExceptionString); - info.AddValue("Properties", m_data.Properties); - info.AddValue("Domain", m_data.Domain); - info.AddValue("Identity", m_data.Identity); + CreateCompositeProperties(); } -#endif + var flattenedProperties = m_compositeProperties.Flatten(); - #endregion Implementation of ISerializable - - #region Public Instance Methods - - /// - /// Gets the portable data for this . - /// - /// The for this event. - /// - /// - /// A new can be constructed using a - /// instance. - /// - /// - /// Does a fix of the data - /// in the logging event before returning the event data. - /// - /// - public LoggingEventData GetLoggingEventData() - { - return GetLoggingEventData(FixFlags.Partial); - } + var fixedProperties = new PropertiesDictionary(); - /// - /// Gets the portable data for this . - /// - /// The set of data to ensure is fixed in the LoggingEventData - /// The for this event. - /// - /// - /// A new can be constructed using a - /// instance. - /// - /// - public LoggingEventData GetLoggingEventData(FixFlags fixFlags) + // Validate properties + foreach (DictionaryEntry entry in flattenedProperties) { - Fix = fixFlags; - return m_data; - } + var key = entry.Key as string; - /// - /// Returns this event's exception's rendered using the - /// . - /// - /// - /// This event's exception's rendered using the . - /// - /// - /// - /// Obsolete. Use instead. - /// - /// - [Obsolete("Use GetExceptionString instead")] - public string GetExceptionStrRep() - { - return GetExceptionString(); - } + if (key != null) + { + var val = entry.Value; - /// - /// Returns this event's exception's rendered using the - /// . - /// - /// - /// This event's exception's rendered using the . - /// - /// - /// - /// Returns this event's exception's rendered using the - /// . - /// - /// - public string GetExceptionString() - { - if (m_data.ExceptionString == null && this.m_cacheUpdatable) + // Fix any IFixingRequired objects + var fixingRequired = val as IFixingRequired; + if (fixingRequired != null) { - if (m_thrownException != null) - { - if (m_repository != null) - { - // Render exception using the repositories renderer map - m_data.ExceptionString = m_repository.RendererMap.FindAndRender(m_thrownException); - } - else - { - // Very last resort - m_data.ExceptionString = m_thrownException.ToString(); - } - } - else - { - m_data.ExceptionString = ""; - } + val = fixingRequired.GetFixedObject(); } - return m_data.ExceptionString; - } - - /// - /// Fix instance fields that hold volatile data. - /// - /// - /// - /// Some of the values in instances of - /// are considered volatile, that is the values are correct at the - /// time the event is delivered to appenders, but will not be consistent - /// at any time afterwards. If an event is to be stored and then processed - /// at a later time these volatile values must be fixed by calling - /// . There is a performance penalty - /// incurred by calling but it - /// is essential to maintaining data consistency. - /// - /// - /// Calling is equivalent to - /// calling passing the parameter - /// false. - /// - /// - /// See for more - /// information. - /// - /// - [Obsolete("Use Fix property")] - public void FixVolatileData() - { - Fix = FixFlags.All; - } - - /// - /// Fixes instance fields that hold volatile data. - /// - /// Set to true to not fix data that takes a long time to fix. - /// - /// - /// Some of the values in instances of - /// are considered volatile, that is the values are correct at the - /// time the event is delivered to appenders, but will not be consistent - /// at any time afterwards. If an event is to be stored and then processed - /// at a later time these volatile values must be fixed by calling - /// . There is a performance penalty - /// for incurred by calling but it - /// is essential to maintaining data consistency. - /// - /// - /// The param controls the data that - /// is fixed. Some of the data that can be fixed takes a long time to - /// generate, therefore if you do not require those settings to be fixed - /// they can be ignored by setting the param - /// to true. This setting will ignore the - /// and settings. - /// - /// - /// Set to false to ensure that all - /// settings are fixed. - /// - /// - [Obsolete("Use Fix property")] - public void FixVolatileData(bool fastButLoose) - { - if (fastButLoose) - { - Fix = FixFlags.Partial; - } - else + // Strip keys with null values + if (val != null) { - Fix = FixFlags.All; + fixedProperties[key] = val; } + } } - /// - /// Fix the fields specified by the parameter - /// - /// the fields to fix - /// - /// - /// Only fields specified in the will be fixed. - /// Fields will not be fixed if they have previously been fixed. - /// It is not possible to 'unfix' a field. - /// - /// - protected virtual void FixVolatileData(FixFlags flags) - { - object forceCreation = null; - - //Unlock the cache so that new values can be stored - //This may not be ideal if we are no longer in the correct context - //and someone calls fix. - m_cacheUpdatable = true; - - // determine the flags that we are actually fixing - var updateFlags = (FixFlags)((flags ^ m_fixFlags) & flags); - - if (updateFlags > 0) - { - if ((updateFlags & FixFlags.Message) != 0) - { - // Force the message to be rendered - forceCreation = this.RenderedMessage; - - m_fixFlags |= FixFlags.Message; - } - - if ((updateFlags & FixFlags.ThreadName) != 0) - { - // Grab the thread name - forceCreation = this.ThreadName; - - m_fixFlags |= FixFlags.ThreadName; - } - - if ((updateFlags & FixFlags.LocationInfo) != 0) - { - // Force the location information to be loaded - forceCreation = this.LocationInformation; - - m_fixFlags |= FixFlags.LocationInfo; - } - - if ((updateFlags & FixFlags.UserName) != 0) - { - // Grab the user name - forceCreation = this.UserName; - - m_fixFlags |= FixFlags.UserName; - } - - if ((updateFlags & FixFlags.Domain) != 0) - { - // Grab the domain name - forceCreation = this.Domain; - - m_fixFlags |= FixFlags.Domain; - } + m_data.Properties = fixedProperties; + } + } - if ((updateFlags & FixFlags.Identity) != 0) - { - // Grab the identity - forceCreation = this.Identity; + /// + /// Lookup a composite property in this event + /// + /// the key for the property to lookup + /// the value for the property + /// + /// + /// This event has composite properties that combine together properties from + /// several different contexts in the following order: + /// + /// + /// this events properties + /// + /// This event has that can be set. These + /// properties are specific to this event only. + /// + /// + /// + /// the thread properties + /// + /// The that are set on the current + /// thread. These properties are shared by all events logged on this thread. + /// + /// + /// + /// the global properties + /// + /// The that are set globally. These + /// properties are shared by all the threads in the AppDomain. + /// + /// + /// + /// + /// + public object LookupProperty(string key) + { + if (m_data.Properties != null) + { + return m_data.Properties[key]; + } - m_fixFlags |= FixFlags.Identity; - } + if (m_compositeProperties == null) + { + CreateCompositeProperties(); + } - if ((updateFlags & FixFlags.Exception) != 0) - { - // Force the exception text to be loaded - forceCreation = GetExceptionString(); + return m_compositeProperties[key]; + } - m_fixFlags |= FixFlags.Exception; - } + /// + /// Get all the composite properties in this event + /// + /// the containing all the properties + /// + /// + /// See for details of the composite properties + /// stored by the event. + /// + /// + /// This method returns a single containing all the + /// properties defined for this event. + /// + /// + public PropertiesDictionary GetProperties() + { + if (m_data.Properties != null) + { + return m_data.Properties; + } - if ((updateFlags & FixFlags.Properties) != 0) - { - CacheProperties(); + if (m_compositeProperties == null) + { + CreateCompositeProperties(); + } - m_fixFlags |= FixFlags.Properties; - } - } + return m_compositeProperties.Flatten(); + } - // avoid warning CS0219 - if (forceCreation != null) - { - } + #endregion Public Instance Methods - //Finaly lock everything we've cached. - m_cacheUpdatable = false; - } + #region Private Instance Fields - #endregion Public Instance Methods + /// + /// The internal logging event data. + /// + private LoggingEventData m_data; - #region Protected Instance Methods + /// + /// The internal logging event data. + /// + private CompositeProperties m_compositeProperties; - private void CreateCompositeProperties() - { - var compositeProperties = new CompositeProperties(); + /// + /// The internal logging event data. + /// + private PropertiesDictionary m_eventProperties; - if (m_eventProperties != null) - { - compositeProperties.Add(m_eventProperties); - } -#if !NETCF - var logicalThreadProperties = LogicalThreadContext.Properties.GetProperties(false); - if (logicalThreadProperties != null) - { - compositeProperties.Add(logicalThreadProperties); - } -#endif - var threadProperties = ThreadContext.Properties.GetProperties(false); - if (threadProperties != null) - { - compositeProperties.Add(threadProperties); - } + /// + /// The fully qualified Type of the calling + /// logger class in the stack frame (i.e. the declaring type of the method). + /// + private readonly Type m_callerStackBoundaryDeclaringType; - // TODO: Add Repository Properties + /// + /// The application supplied message of logging event. + /// + private object m_message; - // event properties - var shouldFixUserName = (m_fixFlags & FixFlags.UserName) != 0; - var shouldFixIdentity = (m_fixFlags & FixFlags.Identity) != 0; - if (shouldFixIdentity || shouldFixUserName) - { - var eventProperties = new PropertiesDictionary(); - if (shouldFixUserName) - { - eventProperties[UserNameProperty] = UserName; - } - - if (shouldFixIdentity) - { - eventProperties[IdentityProperty] = Identity; - } - - compositeProperties.Add(eventProperties); - } + /// + /// The exception that was thrown. + /// + /// + /// This is not serialized. The string representation + /// is serialized instead. + /// + private readonly Exception m_thrownException; - compositeProperties.Add(GlobalContext.Properties.GetReadOnlyProperties()); - m_compositeProperties = compositeProperties; - } + /// + /// The repository that generated the logging event + /// + /// + /// This is not serialized. + /// + private ILoggerRepository m_repository = null; - private void CacheProperties() - { - if (m_data.Properties == null && this.m_cacheUpdatable) - { - if (m_compositeProperties == null) - { - CreateCompositeProperties(); - } - - var flattenedProperties = m_compositeProperties.Flatten(); - - var fixedProperties = new PropertiesDictionary(); - - // Validate properties - foreach (DictionaryEntry entry in flattenedProperties) - { - var key = entry.Key as string; - - if (key != null) - { - var val = entry.Value; - - // Fix any IFixingRequired objects - var fixingRequired = val as IFixingRequired; - if (fixingRequired != null) - { - val = fixingRequired.GetFixedObject(); - } - - // Strip keys with null values - if (val != null) - { - fixedProperties[key] = val; - } - } - } - - m_data.Properties = fixedProperties; - } - } + /// + /// The fix state for this event + /// + /// + /// These flags indicate which fields have been fixed. + /// Not serialized. + /// + private FixFlags m_fixFlags = FixFlags.None; - /// - /// Lookup a composite property in this event - /// - /// the key for the property to lookup - /// the value for the property - /// - /// - /// This event has composite properties that combine together properties from - /// several different contexts in the following order: - /// - /// - /// this events properties - /// - /// This event has that can be set. These - /// properties are specific to this event only. - /// - /// - /// - /// the thread properties - /// - /// The that are set on the current - /// thread. These properties are shared by all events logged on this thread. - /// - /// - /// - /// the global properties - /// - /// The that are set globally. These - /// properties are shared by all the threads in the AppDomain. - /// - /// - /// - /// - /// - public object LookupProperty(string key) - { - if (m_data.Properties != null) - { - return m_data.Properties[key]; - } + /// + /// Indicated that the internal cache is updateable (ie not fixed) + /// + /// + /// This is a seperate flag to m_fixFlags as it allows incrementel fixing and simpler + /// changes in the caching strategy. + /// + private bool m_cacheUpdatable = true; - if (m_compositeProperties == null) - { - CreateCompositeProperties(); - } + #endregion Private Instance Fields - return m_compositeProperties[key]; - } + #region Constants - /// - /// Get all the composite properties in this event - /// - /// the containing all the properties - /// - /// - /// See for details of the composite properties - /// stored by the event. - /// - /// - /// This method returns a single containing all the - /// properties defined for this event. - /// - /// - public PropertiesDictionary GetProperties() - { - if (m_data.Properties != null) - { - return m_data.Properties; - } + /// + /// The key into the Properties map for the host name value. + /// + public const string HostNameProperty = "log4net:HostName"; - if (m_compositeProperties == null) - { - CreateCompositeProperties(); - } + /// + /// The key into the Properties map for the thread identity value. + /// + public const string IdentityProperty = "log4net:Identity"; - return m_compositeProperties.Flatten(); - } + /// + /// The key into the Properties map for the user name value. + /// + public const string UserNameProperty = "log4net:UserName"; - #endregion Public Instance Methods - - #region Private Instance Fields - - /// - /// The internal logging event data. - /// - private LoggingEventData m_data; - - /// - /// The internal logging event data. - /// - private CompositeProperties m_compositeProperties; - - /// - /// The internal logging event data. - /// - private PropertiesDictionary m_eventProperties; - - /// - /// The fully qualified Type of the calling - /// logger class in the stack frame (i.e. the declaring type of the method). - /// - private readonly Type m_callerStackBoundaryDeclaringType; - - /// - /// The application supplied message of logging event. - /// - private object m_message; - - /// - /// The exception that was thrown. - /// - /// - /// This is not serialized. The string representation - /// is serialized instead. - /// - private readonly Exception m_thrownException; - - /// - /// The repository that generated the logging event - /// - /// - /// This is not serialized. - /// - private ILoggerRepository m_repository = null; - - /// - /// The fix state for this event - /// - /// - /// These flags indicate which fields have been fixed. - /// Not serialized. - /// - private FixFlags m_fixFlags = FixFlags.None; - - /// - /// Indicated that the internal cache is updateable (ie not fixed) - /// - /// - /// This is a seperate flag to m_fixFlags as it allows incrementel fixing and simpler - /// changes in the caching strategy. - /// - private bool m_cacheUpdatable = true; - - #endregion Private Instance Fields - - #region Constants - - /// - /// The key into the Properties map for the host name value. - /// - public const string HostNameProperty = "log4net:HostName"; - - /// - /// The key into the Properties map for the thread identity value. - /// - public const string IdentityProperty = "log4net:Identity"; - - /// - /// The key into the Properties map for the user name value. - /// - public const string UserNameProperty = "log4net:UserName"; - - #endregion - } + #endregion + } } \ No newline at end of file diff --git a/src/log4net/Core/MethodItem.cs b/src/log4net/Core/MethodItem.cs index f76ccdbf..113cd37e 100644 --- a/src/log4net/Core/MethodItem.cs +++ b/src/log4net/Core/MethodItem.cs @@ -65,13 +65,13 @@ public MethodItem(string name, string[] parameters) m_parameters = parameters; } - /// - /// constructs a method item from a method base by determining the method name and its parameters. - /// - /// + /// + /// constructs a method item from a method base by determining the method name and its parameters. + /// + /// public MethodItem(System.Reflection.MethodBase methodBase) : this(methodBase.Name, GetMethodParameterNames(methodBase)) - { + { } #endregion diff --git a/src/log4net/Core/StackFrameItem.cs b/src/log4net/Core/StackFrameItem.cs index 778703b9..abad9797 100644 --- a/src/log4net/Core/StackFrameItem.cs +++ b/src/log4net/Core/StackFrameItem.cs @@ -24,28 +24,28 @@ namespace log4net.Core { + /// + /// provides stack frame information without actually referencing a System.Diagnostics.StackFrame + /// as that would require that the containing assembly is loaded. + /// + /// + [Serializable] + public class StackFrameItem + { + #region Public Instance Constructors + /// - /// provides stack frame information without actually referencing a System.Diagnostics.StackFrame - /// as that would require that the containing assembly is loaded. + /// returns a stack frame item from a stack frame. This /// - /// - [Serializable] - public class StackFrameItem + /// + /// + public StackFrameItem(StackFrame frame) { - #region Public Instance Constructors - - /// - /// returns a stack frame item from a stack frame. This - /// - /// - /// - public StackFrameItem(StackFrame frame) - { - // set default values - m_lineNumber = NA; - m_fileName = NA; - m_method = new MethodItem(); - m_className = NA; + // set default values + m_lineNumber = NA; + m_fileName = NA; + m_method = new MethodItem(); + m_className = NA; try { @@ -56,7 +56,7 @@ public StackFrameItem(StackFrame frame) MethodBase method = frame.GetMethod(); if (method != null) { - if(method.DeclaringType != null) + if (method.DeclaringType != null) m_className = method.DeclaringType.FullName; m_method = new MethodItem(method); } @@ -66,130 +66,130 @@ public StackFrameItem(StackFrame frame) LogLog.Error(declaringType, "An exception ocurred while retreiving stack frame information.", ex); } - // set full info - m_fullInfo = m_className + '.' + m_method.Name + '(' + m_fileName + ':' + m_lineNumber + ')'; - } + // set full info + m_fullInfo = m_className + '.' + m_method.Name + '(' + m_fileName + ':' + m_lineNumber + ')'; + } - #endregion - - #region Public Instance Properties - - /// - /// Gets the fully qualified class name of the caller making the logging - /// request. - /// - /// - /// The fully qualified class name of the caller making the logging - /// request. - /// - /// - /// - /// Gets the fully qualified class name of the caller making the logging - /// request. - /// - /// - public string ClassName - { - get { return m_className; } - } + #endregion - /// - /// Gets the file name of the caller. - /// - /// - /// The file name of the caller. - /// - /// - /// - /// Gets the file name of the caller. - /// - /// - public string FileName - { - get { return m_fileName; } - } + #region Public Instance Properties - /// - /// Gets the line number of the caller. - /// - /// - /// The line number of the caller. - /// - /// - /// - /// Gets the line number of the caller. - /// - /// - public string LineNumber - { - get { return m_lineNumber; } - } + /// + /// Gets the fully qualified class name of the caller making the logging + /// request. + /// + /// + /// The fully qualified class name of the caller making the logging + /// request. + /// + /// + /// + /// Gets the fully qualified class name of the caller making the logging + /// request. + /// + /// + public string ClassName + { + get { return m_className; } + } - /// - /// Gets the method name of the caller. - /// - /// - /// The method name of the caller. - /// - /// - /// - /// Gets the method name of the caller. - /// - /// - public MethodItem Method - { - get { return m_method; } - } + /// + /// Gets the file name of the caller. + /// + /// + /// The file name of the caller. + /// + /// + /// + /// Gets the file name of the caller. + /// + /// + public string FileName + { + get { return m_fileName; } + } - /// - /// Gets all available caller information - /// - /// - /// All available caller information, in the format - /// fully.qualified.classname.of.caller.methodName(Filename:line) - /// - /// - /// - /// Gets all available caller information, in the format - /// fully.qualified.classname.of.caller.methodName(Filename:line) - /// - /// - public string FullInfo - { - get { return m_fullInfo; } - } + /// + /// Gets the line number of the caller. + /// + /// + /// The line number of the caller. + /// + /// + /// + /// Gets the line number of the caller. + /// + /// + public string LineNumber + { + get { return m_lineNumber; } + } + + /// + /// Gets the method name of the caller. + /// + /// + /// The method name of the caller. + /// + /// + /// + /// Gets the method name of the caller. + /// + /// + public MethodItem Method + { + get { return m_method; } + } - #endregion Public Instance Properties + /// + /// Gets all available caller information + /// + /// + /// All available caller information, in the format + /// fully.qualified.classname.of.caller.methodName(Filename:line) + /// + /// + /// + /// Gets all available caller information, in the format + /// fully.qualified.classname.of.caller.methodName(Filename:line) + /// + /// + public string FullInfo + { + get { return m_fullInfo; } + } + + #endregion Public Instance Properties - #region Private Instance Fields + #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 string m_lineNumber; + private readonly string m_fileName; + private readonly string m_className; + private readonly string m_fullInfo; private readonly MethodItem m_method; - #endregion + #endregion - #region Private Static Fields + #region Private Static Fields - /// - /// The fully qualified type of the StackFrameItem class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(StackFrameItem); + /// + /// The fully qualified type of the StackFrameItem class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(StackFrameItem); - /// - /// When location information is not available the constant - /// NA is returned. Current value of this string - /// constant is ?. - /// - private const string NA = "?"; + /// + /// When location information is not available the constant + /// NA is returned. Current value of this string + /// constant is ?. + /// + private const string NA = "?"; - #endregion Private Static Fields - } + #endregion Private Static Fields + } } #endif diff --git a/src/log4net/Core/TimeEvaluator.cs b/src/log4net/Core/TimeEvaluator.cs index 3067f56c..af93e55f 100644 --- a/src/log4net/Core/TimeEvaluator.cs +++ b/src/log4net/Core/TimeEvaluator.cs @@ -21,128 +21,128 @@ namespace log4net.Core { + /// + /// An evaluator that triggers after specified number of seconds. + /// + /// + /// + /// This evaluator will trigger if the specified time period + /// has passed since last check. + /// + /// + /// Robert Sevcik + public class TimeEvaluator : ITriggeringEventEvaluator + { /// - /// An evaluator that triggers after specified number of seconds. + /// The time threshold for triggering in seconds. Zero means it won't trigger at all. /// + private int m_interval; + + /// + /// The UTC time of last check. This gets updated when the object is created and when the evaluator triggers. + /// + private DateTime m_lastTimeUtc; + + /// + /// The default time threshold for triggering in seconds. Zero means it won't trigger at all. + /// + const int DEFAULT_INTERVAL = 0; + + /// + /// Create a new evaluator using the time threshold in seconds. + /// + /// + /// + /// Create a new evaluator using the time threshold in seconds. + /// + /// + /// This evaluator will trigger if the specified time period + /// has passed since last check. + /// + /// + public TimeEvaluator() + : this(DEFAULT_INTERVAL) + { + } + + /// + /// Create a new evaluator using the specified time threshold in seconds. + /// + /// + /// The time threshold in seconds to trigger after. + /// Zero means it won't trigger at all. + /// /// /// + /// Create a new evaluator using the specified time threshold in seconds. + /// + /// /// This evaluator will trigger if the specified time period /// has passed since last check. /// /// - /// Robert Sevcik - public class TimeEvaluator : ITriggeringEventEvaluator + public TimeEvaluator(int interval) { - /// - /// The time threshold for triggering in seconds. Zero means it won't trigger at all. - /// - private int m_interval; + m_interval = interval; + m_lastTimeUtc = DateTime.UtcNow; + } - /// - /// The UTC time of last check. This gets updated when the object is created and when the evaluator triggers. - /// - private DateTime m_lastTimeUtc; + /// + /// The time threshold in seconds to trigger after + /// + /// + /// The time threshold in seconds to trigger after. + /// Zero means it won't trigger at all. + /// + /// + /// + /// This evaluator will trigger if the specified time period + /// has passed since last check. + /// + /// + public int Interval + { + get { return m_interval; } + set { m_interval = value; } + } - /// - /// The default time threshold for triggering in seconds. Zero means it won't trigger at all. - /// - const int DEFAULT_INTERVAL = 0; + /// + /// Is this the triggering event? + /// + /// The event to check + /// This method returns true, if the specified time period + /// has passed since last check.. + /// Otherwise it returns false + /// + /// + /// This evaluator will trigger if the specified time period + /// has passed since last check. + /// + /// + public bool IsTriggeringEvent(LoggingEvent loggingEvent) + { + if (loggingEvent == null) + { + throw new ArgumentNullException("loggingEvent"); + } - /// - /// Create a new evaluator using the time threshold in seconds. - /// - /// - /// - /// Create a new evaluator using the time threshold in seconds. - /// - /// - /// This evaluator will trigger if the specified time period - /// has passed since last check. - /// - /// - public TimeEvaluator() - : this(DEFAULT_INTERVAL) - { - } + // disable the evaluator if threshold is zero + if (m_interval == 0) return false; - /// - /// Create a new evaluator using the specified time threshold in seconds. - /// - /// - /// The time threshold in seconds to trigger after. - /// Zero means it won't trigger at all. - /// - /// - /// - /// Create a new evaluator using the specified time threshold in seconds. - /// - /// - /// This evaluator will trigger if the specified time period - /// has passed since last check. - /// - /// - public TimeEvaluator(int interval) - { - m_interval = interval; - m_lastTimeUtc = DateTime.UtcNow; - } + lock (this) // avoid triggering multiple times + { + TimeSpan passed = DateTime.UtcNow.Subtract(m_lastTimeUtc); - /// - /// The time threshold in seconds to trigger after - /// - /// - /// The time threshold in seconds to trigger after. - /// Zero means it won't trigger at all. - /// - /// - /// - /// This evaluator will trigger if the specified time period - /// has passed since last check. - /// - /// - public int Interval + if (passed.TotalSeconds > m_interval) { - get { return m_interval; } - set { m_interval = value; } + m_lastTimeUtc = DateTime.UtcNow; + return true; } - - /// - /// Is this the triggering event? - /// - /// The event to check - /// This method returns true, if the specified time period - /// has passed since last check.. - /// Otherwise it returns false - /// - /// - /// This evaluator will trigger if the specified time period - /// has passed since last check. - /// - /// - public bool IsTriggeringEvent(LoggingEvent loggingEvent) + else { - if (loggingEvent == null) - { - throw new ArgumentNullException("loggingEvent"); - } - - // disable the evaluator if threshold is zero - if (m_interval == 0) return false; - - lock (this) // avoid triggering multiple times - { - TimeSpan passed = DateTime.UtcNow.Subtract(m_lastTimeUtc); - - if (passed.TotalSeconds > m_interval) - { - m_lastTimeUtc = DateTime.UtcNow; - return true; - } - else - { - return false; - } - } + return false; } + } } + } } diff --git a/src/log4net/Core/WrapperMap.cs b/src/log4net/Core/WrapperMap.cs index e9d6cada..b2b30e5d 100644 --- a/src/log4net/Core/WrapperMap.cs +++ b/src/log4net/Core/WrapperMap.cs @@ -78,7 +78,7 @@ public class WrapperMap /// the specified handler to create the wrapper objects. /// /// - public WrapperMap(WrapperCreationHandler createWrapperHandler) + public WrapperMap(WrapperCreationHandler createWrapperHandler) { m_createWrapperHandler = createWrapperHandler; @@ -113,7 +113,7 @@ public virtual ILoggerWrapper GetWrapper(ILogger logger) return null; } - lock(this) + lock (this) { // Lookup hierarchy in map. Hashtable wrappersMap = (Hashtable)m_repositories[logger.Repository]; @@ -139,7 +139,7 @@ public virtual ILoggerWrapper GetWrapper(ILogger logger) // Create a new wrapper wrapping the logger wrapperObject = CreateNewWrapperObject(logger); - + // Store wrapper logger in map wrappersMap[logger] = wrapperObject; } @@ -165,7 +165,7 @@ public virtual ILoggerWrapper GetWrapper(ILogger logger) /// value being the corresponding . /// /// - protected Hashtable Repositories + protected Hashtable Repositories { get { return this.m_repositories; } } @@ -210,7 +210,7 @@ protected virtual ILoggerWrapper CreateNewWrapperObject(ILogger logger) /// protected virtual void RepositoryShutdown(ILoggerRepository repository) { - lock(this) + lock (this) { // Remove the repository from map m_repositories.Remove(repository); @@ -253,7 +253,7 @@ private void ILoggerRepository_Shutdown(object sender, EventArgs e) /// Internal reference to the delegate used to register for repository shutdown events. /// private readonly LoggerRepositoryShutdownEventHandler m_shutdownHandler; - + #endregion Private Instance Variables } } diff --git a/src/log4net/DateFormatter/AbsoluteTimeDateFormatter.cs b/src/log4net/DateFormatter/AbsoluteTimeDateFormatter.cs index b19a1e0a..d510c566 100644 --- a/src/log4net/DateFormatter/AbsoluteTimeDateFormatter.cs +++ b/src/log4net/DateFormatter/AbsoluteTimeDateFormatter.cs @@ -54,7 +54,7 @@ public class AbsoluteTimeDateFormatter : IDateFormatter protected virtual void FormatDateWithoutMillis(DateTime dateToFormat, StringBuilder buffer) { int hour = dateToFormat.Hour; - if (hour < 10) + if (hour < 10) { buffer.Append('0'); } @@ -62,15 +62,15 @@ protected virtual void FormatDateWithoutMillis(DateTime dateToFormat, StringBuil buffer.Append(':'); int mins = dateToFormat.Minute; - if (mins < 10) + if (mins < 10) { buffer.Append('0'); } buffer.Append(mins); buffer.Append(':'); - + int secs = dateToFormat.Second; - if (secs < 10) + if (secs < 10) { buffer.Append('0'); } @@ -101,71 +101,71 @@ protected virtual void FormatDateWithoutMillis(DateTime dateToFormat, StringBuil /// public virtual void FormatDate(DateTime dateToFormat, TextWriter writer) { - lock (s_lastTimeStrings) + lock (s_lastTimeStrings) + { + // 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 { - // 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()]; - } - - if (timeString == null) - { - // lock so that only one thread can use the buffer and - // update the s_lastTimeToTheSecond and s_lastTimeStrings - - // PERF: Try removing this lock and using a new StringBuilder each time - lock(s_lastTimeBuf) + timeString = (string)s_lastTimeStrings[GetType()]; + } + + if (timeString == null) { - timeString = (string) s_lastTimeStrings[GetType()]; + // lock so that only one thread can use the buffer and + // update the s_lastTimeToTheSecond and s_lastTimeStrings - if (timeString == null) - { - // We are in a new second. - s_lastTimeBuf.Length = 0; + // PERF: Try removing this lock and using a new StringBuilder each time + lock (s_lastTimeBuf) + { + timeString = (string)s_lastTimeStrings[GetType()]; - // Calculate the new string for this second - FormatDateWithoutMillis(dateToFormat, s_lastTimeBuf); + if (timeString == null) + { + // We are in a new second. + s_lastTimeBuf.Length = 0; - // Render the string buffer to a string - timeString = s_lastTimeBuf.ToString(); + // Calculate the new string for this second + FormatDateWithoutMillis(dateToFormat, s_lastTimeBuf); + + // 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 diff --git a/src/log4net/DateFormatter/DateTimeDateFormatter.cs b/src/log4net/DateFormatter/DateTimeDateFormatter.cs index 90d529cd..4a9364b1 100644 --- a/src/log4net/DateFormatter/DateTimeDateFormatter.cs +++ b/src/log4net/DateFormatter/DateTimeDateFormatter.cs @@ -75,15 +75,15 @@ public DateTimeDateFormatter() protected override void FormatDateWithoutMillis(DateTime dateToFormat, StringBuilder buffer) { int day = dateToFormat.Day; - if (day < 10) + if (day < 10) { buffer.Append('0'); } buffer.Append(day); - buffer.Append(' '); + buffer.Append(' '); buffer.Append(m_dateTimeFormatInfo.GetAbbreviatedMonthName(dateToFormat.Month)); - buffer.Append(' '); + buffer.Append(' '); buffer.Append(dateToFormat.Year); buffer.Append(' '); diff --git a/src/log4net/DateFormatter/Iso8601DateFormatter.cs b/src/log4net/DateFormatter/Iso8601DateFormatter.cs index 1ff299f1..a78dbb73 100644 --- a/src/log4net/DateFormatter/Iso8601DateFormatter.cs +++ b/src/log4net/DateFormatter/Iso8601DateFormatter.cs @@ -80,7 +80,7 @@ protected override void FormatDateWithoutMillis(DateTime dateToFormat, StringBui buffer.Append('-'); int day = dateToFormat.Day; - if (day < 10) + if (day < 10) { buffer.Append('0'); } diff --git a/src/log4net/Filter/DenyAllFilter.cs b/src/log4net/Filter/DenyAllFilter.cs index 35c11387..562fbc1c 100644 --- a/src/log4net/Filter/DenyAllFilter.cs +++ b/src/log4net/Filter/DenyAllFilter.cs @@ -65,7 +65,7 @@ public DenyAllFilter() /// as any further filters will be ignored! /// /// - public override FilterDecision Decide(LoggingEvent loggingEvent) + public override FilterDecision Decide(LoggingEvent loggingEvent) { return FilterDecision.Deny; } diff --git a/src/log4net/Filter/FilterDecision.cs b/src/log4net/Filter/FilterDecision.cs index c81a156f..9164eea7 100644 --- a/src/log4net/Filter/FilterDecision.cs +++ b/src/log4net/Filter/FilterDecision.cs @@ -38,7 +38,7 @@ public enum FilterDecision : int /// consulting with the remaining filters, if any, in the chain. /// Deny = -1, - + /// /// This filter is neutral with respect to the log event. /// The remaining filters, if any, should be consulted for a final decision. diff --git a/src/log4net/Filter/FilterSkeleton.cs b/src/log4net/Filter/FilterSkeleton.cs index 158d6355..3bab1166 100644 --- a/src/log4net/Filter/FilterSkeleton.cs +++ b/src/log4net/Filter/FilterSkeleton.cs @@ -104,7 +104,7 @@ public abstract class FilterSkeleton : IFilter /// however this method must still be called. /// /// - public virtual void ActivateOptions() + public virtual void ActivateOptions() { } diff --git a/src/log4net/Filter/LevelMatchFilter.cs b/src/log4net/Filter/LevelMatchFilter.cs index 50d291f0..e257286d 100644 --- a/src/log4net/Filter/LevelMatchFilter.cs +++ b/src/log4net/Filter/LevelMatchFilter.cs @@ -122,14 +122,14 @@ public Level LevelToMatch /// the result will be . /// /// - public override FilterDecision Decide(LoggingEvent loggingEvent) + public override FilterDecision Decide(LoggingEvent loggingEvent) { if (loggingEvent == null) { throw new ArgumentNullException("loggingEvent"); } - if (m_levelToMatch != null && m_levelToMatch == loggingEvent.Level) + if (m_levelToMatch != null && m_levelToMatch == loggingEvent.Level) { // Found match return m_acceptOnMatch ? FilterDecision.Accept : FilterDecision.Deny; diff --git a/src/log4net/Filter/LevelRangeFilter.cs b/src/log4net/Filter/LevelRangeFilter.cs index e2bb676c..f29c7fa3 100644 --- a/src/log4net/Filter/LevelRangeFilter.cs +++ b/src/log4net/Filter/LevelRangeFilter.cs @@ -142,38 +142,38 @@ public Level LevelMax /// is returned. /// /// - public override FilterDecision Decide(LoggingEvent loggingEvent) + public override FilterDecision Decide(LoggingEvent loggingEvent) { if (loggingEvent == null) { throw new ArgumentNullException("loggingEvent"); } - if (m_levelMin != null) + if (m_levelMin != null) { - if (loggingEvent.Level < m_levelMin) + if (loggingEvent.Level < m_levelMin) { // level of event is less than minimum return FilterDecision.Deny; } } - if (m_levelMax != null) + if (m_levelMax != null) { - if (loggingEvent.Level > m_levelMax) + if (loggingEvent.Level > m_levelMax) { // level of event is greater than maximum return FilterDecision.Deny; } } - if (m_acceptOnMatch) + if (m_acceptOnMatch) { // this filter set up to bypass later filters and always return // accept if level in range return FilterDecision.Accept; } - else + else { // event is ok for this filter; allow later filters to have a look.. return FilterDecision.Neutral; diff --git a/src/log4net/Filter/LoggerMatchFilter.cs b/src/log4net/Filter/LoggerMatchFilter.cs index 0bc5e65d..8f57744e 100644 --- a/src/log4net/Filter/LoggerMatchFilter.cs +++ b/src/log4net/Filter/LoggerMatchFilter.cs @@ -129,7 +129,7 @@ public string LoggerToMatch /// is returned. /// /// - public override FilterDecision Decide(LoggingEvent loggingEvent) + public override FilterDecision Decide(LoggingEvent loggingEvent) { if (loggingEvent == null) { @@ -137,14 +137,14 @@ public override FilterDecision Decide(LoggingEvent loggingEvent) } // Check if we have been setup to filter - if ((m_loggerToMatch != null && m_loggerToMatch.Length != 0) && + if ((m_loggerToMatch != null && m_loggerToMatch.Length != 0) && loggingEvent.LoggerName.StartsWith(m_loggerToMatch)) { // we've got a match - if (m_acceptOnMatch) + if (m_acceptOnMatch) { return FilterDecision.Accept; - } + } return FilterDecision.Deny; } else diff --git a/src/log4net/Filter/PropertyFilter.cs b/src/log4net/Filter/PropertyFilter.cs index b8815d17..c4438074 100644 --- a/src/log4net/Filter/PropertyFilter.cs +++ b/src/log4net/Filter/PropertyFilter.cs @@ -94,7 +94,7 @@ public string Key /// is returned. /// /// - public override FilterDecision Decide(LoggingEvent loggingEvent) + public override FilterDecision Decide(LoggingEvent loggingEvent) { if (loggingEvent == null) { @@ -123,7 +123,7 @@ public override FilterDecision Decide(LoggingEvent loggingEvent) // to continue processing return FilterDecision.Neutral; } - + // Firstly check if we are matching using a regex if (m_regexToMatch != null) { @@ -132,29 +132,29 @@ public override FilterDecision Decide(LoggingEvent loggingEvent) { // No match, continue processing return FilterDecision.Neutral; - } + } // we've got a match - if (m_acceptOnMatch) + if (m_acceptOnMatch) { return FilterDecision.Accept; - } + } return FilterDecision.Deny; } else if (m_stringToMatch != null) { // Check substring match - if (msg.IndexOf(m_stringToMatch) == -1) + if (msg.IndexOf(m_stringToMatch) == -1) { // No match, continue processing return FilterDecision.Neutral; - } + } // we've got a match - if (m_acceptOnMatch) + if (m_acceptOnMatch) { return FilterDecision.Accept; - } + } return FilterDecision.Deny; } return FilterDecision.Neutral; diff --git a/src/log4net/Filter/StringMatchFilter.cs b/src/log4net/Filter/StringMatchFilter.cs index b2695861..0c4bb7eb 100644 --- a/src/log4net/Filter/StringMatchFilter.cs +++ b/src/log4net/Filter/StringMatchFilter.cs @@ -91,7 +91,7 @@ public StringMatchFilter() /// must be called again. /// /// - public override void ActivateOptions() + public override void ActivateOptions() { if (m_stringRegexToMatch != null) { @@ -186,7 +186,7 @@ public string RegexToMatch /// is returned. /// /// - public override FilterDecision Decide(LoggingEvent loggingEvent) + public override FilterDecision Decide(LoggingEvent loggingEvent) { if (loggingEvent == null) { @@ -202,7 +202,7 @@ public override FilterDecision Decide(LoggingEvent loggingEvent) // to continue processing return FilterDecision.Neutral; } - + // Firstly check if we are matching using a regex if (m_regexToMatch != null) { @@ -211,29 +211,29 @@ public override FilterDecision Decide(LoggingEvent loggingEvent) { // No match, continue processing return FilterDecision.Neutral; - } + } // we've got a match - if (m_acceptOnMatch) + if (m_acceptOnMatch) { return FilterDecision.Accept; - } + } return FilterDecision.Deny; } else if (m_stringToMatch != null) { // Check substring match - if (msg.IndexOf(m_stringToMatch) == -1) + if (msg.IndexOf(m_stringToMatch) == -1) { // No match, continue processing return FilterDecision.Neutral; - } + } // we've got a match - if (m_acceptOnMatch) + if (m_acceptOnMatch) { return FilterDecision.Accept; - } + } return FilterDecision.Deny; } return FilterDecision.Neutral; diff --git a/src/log4net/ILog.cs b/src/log4net/ILog.cs index ed39c164..5558b79f 100644 --- a/src/log4net/ILog.cs +++ b/src/log4net/ILog.cs @@ -91,7 +91,7 @@ public interface ILog : ILoggerWrapper /// /// void Debug(object message); - + /// /// Log a message object with the level including /// the stack trace of the passed @@ -128,7 +128,7 @@ public interface ILog : ILoggerWrapper /// /// /// - void DebugFormat(string format, params object[] args); + void DebugFormat(string format, params object[] args); /// /// Logs a formatted message string with the level. @@ -149,7 +149,7 @@ public interface ILog : ILoggerWrapper /// /// /// - void DebugFormat(string format, object arg0); + void DebugFormat(string format, object arg0); /// /// Logs a formatted message string with the level. @@ -171,7 +171,7 @@ public interface ILog : ILoggerWrapper /// /// /// - void DebugFormat(string format, object arg0, object arg1); + void DebugFormat(string format, object arg0, object arg1); /// /// Logs a formatted message string with the level. @@ -194,7 +194,7 @@ public interface ILog : ILoggerWrapper /// /// /// - void DebugFormat(string format, object arg0, object arg1, object arg2); + void DebugFormat(string format, object arg0, object arg1, object arg2); /// /// Logs a formatted message string with the level. @@ -244,7 +244,7 @@ public interface ILog : ILoggerWrapper /// /// void Info(object message); - + /// /// Logs a message object with the INFO level including /// the stack trace of the passed @@ -302,7 +302,7 @@ public interface ILog : ILoggerWrapper /// /// /// - void InfoFormat(string format, object arg0); + void InfoFormat(string format, object arg0); /// /// Logs a formatted message string with the level. @@ -324,7 +324,7 @@ public interface ILog : ILoggerWrapper /// /// /// - void InfoFormat(string format, object arg0, object arg1); + void InfoFormat(string format, object arg0, object arg1); /// /// Logs a formatted message string with the level. @@ -347,7 +347,7 @@ public interface ILog : ILoggerWrapper /// /// /// - void InfoFormat(string format, object arg0, object arg1, object arg2); + void InfoFormat(string format, object arg0, object arg1, object arg2); /// /// Logs a formatted message string with the level. @@ -397,7 +397,7 @@ public interface ILog : ILoggerWrapper /// /// void Warn(object message); - + /// /// Log a message object with the level including /// the stack trace of the passed @@ -455,7 +455,7 @@ public interface ILog : ILoggerWrapper /// /// /// - void WarnFormat(string format, object arg0); + void WarnFormat(string format, object arg0); /// /// Logs a formatted message string with the level. @@ -477,7 +477,7 @@ public interface ILog : ILoggerWrapper /// /// /// - void WarnFormat(string format, object arg0, object arg1); + void WarnFormat(string format, object arg0, object arg1); /// /// Logs a formatted message string with the level. @@ -500,7 +500,7 @@ public interface ILog : ILoggerWrapper /// /// /// - void WarnFormat(string format, object arg0, object arg1, object arg2); + void WarnFormat(string format, object arg0, object arg1, object arg2); /// /// Logs a formatted message string with the level. @@ -608,7 +608,7 @@ public interface ILog : ILoggerWrapper /// /// /// - void ErrorFormat(string format, object arg0); + void ErrorFormat(string format, object arg0); /// /// Logs a formatted message string with the level. @@ -630,7 +630,7 @@ public interface ILog : ILoggerWrapper /// /// /// - void ErrorFormat(string format, object arg0, object arg1); + void ErrorFormat(string format, object arg0, object arg1); /// /// Logs a formatted message string with the level. @@ -653,7 +653,7 @@ public interface ILog : ILoggerWrapper /// /// /// - void ErrorFormat(string format, object arg0, object arg1, object arg2); + void ErrorFormat(string format, object arg0, object arg1, object arg2); /// /// Logs a formatted message string with the level. @@ -703,7 +703,7 @@ public interface ILog : ILoggerWrapper /// /// void Fatal(object message); - + /// /// Log a message object with the level including /// the stack trace of the passed @@ -761,7 +761,7 @@ public interface ILog : ILoggerWrapper /// /// /// - void FatalFormat(string format, object arg0); + void FatalFormat(string format, object arg0); /// /// Logs a formatted message string with the level. @@ -783,7 +783,7 @@ public interface ILog : ILoggerWrapper /// /// /// - void FatalFormat(string format, object arg0, object arg1); + void FatalFormat(string format, object arg0, object arg1); /// /// Logs a formatted message string with the level. @@ -806,7 +806,7 @@ public interface ILog : ILoggerWrapper /// /// /// - void FatalFormat(string format, object arg0, object arg1, object arg2); + void FatalFormat(string format, object arg0, object arg1, object arg2); /// /// Logs a formatted message string with the level. @@ -900,7 +900,7 @@ public interface ILog : ILoggerWrapper /// /// bool IsDebugEnabled { get; } - + /// /// Checks if this logger is enabled for the level. /// diff --git a/src/log4net/Layout/DynamicPatternLayout.cs b/src/log4net/Layout/DynamicPatternLayout.cs index 2f3e0022..ef6c4bc9 100644 --- a/src/log4net/Layout/DynamicPatternLayout.cs +++ b/src/log4net/Layout/DynamicPatternLayout.cs @@ -50,7 +50,7 @@ namespace log4net.Layout /// </layout> /// /// - public class DynamicPatternLayout: PatternLayout + public class DynamicPatternLayout : PatternLayout { #region Member Variables /// @@ -61,7 +61,7 @@ public class DynamicPatternLayout: PatternLayout /// /// The footer PatternString /// - private PatternString m_footerPatternString = new PatternString(""); + private PatternString m_footerPatternString = new PatternString(""); #endregion #region Constructors @@ -84,7 +84,7 @@ public DynamicPatternLayout() /// the pattern to use /// /// - public DynamicPatternLayout (string pattern) + public DynamicPatternLayout(string pattern) : base(pattern) { } diff --git a/src/log4net/Layout/ExceptionLayout.cs b/src/log4net/Layout/ExceptionLayout.cs index 2748b0db..05c111ad 100644 --- a/src/log4net/Layout/ExceptionLayout.cs +++ b/src/log4net/Layout/ExceptionLayout.cs @@ -58,7 +58,7 @@ public ExceptionLayout() } #endregion - + #region Implementation of IOptionHandler /// @@ -73,7 +73,7 @@ public ExceptionLayout() /// This method does nothing as options become effective immediately. /// /// - public override void ActivateOptions() + public override void ActivateOptions() { // nothing to do. } @@ -93,7 +93,7 @@ public override void ActivateOptions() /// The exception string is retrieved from . /// /// - public override void Format(TextWriter writer, LoggingEvent loggingEvent) + public override void Format(TextWriter writer, LoggingEvent loggingEvent) { if (loggingEvent == null) { diff --git a/src/log4net/Layout/LayoutSkeleton.cs b/src/log4net/Layout/LayoutSkeleton.cs index e61374de..348eb075 100644 --- a/src/log4net/Layout/LayoutSkeleton.cs +++ b/src/log4net/Layout/LayoutSkeleton.cs @@ -221,8 +221,8 @@ public virtual string Footer /// value is true, this layout does not handle the exception. /// /// - public virtual bool IgnoresException - { + public virtual bool IgnoresException + { get { return m_ignoresException; } set { m_ignoresException = value; } } diff --git a/src/log4net/Layout/Pattern/AppDomainPatternConverter.cs b/src/log4net/Layout/Pattern/AppDomainPatternConverter.cs index 83eb2d5f..79c73222 100644 --- a/src/log4net/Layout/Pattern/AppDomainPatternConverter.cs +++ b/src/log4net/Layout/Pattern/AppDomainPatternConverter.cs @@ -35,7 +35,7 @@ namespace log4net.Layout.Pattern /// /// Daniel Cazzulino /// Nicko Cadell - internal sealed class AppDomainPatternConverter : PatternLayoutConverter + internal sealed class AppDomainPatternConverter : PatternLayoutConverter { /// /// Write the event appdomain name to the output diff --git a/src/log4net/Layout/Pattern/AspNetRequestPatternConverter.cs b/src/log4net/Layout/Pattern/AspNetRequestPatternConverter.cs index 2be50431..01b203e9 100644 --- a/src/log4net/Layout/Pattern/AspNetRequestPatternConverter.cs +++ b/src/log4net/Layout/Pattern/AspNetRequestPatternConverter.cs @@ -55,15 +55,18 @@ internal sealed class AspNetRequestPatternConverter : AspNetPatternLayoutConvert /// protected override void Convert(TextWriter writer, LoggingEvent loggingEvent, HttpContext httpContext) { - HttpRequest request = null; - try { - request = httpContext.Request; - } catch (HttpException) { - // likely a case of running in IIS integrated mode - // when inside an Application_Start event. - // treat it like a case of the Request - // property returning null - } + HttpRequest request = null; + try + { + request = httpContext.Request; + } + catch (HttpException) + { + // likely a case of running in IIS integrated mode + // when inside an Application_Start event. + // treat it like a case of the Request + // property returning null + } if (request != null) { diff --git a/src/log4net/Layout/Pattern/DatePatternConverter.cs b/src/log4net/Layout/Pattern/DatePatternConverter.cs index a111b8f4..7f24bbbe 100644 --- a/src/log4net/Layout/Pattern/DatePatternConverter.cs +++ b/src/log4net/Layout/Pattern/DatePatternConverter.cs @@ -92,7 +92,7 @@ internal class DatePatternConverter : PatternLayoutConverter, IOptionHandler /// /// protected IDateFormatter m_dateFormatter; - + #region Implementation of IOptionHandler /// @@ -133,15 +133,15 @@ public void ActivateOptions() } else { - try + try { m_dateFormatter = new SimpleDateFormatter(dateFormatStr); } - catch (Exception e) + catch (Exception e) { - LogLog.Error(declaringType, "Could not instantiate SimpleDateFormatter with ["+dateFormatStr+"]", e); + LogLog.Error(declaringType, "Could not instantiate SimpleDateFormatter with [" + dateFormatStr + "]", e); m_dateFormatter = new Iso8601DateFormatter(); - } + } } } @@ -163,27 +163,27 @@ public void ActivateOptions() /// protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) { - try + try { m_dateFormatter.FormatDate(loggingEvent.TimeStamp, writer); } - catch (Exception ex) + catch (Exception ex) { LogLog.Error(declaringType, "Error occurred while converting date.", ex); } } - #region Private Static Fields + #region Private Static Fields - /// - /// The fully qualified type of the DatePatternConverter class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(DatePatternConverter); + /// + /// The fully qualified type of the DatePatternConverter class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(DatePatternConverter); - #endregion Private Static Fields + #endregion Private Static Fields } } diff --git a/src/log4net/Layout/Pattern/ExceptionPatternConverter.cs b/src/log4net/Layout/Pattern/ExceptionPatternConverter.cs index 275959be..b2262d41 100644 --- a/src/log4net/Layout/Pattern/ExceptionPatternConverter.cs +++ b/src/log4net/Layout/Pattern/ExceptionPatternConverter.cs @@ -40,7 +40,7 @@ namespace log4net.Layout.Pattern /// /// /// Nicko Cadell - internal sealed class ExceptionPatternConverter : PatternLayoutConverter + internal sealed class ExceptionPatternConverter : PatternLayoutConverter { /// /// Default constructor @@ -123,7 +123,7 @@ protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) else { string exceptionString = loggingEvent.GetExceptionString(); - if (exceptionString != null && exceptionString.Length > 0) + if (exceptionString != null && exceptionString.Length > 0) { writer.WriteLine(exceptionString); } diff --git a/src/log4net/Layout/Pattern/FileLocationPatternConverter.cs b/src/log4net/Layout/Pattern/FileLocationPatternConverter.cs index 7f87e755..a1d818d0 100644 --- a/src/log4net/Layout/Pattern/FileLocationPatternConverter.cs +++ b/src/log4net/Layout/Pattern/FileLocationPatternConverter.cs @@ -35,7 +35,7 @@ namespace log4net.Layout.Pattern /// /// /// Nicko Cadell - internal sealed class FileLocationPatternConverter : PatternLayoutConverter + internal sealed class FileLocationPatternConverter : PatternLayoutConverter { /// /// Write the caller location file name to the output diff --git a/src/log4net/Layout/Pattern/FullLocationPatternConverter.cs b/src/log4net/Layout/Pattern/FullLocationPatternConverter.cs index bb39c0d4..1da7519d 100644 --- a/src/log4net/Layout/Pattern/FullLocationPatternConverter.cs +++ b/src/log4net/Layout/Pattern/FullLocationPatternConverter.cs @@ -34,7 +34,7 @@ namespace log4net.Layout.Pattern /// /// /// Nicko Cadell - internal sealed class FullLocationPatternConverter : PatternLayoutConverter + internal sealed class FullLocationPatternConverter : PatternLayoutConverter { /// /// Write the caller location info to the output @@ -48,7 +48,7 @@ internal sealed class FullLocationPatternConverter : PatternLayoutConverter /// protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) { - writer.Write( loggingEvent.LocationInformation.FullInfo ); + writer.Write(loggingEvent.LocationInformation.FullInfo); } } } diff --git a/src/log4net/Layout/Pattern/IdentityPatternConverter.cs b/src/log4net/Layout/Pattern/IdentityPatternConverter.cs index c13a7885..62db1c3b 100644 --- a/src/log4net/Layout/Pattern/IdentityPatternConverter.cs +++ b/src/log4net/Layout/Pattern/IdentityPatternConverter.cs @@ -36,7 +36,7 @@ namespace log4net.Layout.Pattern /// /// Daniel Cazzulino /// Nicko Cadell - internal sealed class IdentityPatternConverter : PatternLayoutConverter + internal sealed class IdentityPatternConverter : PatternLayoutConverter { /// /// Writes the event identity to the output diff --git a/src/log4net/Layout/Pattern/LevelPatternConverter.cs b/src/log4net/Layout/Pattern/LevelPatternConverter.cs index 75b57ec2..2e756935 100644 --- a/src/log4net/Layout/Pattern/LevelPatternConverter.cs +++ b/src/log4net/Layout/Pattern/LevelPatternConverter.cs @@ -35,7 +35,7 @@ namespace log4net.Layout.Pattern /// /// /// Nicko Cadell - internal sealed class LevelPatternConverter : PatternLayoutConverter + internal sealed class LevelPatternConverter : PatternLayoutConverter { /// /// Write the event level to the output @@ -50,7 +50,7 @@ internal sealed class LevelPatternConverter : PatternLayoutConverter /// protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) { - writer.Write( loggingEvent.Level.DisplayName ); + writer.Write(loggingEvent.Level.DisplayName); } } } diff --git a/src/log4net/Layout/Pattern/LineLocationPatternConverter.cs b/src/log4net/Layout/Pattern/LineLocationPatternConverter.cs index b9ce0a3d..d1f3e3a7 100644 --- a/src/log4net/Layout/Pattern/LineLocationPatternConverter.cs +++ b/src/log4net/Layout/Pattern/LineLocationPatternConverter.cs @@ -35,7 +35,7 @@ namespace log4net.Layout.Pattern /// /// /// Nicko Cadell - internal sealed class LineLocationPatternConverter : PatternLayoutConverter + internal sealed class LineLocationPatternConverter : PatternLayoutConverter { /// /// Write the caller location line number to the output diff --git a/src/log4net/Layout/Pattern/LoggerPatternConverter.cs b/src/log4net/Layout/Pattern/LoggerPatternConverter.cs index 087ab013..fe5845a6 100644 --- a/src/log4net/Layout/Pattern/LoggerPatternConverter.cs +++ b/src/log4net/Layout/Pattern/LoggerPatternConverter.cs @@ -34,7 +34,7 @@ namespace log4net.Layout.Pattern /// /// /// Nicko Cadell - internal sealed class LoggerPatternConverter : NamedPatternConverter + internal sealed class LoggerPatternConverter : NamedPatternConverter { /// /// Gets the fully qualified name of the logger @@ -46,7 +46,7 @@ internal sealed class LoggerPatternConverter : NamedPatternConverter /// Returns the of the . /// /// - protected override string GetFullyQualifiedName(LoggingEvent loggingEvent) + protected override string GetFullyQualifiedName(LoggingEvent loggingEvent) { return loggingEvent.LoggerName; } diff --git a/src/log4net/Layout/Pattern/MessagePatternConverter.cs b/src/log4net/Layout/Pattern/MessagePatternConverter.cs index 25fc4210..d9cf372b 100644 --- a/src/log4net/Layout/Pattern/MessagePatternConverter.cs +++ b/src/log4net/Layout/Pattern/MessagePatternConverter.cs @@ -35,7 +35,7 @@ namespace log4net.Layout.Pattern /// /// /// Nicko Cadell - internal sealed class MessagePatternConverter : PatternLayoutConverter + internal sealed class MessagePatternConverter : PatternLayoutConverter { /// /// Writes the event message to the output diff --git a/src/log4net/Layout/Pattern/MethodLocationPatternConverter.cs b/src/log4net/Layout/Pattern/MethodLocationPatternConverter.cs index cbbbc6df..3c935d50 100644 --- a/src/log4net/Layout/Pattern/MethodLocationPatternConverter.cs +++ b/src/log4net/Layout/Pattern/MethodLocationPatternConverter.cs @@ -35,7 +35,7 @@ namespace log4net.Layout.Pattern /// /// /// Nicko Cadell - internal sealed class MethodLocationPatternConverter : PatternLayoutConverter + internal sealed class MethodLocationPatternConverter : PatternLayoutConverter { /// /// Write the method name to the output diff --git a/src/log4net/Layout/Pattern/NamedPatternConverter.cs b/src/log4net/Layout/Pattern/NamedPatternConverter.cs index 2fba1f55..8512a9ac 100644 --- a/src/log4net/Layout/Pattern/NamedPatternConverter.cs +++ b/src/log4net/Layout/Pattern/NamedPatternConverter.cs @@ -68,7 +68,7 @@ public void ActivateOptions() { m_precision = 0; - if (Option != null) + if (Option != null) { string optStr = Option.Trim(); if (optStr.Length > 0) @@ -76,7 +76,7 @@ public void ActivateOptions() int precisionVal; if (SystemInfo.TryParse(optStr, out precisionVal)) { - if (precisionVal <= 0) + if (precisionVal <= 0) { LogLog.Error(declaringType, "NamedPatternConverter: Precision option (" + optStr + ") isn't a positive integer."); } @@ -84,7 +84,7 @@ public void ActivateOptions() { m_precision = precisionVal; } - } + } else { LogLog.Error(declaringType, "NamedPatternConverter: Precision option \"" + optStr + "\" not a decimal integer."); @@ -110,7 +110,7 @@ public void ActivateOptions() /// /// protected abstract string GetFullyQualifiedName(LoggingEvent loggingEvent); - + /// /// Convert the pattern to the rendered message /// @@ -127,45 +127,45 @@ protected sealed override void Convert(TextWriter writer, LoggingEvent loggingEv { writer.Write(name); } - else + else { int len = name.Length; - string trailingDot = string.Empty; - if (name.EndsWith(DOT)) - { - trailingDot = DOT; - name = name.Substring(0, len - 1); - len--; - } + string trailingDot = string.Empty; + if (name.EndsWith(DOT)) + { + trailingDot = DOT; + name = name.Substring(0, len - 1); + len--; + } - int end = name.LastIndexOf(DOT); - for(int i = 1; end > 0 && i < m_precision; i++) + int end = name.LastIndexOf(DOT); + for (int i = 1; end > 0 && i < m_precision; i++) + { + end = name.LastIndexOf('.', end - 1); + } + if (end == -1) + { + writer.Write(name + trailingDot); + } + else { - end = name.LastIndexOf('.', end - 1); - } - if (end == -1) - { - writer.Write(name + trailingDot); - } - else - { - writer.Write(name.Substring(end + 1, len - end - 1) + trailingDot); - } - } + writer.Write(name.Substring(end + 1, len - end - 1) + trailingDot); + } + } } - #region Private Static Fields + #region Private Static Fields - /// - /// The fully qualified type of the NamedPatternConverter class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(NamedPatternConverter); + /// + /// The fully qualified type of the NamedPatternConverter class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(NamedPatternConverter); - private const string DOT = "."; - #endregion Private Static Fields + private const string DOT = "."; + #endregion Private Static Fields } } diff --git a/src/log4net/Layout/Pattern/NdcPatternConverter.cs b/src/log4net/Layout/Pattern/NdcPatternConverter.cs index edf1ff10..a64dbb98 100644 --- a/src/log4net/Layout/Pattern/NdcPatternConverter.cs +++ b/src/log4net/Layout/Pattern/NdcPatternConverter.cs @@ -37,7 +37,7 @@ namespace log4net.Layout.Pattern /// /// /// Nicko Cadell - internal sealed class NdcPatternConverter : PatternLayoutConverter + internal sealed class NdcPatternConverter : PatternLayoutConverter { /// /// Write the event NDC to the output diff --git a/src/log4net/Layout/Pattern/PatternLayoutConverter.cs b/src/log4net/Layout/Pattern/PatternLayoutConverter.cs index 4886f7fd..23371496 100644 --- a/src/log4net/Layout/Pattern/PatternLayoutConverter.cs +++ b/src/log4net/Layout/Pattern/PatternLayoutConverter.cs @@ -45,8 +45,8 @@ public abstract class PatternLayoutConverter : PatternConverter /// /// Initializes a new instance of the class. /// - protected PatternLayoutConverter() - { + protected PatternLayoutConverter() + { } #endregion Protected Instance Constructors @@ -69,8 +69,8 @@ protected PatternLayoutConverter() /// value is true, this converter does not handle the exception. /// /// - public virtual bool IgnoresException - { + public virtual bool IgnoresException + { get { return m_ignoresException; } set { m_ignoresException = value; } } @@ -106,7 +106,7 @@ protected override void Convert(TextWriter writer, object state) } else { - throw new ArgumentException("state must be of type ["+typeof(LoggingEvent).FullName+"]", "state"); + throw new ArgumentException("state must be of type [" + typeof(LoggingEvent).FullName + "]", "state"); } } diff --git a/src/log4net/Layout/Pattern/PropertyPatternConverter.cs b/src/log4net/Layout/Pattern/PropertyPatternConverter.cs index 1857f033..bb66c961 100644 --- a/src/log4net/Layout/Pattern/PropertyPatternConverter.cs +++ b/src/log4net/Layout/Pattern/PropertyPatternConverter.cs @@ -42,7 +42,7 @@ namespace log4net.Layout.Pattern /// /// /// Nicko Cadell - internal sealed class PropertyPatternConverter : PatternLayoutConverter + internal sealed class PropertyPatternConverter : PatternLayoutConverter { /// /// Write the property value to the output diff --git a/src/log4net/Layout/Pattern/RelativeTimePatternConverter.cs b/src/log4net/Layout/Pattern/RelativeTimePatternConverter.cs index 70204007..29f79822 100644 --- a/src/log4net/Layout/Pattern/RelativeTimePatternConverter.cs +++ b/src/log4net/Layout/Pattern/RelativeTimePatternConverter.cs @@ -34,7 +34,7 @@ namespace log4net.Layout.Pattern /// /// /// Nicko Cadell - internal sealed class RelativeTimePatternConverter : PatternLayoutConverter + internal sealed class RelativeTimePatternConverter : PatternLayoutConverter { /// /// Write the relative time to the output @@ -50,7 +50,7 @@ internal sealed class RelativeTimePatternConverter : PatternLayoutConverter /// protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) { - writer.Write( TimeDifferenceInMillis(LoggingEvent.StartTimeUtc, loggingEvent.TimeStampUtc).ToString(System.Globalization.NumberFormatInfo.InvariantInfo) ); + writer.Write(TimeDifferenceInMillis(LoggingEvent.StartTimeUtc, loggingEvent.TimeStampUtc).ToString(System.Globalization.NumberFormatInfo.InvariantInfo)); } /// diff --git a/src/log4net/Layout/Pattern/StackTraceDetailPatternConverter.cs b/src/log4net/Layout/Pattern/StackTraceDetailPatternConverter.cs index 9e020cb3..a97a1b5a 100644 --- a/src/log4net/Layout/Pattern/StackTraceDetailPatternConverter.cs +++ b/src/log4net/Layout/Pattern/StackTraceDetailPatternConverter.cs @@ -28,63 +28,63 @@ namespace log4net.Layout.Pattern { - /// - /// Write the caller stack frames to the output - /// - /// - /// - /// Writes the to the output writer, using format: - /// type3.MethodCall3(type param,...) > type2.MethodCall2(type param,...) > type1.MethodCall1(type param,...) - /// - /// - /// Adam Davies - internal class StackTraceDetailPatternConverter : StackTracePatternConverter + /// + /// Write the caller stack frames to the output + /// + /// + /// + /// Writes the to the output writer, using format: + /// type3.MethodCall3(type param,...) > type2.MethodCall2(type param,...) > type1.MethodCall1(type param,...) + /// + /// + /// Adam Davies + internal class StackTraceDetailPatternConverter : StackTracePatternConverter + { + internal override string GetMethodInformation(MethodItem method) { - internal override string GetMethodInformation(MethodItem method) - { - string returnValue=""; + string returnValue = ""; - try - { - string param = ""; - string[] names = method.Parameters; - StringBuilder sb = new StringBuilder(); - if (names != null && names.GetUpperBound(0) > 0) - { - for (int i = 0; i <= names.GetUpperBound(0); i++) - { - sb.AppendFormat("{0}, ", names[i]); - } - } + try + { + string param = ""; + string[] names = method.Parameters; + StringBuilder sb = new StringBuilder(); + if (names != null && names.GetUpperBound(0) > 0) + { + for (int i = 0; i <= names.GetUpperBound(0); i++) + { + sb.AppendFormat("{0}, ", names[i]); + } + } - if (sb.Length > 0) - { - sb.Remove(sb.Length - 2, 2); - param = sb.ToString(); - } + if (sb.Length > 0) + { + sb.Remove(sb.Length - 2, 2); + param = sb.ToString(); + } - returnValue=base.GetMethodInformation(method) + "(" + param + ")"; - } - catch (Exception ex) - { - LogLog.Error(declaringType, "An exception ocurred while retreiving method information.", ex); - } + returnValue = base.GetMethodInformation(method) + "(" + param + ")"; + } + catch (Exception ex) + { + LogLog.Error(declaringType, "An exception ocurred while retreiving method information.", ex); + } - return returnValue; - } + return returnValue; + } - #region Private Static Fields + #region Private Static Fields - /// - /// The fully qualified type of the StackTraceDetailPatternConverter class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(StackTracePatternConverter); + /// + /// The fully qualified type of the StackTraceDetailPatternConverter class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(StackTracePatternConverter); - #endregion Private Static Fields - } + #endregion Private Static Fields + } } #endif // !NETCF && NET_2_0 \ No newline at end of file diff --git a/src/log4net/Layout/Pattern/StackTracePatternConverter.cs b/src/log4net/Layout/Pattern/StackTracePatternConverter.cs index 022113cd..df3ccb5d 100644 --- a/src/log4net/Layout/Pattern/StackTracePatternConverter.cs +++ b/src/log4net/Layout/Pattern/StackTracePatternConverter.cs @@ -38,7 +38,7 @@ namespace log4net.Layout.Pattern internal class StackTracePatternConverter : PatternLayoutConverter, IOptionHandler { private int m_stackFrameLevel = 1; - + /// /// Initialize the converter /// @@ -59,14 +59,14 @@ public void ActivateOptions() { if (Option == null) return; - + string optStr = Option.Trim(); if (optStr.Length != 0) { int stackLevelVal; if (SystemInfo.TryParse(optStr, out stackLevelVal)) { - if (stackLevelVal <= 0) + if (stackLevelVal <= 0) { LogLog.Error(declaringType, "StackTracePatternConverter: StackeFrameLevel option (" + optStr + ") isn't a positive integer."); } @@ -74,14 +74,14 @@ public void ActivateOptions() { m_stackFrameLevel = stackLevelVal; } - } + } else { LogLog.Error(declaringType, "StackTracePatternConverter: StackFrameLevel option \"" + optStr + "\" not a decimal integer."); } } } - + /// /// Write the strack frames to the output /// @@ -100,7 +100,7 @@ protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) LogLog.Error(declaringType, "loggingEvent.LocationInformation.StackFrames was null or empty."); return; } - + int stackFrameIndex = m_stackFrameLevel - 1; while (stackFrameIndex >= 0) { @@ -109,41 +109,41 @@ protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) stackFrameIndex--; continue; } - + StackFrameItem stackFrame = stackframes[stackFrameIndex]; - writer.Write("{0}.{1}", stackFrame.ClassName, GetMethodInformation(stackFrame.Method)); + writer.Write("{0}.{1}", stackFrame.ClassName, GetMethodInformation(stackFrame.Method)); if (stackFrameIndex > 0) { - // TODO: make this user settable? + // TODO: make this user settable? writer.Write(" > "); } stackFrameIndex--; } } - /// - /// Returns the Name of the method - /// - /// - /// This method was created, so this class could be used as a base class for StackTraceDetailPatternConverter - /// string - internal virtual string GetMethodInformation(MethodItem method) - { - return method.Name; - } - + /// + /// Returns the Name of the method + /// + /// + /// This method was created, so this class could be used as a base class for StackTraceDetailPatternConverter + /// string + internal virtual string GetMethodInformation(MethodItem method) + { + return method.Name; + } + #region Private Static Fields - /// - /// The fully qualified type of the StackTracePatternConverter class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(StackTracePatternConverter); + /// + /// The fully qualified type of the StackTracePatternConverter class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(StackTracePatternConverter); - #endregion Private Static Fields + #endregion Private Static Fields } } #endif // !NETCF && NET_2_0 diff --git a/src/log4net/Layout/Pattern/ThreadPatternConverter.cs b/src/log4net/Layout/Pattern/ThreadPatternConverter.cs index faae9a95..4d5ce45a 100644 --- a/src/log4net/Layout/Pattern/ThreadPatternConverter.cs +++ b/src/log4net/Layout/Pattern/ThreadPatternConverter.cs @@ -34,7 +34,7 @@ namespace log4net.Layout.Pattern /// /// /// Nicko Cadell - internal sealed class ThreadPatternConverter : PatternLayoutConverter + internal sealed class ThreadPatternConverter : PatternLayoutConverter { /// /// Write the ThreadName to the output diff --git a/src/log4net/Layout/Pattern/TypeNamePatternConverter.cs b/src/log4net/Layout/Pattern/TypeNamePatternConverter.cs index faa47d25..e65b1a5c 100644 --- a/src/log4net/Layout/Pattern/TypeNamePatternConverter.cs +++ b/src/log4net/Layout/Pattern/TypeNamePatternConverter.cs @@ -34,7 +34,7 @@ namespace log4net.Layout.Pattern /// /// /// Nicko Cadell - internal sealed class TypeNamePatternConverter : NamedPatternConverter + internal sealed class TypeNamePatternConverter : NamedPatternConverter { /// /// Gets the fully qualified name of the class @@ -46,18 +46,18 @@ internal sealed class TypeNamePatternConverter : NamedPatternConverter /// Returns the of the . /// /// - protected override string GetFullyQualifiedName(LoggingEvent loggingEvent) + protected override string GetFullyQualifiedName(LoggingEvent loggingEvent) { if (loggingEvent == null) { return string.Empty; } - + if (loggingEvent.LocationInformation == null) { return string.Empty; } - + return loggingEvent.LocationInformation.ClassName; } } diff --git a/src/log4net/Layout/Pattern/UserNamePatternConverter.cs b/src/log4net/Layout/Pattern/UserNamePatternConverter.cs index 932f40de..1b2c49a4 100644 --- a/src/log4net/Layout/Pattern/UserNamePatternConverter.cs +++ b/src/log4net/Layout/Pattern/UserNamePatternConverter.cs @@ -30,7 +30,7 @@ namespace log4net.Layout.Pattern /// /// Douglas de la Torre /// Nicko Cadell - internal sealed class UserNamePatternConverter : PatternLayoutConverter + internal sealed class UserNamePatternConverter : PatternLayoutConverter { /// /// Convert the pattern to the rendered message @@ -39,7 +39,7 @@ internal sealed class UserNamePatternConverter : PatternLayoutConverter /// the event being logged protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) { - writer.Write( loggingEvent.UserName ); + writer.Write(loggingEvent.UserName); } } } diff --git a/src/log4net/Layout/Pattern/UtcDatePatternConverter.cs b/src/log4net/Layout/Pattern/UtcDatePatternConverter.cs index 5e6b9126..c4ba2d18 100644 --- a/src/log4net/Layout/Pattern/UtcDatePatternConverter.cs +++ b/src/log4net/Layout/Pattern/UtcDatePatternConverter.cs @@ -65,27 +65,27 @@ internal class UtcDatePatternConverter : DatePatternConverter /// protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) { - try + try { m_dateFormatter.FormatDate(loggingEvent.TimeStampUtc, writer); } - catch (Exception ex) + catch (Exception ex) { LogLog.Error(declaringType, "Error occurred while converting date.", ex); } } - #region Private Static Fields + #region Private Static Fields - /// - /// The fully qualified type of the UtcDatePatternConverter class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(UtcDatePatternConverter); + /// + /// The fully qualified type of the UtcDatePatternConverter class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(UtcDatePatternConverter); - #endregion Private Static Fields + #endregion Private Static Fields } } diff --git a/src/log4net/Layout/PatternLayout.cs b/src/log4net/Layout/PatternLayout.cs index 60a1495b..bbf131c5 100644 --- a/src/log4net/Layout/PatternLayout.cs +++ b/src/log4net/Layout/PatternLayout.cs @@ -25,12 +25,12 @@ using log4net.Layout.Pattern; using log4net.Util; using log4net.Util.PatternStringConverters; -using AppDomainPatternConverter=log4net.Layout.Pattern.AppDomainPatternConverter; -using DatePatternConverter=log4net.Layout.Pattern.DatePatternConverter; -using IdentityPatternConverter=log4net.Layout.Pattern.IdentityPatternConverter; -using PropertyPatternConverter=log4net.Layout.Pattern.PropertyPatternConverter; -using UserNamePatternConverter=log4net.Layout.Pattern.UserNamePatternConverter; -using UtcDatePatternConverter=log4net.Layout.Pattern.UtcDatePatternConverter; +using AppDomainPatternConverter = log4net.Layout.Pattern.AppDomainPatternConverter; +using DatePatternConverter = log4net.Layout.Pattern.DatePatternConverter; +using IdentityPatternConverter = log4net.Layout.Pattern.IdentityPatternConverter; +using PropertyPatternConverter = log4net.Layout.Pattern.PropertyPatternConverter; +using UserNamePatternConverter = log4net.Layout.Pattern.UserNamePatternConverter; +using UtcDatePatternConverter = log4net.Layout.Pattern.UtcDatePatternConverter; namespace log4net.Layout { @@ -106,46 +106,46 @@ namespace log4net.Layout /// /// aspnet-cache /// - /// - /// Used to output all cache items in the case of %aspnet-cache or just one named item if used as %aspnet-cache{key} - /// - /// - /// This pattern is not available for Compact Framework or Client Profile assemblies. - /// + /// + /// Used to output all cache items in the case of %aspnet-cache or just one named item if used as %aspnet-cache{key} + /// + /// + /// This pattern is not available for Compact Framework or Client Profile assemblies. + /// /// /// /// /// aspnet-context /// - /// - /// Used to output all context items in the case of %aspnet-context or just one named item if used as %aspnet-context{key} - /// - /// - /// This pattern is not available for Compact Framework or Client Profile assemblies. - /// - /// + /// + /// Used to output all context items in the case of %aspnet-context or just one named item if used as %aspnet-context{key} + /// + /// + /// This pattern is not available for Compact Framework or Client Profile assemblies. + /// + /// /// /// /// aspnet-request /// - /// - /// Used to output all request parameters in the case of %aspnet-request or just one named param if used as %aspnet-request{key} - /// - /// - /// This pattern is not available for Compact Framework or Client Profile assemblies. - /// - /// + /// + /// Used to output all request parameters in the case of %aspnet-request or just one named param if used as %aspnet-request{key} + /// + /// + /// This pattern is not available for Compact Framework or Client Profile assemblies. + /// + /// /// /// /// aspnet-session /// - /// - /// Used to output all session items in the case of %aspnet-session or just one named item if used as %aspnet-session{key} - /// - /// - /// This pattern is not available for Compact Framework or Client Profile assemblies. - /// - /// + /// + /// Used to output all session items in the case of %aspnet-session or just one named item if used as %aspnet-session{key} + /// + /// + /// This pattern is not available for Compact Framework or Client Profile assemblies. + /// + /// /// /// /// c @@ -466,34 +466,34 @@ namespace log4net.Layout /// between braces. For example, %stacktrace{level}. /// If no stack trace level specifier is given then 1 is assumed /// - /// - /// Output uses the format: - /// type3.MethodCall3 > type2.MethodCall2 > type1.MethodCall1 - /// - /// - /// This pattern is not available for Compact Framework assemblies. - /// - /// + /// + /// Output uses the format: + /// type3.MethodCall3 > type2.MethodCall2 > type1.MethodCall1 + /// + /// + /// This pattern is not available for Compact Framework assemblies. + /// + /// + /// + /// + /// stacktracedetail + /// + /// + /// Used to output the stack trace of the logging event + /// The stack trace level specifier may be enclosed + /// between braces. For example, %stacktracedetail{level}. + /// If no stack trace level specifier is given then 1 is assumed + /// + /// + /// Output uses the format: + /// type3.MethodCall3(type param,...) > type2.MethodCall2(type param,...) > type1.MethodCall1(type param,...) + /// + /// + /// This pattern is not available for Compact Framework assemblies. + /// + /// /// - /// - /// stacktracedetail - /// - /// - /// Used to output the stack trace of the logging event - /// The stack trace level specifier may be enclosed - /// between braces. For example, %stacktracedetail{level}. - /// If no stack trace level specifier is given then 1 is assumed - /// - /// - /// Output uses the format: - /// type3.MethodCall3(type param,...) > type2.MethodCall2(type param,...) > type1.MethodCall1(type param,...) - /// - /// - /// This pattern is not available for Compact Framework assemblies. - /// - /// - /// - /// + /// /// t /// Equivalent to thread /// @@ -793,7 +793,7 @@ public class PatternLayout : LayoutSkeleton /// which just prints the application supplied message. /// /// - public const string DefaultConversionPattern ="%message%newline"; + public const string DefaultConversionPattern = "%message%newline"; /// /// A detailed conversion pattern @@ -823,12 +823,12 @@ public class PatternLayout : LayoutSkeleton #endregion Static Fields #region Member Variables - + /// /// the pattern /// private string m_pattern; - + /// /// the head of the pattern converter chain /// @@ -859,8 +859,8 @@ static PatternLayout() s_globalRulesRegistry.Add("newline", typeof(NewLinePatternConverter)); s_globalRulesRegistry.Add("n", typeof(NewLinePatternConverter)); -// .NET Compact Framework 1.0 has no support for ASP.NET -// SSCLI 1.0 has no support for ASP.NET + // .NET Compact Framework 1.0 has no support for ASP.NET + // SSCLI 1.0 has no support for ASP.NET #if !NETCF && !SSCLI && !CLIENT_PROFILE && !NETSTANDARD s_globalRulesRegistry.Add("aspnet-cache", typeof(AspNetCachePatternConverter)); s_globalRulesRegistry.Add("aspnet-context", typeof(AspNetContextPatternConverter)); @@ -904,10 +904,10 @@ static PatternLayout() s_globalRulesRegistry.Add("r", typeof(RelativeTimePatternConverter)); s_globalRulesRegistry.Add("timestamp", typeof(RelativeTimePatternConverter)); - + #if !NETCF && !NETSTANDARD1_3 s_globalRulesRegistry.Add("stacktrace", typeof(StackTracePatternConverter)); - s_globalRulesRegistry.Add("stacktracedetail", typeof(StackTraceDetailPatternConverter)); + s_globalRulesRegistry.Add("stacktracedetail", typeof(StackTraceDetailPatternConverter)); #endif s_globalRulesRegistry.Add("t", typeof(ThreadPatternConverter)); @@ -976,7 +976,7 @@ public PatternLayout() : this(DefaultConversionPattern) /// need not be called. This may not be the case when using a subclass. /// /// - public PatternLayout(string pattern) + public PatternLayout(string pattern) { // By default we do not process the exception IgnoresException = true; @@ -991,7 +991,7 @@ public PatternLayout(string pattern) } #endregion - + /// /// The pattern formatting string /// @@ -1004,7 +1004,7 @@ public PatternLayout(string pattern) /// public string ConversionPattern { - get { return m_pattern; } + get { return m_pattern; } set { m_pattern = value; } } @@ -1019,27 +1019,27 @@ public string ConversionPattern /// global and instance rules on the . /// /// - protected virtual PatternParser CreatePatternParser(string pattern) + protected virtual PatternParser CreatePatternParser(string pattern) { PatternParser patternParser = new PatternParser(pattern); // Add all the builtin patterns - foreach(DictionaryEntry entry in s_globalRulesRegistry) + foreach (DictionaryEntry entry in s_globalRulesRegistry) { - ConverterInfo converterInfo = new ConverterInfo(); - converterInfo.Name = (string)entry.Key; - converterInfo.Type = (Type)entry.Value; - patternParser.PatternConverters[entry.Key] = converterInfo; + ConverterInfo converterInfo = new ConverterInfo(); + converterInfo.Name = (string)entry.Key; + converterInfo.Type = (Type)entry.Value; + patternParser.PatternConverters[entry.Key] = converterInfo; } // Add the instance patterns - foreach(DictionaryEntry entry in m_instanceRulesRegistry) + foreach (DictionaryEntry entry in m_instanceRulesRegistry) { patternParser.PatternConverters[entry.Key] = entry.Value; } return patternParser; } - + #region Implementation of IOptionHandler /// @@ -1058,12 +1058,12 @@ protected virtual PatternParser CreatePatternParser(string pattern) /// must be called again. /// /// - public override void ActivateOptions() + public override void ActivateOptions() { m_head = CreatePatternParser(m_pattern).Parse(); PatternConverter curConverter = m_head; - while(curConverter != null) + while (curConverter != null) { PatternLayoutConverter layoutConverter = curConverter as PatternLayoutConverter; if (layoutConverter != null) @@ -1095,7 +1095,7 @@ public override void ActivateOptions() /// specified in the property. /// /// - public override void Format(TextWriter writer, LoggingEvent loggingEvent) + public override void Format(TextWriter writer, LoggingEvent loggingEvent) { if (writer == null) { @@ -1109,7 +1109,7 @@ public override void Format(TextWriter writer, LoggingEvent loggingEvent) PatternConverter c = m_head; // loop through the chain of pattern converters - while(c != null) + while (c != null) { c.Format(writer, loggingEvent); c = c.Next; @@ -1130,13 +1130,13 @@ public override void Format(TextWriter writer, LoggingEvent loggingEvent) /// public void AddConverter(ConverterInfo converterInfo) { - if (converterInfo == null) throw new ArgumentNullException("converterInfo"); + if (converterInfo == null) throw new ArgumentNullException("converterInfo"); - if (!typeof(PatternConverter).IsAssignableFrom(converterInfo.Type)) - { - throw new ArgumentException("The converter type specified [" + converterInfo.Type + "] must be a subclass of log4net.Util.PatternConverter", "converterInfo"); - } - m_instanceRulesRegistry[converterInfo.Name] = converterInfo; + if (!typeof(PatternConverter).IsAssignableFrom(converterInfo.Type)) + { + throw new ArgumentException("The converter type specified [" + converterInfo.Type + "] must be a subclass of log4net.Util.PatternConverter", "converterInfo"); + } + m_instanceRulesRegistry[converterInfo.Name] = converterInfo; } /// @@ -1157,14 +1157,14 @@ public void AddConverter(ConverterInfo converterInfo) /// public void AddConverter(string name, Type type) { - if (name == null) throw new ArgumentNullException("name"); - if (type == null) throw new ArgumentNullException("type"); + if (name == null) throw new ArgumentNullException("name"); + if (type == null) throw new ArgumentNullException("type"); - ConverterInfo converterInfo = new ConverterInfo(); - converterInfo.Name = name; - converterInfo.Type = type; + ConverterInfo converterInfo = new ConverterInfo(); + converterInfo.Name = name; + converterInfo.Type = type; - AddConverter(converterInfo); + AddConverter(converterInfo); } } } diff --git a/src/log4net/Layout/RawLayoutConverter.cs b/src/log4net/Layout/RawLayoutConverter.cs index 3667f814..905d6846 100644 --- a/src/log4net/Layout/RawLayoutConverter.cs +++ b/src/log4net/Layout/RawLayoutConverter.cs @@ -51,7 +51,7 @@ public class RawLayoutConverter : IConvertFrom /// as the . /// /// - public bool CanConvertFrom(Type sourceType) + public bool CanConvertFrom(Type sourceType) { // Accept an ILayout object return (typeof(ILayout).IsAssignableFrom(sourceType)); @@ -71,10 +71,10 @@ public bool CanConvertFrom(Type sourceType) /// exception is thrown. /// /// - public object ConvertFrom(object source) + public object ConvertFrom(object source) { ILayout layout = source as ILayout; - if (layout != null) + if (layout != null) { return new Layout2RawLayoutAdapter(layout); } diff --git a/src/log4net/Layout/RawPropertyLayout.cs b/src/log4net/Layout/RawPropertyLayout.cs index 6c4303e7..60b2c6bb 100644 --- a/src/log4net/Layout/RawPropertyLayout.cs +++ b/src/log4net/Layout/RawPropertyLayout.cs @@ -65,7 +65,7 @@ public string Key get { return m_key; } set { m_key = value; } } - + #region Implementation of IRawLayout /// diff --git a/src/log4net/Layout/RawTimeStampLayout.cs b/src/log4net/Layout/RawTimeStampLayout.cs index 81c37b4c..e8921ddb 100644 --- a/src/log4net/Layout/RawTimeStampLayout.cs +++ b/src/log4net/Layout/RawTimeStampLayout.cs @@ -47,7 +47,7 @@ public RawTimeStampLayout() } #endregion - + #region Implementation of IRawLayout /// diff --git a/src/log4net/Layout/RawUtcTimeStampLayout.cs b/src/log4net/Layout/RawUtcTimeStampLayout.cs index 55bec72e..76941407 100644 --- a/src/log4net/Layout/RawUtcTimeStampLayout.cs +++ b/src/log4net/Layout/RawUtcTimeStampLayout.cs @@ -47,7 +47,7 @@ public RawUtcTimeStampLayout() } #endregion - + #region Implementation of IRawLayout /// diff --git a/src/log4net/Layout/SimpleLayout.cs b/src/log4net/Layout/SimpleLayout.cs index 8d4640aa..99f1138d 100644 --- a/src/log4net/Layout/SimpleLayout.cs +++ b/src/log4net/Layout/SimpleLayout.cs @@ -53,7 +53,7 @@ public SimpleLayout() } #endregion - + #region Implementation of IOptionHandler /// @@ -72,7 +72,7 @@ public SimpleLayout() /// must be called again. /// /// - public override void ActivateOptions() + public override void ActivateOptions() { // nothing to do. } @@ -93,7 +93,7 @@ public override void ActivateOptions() /// output is terminated by a newline. /// /// - public override void Format(TextWriter writer, LoggingEvent loggingEvent) + public override void Format(TextWriter writer, LoggingEvent loggingEvent) { if (loggingEvent == null) { diff --git a/src/log4net/Layout/XmlLayout.cs b/src/log4net/Layout/XmlLayout.cs index 15c925ef..b30686a6 100644 --- a/src/log4net/Layout/XmlLayout.cs +++ b/src/log4net/Layout/XmlLayout.cs @@ -97,7 +97,7 @@ public XmlLayout() : base() /// appender as well. /// /// - public XmlLayout(bool locationInfo) : base(locationInfo) + public XmlLayout(bool locationInfo) : base(locationInfo) { } @@ -121,7 +121,7 @@ public string Prefix set { m_prefix = value; } } - + /// /// Set whether or not to base64 encode the message. /// @@ -137,8 +137,8 @@ public string Prefix /// public bool Base64EncodeMessage { - get {return m_base64Message;} - set {m_base64Message=value;} + get { return m_base64Message; } + set { m_base64Message = value; } } /// @@ -156,8 +156,8 @@ public bool Base64EncodeMessage /// public bool Base64EncodeProperties { - get {return m_base64Properties;} - set {m_base64Properties=value;} + get { return m_base64Properties; } + set { m_base64Properties = value; } } #endregion Public Instance Properties @@ -183,7 +183,7 @@ public bool Base64EncodeProperties /// Builds a cache of the element names /// /// - public override void ActivateOptions() + public override void ActivateOptions() { base.ActivateOptions(); @@ -198,7 +198,7 @@ public override void ActivateOptions() m_elmLocation = m_prefix + ":" + ELM_LOCATION; } } - + #endregion Implementation of IOptionHandler #region Override implementation of XMLLayoutBase @@ -216,12 +216,12 @@ public override void ActivateOptions() /// protected override void FormatXml(XmlWriter writer, LoggingEvent loggingEvent) { - #if NETSTANDARD +#if NETSTANDARD writer.WriteStartElement(m_prefix, ELM_EVENT, m_prefix); // writer.WriteAttributeString("xmlns", "log4net", null, "http://logging.apache.org/log4net/schemas/log4net-events-1.2"); - #else +#else writer.WriteStartElement(m_elmEvent); - #endif +#endif writer.WriteAttributeString(ATTR_LOGGER, loggingEvent.LoggerName); #if NET_2_0 || NETCF_2_0 || MONO_2_0 || NETSTANDARD @@ -245,13 +245,13 @@ protected override void FormatXml(XmlWriter writer, LoggingEvent loggingEvent) { writer.WriteAttributeString(ATTR_USERNAME, loggingEvent.UserName); } - + // Append the message text - #if NETSTANDARD +#if NETSTANDARD writer.WriteStartElement(m_prefix, ELM_MESSAGE, m_prefix); - #else +#else writer.WriteStartElement(m_elmMessage); - #endif +#endif if (!this.Base64EncodeMessage) { Transform.WriteEscapedXmlString(writer, loggingEvent.RenderedMessage, this.InvalidCharReplacement); @@ -260,7 +260,7 @@ protected override void FormatXml(XmlWriter writer, LoggingEvent loggingEvent) { byte[] messageBytes = Encoding.UTF8.GetBytes(loggingEvent.RenderedMessage); string base64Message = Convert.ToBase64String(messageBytes, 0, messageBytes.Length); - Transform.WriteEscapedXmlString(writer, base64Message,this.InvalidCharReplacement); + Transform.WriteEscapedXmlString(writer, base64Message, this.InvalidCharReplacement); } writer.WriteEndElement(); @@ -269,25 +269,25 @@ protected override void FormatXml(XmlWriter writer, LoggingEvent loggingEvent) // Append the properties text if (properties.Count > 0) { - #if NETSTANDARD +#if NETSTANDARD writer.WriteStartElement(m_prefix, ELM_PROPERTIES, m_prefix); - #else +#else writer.WriteStartElement(m_elmProperties); - #endif - foreach(System.Collections.DictionaryEntry entry in properties) +#endif + foreach (System.Collections.DictionaryEntry entry in properties) { - #if NETSTANDARD +#if NETSTANDARD writer.WriteStartElement(m_prefix, ELM_DATA, m_prefix); - #else +#else writer.WriteStartElement(m_elmData); - #endif - writer.WriteAttributeString(ATTR_NAME, Transform.MaskXmlInvalidCharacters((string)entry.Key,this.InvalidCharReplacement)); +#endif + writer.WriteAttributeString(ATTR_NAME, Transform.MaskXmlInvalidCharacters((string)entry.Key, this.InvalidCharReplacement)); // Use an ObjectRenderer to convert the object to a string - string valueStr =null; + string valueStr = null; if (!this.Base64EncodeProperties) { - valueStr = Transform.MaskXmlInvalidCharacters(loggingEvent.Repository.RendererMap.FindAndRender(entry.Value),this.InvalidCharReplacement); + valueStr = Transform.MaskXmlInvalidCharacters(loggingEvent.Repository.RendererMap.FindAndRender(entry.Value), this.InvalidCharReplacement); } else { @@ -305,24 +305,24 @@ protected override void FormatXml(XmlWriter writer, LoggingEvent loggingEvent) if (exceptionStr != null && exceptionStr.Length > 0) { // Append the stack trace line - #if NETSTANDARD +#if NETSTANDARD writer.WriteStartElement(m_prefix, ELM_EXCEPTION, m_prefix); - #else +#else writer.WriteStartElement(m_elmException); - #endif - Transform.WriteEscapedXmlString(writer, exceptionStr,this.InvalidCharReplacement); +#endif + Transform.WriteEscapedXmlString(writer, exceptionStr, this.InvalidCharReplacement); writer.WriteEndElement(); } if (LocationInfo) - { + { LocationInfo locationInfo = loggingEvent.LocationInformation; - #if NETSTANDARD +#if NETSTANDARD writer.WriteStartElement(m_prefix, ELM_LOCATION, m_prefix); - #else +#else writer.WriteStartElement(m_elmLocation); - #endif +#endif writer.WriteAttributeString(ATTR_CLASS, locationInfo.ClassName); writer.WriteAttributeString(ATTR_METHOD, locationInfo.MethodName); writer.WriteAttributeString(ATTR_FILE, locationInfo.FileName); @@ -336,7 +336,7 @@ protected override void FormatXml(XmlWriter writer, LoggingEvent loggingEvent) #endregion Override implementation of XMLLayoutBase #region Private Instance Fields - + /// /// The prefix to use for all generated element names /// @@ -349,8 +349,8 @@ protected override void FormatXml(XmlWriter writer, LoggingEvent loggingEvent) private string m_elmException = ELM_EXCEPTION; private string m_elmLocation = ELM_LOCATION; - private bool m_base64Message=false; - private bool m_base64Properties=false; + private bool m_base64Message = false; + private bool m_base64Properties = false; #endregion Private Instance Fields diff --git a/src/log4net/Layout/XmlLayoutBase.cs b/src/log4net/Layout/XmlLayoutBase.cs index 3bee490d..eb572284 100644 --- a/src/log4net/Layout/XmlLayoutBase.cs +++ b/src/log4net/Layout/XmlLayoutBase.cs @@ -126,8 +126,8 @@ public bool LocationInfo /// public string InvalidCharReplacement { - get {return m_invalidCharReplacement;} - set {m_invalidCharReplacement=value;} + get { return m_invalidCharReplacement; } + set { m_invalidCharReplacement = value; } } #endregion @@ -149,7 +149,7 @@ public string InvalidCharReplacement /// must be called again. /// /// - public override void ActivateOptions() + public override void ActivateOptions() { // nothing to do } @@ -190,7 +190,7 @@ public override string ContentType /// method rather than this method. /// /// - public override void Format(TextWriter writer, LoggingEvent loggingEvent) + public override void Format(TextWriter writer, LoggingEvent loggingEvent) { if (loggingEvent == null) { @@ -238,7 +238,7 @@ public override void Format(TextWriter writer, LoggingEvent loggingEvent) #endregion Protected Instance Methods #region Private Instance Fields - + /// /// Flag to indicate if location information should be included in /// the XML events. @@ -248,7 +248,7 @@ public override void Format(TextWriter writer, LoggingEvent loggingEvent) /// /// The string to replace invalid chars with /// - private string m_invalidCharReplacement="?"; + private string m_invalidCharReplacement = "?"; #endregion Private Instance Fields } diff --git a/src/log4net/Layout/XmlLayoutSchemaLog4j.cs b/src/log4net/Layout/XmlLayoutSchemaLog4j.cs index db6fb5a2..448b145f 100644 --- a/src/log4net/Layout/XmlLayoutSchemaLog4j.cs +++ b/src/log4net/Layout/XmlLayoutSchemaLog4j.cs @@ -73,7 +73,7 @@ public XmlLayoutSchemaLog4j() : base() /// appender as well. /// /// - public XmlLayoutSchemaLog4j(bool locationInfo) : base(locationInfo) + public XmlLayoutSchemaLog4j(bool locationInfo) : base(locationInfo) { } @@ -92,8 +92,8 @@ public XmlLayoutSchemaLog4j(bool locationInfo) : base(locationInfo) public string Version { get { return "1.2"; } - set - { + set + { if (value != "1.2") { throw new ArgumentException("Only version 1.2 of the log4j schema is currently supported"); @@ -141,42 +141,42 @@ protected override void FormatXml(XmlWriter writer, LoggingEvent loggingEvent) // Translate logging events for log4j // Translate hostname property - if (loggingEvent.LookupProperty(LoggingEvent.HostNameProperty) != null && + if (loggingEvent.LookupProperty(LoggingEvent.HostNameProperty) != null && loggingEvent.LookupProperty("log4jmachinename") == null) { loggingEvent.GetProperties()["log4jmachinename"] = loggingEvent.LookupProperty(LoggingEvent.HostNameProperty); } // translate appdomain name - if (loggingEvent.LookupProperty("log4japp") == null && - loggingEvent.Domain != null && + if (loggingEvent.LookupProperty("log4japp") == null && + loggingEvent.Domain != null && loggingEvent.Domain.Length > 0) { loggingEvent.GetProperties()["log4japp"] = loggingEvent.Domain; } // translate identity name - if (loggingEvent.Identity != null && - loggingEvent.Identity.Length > 0 && + if (loggingEvent.Identity != null && + loggingEvent.Identity.Length > 0 && loggingEvent.LookupProperty(LoggingEvent.IdentityProperty) == null) { loggingEvent.GetProperties()[LoggingEvent.IdentityProperty] = loggingEvent.Identity; } // translate user name - if (loggingEvent.UserName != null && - loggingEvent.UserName.Length > 0 && + if (loggingEvent.UserName != null && + loggingEvent.UserName.Length > 0 && loggingEvent.LookupProperty(LoggingEvent.UserNameProperty) == null) { loggingEvent.GetProperties()[LoggingEvent.UserNameProperty] = loggingEvent.UserName; } // Write the start element - #if NETSTANDARD +#if NETSTANDARD writer.WriteStartElement("log4j", "event", "log4net"); - #else +#else writer.WriteStartElement("log4j:event"); - #endif +#endif writer.WriteAttributeString("logger", loggingEvent.LoggerName); // Calculate the timestamp as the number of milliseconds since january 1970 @@ -189,14 +189,14 @@ protected override void FormatXml(XmlWriter writer, LoggingEvent loggingEvent) writer.WriteAttributeString("timestamp", XmlConvert.ToString((long)timeSince1970.TotalMilliseconds)); writer.WriteAttributeString("level", loggingEvent.Level.DisplayName); writer.WriteAttributeString("thread", loggingEvent.ThreadName); - + // Append the message text - #if NETSTANDARD +#if NETSTANDARD writer.WriteStartElement("log4j", "message", "log4net"); - #else +#else writer.WriteStartElement("log4j:message"); - #endif - Transform.WriteEscapedXmlString(writer, loggingEvent.RenderedMessage,this.InvalidCharReplacement); +#endif + Transform.WriteEscapedXmlString(writer, loggingEvent.RenderedMessage, this.InvalidCharReplacement); writer.WriteEndElement(); object ndcObj = loggingEvent.LookupProperty("NDC"); @@ -207,12 +207,12 @@ protected override void FormatXml(XmlWriter writer, LoggingEvent loggingEvent) if (valueStr != null && valueStr.Length > 0) { // Append the NDC text - #if NETSTANDARD +#if NETSTANDARD writer.WriteStartElement("log4j", "NDC", "log4net"); - #else +#else writer.WriteStartElement("log4j:NDC"); - #endif - Transform.WriteEscapedXmlString(writer, valueStr,this.InvalidCharReplacement); +#endif + Transform.WriteEscapedXmlString(writer, valueStr, this.InvalidCharReplacement); writer.WriteEndElement(); } } @@ -221,18 +221,18 @@ protected override void FormatXml(XmlWriter writer, LoggingEvent loggingEvent) PropertiesDictionary properties = loggingEvent.GetProperties(); if (properties.Count > 0) { - #if NETSTANDARD +#if NETSTANDARD writer.WriteStartElement("log4j", "properties", "log4net"); - #else +#else writer.WriteStartElement("log4j:properties"); - #endif - foreach(System.Collections.DictionaryEntry entry in properties) +#endif + foreach (System.Collections.DictionaryEntry entry in properties) { - #if NETSTANDARD +#if NETSTANDARD writer.WriteStartElement("log4j", "data", "log4net"); - #else +#else writer.WriteStartElement("log4j:data"); - #endif +#endif writer.WriteAttributeString("name", (string)entry.Key); // Use an ObjectRenderer to convert the object to a string @@ -248,24 +248,24 @@ protected override void FormatXml(XmlWriter writer, LoggingEvent loggingEvent) if (exceptionStr != null && exceptionStr.Length > 0) { // Append the stack trace line - #if NETSTANDARD +#if NETSTANDARD writer.WriteStartElement("log4j", "throwable", "log4net"); - #else +#else writer.WriteStartElement("log4j:throwable"); - #endif - Transform.WriteEscapedXmlString(writer, exceptionStr,this.InvalidCharReplacement); +#endif + Transform.WriteEscapedXmlString(writer, exceptionStr, this.InvalidCharReplacement); writer.WriteEndElement(); } if (LocationInfo) - { + { LocationInfo locationInfo = loggingEvent.LocationInformation; - #if NETSTANDARD +#if NETSTANDARD writer.WriteStartElement("log4j", "locationInfo", "log4net"); - #else +#else writer.WriteStartElement("log4j:locationInfo"); - #endif +#endif writer.WriteAttributeString("class", locationInfo.ClassName); writer.WriteAttributeString("method", locationInfo.MethodName); writer.WriteAttributeString("file", locationInfo.FileName); diff --git a/src/log4net/LogManager.cs b/src/log4net/LogManager.cs index 664d39cd..0eb25ce5 100644 --- a/src/log4net/LogManager.cs +++ b/src/log4net/LogManager.cs @@ -86,11 +86,11 @@ private LogManager() /// /// The fully qualified logger name to look for. /// The logger found, or null if no logger could be found. - public static ILog Exists(string name) + public static ILog Exists(string name) { return Exists(Assembly.GetCallingAssembly(), name); } - + /// Get the currently defined loggers. /// /// Returns all the currently defined loggers in the default repository. @@ -103,7 +103,7 @@ public static ILog[] GetCurrentLoggers() { return GetCurrentLoggers(Assembly.GetCallingAssembly()); } - + /// Get or create a logger. /// /// Retrieves or creates a named logger. @@ -128,23 +128,23 @@ public static ILog GetLogger(string name) } #endif // !NETSTANDARD1_3 - /// - /// Returns the named logger if it exists. - /// - /// - /// - /// If the named logger exists (in the specified repository) then it - /// returns a reference to the logger, otherwise it returns - /// null. - /// - /// - /// The repository to lookup in. - /// The fully qualified logger name to look for. - /// - /// The logger found, or null if the logger doesn't exist in the specified - /// repository. - /// - public static ILog Exists(string repository, string name) + /// + /// Returns the named logger if it exists. + /// + /// + /// + /// If the named logger exists (in the specified repository) then it + /// returns a reference to the logger, otherwise it returns + /// null. + /// + /// + /// The repository to lookup in. + /// The fully qualified logger name to look for. + /// + /// The logger found, or null if the logger doesn't exist in the specified + /// repository. + /// + public static ILog Exists(string repository, string name) { return WrapLogger(LoggerManager.Exists(repository, name)); } @@ -165,7 +165,7 @@ public static ILog Exists(string repository, string name) /// The logger, or null if the logger doesn't exist in the specified /// assembly's repository. /// - public static ILog Exists(Assembly repositoryAssembly, string name) + public static ILog Exists(Assembly repositoryAssembly, string name) { return WrapLogger(LoggerManager.Exists(repositoryAssembly, name)); } @@ -242,7 +242,7 @@ public static ILog GetLogger(string repository, string name) public static ILog GetLogger(Assembly repositoryAssembly, string name) { return WrapLogger(LoggerManager.GetLogger(repositoryAssembly, name)); - } + } /// /// Shorthand for . @@ -252,7 +252,7 @@ public static ILog GetLogger(Assembly repositoryAssembly, string name) /// /// The full name of will be used as the name of the logger to retrieve. /// The logger with the name specified. - public static ILog GetLogger(Type type) + public static ILog GetLogger(Type type) { #if NETSTANDARD1_3 return GetLogger(type.GetTypeInfo().Assembly, type.FullName); @@ -270,7 +270,7 @@ public static ILog GetLogger(Type type) /// The repository to lookup in. /// The full name of will be used as the name of the logger to retrieve. /// The logger with the name specified. - public static ILog GetLogger(string repository, Type type) + public static ILog GetLogger(string repository, Type type) { return WrapLogger(LoggerManager.GetLogger(repository, type)); } @@ -284,7 +284,7 @@ public static ILog GetLogger(string repository, Type type) /// The assembly to use to lookup the repository. /// The full name of will be used as the name of the logger to retrieve. /// The logger with the name specified. - public static ILog GetLogger(Assembly repositoryAssembly, Type type) + public static ILog GetLogger(Assembly repositoryAssembly, Type type) { return WrapLogger(LoggerManager.GetLogger(repositoryAssembly, type)); } @@ -312,7 +312,7 @@ public static ILog GetLogger(Assembly repositoryAssembly, Type type) /// and again to a nested appender. /// /// - public static void Shutdown() + public static void Shutdown() { LoggerManager.Shutdown(); } @@ -337,7 +337,7 @@ public static void Shutdown() /// and again to a nested appender. /// /// - public static void ShutdownRepository() + public static void ShutdownRepository() { ShutdownRepository(Assembly.GetCallingAssembly()); } @@ -363,7 +363,7 @@ public static void ShutdownRepository() /// /// /// The repository to shutdown. - public static void ShutdownRepository(string repository) + public static void ShutdownRepository(string repository) { LoggerManager.ShutdownRepository(repository); } @@ -390,7 +390,7 @@ public static void ShutdownRepository(string repository) /// /// /// The assembly to use to lookup the repository. - public static void ShutdownRepository(Assembly repositoryAssembly) + public static void ShutdownRepository(Assembly repositoryAssembly) { LoggerManager.ShutdownRepository(repositoryAssembly); } @@ -410,7 +410,7 @@ public static void ShutdownRepository(Assembly repositoryAssembly) /// message disabling is set to its default "off" value. /// /// - public static void ResetConfiguration() + public static void ResetConfiguration() { ResetConfiguration(Assembly.GetCallingAssembly()); } @@ -430,7 +430,7 @@ public static void ResetConfiguration() /// /// /// The repository to reset. - public static void ResetConfiguration(string repository) + public static void ResetConfiguration(string repository) { LoggerManager.ResetConfiguration(repository); } @@ -449,7 +449,7 @@ public static void ResetConfiguration(string repository) /// /// /// The assembly to use to lookup the repository to reset. - public static void ResetConfiguration(Assembly repositoryAssembly) + public static void ResetConfiguration(Assembly repositoryAssembly) { LoggerManager.ResetConfiguration(repositoryAssembly); } @@ -751,27 +751,27 @@ public static ILoggerRepository[] GetAllRepositories() return LoggerManager.GetAllRepositories(); } - /// - /// Flushes logging events buffered in all configured appenders in the default repository. - /// - /// The maximum time in milliseconds to wait for logging events from asycnhronous appenders to be flushed. - /// True if all logging events were flushed successfully, else false. - public static bool Flush(int millisecondsTimeout) - { + /// + /// Flushes logging events buffered in all configured appenders in the default repository. + /// + /// The maximum time in milliseconds to wait for logging events from asycnhronous appenders to be flushed. + /// True if all logging events were flushed successfully, else false. + public static bool Flush(int millisecondsTimeout) + { #if !NETSTANDARD1_3 // Excluded because GetCallingAssembly() is not available in CoreFX (https://github.com/dotnet/corefx/issues/2221). - Appender.IFlushable flushableRepository = LoggerManager.GetRepository(Assembly.GetCallingAssembly()) as Appender.IFlushable; - if (flushableRepository == null) - { - return false; - } - else - { - return flushableRepository.Flush(millisecondsTimeout); - } + Appender.IFlushable flushableRepository = LoggerManager.GetRepository(Assembly.GetCallingAssembly()) as Appender.IFlushable; + if (flushableRepository == null) + { + return false; + } + else + { + return flushableRepository.Flush(millisecondsTimeout); + } #else return false; #endif - } + } #endregion Domain & Repository Manager Methods @@ -795,7 +795,7 @@ private static ILog WrapLogger(ILogger logger) private static ILog[] WrapLoggers(ILogger[] loggers) { ILog[] results = new ILog[loggers.Length]; - for(int i=0; i /// /*[Obsolete("NDC has been replaced by ThreadContext.Stacks")]*/ - public static void Clear() + public static void Clear() { ThreadContext.Stacks["NDC"].Clear(); } @@ -152,7 +152,7 @@ public static void Clear() /// /// /*[Obsolete("NDC has been replaced by ThreadContext.Stacks")]*/ - public static Stack CloneStack() + public static Stack CloneStack() { return ThreadContext.Stacks["NDC"].InternalStack; } @@ -179,7 +179,7 @@ public static Stack CloneStack() /// /// /*[Obsolete("NDC has been replaced by ThreadContext.Stacks", true)]*/ - public static void Inherit(Stack stack) + public static void Inherit(Stack stack) { ThreadContext.Stacks["NDC"].InternalStack = stack; } @@ -205,7 +205,7 @@ public static void Inherit(Stack stack) /// /// /*[Obsolete("NDC has been replaced by ThreadContext.Stacks")]*/ - public static string Pop() + public static string Pop() { return ThreadContext.Stacks["NDC"].Pop(); } @@ -241,7 +241,7 @@ public static string Pop() /// /// /*[Obsolete("NDC has been replaced by ThreadContext.Stacks")]*/ - public static IDisposable Push(string message) + public static IDisposable Push(string message) { return ThreadContext.Stacks["NDC"].Push(message); } @@ -300,7 +300,7 @@ public static IDisposable PushFormat(string messageFormat, params object[] args) /// /// /*[Obsolete("NDC has been replaced by ThreadContext.Stacks")]*/ - public static void Remove() + public static void Remove() { } @@ -324,7 +324,7 @@ public static void Remove() /// /// /*[Obsolete("NDC has been replaced by ThreadContext.Stacks")]*/ - public static void SetMaxDepth(int maxDepth) + public static void SetMaxDepth(int maxDepth) { if (maxDepth >= 0) { @@ -336,7 +336,7 @@ public static void SetMaxDepth(int maxDepth) } else { - while(stack.Count > maxDepth) + while (stack.Count > maxDepth) { stack.Pop(); } diff --git a/src/log4net/ObjectRenderer/DefaultRenderer.cs b/src/log4net/ObjectRenderer/DefaultRenderer.cs index 73add46a..ff23b198 100644 --- a/src/log4net/ObjectRenderer/DefaultRenderer.cs +++ b/src/log4net/ObjectRenderer/DefaultRenderer.cs @@ -157,7 +157,7 @@ public void RenderObject(RendererMap rendererMap, object obj, TextWriter writer) writer.Write(SystemInfo.NullText); return; } - + Array objArray = obj as Array; if (objArray != null) { @@ -177,7 +177,7 @@ public void RenderObject(RendererMap rendererMap, object obj, TextWriter writer) writer.Write("{}"); return; } - + // This is a special check to allow us to get the enumerator from the IDictionary // interface as this guarantees us DictionaryEntry objects. Note that in .NET 2.0 // the generic IDictionary<> interface enumerates KeyValuePair objects rather than @@ -200,7 +200,7 @@ public void RenderObject(RendererMap rendererMap, object obj, TextWriter writer) RenderEnumerator(rendererMap, objEnumerator, writer); return; } - + if (obj is DictionaryEntry) { RenderDictionaryEntry(rendererMap, (DictionaryEntry)obj, writer); @@ -208,7 +208,7 @@ public void RenderObject(RendererMap rendererMap, object obj, TextWriter writer) } string str = obj.ToString(); - writer.Write( (str==null) ? SystemInfo.NullText : str ); + writer.Write((str == null) ? SystemInfo.NullText : str); } #endregion @@ -246,7 +246,7 @@ private void RenderArray(RendererMap rendererMap, Array array, TextWriter writer if (len > 0) { rendererMap.FindAndRender(array.GetValue(0), writer); - for(int i=1; i. /// /// - public void FindAndRender(object obj, TextWriter writer) + public void FindAndRender(object obj, TextWriter writer) { if (obj == null) { writer.Write(SystemInfo.NullText); } - else + else { // Optimisation for strings string str = obj as string; @@ -117,10 +117,10 @@ public void FindAndRender(object obj, TextWriter writer) { Get(obj.GetType()).RenderObject(this, obj, writer); } - catch(Exception ex) + catch (Exception ex) { // Exception rendering the object - LogLog.Error(declaringType, "Exception while rendering object of type ["+obj.GetType().FullName+"]", ex); + LogLog.Error(declaringType, "Exception while rendering object of type [" + obj.GetType().FullName + "]", ex); // return default message string objectTypeName = ""; @@ -129,7 +129,7 @@ public void FindAndRender(object obj, TextWriter writer) objectTypeName = obj.GetType().FullName; } - writer.Write("Exception rendering object type ["+objectTypeName+"]"); + writer.Write("Exception rendering object type [" + objectTypeName + "]"); if (ex != null) { string exceptionText = null; @@ -165,9 +165,9 @@ public void FindAndRender(object obj, TextWriter writer) /// with the type of the object parameter. /// /// - public IObjectRenderer Get(Object obj) + public IObjectRenderer Get(Object obj) { - if (obj == null) + if (obj == null) { return null; } @@ -176,7 +176,7 @@ public IObjectRenderer Get(Object obj) return Get(obj.GetType()); } } - + /// /// Gets the renderer for the specified type /// @@ -189,7 +189,7 @@ public IObjectRenderer Get(Object obj) /// will be returned. /// /// - public IObjectRenderer Get(Type type) + public IObjectRenderer Get(Type type) { if (type == null) { @@ -206,7 +206,7 @@ public IObjectRenderer Get(Type type) #if NETSTANDARD1_3 for (Type cur = type; cur != null; cur = cur.GetTypeInfo().BaseType) #else - for(Type cur = type; cur != null; cur = cur.BaseType) + for (Type cur = type; cur != null; cur = cur.BaseType) #endif { // Search the type's interfaces @@ -231,28 +231,28 @@ public IObjectRenderer Get(Type type) } return result; - } + } /// /// Internal function to recursively search interfaces /// /// the type to lookup the renderer for /// the renderer for the specified type - private IObjectRenderer SearchTypeAndInterfaces(Type type) + private IObjectRenderer SearchTypeAndInterfaces(Type type) { IObjectRenderer r = (IObjectRenderer)m_map[type]; - if (r != null) + if (r != null) { return r; - } - else + } + else { - foreach(Type t in type.GetInterfaces()) + foreach (Type t in type.GetInterfaces()) { r = SearchTypeAndInterfaces(t); if (r != null) { - return r; + return r; } } } @@ -283,7 +283,7 @@ public IObjectRenderer DefaultRenderer /// cannot be removed. /// /// - public void Clear() + public void Clear() { lock (m_map) { @@ -308,7 +308,7 @@ public void Clear() /// specifying the same as an argument. /// /// - public void Put(Type typeToRender, IObjectRenderer renderer) + public void Put(Type typeToRender, IObjectRenderer renderer) { lock (m_cache) { @@ -328,6 +328,6 @@ public void Put(Type typeToRender, IObjectRenderer renderer) { m_map[typeToRender] = renderer; } - } + } } } diff --git a/src/log4net/Plugin/PluginCollection.cs b/src/log4net/Plugin/PluginCollection.cs index c3c28e77..4019d673 100644 --- a/src/log4net/Plugin/PluginCollection.cs +++ b/src/log4net/Plugin/PluginCollection.cs @@ -73,7 +73,7 @@ public interface IPluginCollectionEnumerator private int m_version = 0; #endregion Implementation (data) - + #region Static Wrappers /// @@ -85,7 +85,7 @@ public interface IPluginCollectionEnumerator /// public static PluginCollection ReadOnly(PluginCollection list) { - if(list == null) throw new ArgumentNullException("list"); + if (list == null) throw new ArgumentNullException("list"); return new ReadOnlyPluginCollection(list); } @@ -102,7 +102,7 @@ public PluginCollection() { m_array = new IPlugin[DEFAULT_CAPACITY]; } - + /// /// Initializes a new instance of the PluginCollection class /// that has the specified initial capacity. @@ -136,7 +136,7 @@ public PluginCollection(IPlugin[] a) m_array = new IPlugin[a.Length]; AddRange(a); } - + /// /// Initializes a new instance of the PluginCollection class /// that contains elements copied from the specified collection. @@ -153,7 +153,7 @@ public PluginCollection(ICollection col) /// Used to access protected constructor /// /// - protected internal enum Tag + protected internal enum Tag { /// /// A value @@ -172,7 +172,7 @@ protected internal PluginCollection(Tag tag) } #endregion - + #region Operations (type-safe ICollection) /// @@ -205,8 +205,8 @@ public virtual void CopyTo(IPlugin[] array, int start) { throw new System.ArgumentException("Destination array was not long enough."); } - - Array.Copy(m_array, 0, array, start, m_count); + + Array.Copy(m_array, 0, array, start, m_count); } /// @@ -230,7 +230,7 @@ public virtual object SyncRoot } #endregion - + #region Operations (type-safe IList) /// @@ -250,13 +250,13 @@ public virtual IPlugin this[int index] get { ValidateIndex(index); // throws - return m_array[index]; + return m_array[index]; } set { ValidateIndex(index); // throws - ++m_version; - m_array[index] = value; + ++m_version; + m_array[index] = value; } } @@ -277,7 +277,7 @@ public virtual int Add(IPlugin item) return m_count++; } - + /// /// Removes all elements from the PluginCollection. /// @@ -287,7 +287,7 @@ public virtual void Clear() m_array = new IPlugin[DEFAULT_CAPACITY]; m_count = 0; } - + /// /// Creates a shallow copy of the . /// @@ -309,7 +309,7 @@ public virtual object Clone() /// true if is found in the PluginCollection; otherwise, false. public virtual bool Contains(IPlugin item) { - for (int i=0; i != m_count; ++i) + for (int i = 0; i != m_count; ++i) { if (m_array[i].Equals(item)) { @@ -330,7 +330,7 @@ public virtual bool Contains(IPlugin item) /// public virtual int IndexOf(IPlugin item) { - for (int i=0; i != m_count; ++i) + for (int i = 0; i != m_count; ++i) { if (m_array[i].Equals(item)) { @@ -353,7 +353,7 @@ public virtual int IndexOf(IPlugin item) public virtual void Insert(int index, IPlugin item) { ValidateIndex(index, true); // throws - + if (m_count == m_array.Length) { EnsureCapacity(m_count + 1); @@ -377,7 +377,7 @@ public virtual void Insert(int index, IPlugin item) /// The specified was not found in the PluginCollection. /// public virtual void Remove(IPlugin item) - { + { int i = IndexOf(item); if (i < 0) { @@ -399,14 +399,14 @@ public virtual void Remove(IPlugin item) public virtual void RemoveAt(int index) { ValidateIndex(index); // throws - + m_count--; if (index < m_count) { Array.Copy(m_array, index + 1, m_array, index, m_count - index); } - + // We can't set the deleted entry equal to null, because it might be a value type. // Instead, we'll create an empty single-element array of the right type and copy it // over the entry we want to erase. @@ -436,7 +436,7 @@ public virtual bool IsReadOnly #endregion #region Operations (type-safe IEnumerable) - + /// /// Returns an enumerator that can iterate through the PluginCollection. /// @@ -449,7 +449,7 @@ public virtual IPluginCollectionEnumerator GetEnumerator() #endregion #region Public helpers (just to mimic some nice features of ArrayList) - + /// /// Gets or sets the number of elements the PluginCollection can contain. /// @@ -458,9 +458,9 @@ public virtual IPluginCollectionEnumerator GetEnumerator() /// public virtual int Capacity { - get - { - return m_array.Length; + get + { + return m_array.Length; } set { @@ -496,7 +496,7 @@ public virtual int AddRange(PluginCollection x) { EnsureCapacity(m_count + x.Count); } - + Array.Copy(x.m_array, 0, m_array, m_count, x.Count); m_count += x.Count; m_version++; @@ -535,14 +535,14 @@ public virtual int AddRange(ICollection col) EnsureCapacity(m_count + col.Count); } - foreach(object item in col) + foreach (object item in col) { Add((IPlugin)item); } return m_count; } - + /// /// Sets the capacity to the actual number of elements. /// @@ -572,7 +572,7 @@ private void ValidateIndex(int i) /// private void ValidateIndex(int i, bool allowEqualEnd) { - int max = (allowEqualEnd) ? (m_count) : (m_count-1); + int max = (allowEqualEnd) ? (m_count) : (m_count - 1); if (i < 0 || i > max) { throw log4net.Util.SystemInfo.CreateArgumentOutOfRangeException("i", (object)i, "Index was out of range. Must be non-negative and less than the size of the collection. [" + (object)i + "] Specified argument was out of the range of valid values."); @@ -591,7 +591,7 @@ private void EnsureCapacity(int min) } #endregion - + #region Implementation (ICollection) void ICollection.CopyTo(Array array, int start) @@ -659,15 +659,15 @@ IEnumerator IEnumerable.GetEnumerator() private sealed class Enumerator : IEnumerator, IPluginCollectionEnumerator { #region Implementation (data) - + private readonly PluginCollection m_collection; private int m_index; private int m_version; - + #endregion Implementation (data) - + #region Construction - + /// /// Initializes a new instance of the Enumerator class. /// @@ -678,11 +678,11 @@ internal Enumerator(PluginCollection tc) m_index = -1; m_version = tc.m_version; } - + #endregion - + #region Operations (type-safe IEnumerator) - + /// /// Gets the current element in the collection. /// @@ -724,14 +724,14 @@ public void Reset() } #endregion - + #region Implementation (IEnumerator) - + object IEnumerator.Current { get { return this.Current; } } - + #endregion } @@ -766,7 +766,7 @@ public override void CopyTo(IPlugin[] array) public override void CopyTo(IPlugin[] array, int start) { - m_collection.CopyTo(array,start); + m_collection.CopyTo(array, start); } public override int Count { @@ -797,7 +797,7 @@ public override int Add(IPlugin x) { throw new NotSupportedException("This is a Read Only Collection and can not be modified"); } - + public override void Clear() { throw new NotSupportedException("This is a Read Only Collection and can not be modified"); @@ -819,7 +819,7 @@ public override void Insert(int pos, IPlugin x) } public override void Remove(IPlugin x) - { + { throw new NotSupportedException("This is a Read Only Collection and can not be modified"); } diff --git a/src/log4net/Plugin/PluginMap.cs b/src/log4net/Plugin/PluginMap.cs index 5c818d3e..9908f36f 100644 --- a/src/log4net/Plugin/PluginMap.cs +++ b/src/log4net/Plugin/PluginMap.cs @@ -82,7 +82,7 @@ public IPlugin this[string name] throw new ArgumentNullException("name"); } - lock(this) + lock (this) { return (IPlugin)m_mapName2Plugin[name]; } @@ -102,13 +102,13 @@ public PluginCollection AllPlugins { get { - lock(this) + lock (this) { return new PluginCollection(m_mapName2Plugin.Values); } } } - + #endregion Public Instance Properties #region Public Instance Methods @@ -137,7 +137,7 @@ public void Add(IPlugin plugin) IPlugin curPlugin = null; - lock(this) + lock (this) { // Get the current plugin if it exists curPlugin = m_mapName2Plugin[plugin.Name] as IPlugin; @@ -171,7 +171,7 @@ public void Remove(IPlugin plugin) { throw new ArgumentNullException("plugin"); } - lock(this) + lock (this) { m_mapName2Plugin.Remove(plugin.Name); } diff --git a/src/log4net/Plugin/PluginSkeleton.cs b/src/log4net/Plugin/PluginSkeleton.cs index 2c3d0f98..df263e1b 100644 --- a/src/log4net/Plugin/PluginSkeleton.cs +++ b/src/log4net/Plugin/PluginSkeleton.cs @@ -70,8 +70,8 @@ protected PluginSkeleton(string name) /// plugin has been attached to a repository. /// /// - public virtual string Name - { + public virtual string Name + { get { return m_name; } set { m_name = value; } } @@ -123,9 +123,9 @@ public virtual void Shutdown() /// attached to. /// /// - protected virtual ILoggerRepository LoggerRepository + protected virtual ILoggerRepository LoggerRepository { - get { return this.m_repository; } + get { return this.m_repository; } set { this.m_repository = value; } } diff --git a/src/log4net/Plugin/RemoteLoggingServerPlugin.cs b/src/log4net/Plugin/RemoteLoggingServerPlugin.cs index ec059785..bee95b4c 100644 --- a/src/log4net/Plugin/RemoteLoggingServerPlugin.cs +++ b/src/log4net/Plugin/RemoteLoggingServerPlugin.cs @@ -77,7 +77,7 @@ public RemoteLoggingServerPlugin() : base("RemoteLoggingServerPlugin:Unset URI") /// with specified name. /// /// - public RemoteLoggingServerPlugin(string sinkUri) : base("RemoteLoggingServerPlugin:"+sinkUri) + public RemoteLoggingServerPlugin(string sinkUri) : base("RemoteLoggingServerPlugin:" + sinkUri) { m_sinkUri = sinkUri; } @@ -98,8 +98,8 @@ public RemoteLoggingServerPlugin(string sinkUri) : base("RemoteLoggingServerPlug /// /// /// - public virtual string SinkUri - { + public virtual string SinkUri + { get { return m_sinkUri; } set { m_sinkUri = value; } } @@ -128,13 +128,13 @@ public override void Attach(ILoggerRepository repository) base.Attach(repository); // Create the sink and marshal it - m_sink = new RemoteLoggingSinkImpl(repository); + m_sink = new RemoteLoggingSinkImpl(repository); try { - RemotingServices.Marshal(m_sink, m_sinkUri, typeof(IRemoteLoggingSink)); + RemotingServices.Marshal(m_sink, m_sinkUri, typeof(IRemoteLoggingSink)); } - catch(Exception ex) + catch (Exception ex) { LogLog.Error(declaringType, "Failed to Marshal remoting sink", ex); } @@ -152,7 +152,7 @@ public override void Attach(ILoggerRepository repository) #if NET_4_0 || MONO_4_0 [System.Security.SecuritySafeCritical] #endif - public override void Shutdown() + public override void Shutdown() { // Stops the sink from receiving messages RemotingServices.Disconnect(m_sink); @@ -170,18 +170,18 @@ public override void Shutdown() #endregion Private Instance Fields - #region Private Static Fields + #region Private Static Fields - /// - /// The fully qualified type of the RemoteLoggingServerPlugin class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(RemoteLoggingServerPlugin); + /// + /// The fully qualified type of the RemoteLoggingServerPlugin class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(RemoteLoggingServerPlugin); - #endregion Private Static Fields + #endregion Private Static Fields /// /// Delivers objects to a remote sink. @@ -228,7 +228,7 @@ public void LogEvents(LoggingEvent[] events) { if (events != null) { - foreach(LoggingEvent logEvent in events) + foreach (LoggingEvent logEvent in events) { if (logEvent != null) { @@ -257,7 +257,7 @@ public void LogEvents(LoggingEvent[] events) #if NET_4_0 || MONO_4_0 [System.Security.SecurityCritical] #endif - public override object InitializeLifetimeService() + public override object InitializeLifetimeService() { return null; } diff --git a/src/log4net/Repository/ConfigurationChangedEventArgs.cs b/src/log4net/Repository/ConfigurationChangedEventArgs.cs index 77df7d41..f20f1c08 100644 --- a/src/log4net/Repository/ConfigurationChangedEventArgs.cs +++ b/src/log4net/Repository/ConfigurationChangedEventArgs.cs @@ -24,28 +24,28 @@ namespace log4net.Repository { + /// + /// + /// + public class ConfigurationChangedEventArgs : EventArgs + { + private readonly ICollection configurationMessages; + /// /// /// - public class ConfigurationChangedEventArgs : EventArgs + /// + public ConfigurationChangedEventArgs(ICollection configurationMessages) { - private readonly ICollection configurationMessages; - - /// - /// - /// - /// - public ConfigurationChangedEventArgs(ICollection configurationMessages) - { - this.configurationMessages = configurationMessages; - } + this.configurationMessages = configurationMessages; + } - /// - /// - /// - public ICollection ConfigurationMessages - { - get { return configurationMessages; } - } + /// + /// + /// + public ICollection ConfigurationMessages + { + get { return configurationMessages; } } + } } diff --git a/src/log4net/Repository/Hierarchy/DefaultLoggerFactory.cs b/src/log4net/Repository/Hierarchy/DefaultLoggerFactory.cs index 9bb079b6..2f55243e 100644 --- a/src/log4net/Repository/Hierarchy/DefaultLoggerFactory.cs +++ b/src/log4net/Repository/Hierarchy/DefaultLoggerFactory.cs @@ -73,7 +73,7 @@ internal DefaultLoggerFactory() /// must be returned. /// /// - public Logger CreateLogger(ILoggerRepository repository, string name) + public Logger CreateLogger(ILoggerRepository repository, string name) { if (name == null) { diff --git a/src/log4net/Repository/Hierarchy/Hierarchy.cs b/src/log4net/Repository/Hierarchy/Hierarchy.cs index ce215be5..144b5c40 100644 --- a/src/log4net/Repository/Hierarchy/Hierarchy.cs +++ b/src/log4net/Repository/Hierarchy/Hierarchy.cs @@ -232,11 +232,11 @@ public bool EmittedNoAppenderWarning /// public Logger Root { - get - { + get + { if (m_root == null) { - lock(this) + lock (this) { if (m_root == null) { @@ -249,7 +249,7 @@ public Logger Root } } } - return m_root; + return m_root; } } @@ -290,14 +290,14 @@ public ILoggerFactory LoggerFactory /// its reference, otherwise returns null. /// /// - public override ILogger Exists(string name) - { + public override ILogger Exists(string name) + { if (name == null) { throw new ArgumentNullException("name"); } - lock(m_ht) + lock (m_ht) { return m_ht[new LoggerKey(name)] as Logger; } @@ -314,19 +314,19 @@ public override ILogger Exists(string name) /// enumeration. /// /// - public override ILogger[] GetCurrentLoggers() + public override ILogger[] GetCurrentLoggers() { // The accumulation in loggers is necessary because not all elements in // ht are Logger objects as there might be some ProvisionNodes // as well. - lock(m_ht) + lock (m_ht) { System.Collections.ArrayList loggers = new System.Collections.ArrayList(m_ht.Count); - + // Iterate through m_ht values - foreach(object node in m_ht.Values) + foreach (object node in m_ht.Values) { - if (node is Logger) + if (node is Logger) { loggers.Add(node); } @@ -352,7 +352,7 @@ public override ILogger[] GetCurrentLoggers() /// /// The name of the logger to retrieve /// The logger object with the name specified - public override ILogger GetLogger(string name) + public override ILogger GetLogger(string name) { if (name == null) { @@ -383,18 +383,18 @@ public override ILogger GetLogger(string name) /// and again to a nested appender. /// /// - public override void Shutdown() + public override void Shutdown() { - LogLog.Debug(declaringType, "Shutdown called on Hierarchy ["+this.Name+"]"); + LogLog.Debug(declaringType, "Shutdown called on Hierarchy [" + this.Name + "]"); // begin by closing nested appenders Root.CloseNestedAppenders(); - lock(m_ht) + lock (m_ht) { ILogger[] currentLoggers = this.GetCurrentLoggers(); - foreach(Logger logger in currentLoggers) + foreach (Logger logger in currentLoggers) { logger.CloseNestedAppenders(); } @@ -402,7 +402,7 @@ public override void Shutdown() // then, remove all appenders Root.RemoveAllAppenders(); - foreach(Logger logger in currentLoggers) + foreach (Logger logger in currentLoggers) { logger.RemoveAllAppenders(); } @@ -431,17 +431,17 @@ public override void Shutdown() /// block all logging until it is completed. /// /// - public override void ResetConfiguration() + public override void ResetConfiguration() { Root.Level = LevelMap.LookupWithDefault(Level.Debug); Threshold = LevelMap.LookupWithDefault(Level.All); - + // the synchronization is needed to prevent hashtable surprises - lock(m_ht) - { + lock (m_ht) + { Shutdown(); // nested locks are OK - - foreach(Logger l in this.GetCurrentLoggers()) + + foreach (Logger l in this.GetCurrentLoggers()) { l.Level = null; l.Additivity = true; @@ -500,7 +500,7 @@ public override Appender.IAppender[] GetAppenders() CollectAppenders(appenderList, Root); - foreach(Logger logger in GetCurrentLoggers()) + foreach (Logger logger in GetCurrentLoggers()) { CollectAppenders(appenderList, logger); } @@ -510,9 +510,9 @@ public override Appender.IAppender[] GetAppenders() #endregion Override Implementation of LoggerRepositorySkeleton - #region Private Static Methods + #region Private Static Methods - /// + /// /// Collect the appenders from an . /// The appender may also be a container. /// @@ -539,17 +539,17 @@ private static void CollectAppender(System.Collections.ArrayList appenderList, A /// private static void CollectAppenders(System.Collections.ArrayList appenderList, IAppenderAttachable container) { - foreach(Appender.IAppender appender in container.Appenders) + foreach (Appender.IAppender appender in container.Appenders) { CollectAppender(appenderList, appender); } - } + } - #endregion + #endregion - #region Implementation of IBasicRepositoryConfigurator + #region Implementation of IBasicRepositoryConfigurator - /// + /// /// Initialize the log4net system using the specified appender /// /// the appender to use to log all logging events @@ -558,14 +558,14 @@ void IBasicRepositoryConfigurator.Configure(IAppender appender) BasicRepositoryConfigure(appender); } - /// - /// Initialize the log4net system using the specified appenders - /// - /// the appenders to use to log all logging events - void IBasicRepositoryConfigurator.Configure(params IAppender[] appenders) - { - BasicRepositoryConfigure(appenders); - } + /// + /// Initialize the log4net system using the specified appenders + /// + /// the appenders to use to log all logging events + void IBasicRepositoryConfigurator.Configure(params IAppender[] appenders) + { + BasicRepositoryConfigure(appenders); + } /// /// Initialize the log4net system using the specified appenders @@ -580,25 +580,25 @@ void IBasicRepositoryConfigurator.Configure(params IAppender[] appenders) /// protected void BasicRepositoryConfigure(params IAppender[] appenders) { - ArrayList configurationMessages = new ArrayList(); + ArrayList configurationMessages = new ArrayList(); - using (new LogLog.LogReceivedAdapter(configurationMessages)) - { - foreach (IAppender appender in appenders) - { - Root.AddAppender(appender); - } - } + using (new LogLog.LogReceivedAdapter(configurationMessages)) + { + foreach (IAppender appender in appenders) + { + Root.AddAppender(appender); + } + } - Configured = true; + Configured = true; - ConfigurationMessages = configurationMessages; + ConfigurationMessages = configurationMessages; // Notify listeners - OnConfigurationChanged(new ConfigurationChangedEventArgs(configurationMessages)); + OnConfigurationChanged(new ConfigurationChangedEventArgs(configurationMessages)); } - #endregion Implementation of IBasicRepositoryConfigurator + #endregion Implementation of IBasicRepositoryConfigurator #region Implementation of IXmlRepositoryConfigurator @@ -624,20 +624,20 @@ void IXmlRepositoryConfigurator.Configure(System.Xml.XmlElement element) /// protected void XmlRepositoryConfigure(System.Xml.XmlElement element) { - ArrayList configurationMessages = new ArrayList(); + ArrayList configurationMessages = new ArrayList(); - using (new LogLog.LogReceivedAdapter(configurationMessages)) - { - XmlHierarchyConfigurator config = new XmlHierarchyConfigurator(this); - config.Configure(element); - } + using (new LogLog.LogReceivedAdapter(configurationMessages)) + { + XmlHierarchyConfigurator config = new XmlHierarchyConfigurator(this); + config.Configure(element); + } - Configured = true; + Configured = true; - ConfigurationMessages = configurationMessages; + ConfigurationMessages = configurationMessages; // Notify listeners - OnConfigurationChanged(new ConfigurationChangedEventArgs(configurationMessages)); + OnConfigurationChanged(new ConfigurationChangedEventArgs(configurationMessages)); } #endregion Implementation of IXmlRepositoryConfigurator @@ -665,7 +665,7 @@ protected void XmlRepositoryConfigure(System.Xml.XmlElement element) /// See also the property. /// /// - public bool IsDisabled(Level level) + public bool IsDisabled(Level level) { // Cast level to object for performance if ((object)level == null) @@ -698,9 +698,9 @@ public bool IsDisabled(Level level) /// invoking this method. /// /// - public void Clear() + public void Clear() { - lock(m_ht) + lock (m_ht) { m_ht.Clear(); } @@ -721,7 +721,7 @@ public void Clear() /// ancestors as well as children. /// /// - public Logger GetLogger(string name, ILoggerFactory factory) + public Logger GetLogger(string name, ILoggerFactory factory) { if (name == null) { @@ -732,41 +732,41 @@ public Logger GetLogger(string name, ILoggerFactory factory) throw new ArgumentNullException("factory"); } - LoggerKey key = new LoggerKey(name); - + LoggerKey key = new LoggerKey(name); + // Synchronize to prevent write conflicts. Read conflicts (in // GetEffectiveLevel() method) are possible only if variable // assignments are non-atomic. - lock(m_ht) + lock (m_ht) { Logger logger = null; Object node = m_ht[key]; - if (node == null) + if (node == null) { logger = factory.CreateLogger(this, name); logger.Hierarchy = this; - m_ht[key] = logger; + m_ht[key] = logger; UpdateParents(logger); OnLoggerCreationEvent(logger); return logger; - } - + } + Logger nodeLogger = node as Logger; - if (nodeLogger != null) + if (nodeLogger != null) { return nodeLogger; - } - + } + ProvisionNode nodeProvisionNode = node as ProvisionNode; - if (nodeProvisionNode != null) + if (nodeProvisionNode != null) { logger = factory.CreateLogger(this, name); - logger.Hierarchy = this; + logger.Hierarchy = this; m_ht[key] = logger; UpdateChildren(nodeProvisionNode, logger); - UpdateParents(logger); + UpdateParents(logger); OnLoggerCreationEvent(logger); return logger; } @@ -787,7 +787,7 @@ public Logger GetLogger(string name, ILoggerFactory factory) /// /// Raises the logger creation event. /// - protected virtual void OnLoggerCreationEvent(Logger logger) + protected virtual void OnLoggerCreationEvent(Logger logger) { LoggerCreationEventHandler handler = m_loggerCreatedEvent; if (handler != null) @@ -835,25 +835,25 @@ protected virtual void OnLoggerCreationEvent(Logger logger) /// /// /// - private void UpdateParents(Logger log) + private void UpdateParents(Logger log) { string name = log.Name; int length = name.Length; bool parentFound = false; - + // if name = "w.x.y.z", loop through "w.x.y", "w.x" and "w", but not "w.x.y.z" - for(int i = name.LastIndexOf('.', length-1); i >= 0; i = name.LastIndexOf('.', i-1)) + for (int i = name.LastIndexOf('.', length - 1); i >= 0; i = name.LastIndexOf('.', i - 1)) { string substr = name.Substring(0, i); LoggerKey key = new LoggerKey(substr); // simple constructor Object node = m_ht[key]; // Create a provision node for a future parent. - if (node == null) + if (node == null) { ProvisionNode pn = new ProvisionNode(log); m_ht[key] = pn; - } + } else { Logger nodeLogger = node as Logger; @@ -872,19 +872,20 @@ private void UpdateParents(Logger log) } else { - LogLog.Error(declaringType, "Unexpected object type ["+node.GetType()+"] in ht.", new LogException()); + LogLog.Error(declaringType, "Unexpected object type [" + node.GetType() + "] in ht.", new LogException()); } - } + } } - if (i == 0) { - // logger name starts with a dot - // and we've hit the start - break; + if (i == 0) + { + // logger name starts with a dot + // and we've hit the start + break; } } // If we could not find any existing parents, then link with root. - if (!parentFound) + if (!parentFound) { log.Parent = this.Root; } @@ -914,18 +915,18 @@ private void UpdateParents(Logger log) /// c's parent field to log. /// /// - private static void UpdateChildren(ProvisionNode pn, Logger log) + private static void UpdateChildren(ProvisionNode pn, Logger log) { - for(int i = 0; i < pn.Count; i++) + for (int i = 0; i < pn.Count; i++) { Logger childLogger = (Logger)pn[i]; // Unless this child already points to a correct (lower) parent, // make log.Parent point to childLogger.Parent and childLogger.Parent to log. - if (!childLogger.Parent.Name.StartsWith(log.Name)) + if (!childLogger.Parent.Name.StartsWith(log.Name)) { log.Parent = childLogger.Parent; - childLogger.Parent = log; + childLogger.Parent = log; } } } @@ -953,7 +954,7 @@ internal void AddLevel(LevelEntry levelEntry) Level previousLevel = LevelMap[levelEntry.Name]; if (previousLevel == null) { - throw new InvalidOperationException("Cannot redefine level ["+levelEntry.Name+"] because it is not defined in the LevelMap. To define the level supply the level value."); + throw new InvalidOperationException("Cannot redefine level [" + levelEntry.Name + "] because it is not defined in the LevelMap. To define the level supply the level value."); } levelEntry.Value = previousLevel.Value; @@ -1031,7 +1032,7 @@ public string DisplayName /// string info about this object public override string ToString() { - return "LevelEntry(Value="+m_levelValue+", Name="+m_levelName+", DisplayName="+m_levelDisplayName+")"; + return "LevelEntry(Value=" + m_levelValue + ", Name=" + m_levelName + ", DisplayName=" + m_levelDisplayName + ")"; } } @@ -1063,24 +1064,24 @@ internal void AddProperty(PropertyEntry propertyEntry) private System.Collections.Hashtable m_ht; private Logger m_root; - + private bool m_emittedNoAppenderWarning = false; - private event LoggerCreationEventHandler m_loggerCreatedEvent; + private event LoggerCreationEventHandler m_loggerCreatedEvent; #endregion Private Instance Fields - #region Private Static Fields + #region Private Static Fields - /// - /// The fully qualified type of the Hierarchy class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(Hierarchy); + /// + /// The fully qualified type of the Hierarchy class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(Hierarchy); - #endregion Private Static Fields + #endregion Private Static Fields } } diff --git a/src/log4net/Repository/Hierarchy/Logger.cs b/src/log4net/Repository/Hierarchy/Logger.cs index dbeab32e..0ec41db2 100644 --- a/src/log4net/Repository/Hierarchy/Logger.cs +++ b/src/log4net/Repository/Hierarchy/Logger.cs @@ -70,7 +70,7 @@ public abstract class Logger : IAppenderAttachable, ILogger /// logger creator. /// /// - protected Logger(string name) + protected Logger(string name) { #if NETCF || NETSTANDARD1_3 // NETCF: String.Intern causes Native Exception @@ -140,14 +140,14 @@ public virtual bool Additivity /// public virtual Level EffectiveLevel { - get + get { - for(Logger c = this; c != null; c = c.m_parent) + for (Logger c = this; c != null; c = c.m_parent) { Level level = c.m_level; // Casting level to Object for performance, otherwise the overloaded operator is called - if ((object)level != null) + if ((object)level != null) { return level; } @@ -208,7 +208,7 @@ public virtual Level Level /// appenders, then it won't be added again. /// /// - public virtual void AddAppender(IAppender newAppender) + public virtual void AddAppender(IAppender newAppender) { if (newAppender == null) { @@ -218,7 +218,7 @@ public virtual void AddAppender(IAppender newAppender) m_appenderLock.AcquireWriterLock(); try { - if (m_appenderAttachedImpl == null) + if (m_appenderAttachedImpl == null) { m_appenderAttachedImpl = new log4net.Util.AppenderAttachedImpl(); } @@ -242,7 +242,7 @@ public virtual void AddAppender(IAppender newAppender) /// can be found, then a is returned. /// /// - public virtual AppenderCollection Appenders + public virtual AppenderCollection Appenders { get { @@ -253,7 +253,7 @@ public virtual AppenderCollection Appenders { return AppenderCollection.EmptyCollection; } - else + else { return m_appenderAttachedImpl.Appenders; } @@ -275,7 +275,7 @@ public virtual AppenderCollection Appenders /// Returns the named appender, or null if the appender is not found. /// /// - public virtual IAppender GetAppender(string name) + public virtual IAppender GetAppender(string name) { m_appenderLock.AcquireReaderLock(); try @@ -304,12 +304,12 @@ public virtual IAppender GetAppender(string name) /// This is useful when re-reading configuration information. /// /// - public virtual void RemoveAllAppenders() + public virtual void RemoveAllAppenders() { m_appenderLock.AcquireWriterLock(); try { - if (m_appenderAttachedImpl != null) + if (m_appenderAttachedImpl != null) { m_appenderAttachedImpl.RemoveAllAppenders(); m_appenderAttachedImpl = null; @@ -334,12 +334,12 @@ public virtual void RemoveAllAppenders() /// on the appender removed. /// /// - public virtual IAppender RemoveAppender(IAppender appender) + public virtual IAppender RemoveAppender(IAppender appender) { m_appenderLock.AcquireWriterLock(); try { - if (appender != null && m_appenderAttachedImpl != null) + if (appender != null && m_appenderAttachedImpl != null) { return m_appenderAttachedImpl.RemoveAppender(appender); } @@ -364,7 +364,7 @@ public virtual IAppender RemoveAppender(IAppender appender) /// on the appender removed. /// /// - public virtual IAppender RemoveAppender(string name) + public virtual IAppender RemoveAppender(string name) { m_appenderLock.AcquireWriterLock(); try @@ -380,7 +380,7 @@ public virtual IAppender RemoveAppender(string name) } return null; } - + #endregion #region Implementation of ILogger @@ -418,13 +418,13 @@ public virtual string Name /// This method must not throw any exception to the caller. /// /// - public virtual void Log(Type callerStackBoundaryDeclaringType, Level level, object message, Exception exception) + public virtual void Log(Type callerStackBoundaryDeclaringType, Level level, object message, Exception exception) { try { if (IsEnabledFor(level)) { - ForcedLog((callerStackBoundaryDeclaringType != null) ? callerStackBoundaryDeclaringType : declaringType, level, message, exception); + ForcedLog((callerStackBoundaryDeclaringType != null) ? callerStackBoundaryDeclaringType : declaringType, level, message, exception); } } catch (Exception ex) @@ -531,11 +531,11 @@ public virtual bool IsEnabledFor(Level level) /// /// public ILoggerRepository Repository - { + { get { return m_hierarchy; } } - #endregion Implementation of ILogger + #endregion Implementation of ILogger /// /// Deliver the to the attached appenders. @@ -553,7 +553,7 @@ public ILoggerRepository Repository /// to log the particular log request. /// /// - protected virtual void CallAppenders(LoggingEvent loggingEvent) + protected virtual void CallAppenders(LoggingEvent loggingEvent) { if (loggingEvent == null) { @@ -562,15 +562,15 @@ protected virtual void CallAppenders(LoggingEvent loggingEvent) int writes = 0; - for(Logger c=this; c != null; c=c.m_parent) + for (Logger c = this; c != null; c = c.m_parent) { - if (c.m_appenderAttachedImpl != null) + if (c.m_appenderAttachedImpl != null) { // Protected against simultaneous call to addAppender, removeAppender,... c.m_appenderLock.AcquireReaderLock(); try { - if (c.m_appenderAttachedImpl != null) + if (c.m_appenderAttachedImpl != null) { writes += c.m_appenderAttachedImpl.AppendLoopOnAppenders(loggingEvent); } @@ -581,12 +581,12 @@ protected virtual void CallAppenders(LoggingEvent loggingEvent) } } - if (!c.m_additive) + if (!c.m_additive) { break; } } - + // No appenders in hierarchy, warn user only once. // // Note that by including the AppDomain values for the currently running @@ -596,7 +596,7 @@ protected virtual void CallAppenders(LoggingEvent loggingEvent) // or impossible to determine which .config file is missing appender // definitions. // - if (!m_hierarchy.EmittedNoAppenderWarning && writes == 0) + if (!m_hierarchy.EmittedNoAppenderWarning && writes == 0) { m_hierarchy.EmittedNoAppenderWarning = true; LogLog.Debug(declaringType, "No appenders could be found for logger [" + Name + "] repository [" + Repository.Name + "]"); @@ -610,7 +610,7 @@ protected virtual void CallAppenders(LoggingEvent loggingEvent) LogLog.Debug(declaringType, " DynamicDirectory: " + AppDomain.CurrentDomain.DynamicDirectory); #endif } - catch(System.Security.SecurityException) + catch (System.Security.SecurityException) { // Insufficient permissions to display info from the AppDomain } @@ -625,7 +625,7 @@ protected virtual void CallAppenders(LoggingEvent loggingEvent) /// Used to ensure that the appenders are correctly shutdown. /// /// - public virtual void CloseNestedAppenders() + public virtual void CloseNestedAppenders() { m_appenderLock.AcquireWriterLock(); try @@ -633,7 +633,7 @@ public virtual void CloseNestedAppenders() if (m_appenderAttachedImpl != null) { AppenderCollection appenders = m_appenderAttachedImpl.Appenders; - foreach(IAppender appender in appenders) + foreach (IAppender appender in appenders) { if (appender is IAppenderAttachable) { @@ -660,11 +660,11 @@ public virtual void CloseNestedAppenders() /// the . /// /// - public virtual void Log(Level level, object message, Exception exception) + public virtual void Log(Level level, object message, Exception exception) { if (IsEnabledFor(level)) { - ForcedLog(declaringType, level, message, exception); + ForcedLog(declaringType, level, message, exception); } } @@ -682,7 +682,7 @@ public virtual void Log(Level level, object message, Exception exception) /// appenders. /// /// - protected virtual void ForcedLog(Type callerStackBoundaryDeclaringType, Level level, object message, Exception exception) + protected virtual void ForcedLog(Type callerStackBoundaryDeclaringType, Level level, object message, Exception exception) { CallAppenders(new LoggingEvent(callerStackBoundaryDeclaringType, this.Hierarchy, this.Name, level, message, exception)); } @@ -696,7 +696,7 @@ protected virtual void ForcedLog(Type callerStackBoundaryDeclaringType, Level le /// Delivers the logging event to the attached appenders. /// /// - protected virtual void ForcedLog(LoggingEvent logEvent) + protected virtual void ForcedLog(LoggingEvent logEvent) { // The logging event may not have been created by this logger // the Repository may not be correctly set on the event. This @@ -708,10 +708,10 @@ protected virtual void ForcedLog(LoggingEvent logEvent) #region Private Static Fields - /// - /// The fully qualified type of the Logger class. - /// - private static readonly Type declaringType = typeof(Logger); + /// + /// The fully qualified type of the Logger class. + /// + private static readonly Type declaringType = typeof(Logger); #endregion Private Static Fields @@ -720,7 +720,7 @@ protected virtual void ForcedLog(LoggingEvent logEvent) /// /// The name of this logger. /// - private readonly string m_name; + private readonly string m_name; /// /// The assigned level of this logger. @@ -782,7 +782,7 @@ protected virtual void ForcedLog(LoggingEvent logEvent) /// Lock to protect AppenderAttachedImpl variable m_appenderAttachedImpl /// private readonly ReaderWriterLock m_appenderLock = new ReaderWriterLock(); - + #endregion } } diff --git a/src/log4net/Repository/Hierarchy/LoggerKey.cs b/src/log4net/Repository/Hierarchy/LoggerKey.cs index 00671520..7d74ad83 100644 --- a/src/log4net/Repository/Hierarchy/LoggerKey.cs +++ b/src/log4net/Repository/Hierarchy/LoggerKey.cs @@ -62,7 +62,7 @@ internal sealed class LoggerKey /// /// /// The name of the logger. - internal LoggerKey(string name) + internal LoggerKey(string name) { #if NETCF || NETSTANDARD1_3 // NETCF: String.Intern causes Native Exception @@ -86,7 +86,7 @@ internal LoggerKey(string name) /// Returns the cached hashcode. /// /// - public override int GetHashCode() + public override int GetHashCode() { return m_hashCache; } @@ -104,22 +104,22 @@ public override int GetHashCode() /// Compares the references of the interned strings. /// /// - public override bool Equals(object obj) + public override bool Equals(object obj) { // Compare reference type of this against argument if (((object)this) == obj) { return true; } - + LoggerKey objKey = obj as LoggerKey; - if (objKey != null) + if (objKey != null) { #if NETCF || NETSTANDARD1_3 return ( m_name == objKey.m_name ); #else // Compare reference types rather than string's overloaded == - return ( ((object)m_name) == ((object)objKey.m_name) ); + return (((object)m_name) == ((object)objKey.m_name)); #endif } return false; @@ -129,10 +129,10 @@ public override bool Equals(object obj) #region Private Instance Fields - private readonly string m_name; + private readonly string m_name; private readonly int m_hashCache; #endregion Private Instance Fields - } + } } diff --git a/src/log4net/Repository/Hierarchy/RootLogger.cs b/src/log4net/Repository/Hierarchy/RootLogger.cs index dae8aa9c..10cb8780 100644 --- a/src/log4net/Repository/Hierarchy/RootLogger.cs +++ b/src/log4net/Repository/Hierarchy/RootLogger.cs @@ -79,9 +79,9 @@ public RootLogger(Level level) : base("root") /// value of . /// /// - public override Level EffectiveLevel + public override Level EffectiveLevel { - get + get { return base.Level; } @@ -104,11 +104,11 @@ public override Level Level get { return base.Level; } set { - if (value == null) + if (value == null) { LogLog.Error(declaringType, "You have tried to set a null level to root.", new LogException()); } - else + else { base.Level = value; } @@ -117,17 +117,17 @@ public override Level Level #endregion Override implementation of Logger - #region Private Static Fields + #region Private Static Fields - /// - /// The fully qualified type of the RootLogger class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(RootLogger); + /// + /// The fully qualified type of the RootLogger class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(RootLogger); - #endregion Private Static Fields + #endregion Private Static Fields } } diff --git a/src/log4net/Repository/Hierarchy/XmlHierarchyConfigurator.cs b/src/log4net/Repository/Hierarchy/XmlHierarchyConfigurator.cs index b7bb6053..164933fa 100644 --- a/src/log4net/Repository/Hierarchy/XmlHierarchyConfigurator.cs +++ b/src/log4net/Repository/Hierarchy/XmlHierarchyConfigurator.cs @@ -44,7 +44,7 @@ public class XmlHierarchyConfigurator { private enum ConfigUpdateMode { - Merge, + Merge, Overwrite } @@ -60,7 +60,7 @@ private enum ConfigUpdateMode /// with the specified . /// /// - public XmlHierarchyConfigurator(Hierarchy hierarchy) + public XmlHierarchyConfigurator(Hierarchy hierarchy) { m_hierarchy = hierarchy; m_appenderBag = new Hashtable(); @@ -79,11 +79,11 @@ public XmlHierarchyConfigurator(Hierarchy hierarchy) /// Configure the hierarchy by parsing a DOM tree of XML elements. /// /// - public void Configure(XmlElement element) + public void Configure(XmlElement element) { if (element == null || m_hierarchy == null) { - return; + return; } string rootElementName = element.LocalName; @@ -91,43 +91,43 @@ public void Configure(XmlElement element) if (rootElementName != CONFIGURATION_TAG) { LogLog.Error(declaringType, "Xml element is - not a <" + CONFIGURATION_TAG + "> element."); - return; + return; } - if (!LogLog.EmitInternalMessages) - { - // Look for a emitDebug attribute to enable internal debug - string emitDebugAttribute = element.GetAttribute(EMIT_INTERNAL_DEBUG_ATTR); - LogLog.Debug(declaringType, EMIT_INTERNAL_DEBUG_ATTR + " attribute [" + emitDebugAttribute + "]."); + if (!LogLog.EmitInternalMessages) + { + // Look for a emitDebug attribute to enable internal debug + string emitDebugAttribute = element.GetAttribute(EMIT_INTERNAL_DEBUG_ATTR); + LogLog.Debug(declaringType, EMIT_INTERNAL_DEBUG_ATTR + " attribute [" + emitDebugAttribute + "]."); - if (emitDebugAttribute.Length > 0 && emitDebugAttribute != "null") - { - LogLog.EmitInternalMessages = OptionConverter.ToBoolean(emitDebugAttribute, true); - } - else - { - LogLog.Debug(declaringType, "Ignoring " + EMIT_INTERNAL_DEBUG_ATTR + " attribute."); - } - } + if (emitDebugAttribute.Length > 0 && emitDebugAttribute != "null") + { + LogLog.EmitInternalMessages = OptionConverter.ToBoolean(emitDebugAttribute, true); + } + else + { + LogLog.Debug(declaringType, "Ignoring " + EMIT_INTERNAL_DEBUG_ATTR + " attribute."); + } + } - if (!LogLog.InternalDebugging) + if (!LogLog.InternalDebugging) { // Look for a debug attribute to enable internal debug string debugAttribute = element.GetAttribute(INTERNAL_DEBUG_ATTR); - LogLog.Debug(declaringType, INTERNAL_DEBUG_ATTR+" attribute [" + debugAttribute + "]."); + LogLog.Debug(declaringType, INTERNAL_DEBUG_ATTR + " attribute [" + debugAttribute + "]."); - if (debugAttribute.Length>0 && debugAttribute != "null") - { + if (debugAttribute.Length > 0 && debugAttribute != "null") + { LogLog.InternalDebugging = OptionConverter.ToBoolean(debugAttribute, true); } - else + else { LogLog.Debug(declaringType, "Ignoring " + INTERNAL_DEBUG_ATTR + " attribute."); } string confDebug = element.GetAttribute(CONFIG_DEBUG_ATTR); - if (confDebug.Length>0 && confDebug != "null") - { + if (confDebug.Length > 0 && confDebug != "null") + { LogLog.Warn(declaringType, "The \"" + CONFIG_DEBUG_ATTR + "\" attribute is deprecated."); LogLog.Warn(declaringType, "Use the \"" + INTERNAL_DEBUG_ATTR + "\" attribute instead."); LogLog.InternalDebugging = OptionConverter.ToBoolean(confDebug, true); @@ -170,23 +170,23 @@ public void Configure(XmlElement element) foreach (XmlNode currentNode in element.ChildNodes) { - if (currentNode.NodeType == XmlNodeType.Element) + if (currentNode.NodeType == XmlNodeType.Element) { XmlElement currentElement = (XmlElement)currentNode; if (currentElement.LocalName == LOGGER_TAG) { ParseLogger(currentElement); - } + } else if (currentElement.LocalName == CATEGORY_TAG) { // TODO: deprecated use of category ParseLogger(currentElement); - } + } else if (currentElement.LocalName == ROOT_TAG) { ParseRoot(currentElement); - } + } else if (currentElement.LocalName == RENDERER_TAG) { ParseRenderer(currentElement); @@ -207,9 +207,9 @@ public void Configure(XmlElement element) // Lastly set the hierarchy threshold string thresholdStr = element.GetAttribute(THRESHOLD_ATTR); LogLog.Debug(declaringType, "Hierarchy Threshold [" + thresholdStr + "]"); - if (thresholdStr.Length > 0 && thresholdStr != "null") + if (thresholdStr.Length > 0 && thresholdStr != "null") { - Level thresholdLevel = (Level) ConvertStringTo(typeof(Level), thresholdStr); + Level thresholdLevel = (Level)ConvertStringTo(typeof(Level), thresholdStr); if (thresholdLevel != null) { m_hierarchy.Threshold = thresholdLevel; @@ -223,7 +223,7 @@ public void Configure(XmlElement element) // Done reading config } - #endregion Public Instance Methods + #endregion Public Instance Methods #region Protected Instance Methods @@ -238,16 +238,16 @@ public void Configure(XmlElement element) /// the appender. /// /// - protected IAppender FindAppenderByReference(XmlElement appenderRef) - { + protected IAppender FindAppenderByReference(XmlElement appenderRef) + { string appenderName = appenderRef.GetAttribute(REF_ATTR); IAppender appender = (IAppender)m_appenderBag[appenderName]; - if (appender != null) + if (appender != null) { return appender; - } - else + } + else { // Find the element with that id XmlElement element = null; @@ -264,11 +264,11 @@ protected IAppender FindAppenderByReference(XmlElement appenderRef) } } - if (element == null) + if (element == null) { - LogLog.Error(declaringType, "XmlHierarchyConfigurator: No appender named [" + appenderName + "] could be found."); + LogLog.Error(declaringType, "XmlHierarchyConfigurator: No appender named [" + appenderName + "] could be found."); return null; - } + } else { appender = ParseAppender(element); @@ -278,7 +278,7 @@ protected IAppender FindAppenderByReference(XmlElement appenderRef) } return appender; } - } + } } /// @@ -292,13 +292,13 @@ protected IAppender FindAppenderByReference(XmlElement appenderRef) /// the appender instance. /// /// - protected IAppender ParseAppender(XmlElement appenderElement) + protected IAppender ParseAppender(XmlElement appenderElement) { string appenderName = appenderElement.GetAttribute(NAME_ATTR); string typeName = appenderElement.GetAttribute(TYPE_ATTR); LogLog.Debug(declaringType, "Loading Appender [" + appenderName + "] type: [" + typeName + "]"); - try + try { #if NETSTANDARD1_3 IAppender appender = (IAppender)Activator.CreateInstance(SystemInfo.GetTypeFromString(this.GetType().GetTypeInfo().Assembly, typeName, true, true)); @@ -310,7 +310,7 @@ protected IAppender ParseAppender(XmlElement appenderElement) foreach (XmlNode currentNode in appenderElement.ChildNodes) { /* We're only interested in Elements */ - if (currentNode.NodeType == XmlNodeType.Element) + if (currentNode.NodeType == XmlNodeType.Element) { XmlElement currentElement = (XmlElement)currentNode; @@ -320,7 +320,7 @@ protected IAppender ParseAppender(XmlElement appenderElement) string refName = currentElement.GetAttribute(REF_ATTR); IAppenderAttachable appenderContainer = appender as IAppenderAttachable; - if (appenderContainer != null) + if (appenderContainer != null) { LogLog.Debug(declaringType, "Attaching appender named [" + refName + "] to appender named [" + appender.Name + "]."); @@ -329,10 +329,10 @@ protected IAppender ParseAppender(XmlElement appenderElement) { appenderContainer.AddAppender(referencedAppender); } - } - else + } + else { - LogLog.Error(declaringType, "Requesting attachment of appender named ["+refName+ "] to appender named [" + appender.Name + "] which does not implement log4net.Core.IAppenderAttachable."); + LogLog.Error(declaringType, "Requesting attachment of appender named [" + refName + "] to appender named [" + appender.Name + "] which does not implement log4net.Core.IAppenderAttachable."); } } else @@ -344,15 +344,15 @@ protected IAppender ParseAppender(XmlElement appenderElement) } IOptionHandler optionHandler = appender as IOptionHandler; - if (optionHandler != null) + if (optionHandler != null) { optionHandler.ActivateOptions(); } - LogLog.Debug(declaringType, "Created Appender [" + appenderName + "]"); + LogLog.Debug(declaringType, "Created Appender [" + appenderName + "]"); return appender; } - catch (Exception ex) + catch (Exception ex) { // Yes, it's ugly. But all exceptions point to the same problem: we can't create an Appender @@ -370,7 +370,7 @@ protected IAppender ParseAppender(XmlElement appenderElement) /// Parse an XML element that represents a logger. /// /// - protected void ParseLogger(XmlElement loggerElement) + protected void ParseLogger(XmlElement loggerElement) { // Create a new log4net.Logger object from the element. string loggerName = loggerElement.GetAttribute(NAME_ATTR); @@ -381,10 +381,10 @@ protected void ParseLogger(XmlElement loggerElement) // Setting up a logger needs to be an atomic operation, in order // to protect potential log operations while logger // configuration is in progress. - lock(log) + lock (log) { bool additivity = OptionConverter.ToBoolean(loggerElement.GetAttribute(ADDITIVITY_ATTR), true); - + LogLog.Debug(declaringType, "Setting [" + log.Name + "] additivity to [" + additivity + "]."); log.Additivity = additivity; ParseChildrenOfLoggerElement(loggerElement, log, false); @@ -400,12 +400,12 @@ protected void ParseLogger(XmlElement loggerElement) /// Parse an XML element that represents the root logger. /// /// - protected void ParseRoot(XmlElement rootElement) + protected void ParseRoot(XmlElement rootElement) { Logger root = m_hierarchy.Root; // logger configuration needs to be atomic - lock(root) - { + lock (root) + { ParseChildrenOfLoggerElement(rootElement, root, true); } } @@ -421,7 +421,7 @@ protected void ParseRoot(XmlElement rootElement) /// Parse the child elements of a <logger> element. /// /// - protected void ParseChildrenOfLoggerElement(XmlElement catElement, Logger log, bool isRoot) + protected void ParseChildrenOfLoggerElement(XmlElement catElement, Logger log, bool isRoot) { // Remove all existing appenders from log. They will be // reconstructed if need be. @@ -429,28 +429,28 @@ protected void ParseChildrenOfLoggerElement(XmlElement catElement, Logger log, b foreach (XmlNode currentNode in catElement.ChildNodes) { - if (currentNode.NodeType == XmlNodeType.Element) + if (currentNode.NodeType == XmlNodeType.Element) { - XmlElement currentElement = (XmlElement) currentNode; - + XmlElement currentElement = (XmlElement)currentNode; + if (currentElement.LocalName == APPENDER_REF_TAG) { IAppender appender = FindAppenderByReference(currentElement); - string refName = currentElement.GetAttribute(REF_ATTR); + string refName = currentElement.GetAttribute(REF_ATTR); if (appender != null) { LogLog.Debug(declaringType, "Adding appender named [" + refName + "] to logger [" + log.Name + "]."); log.AddAppender(appender); } - else + else { LogLog.Error(declaringType, "Appender named [" + refName + "] not found."); } - } - else if (currentElement.LocalName == LEVEL_TAG || currentElement.LocalName == PRIORITY_TAG) + } + else if (currentElement.LocalName == LEVEL_TAG || currentElement.LocalName == PRIORITY_TAG) { - ParseLevel(currentElement, log, isRoot); - } + ParseLevel(currentElement, log, isRoot); + } else { SetParameter(currentElement, log); @@ -459,7 +459,7 @@ protected void ParseChildrenOfLoggerElement(XmlElement catElement, Logger log, b } IOptionHandler optionHandler = log as IOptionHandler; - if (optionHandler != null) + if (optionHandler != null) { optionHandler.ActivateOptions(); } @@ -474,29 +474,29 @@ protected void ParseChildrenOfLoggerElement(XmlElement catElement, Logger log, b /// Parse an XML element that represents a renderer. /// /// - protected void ParseRenderer(XmlElement element) + protected void ParseRenderer(XmlElement element) { string renderingClassName = element.GetAttribute(RENDERING_TYPE_ATTR); string renderedClassName = element.GetAttribute(RENDERED_TYPE_ATTR); LogLog.Debug(declaringType, "Rendering class [" + renderingClassName + "], Rendered class [" + renderedClassName + "]."); IObjectRenderer renderer = (IObjectRenderer)OptionConverter.InstantiateByClassName(renderingClassName, typeof(IObjectRenderer), null); - if (renderer == null) + if (renderer == null) { LogLog.Error(declaringType, "Could not instantiate renderer [" + renderingClassName + "]."); return; - } - else + } + else { - try + try { #if NETSTANDARD1_3 m_hierarchy.RendererMap.Put(SystemInfo.GetTypeFromString(this.GetType().GetTypeInfo().Assembly, renderedClassName, true, true), renderer); #else m_hierarchy.RendererMap.Put(SystemInfo.GetTypeFromString(renderedClassName, true, true), renderer); #endif - } - catch(Exception e) + } + catch (Exception e) { LogLog.Error(declaringType, "Could not find class [" + renderedClassName + "].", e); } @@ -514,30 +514,30 @@ protected void ParseRenderer(XmlElement element) /// Parse an XML element that represents a level. /// /// - protected void ParseLevel(XmlElement element, Logger log, bool isRoot) + protected void ParseLevel(XmlElement element, Logger log, bool isRoot) { string loggerName = log.Name; - if (isRoot) + if (isRoot) { loggerName = "root"; } string levelStr = element.GetAttribute(VALUE_ATTR); LogLog.Debug(declaringType, "Logger [" + loggerName + "] Level string is [" + levelStr + "]."); - - if (INHERITED == levelStr) + + if (INHERITED == levelStr) { - if (isRoot) + if (isRoot) { LogLog.Error(declaringType, "Root level cannot be inherited. Ignoring directive."); - } - else + } + else { - LogLog.Debug(declaringType, "Logger [" + loggerName + "] level set to inherit from parent."); + LogLog.Debug(declaringType, "Logger [" + loggerName + "] level set to inherit from parent."); log.Level = null; } - } - else + } + else { log.Level = log.Hierarchy.LevelMap[levelStr]; if (log.Level == null) @@ -546,7 +546,7 @@ protected void ParseLevel(XmlElement element, Logger log, bool isRoot) } else { - LogLog.Debug(declaringType, "Logger [" + loggerName + "] level set to [name=\"" + log.Level.Name + "\",value=" + log.Level.Value + "]."); + LogLog.Debug(declaringType, "Logger [" + loggerName + "] level set to [name=\"" + log.Level.Name + "\",value=" + log.Level.Value + "]."); } } } @@ -567,7 +567,7 @@ protected void ParseLevel(XmlElement element, Logger log, bool isRoot) /// string argument and return a value that can be used to /// set the property. /// - protected void SetParameter(XmlElement element, object target) + protected void SetParameter(XmlElement element, object target) { // Get the property name string name = element.GetAttribute(NAME_ATTR); @@ -620,7 +620,7 @@ protected void SetParameter(XmlElement element, object target) else if (element.HasChildNodes) { // Concatenate the CDATA and Text nodes together - foreach(XmlNode childNode in element.ChildNodes) + foreach (XmlNode childNode in element.ChildNodes) { if (childNode.NodeType == XmlNodeType.CDATA || childNode.NodeType == XmlNodeType.Text) { @@ -636,19 +636,20 @@ protected void SetParameter(XmlElement element, object target) } } - if(propertyValue != null) + if (propertyValue != null) { #if !NETCF && !NETSTANDARD1_3 // NETSTANDARD1_3: System.Runtime.InteropServices.RuntimeInformation not available on desktop 4.6 try { // Expand environment variables in the string. - IDictionary environmentVariables = Environment.GetEnvironmentVariables(); - if (HasCaseInsensitiveEnvironment) { - environmentVariables = CreateCaseInsensitiveWrapper(environmentVariables); - } + IDictionary environmentVariables = Environment.GetEnvironmentVariables(); + if (HasCaseInsensitiveEnvironment) + { + environmentVariables = CreateCaseInsensitiveWrapper(environmentVariables); + } propertyValue = OptionConverter.SubstituteVariables(propertyValue, environmentVariables); } - catch(System.Security.SecurityException) + catch (System.Security.SecurityException) { // This security exception will occur if the caller does not have // unrestricted environment permission. If this occurs the expansion @@ -672,7 +673,7 @@ protected void SetParameter(XmlElement element, object target) Type subType = SystemInfo.GetTypeFromString(subTypeString, true, true); #endif - LogLog.Debug(declaringType, "Parameter ["+name+"] specified subtype ["+subType.FullName+"]"); + LogLog.Debug(declaringType, "Parameter [" + name + "] specified subtype [" + subType.FullName + "]"); if (!propertyType.IsAssignableFrom(subType)) { @@ -687,7 +688,7 @@ protected void SetParameter(XmlElement element, object target) } else { - LogLog.Error(declaringType, "subtype ["+subType.FullName+"] set on ["+name+"] is not a subclass of property type ["+propertyType.FullName+"] and there are no acceptable type conversions."); + LogLog.Error(declaringType, "subtype [" + subType.FullName + "] set on [" + name + "] is not a subclass of property type [" + propertyType.FullName + "] and there are no acceptable type conversions."); } } else @@ -697,9 +698,9 @@ protected void SetParameter(XmlElement element, object target) propertyType = subType; } } - catch(Exception ex) + catch (Exception ex) { - LogLog.Error(declaringType, "Failed to find type ["+subTypeString+"] set on ["+name+"]", ex); + LogLog.Error(declaringType, "Failed to find type [" + subTypeString + "] set on [" + name + "]", ex); } } @@ -707,7 +708,7 @@ protected void SetParameter(XmlElement element, object target) // to pass to this property. object convertedValue = ConvertStringTo(propertyType, propertyValue); - + // Check if we need to do an additional conversion if (convertedValue != null && parsedObjectConversionTargetType != null) { @@ -731,7 +732,7 @@ protected void SetParameter(XmlElement element, object target) propInfo.SetValue(target, convertedValue, BindingFlags.SetProperty, null, null, CultureInfo.InvariantCulture); #endif } - catch(TargetInvocationException targetInvocationEx) + catch (TargetInvocationException targetInvocationEx) { LogLog.Error(declaringType, "Failed to set parameter [" + propInfo.Name + "] on object [" + target + "] using value [" + convertedValue + "]", targetInvocationEx.InnerException); } @@ -747,10 +748,10 @@ protected void SetParameter(XmlElement element, object target) #if NETSTANDARD1_3 // TODO BindingFlags is available for netstandard1.5 methInfo.Invoke(target, new[] { convertedValue }); #else - methInfo.Invoke(target, BindingFlags.InvokeMethod, null, new object[] {convertedValue}, CultureInfo.InvariantCulture); + methInfo.Invoke(target, BindingFlags.InvokeMethod, null, new object[] { convertedValue }, CultureInfo.InvariantCulture); #endif } - catch(TargetInvocationException targetInvocationEx) + catch (TargetInvocationException targetInvocationEx) { LogLog.Error(declaringType, "Failed to set parameter [" + name + "] on object [" + target + "] using value [" + convertedValue + "]", targetInvocationEx.InnerException); } @@ -788,14 +789,14 @@ protected void SetParameter(XmlElement element, object target) if (createdObject == null) { - LogLog.Error(declaringType, "Failed to create object to set param: "+name); + LogLog.Error(declaringType, "Failed to create object to set param: " + name); } else { if (propInfo != null) { // Got a converted result - LogLog.Debug(declaringType, "Setting Property ["+ propInfo.Name +"] to object ["+ createdObject +"]"); + LogLog.Debug(declaringType, "Setting Property [" + propInfo.Name + "] to object [" + createdObject + "]"); try { @@ -806,7 +807,7 @@ protected void SetParameter(XmlElement element, object target) propInfo.SetValue(target, createdObject, BindingFlags.SetProperty, null, null, CultureInfo.InvariantCulture); #endif } - catch(TargetInvocationException targetInvocationEx) + catch (TargetInvocationException targetInvocationEx) { LogLog.Error(declaringType, "Failed to set parameter [" + propInfo.Name + "] on object [" + target + "] using value [" + createdObject + "]", targetInvocationEx.InnerException); } @@ -814,7 +815,7 @@ protected void SetParameter(XmlElement element, object target) else if (methInfo != null) { // Got a converted result - LogLog.Debug(declaringType, "Setting Collection Property ["+ methInfo.Name +"] to object ["+ createdObject +"]"); + LogLog.Debug(declaringType, "Setting Collection Property [" + methInfo.Name + "] to object [" + createdObject + "]"); try { @@ -822,10 +823,10 @@ protected void SetParameter(XmlElement element, object target) #if NETSTANDARD1_3 // TODO BindingFlags is available for netstandard1.5 methInfo.Invoke(target, new[] { createdObject }); #else - methInfo.Invoke(target, BindingFlags.InvokeMethod, null, new object[] {createdObject}, CultureInfo.InvariantCulture); + methInfo.Invoke(target, BindingFlags.InvokeMethod, null, new object[] { createdObject }, CultureInfo.InvariantCulture); #endif } - catch(TargetInvocationException targetInvocationEx) + catch (TargetInvocationException targetInvocationEx) { LogLog.Error(declaringType, "Failed to set parameter [" + methInfo.Name + "] on object [" + target + "] using value [" + createdObject + "]", targetInvocationEx.InnerException); } @@ -842,7 +843,7 @@ protected void SetParameter(XmlElement element, object target) /// true if the element has any attributes or child elements, false otherwise private bool HasAttributesOrElements(XmlElement element) { - foreach(XmlNode node in element.ChildNodes) + foreach (XmlNode node in element.ChildNodes) { if (node.NodeType == XmlNodeType.Attribute || node.NodeType == XmlNodeType.Element) { @@ -895,7 +896,7 @@ private MethodInfo FindMethodInfo(Type targetType, string name) MethodInfo[] methods = targetType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); - foreach(MethodInfo methInfo in methods) + foreach (MethodInfo methInfo in methods) { if (!methInfo.IsStatic) { @@ -939,7 +940,7 @@ protected object ConvertStringTo(Type type, string value) if (levelValue == null) { - LogLog.Error(declaringType, "XmlHierarchyConfigurator: Unknown Level Specified ["+ value +"]"); + LogLog.Error(declaringType, "XmlHierarchyConfigurator: Unknown Level Specified [" + value + "]"); } return levelValue; @@ -966,7 +967,7 @@ protected object ConvertStringTo(Type type, string value) /// type. /// /// - protected object CreateObjectFromXml(XmlElement element, Type defaultTargetType, Type typeConstraint) + protected object CreateObjectFromXml(XmlElement element, Type defaultTargetType, Type typeConstraint) { Type objectType = null; @@ -976,7 +977,7 @@ protected object CreateObjectFromXml(XmlElement element, Type defaultTargetType, { if (defaultTargetType == null) { - LogLog.Error(declaringType, "Object type not specified. Cannot create object of type ["+typeConstraint.FullName+"]. Missing Value or Type."); + LogLog.Error(declaringType, "Object type not specified. Cannot create object of type [" + typeConstraint.FullName + "]. Missing Value or Type."); return null; } else @@ -996,9 +997,9 @@ protected object CreateObjectFromXml(XmlElement element, Type defaultTargetType, objectType = SystemInfo.GetTypeFromString(objectTypeString, true, true); #endif } - catch(Exception ex) + catch (Exception ex) { - LogLog.Error(declaringType, "Failed to find type ["+objectTypeString+"]", ex); + LogLog.Error(declaringType, "Failed to find type [" + objectTypeString + "]", ex); return null; } } @@ -1017,7 +1018,7 @@ protected object CreateObjectFromXml(XmlElement element, Type defaultTargetType, } else { - LogLog.Error(declaringType, "Object type ["+objectType.FullName+"] is not assignable to type ["+typeConstraint.FullName+"]. There are no acceptable type conversions."); + LogLog.Error(declaringType, "Object type [" + objectType.FullName + "] is not assignable to type [" + typeConstraint.FullName + "]. There are no acceptable type conversions."); return null; } } @@ -1029,15 +1030,15 @@ protected object CreateObjectFromXml(XmlElement element, Type defaultTargetType, { createdObject = Activator.CreateInstance(objectType); } - catch(Exception createInstanceEx) + catch (Exception createInstanceEx) { - LogLog.Error(declaringType, "XmlHierarchyConfigurator: Failed to construct object of type [" + objectType.FullName + "] Exception: "+createInstanceEx.ToString()); + LogLog.Error(declaringType, "XmlHierarchyConfigurator: Failed to construct object of type [" + objectType.FullName + "] Exception: " + createInstanceEx.ToString()); } // Set any params on object foreach (XmlNode currentNode in element.ChildNodes) { - if (currentNode.NodeType == XmlNodeType.Element) + if (currentNode.NodeType == XmlNodeType.Element) { SetParameter((XmlElement)currentNode, createdObject); } @@ -1068,9 +1069,9 @@ protected object CreateObjectFromXml(XmlElement element, Type defaultTargetType, #if !NETCF && !NETSTANDARD1_3 // NETSTANDARD1_3: System.Runtime.InteropServices.RuntimeInformation not available on desktop 4.6 private bool HasCaseInsensitiveEnvironment - { - get - { + { + get + { #if NET_1_0 || NET_1_1 || CLI_1_0 // actually there is no guarantee, but we don't know better return true; @@ -1078,55 +1079,56 @@ private bool HasCaseInsensitiveEnvironment // see above return false; #else - PlatformID platform = Environment.OSVersion.Platform; - return platform != PlatformID.Unix && platform != PlatformID.MacOSX; + PlatformID platform = Environment.OSVersion.Platform; + return platform != PlatformID.Unix && platform != PlatformID.MacOSX; #endif - } + } } - private IDictionary CreateCaseInsensitiveWrapper(IDictionary dict) - { - if (dict == null) - { - return dict; - } - Hashtable hash = SystemInfo.CreateCaseInsensitiveHashtable(); - foreach (DictionaryEntry entry in dict) { - hash[entry.Key] = entry.Value; - } - return hash; + private IDictionary CreateCaseInsensitiveWrapper(IDictionary dict) + { + if (dict == null) + { + return dict; + } + Hashtable hash = SystemInfo.CreateCaseInsensitiveHashtable(); + foreach (DictionaryEntry entry in dict) + { + hash[entry.Key] = entry.Value; + } + return hash; } #endif #region Private Constants // String constants used while parsing the XML data - private const string CONFIGURATION_TAG = "log4net"; - private const string RENDERER_TAG = "renderer"; - private const string APPENDER_TAG = "appender"; - private const string APPENDER_REF_TAG = "appender-ref"; - private const string PARAM_TAG = "param"; + private const string CONFIGURATION_TAG = "log4net"; + private const string RENDERER_TAG = "renderer"; + private const string APPENDER_TAG = "appender"; + private const string APPENDER_REF_TAG = "appender-ref"; + private const string PARAM_TAG = "param"; // TODO: Deprecate use of category tags - private const string CATEGORY_TAG = "category"; + private const string CATEGORY_TAG = "category"; // TODO: Deprecate use of priority tag - private const string PRIORITY_TAG = "priority"; - - private const string LOGGER_TAG = "logger"; - private const string NAME_ATTR = "name"; - private const string TYPE_ATTR = "type"; - private const string VALUE_ATTR = "value"; - private const string ROOT_TAG = "root"; - private const string LEVEL_TAG = "level"; - private const string REF_ATTR = "ref"; - private const string ADDITIVITY_ATTR = "additivity"; - private const string THRESHOLD_ATTR = "threshold"; - private const string CONFIG_DEBUG_ATTR = "configDebug"; - private const string INTERNAL_DEBUG_ATTR = "debug"; - private const string EMIT_INTERNAL_DEBUG_ATTR = "emitDebug"; - private const string CONFIG_UPDATE_MODE_ATTR = "update"; - private const string RENDERING_TYPE_ATTR = "renderingClass"; - private const string RENDERED_TYPE_ATTR = "renderedClass"; + private const string PRIORITY_TAG = "priority"; + + private const string LOGGER_TAG = "logger"; + private const string NAME_ATTR = "name"; + private const string TYPE_ATTR = "type"; + private const string VALUE_ATTR = "value"; + private const string ROOT_TAG = "root"; + private const string LEVEL_TAG = "level"; + private const string REF_ATTR = "ref"; + private const string ADDITIVITY_ATTR = "additivity"; + private const string THRESHOLD_ATTR = "threshold"; + private const string CONFIG_DEBUG_ATTR = "configDebug"; + private const string INTERNAL_DEBUG_ATTR = "debug"; + private const string EMIT_INTERNAL_DEBUG_ATTR = "emitDebug"; + private const string CONFIG_UPDATE_MODE_ATTR = "update"; + private const string RENDERING_TYPE_ATTR = "renderingClass"; + private const string RENDERED_TYPE_ATTR = "renderedClass"; // flag used on the level element private const string INHERITED = "inherited"; @@ -1147,17 +1149,17 @@ private IDictionary CreateCaseInsensitiveWrapper(IDictionary dict) #endregion Private Instance Fields - #region Private Static Fields + #region Private Static Fields - /// - /// The fully qualified type of the XmlHierarchyConfigurator class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(XmlHierarchyConfigurator); + /// + /// The fully qualified type of the XmlHierarchyConfigurator class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(XmlHierarchyConfigurator); - #endregion Private Static Fields + #endregion Private Static Fields } } diff --git a/src/log4net/Repository/IBasicRepositoryConfigurator.cs b/src/log4net/Repository/IBasicRepositoryConfigurator.cs index b6196f7b..a0bfb2f9 100644 --- a/src/log4net/Repository/IBasicRepositoryConfigurator.cs +++ b/src/log4net/Repository/IBasicRepositoryConfigurator.cs @@ -46,18 +46,18 @@ public interface IBasicRepositoryConfigurator /// specified appender. /// /// - void Configure(Appender.IAppender appender); + void Configure(Appender.IAppender appender); - /// - /// Initialize the repository using the specified appenders - /// - /// the appenders to use to log all logging events - /// - /// - /// Configure the repository to route all logging events to the - /// specified appenders. - /// - /// - void Configure(params Appender.IAppender[] appenders); + /// + /// Initialize the repository using the specified appenders + /// + /// the appenders to use to log all logging events + /// + /// + /// Configure the repository to route all logging events to the + /// specified appenders. + /// + /// + void Configure(params Appender.IAppender[] appenders); } } diff --git a/src/log4net/Repository/ILoggerRepository.cs b/src/log4net/Repository/ILoggerRepository.cs index 9ea0fd4e..29d64ea8 100644 --- a/src/log4net/Repository/ILoggerRepository.cs +++ b/src/log4net/Repository/ILoggerRepository.cs @@ -74,8 +74,8 @@ namespace log4net.Repository /// public delegate void LoggerRepositoryConfigurationChangedEventHandler(object sender, EventArgs e); - #endregion - + #endregion + /// /// Interface implemented by logger repositories. /// @@ -276,11 +276,11 @@ public interface ILoggerRepository /// bool Configured { get; set; } - /// - /// Collection of internal messages captured during the most - /// recent configuration process. - /// - ICollection ConfigurationMessages { get; set; } + /// + /// Collection of internal messages captured during the most + /// recent configuration process. + /// + ICollection ConfigurationMessages { get; set; } /// /// Event to notify that the repository has been shutdown. diff --git a/src/log4net/Repository/LoggerRepositorySkeleton.cs b/src/log4net/Repository/LoggerRepositorySkeleton.cs index 7a69a247..11afa005 100644 --- a/src/log4net/Repository/LoggerRepositorySkeleton.cs +++ b/src/log4net/Repository/LoggerRepositorySkeleton.cs @@ -51,7 +51,7 @@ public abstract class LoggerRepositorySkeleton : ILoggerRepository, Appender.IFl private LevelMap m_levelMap; private Level m_threshold; private bool m_configured; - private ICollection m_configurationMessages; + private ICollection m_configurationMessages; private event LoggerRepositoryShutdownEventHandler m_shutdownEvent; private event LoggerRepositoryConfigurationResetEventHandler m_configurationResetEvent; private event LoggerRepositoryConfigurationChangedEventHandler m_configurationChangedEvent; @@ -88,7 +88,7 @@ protected LoggerRepositorySkeleton(PropertiesDictionary properties) m_rendererMap = new RendererMap(); m_pluginMap = new PluginMap(this); m_levelMap = new LevelMap(); - m_configurationMessages = EmptyCollection.Instance; + m_configurationMessages = EmptyCollection.Instance; m_configured = false; AddBuiltinLevels(); @@ -135,10 +135,10 @@ public virtual Level Threshold { get { return m_threshold; } set - { + { if (value != null) { - m_threshold = value; + m_threshold = value; } else { @@ -255,10 +255,10 @@ public virtual LevelMap LevelMap /// listeners and all attached plugins of the shutdown event. /// /// - public virtual void Shutdown() + public virtual void Shutdown() { // Shutdown attached plugins - foreach(IPlugin plugin in PluginMap.AllPlugins) + foreach (IPlugin plugin in PluginMap.AllPlugins) { plugin.Shutdown(); } @@ -283,12 +283,12 @@ public virtual void Shutdown() /// block all logging until it is completed. /// /// - public virtual void ResetConfiguration() + public virtual void ResetConfiguration() { // Clear internal data structures m_rendererMap.Clear(); m_levelMap.Clear(); - m_configurationMessages = EmptyCollection.Instance; + m_configurationMessages = EmptyCollection.Instance; // Add the predefined levels to the map AddBuiltinLevels(); @@ -328,23 +328,23 @@ public virtual void ResetConfiguration() /// Flag indicates if this repository has been configured. /// /// - public virtual bool Configured - { + public virtual bool Configured + { get { return m_configured; } set { m_configured = value; } } - /// - /// Contains a list of internal messages captures during the - /// last configuration. - /// - public virtual ICollection ConfigurationMessages - { - get { return m_configurationMessages; } - set { m_configurationMessages = value; } - } + /// + /// Contains a list of internal messages captures during the + /// last configuration. + /// + public virtual ICollection ConfigurationMessages + { + get { return m_configurationMessages; } + set { m_configurationMessages = value; } + } - /// + /// /// Event to notify that the repository has been shutdown. /// /// @@ -405,9 +405,9 @@ public event LoggerRepositoryConfigurationChangedEventHandler ConfigurationChang /// /// These properties can be specified on a repository specific basis /// - public PropertiesDictionary Properties - { - get { return m_properties; } + public PropertiesDictionary Properties + { + get { return m_properties; } } /// @@ -423,18 +423,18 @@ public PropertiesDictionary Properties #endregion - #region Private Static Fields + #region Private Static Fields - /// - /// The fully qualified type of the LoggerRepositorySkeleton class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(LoggerRepositorySkeleton); + /// + /// The fully qualified type of the LoggerRepositorySkeleton class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(LoggerRepositorySkeleton); - #endregion Private Static Fields + #endregion Private Static Fields private void AddBuiltinLevels() { @@ -444,17 +444,17 @@ private void AddBuiltinLevels() // Unrecoverable errors m_levelMap.Add(Level.Emergency); m_levelMap.Add(Level.Fatal); - m_levelMap.Add(Level.Alert); + m_levelMap.Add(Level.Alert); // Recoverable errors - m_levelMap.Add(Level.Critical); - m_levelMap.Add(Level.Severe); - m_levelMap.Add(Level.Error); + m_levelMap.Add(Level.Critical); + m_levelMap.Add(Level.Severe); + m_levelMap.Add(Level.Error); m_levelMap.Add(Level.Warn); // Information - m_levelMap.Add(Level.Notice); - m_levelMap.Add(Level.Info); + m_levelMap.Add(Level.Notice); + m_levelMap.Add(Level.Info); // Debug m_levelMap.Add(Level.Debug); @@ -477,7 +477,7 @@ private void AddBuiltinLevels() /// Adds an object renderer for a specific class. /// /// - public virtual void AddRenderer(Type typeToRender, IObjectRenderer rendererInstance) + public virtual void AddRenderer(Type typeToRender, IObjectRenderer rendererInstance) { if (typeToRender == null) { @@ -575,58 +575,58 @@ public void RaiseConfigurationChanged(EventArgs e) OnConfigurationChanged(e); } - private static int GetWaitTime(DateTime startTimeUtc, int millisecondsTimeout) - { - if (millisecondsTimeout == Timeout.Infinite) return Timeout.Infinite; - if (millisecondsTimeout == 0) return 0; + private static int GetWaitTime(DateTime startTimeUtc, int millisecondsTimeout) + { + if (millisecondsTimeout == Timeout.Infinite) return Timeout.Infinite; + if (millisecondsTimeout == 0) return 0; - int elapsedMilliseconds = (int)(DateTime.UtcNow - startTimeUtc).TotalMilliseconds; - int timeout = millisecondsTimeout - elapsedMilliseconds; - if (timeout < 0) timeout = 0; - return timeout; + int elapsedMilliseconds = (int)(DateTime.UtcNow - startTimeUtc).TotalMilliseconds; + int timeout = millisecondsTimeout - elapsedMilliseconds; + if (timeout < 0) timeout = 0; + return timeout; + } + + /// + /// Flushes all configured Appenders that implement . + /// + /// The maximum time in milliseconds to wait for logging events from asycnhronous appenders to be flushed, + /// or to wait indefinitely. + /// True if all logging events were flushed successfully, else false. + public bool Flush(int millisecondsTimeout) + { + if (millisecondsTimeout < -1) throw new ArgumentOutOfRangeException("millisecondsTimeout", "Timeout must be -1 (Timeout.Infinite) or non-negative"); + + // Assume success until one of the appenders fails + bool result = true; + + // Use DateTime.UtcNow rather than a System.Diagnostics.Stopwatch for compatibility with .NET 1.x + DateTime startTimeUtc = DateTime.UtcNow; + + // Do buffering appenders first. These may be forwarding to other appenders + foreach (log4net.Appender.IAppender appender in GetAppenders()) + { + log4net.Appender.IFlushable flushable = appender as log4net.Appender.IFlushable; + if (flushable == null) continue; + if (appender is Appender.BufferingAppenderSkeleton) + { + int timeout = GetWaitTime(startTimeUtc, millisecondsTimeout); + if (!flushable.Flush(timeout)) result = false; } + } - /// - /// Flushes all configured Appenders that implement . - /// - /// The maximum time in milliseconds to wait for logging events from asycnhronous appenders to be flushed, - /// or to wait indefinitely. - /// True if all logging events were flushed successfully, else false. - public bool Flush(int millisecondsTimeout) + // Do non-buffering appenders. + foreach (log4net.Appender.IAppender appender in GetAppenders()) + { + log4net.Appender.IFlushable flushable = appender as log4net.Appender.IFlushable; + if (flushable == null) continue; + if (!(appender is Appender.BufferingAppenderSkeleton)) { - if (millisecondsTimeout < -1) throw new ArgumentOutOfRangeException("millisecondsTimeout", "Timeout must be -1 (Timeout.Infinite) or non-negative"); - - // Assume success until one of the appenders fails - bool result = true; - - // Use DateTime.UtcNow rather than a System.Diagnostics.Stopwatch for compatibility with .NET 1.x - DateTime startTimeUtc = DateTime.UtcNow; - - // Do buffering appenders first. These may be forwarding to other appenders - foreach(log4net.Appender.IAppender appender in GetAppenders()) - { - log4net.Appender.IFlushable flushable = appender as log4net.Appender.IFlushable; - if (flushable == null) continue; - if (appender is Appender.BufferingAppenderSkeleton) - { - int timeout = GetWaitTime(startTimeUtc, millisecondsTimeout); - if (!flushable.Flush(timeout)) result = false; - } - } - - // Do non-buffering appenders. - foreach (log4net.Appender.IAppender appender in GetAppenders()) - { - log4net.Appender.IFlushable flushable = appender as log4net.Appender.IFlushable; - if (flushable == null) continue; - if (!(appender is Appender.BufferingAppenderSkeleton)) - { - int timeout = GetWaitTime(startTimeUtc, millisecondsTimeout); - if (!flushable.Flush(timeout)) result = false; - } - } - - return result; + int timeout = GetWaitTime(startTimeUtc, millisecondsTimeout); + if (!flushable.Flush(timeout)) result = false; } + } + + return result; + } } } diff --git a/src/log4net/Util/AppenderAttachedImpl.cs b/src/log4net/Util/AppenderAttachedImpl.cs index b6fc0fd7..f638f2bf 100644 --- a/src/log4net/Util/AppenderAttachedImpl.cs +++ b/src/log4net/Util/AppenderAttachedImpl.cs @@ -67,7 +67,7 @@ public AppenderAttachedImpl() /// attached appenders. /// /// - public int AppendLoopOnAppenders(LoggingEvent loggingEvent) + public int AppendLoopOnAppenders(LoggingEvent loggingEvent) { if (loggingEvent == null) { @@ -75,7 +75,7 @@ public int AppendLoopOnAppenders(LoggingEvent loggingEvent) } // m_appenderList is null when empty - if (m_appenderList == null) + if (m_appenderList == null) { return 0; } @@ -85,13 +85,13 @@ public int AppendLoopOnAppenders(LoggingEvent loggingEvent) m_appenderArray = m_appenderList.ToArray(); } - foreach(IAppender appender in m_appenderArray) + foreach (IAppender appender in m_appenderArray) { try { appender.DoAppend(loggingEvent); } - catch(Exception ex) + catch (Exception ex) { LogLog.Error(declaringType, "Failed to append to appender [" + appender.Name + "]", ex); } @@ -110,7 +110,7 @@ public int AppendLoopOnAppenders(LoggingEvent loggingEvent) /// attached appenders. /// /// - public int AppendLoopOnAppenders(LoggingEvent[] loggingEvents) + public int AppendLoopOnAppenders(LoggingEvent[] loggingEvents) { if (loggingEvents == null) { @@ -127,7 +127,7 @@ public int AppendLoopOnAppenders(LoggingEvent[] loggingEvents) } // m_appenderList is null when empty - if (m_appenderList == null) + if (m_appenderList == null) { return 0; } @@ -137,13 +137,13 @@ public int AppendLoopOnAppenders(LoggingEvent[] loggingEvents) m_appenderArray = m_appenderList.ToArray(); } - foreach(IAppender appender in m_appenderArray) + foreach (IAppender appender in m_appenderArray) { try { CallAppend(appender, loggingEvents); } - catch(Exception ex) + catch (Exception ex) { LogLog.Error(declaringType, "Failed to append to appender [" + appender.Name + "]", ex); } @@ -153,9 +153,9 @@ public int AppendLoopOnAppenders(LoggingEvent[] loggingEvents) #endregion Public Instance Methods - #region Private Static Methods + #region Private Static Methods - /// + /// /// Calls the DoAppende method on the with /// the objects supplied. /// @@ -178,18 +178,18 @@ private static void CallAppend(IAppender appender, LoggingEvent[] loggingEvents) } else { - foreach(LoggingEvent loggingEvent in loggingEvents) + foreach (LoggingEvent loggingEvent in loggingEvents) { appender.DoAppend(loggingEvent); } } - } + } - #endregion + #endregion - #region Implementation of IAppenderAttachable + #region Implementation of IAppenderAttachable - /// + /// /// Attaches an appender. /// /// The appender to add. @@ -198,16 +198,16 @@ private static void CallAppend(IAppender appender, LoggingEvent[] loggingEvents) /// If the appender is already in the list it won't be added again. /// /// - public void AddAppender(IAppender newAppender) + public void AddAppender(IAppender newAppender) { // Null values for newAppender parameter are strictly forbidden. if (newAppender == null) { throw new ArgumentNullException("newAppender"); } - + m_appenderArray = null; - if (m_appenderList == null) + if (m_appenderList == null) { m_appenderList = new AppenderCollection(1); } @@ -229,7 +229,7 @@ public void AddAppender(IAppender newAppender) /// The read only collection of all currently attached appenders. /// /// - public AppenderCollection Appenders + public AppenderCollection Appenders { get { @@ -238,7 +238,7 @@ public AppenderCollection Appenders // We must always return a valid collection return AppenderCollection.EmptyCollection; } - else + else { return AppenderCollection.ReadOnly(m_appenderList); } @@ -258,11 +258,11 @@ public AppenderCollection Appenders /// Lookup an attached appender by name. /// /// - public IAppender GetAppender(string name) + public IAppender GetAppender(string name) { if (m_appenderList != null && name != null) { - foreach(IAppender appender in m_appenderList) + foreach (IAppender appender in m_appenderList) { if (name == appender.Name) { @@ -270,7 +270,7 @@ public IAppender GetAppender(string name) } } } - return null; + return null; } /// @@ -281,22 +281,22 @@ public IAppender GetAppender(string name) /// Removes and closes all attached appenders /// /// - public void RemoveAllAppenders() + public void RemoveAllAppenders() { - if (m_appenderList != null) + if (m_appenderList != null) { - foreach(IAppender appender in m_appenderList) + foreach (IAppender appender in m_appenderList) { try { appender.Close(); } - catch(Exception ex) + catch (Exception ex) { - LogLog.Error(declaringType, "Failed to Close appender ["+appender.Name+"]", ex); + LogLog.Error(declaringType, "Failed to Close appender [" + appender.Name + "]", ex); } } - m_appenderList = null; + m_appenderList = null; m_appenderArray = null; } } @@ -313,9 +313,9 @@ public void RemoveAllAppenders() /// on the appender removed. /// /// - public IAppender RemoveAppender(IAppender appender) + public IAppender RemoveAppender(IAppender appender) { - if (appender != null && m_appenderList != null) + if (appender != null && m_appenderList != null) { m_appenderList.Remove(appender); if (m_appenderList.Count == 0) @@ -339,7 +339,7 @@ public IAppender RemoveAppender(IAppender appender) /// on the appender removed. /// /// - public IAppender RemoveAppender(string name) + public IAppender RemoveAppender(string name) { return RemoveAppender(GetAppender(name)); } @@ -360,17 +360,17 @@ public IAppender RemoveAppender(string name) #endregion Private Instance Fields - #region Private Static Fields + #region Private Static Fields - /// - /// The fully qualified type of the AppenderAttachedImpl class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(AppenderAttachedImpl); + /// + /// The fully qualified type of the AppenderAttachedImpl class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(AppenderAttachedImpl); - #endregion Private Static Fields + #endregion Private Static Fields } } diff --git a/src/log4net/Util/CompositeProperties.cs b/src/log4net/Util/CompositeProperties.cs index 987661c6..66ac7b7e 100644 --- a/src/log4net/Util/CompositeProperties.cs +++ b/src/log4net/Util/CompositeProperties.cs @@ -80,7 +80,7 @@ internal CompositeProperties() /// public object this[string key] { - get + get { // Look in the flattened properties first if (m_flattened != null) @@ -89,7 +89,7 @@ public object this[string key] } // Look for the key in all the nested properties - foreach(ReadOnlyPropertiesDictionary cur in m_nestedProperties) + foreach (ReadOnlyPropertiesDictionary cur in m_nestedProperties) { if (cur.Contains(key)) { @@ -136,11 +136,11 @@ public PropertiesDictionary Flatten() { m_flattened = new PropertiesDictionary(); - for(int i=m_nestedProperties.Count; --i>=0; ) + for (int i = m_nestedProperties.Count; --i >= 0;) { ReadOnlyPropertiesDictionary cur = (ReadOnlyPropertiesDictionary)m_nestedProperties[i]; - foreach(DictionaryEntry entry in cur) + foreach (DictionaryEntry entry in cur) { m_flattened[(string)entry.Key] = entry.Value; } diff --git a/src/log4net/Util/ConverterInfo.cs b/src/log4net/Util/ConverterInfo.cs index b64edc9d..31b189ed 100644 --- a/src/log4net/Util/ConverterInfo.cs +++ b/src/log4net/Util/ConverterInfo.cs @@ -23,72 +23,72 @@ namespace log4net.Util { + /// + /// Wrapper class used to map converter names to converter types + /// + /// + /// + /// Pattern converter info class used during configuration by custom + /// PatternString and PatternLayer converters. + /// + /// + public sealed class ConverterInfo + { + private string m_name; + private Type m_type; + private readonly PropertiesDictionary properties = new PropertiesDictionary(); + + /// + /// default constructor + /// + public ConverterInfo() + { + } + /// - /// Wrapper class used to map converter names to converter types + /// Gets or sets the name of the conversion pattern /// /// /// - /// Pattern converter info class used during configuration by custom - /// PatternString and PatternLayer converters. + /// The name of the pattern in the format string /// /// - public sealed class ConverterInfo + public string Name { - private string m_name; - private Type m_type; - private readonly PropertiesDictionary properties = new PropertiesDictionary(); - - /// - /// default constructor - /// - public ConverterInfo() - { - } - - /// - /// Gets or sets the name of the conversion pattern - /// - /// - /// - /// The name of the pattern in the format string - /// - /// - public string Name - { - get { return m_name; } - set { m_name = value; } - } + get { return m_name; } + set { m_name = value; } + } - /// - /// Gets or sets the type of the converter - /// - /// - /// - /// The value specified must extend the - /// type. - /// - /// - public Type Type - { - get { return m_type; } - set { m_type = value; } - } + /// + /// Gets or sets the type of the converter + /// + /// + /// + /// The value specified must extend the + /// type. + /// + /// + public Type Type + { + get { return m_type; } + set { m_type = value; } + } - /// - /// - /// - /// - public void AddProperty(PropertyEntry entry) - { - properties[entry.Key] = entry.Value; - } + /// + /// + /// + /// + public void AddProperty(PropertyEntry entry) + { + properties[entry.Key] = entry.Value; + } - /// - /// - /// - public PropertiesDictionary Properties - { - get { return properties; } - } + /// + /// + /// + public PropertiesDictionary Properties + { + get { return properties; } } + } } diff --git a/src/log4net/Util/CountingQuietTextWriter.cs b/src/log4net/Util/CountingQuietTextWriter.cs index 505163a3..97bdaa41 100644 --- a/src/log4net/Util/CountingQuietTextWriter.cs +++ b/src/log4net/Util/CountingQuietTextWriter.cs @@ -35,7 +35,7 @@ namespace log4net.Util /// /// Nicko Cadell /// Gert Driesen - public class CountingQuietTextWriter : QuietTextWriter + public class CountingQuietTextWriter : QuietTextWriter { #region Public Instance Constructors @@ -58,7 +58,7 @@ public CountingQuietTextWriter(TextWriter writer, IErrorHandler errorHandler) : #endregion Public Instance Constructors #region Override implementation of QuietTextWriter - + /// /// Writes a character to the underlying writer and counts the number of bytes written. /// @@ -69,22 +69,22 @@ public CountingQuietTextWriter(TextWriter writer, IErrorHandler errorHandler) : /// the number of bytes written. /// /// - public override void Write(char value) + public override void Write(char value) { - try + try { base.Write(value); // get the number of bytes needed to represent the // char using the supplied encoding. m_countBytes += this.Encoding.GetByteCount(new char[] { value }); - } - catch(Exception e) + } + catch (Exception e) { this.ErrorHandler.Error("Failed to write [" + value + "].", e, ErrorCode.WriteFailure); } } - + /// /// Writes a buffer to the underlying writer and counts the number of bytes written. /// @@ -97,19 +97,19 @@ public override void Write(char value) /// the number of bytes written. /// /// - public override void Write(char[] buffer, int index, int count) + public override void Write(char[] buffer, int index, int count) { if (count > 0) { - try + try { base.Write(buffer, index, count); // get the number of bytes needed to represent the // char array using the supplied encoding. m_countBytes += this.Encoding.GetByteCount(buffer, index, count); - } - catch(Exception e) + } + catch (Exception e) { this.ErrorHandler.Error("Failed to write buffer.", e, ErrorCode.WriteFailure); } @@ -126,11 +126,11 @@ public override void Write(char[] buffer, int index, int count) /// the number of bytes written. /// /// - public override void Write(string str) + public override void Write(string str) { if (str != null && str.Length > 0) { - try + try { base.Write(str); @@ -138,13 +138,13 @@ public override void Write(string str) // string using the supplied encoding. m_countBytes += this.Encoding.GetByteCount(str); } - catch(Exception e) + catch (Exception e) { this.ErrorHandler.Error("Failed to write [" + str + "].", e, ErrorCode.WriteFailure); } } } - + #endregion Override implementation of QuietTextWriter #region Public Instance Properties @@ -160,14 +160,14 @@ public override void Write(string str) /// Gets or sets the total number of bytes written. /// /// - public long Count + public long Count { get { return m_countBytes; } set { m_countBytes = value; } } #endregion Public Instance Properties - + #region Private Instance Fields /// diff --git a/src/log4net/Util/CyclicBuffer.cs b/src/log4net/Util/CyclicBuffer.cs index ca5ca70d..f99fb482 100644 --- a/src/log4net/Util/CyclicBuffer.cs +++ b/src/log4net/Util/CyclicBuffer.cs @@ -48,9 +48,9 @@ public class CyclicBuffer /// /// /// The argument is not a positive integer. - public CyclicBuffer(int maxSize) + public CyclicBuffer(int maxSize) { - if (maxSize < 1) + if (maxSize < 1) { throw SystemInfo.CreateArgumentOutOfRangeException("maxSize", (object)maxSize, "Parameter: maxSize, Value: [" + maxSize + "] out of range. Non zero positive integer required"); } @@ -65,7 +65,7 @@ public CyclicBuffer(int maxSize) #endregion Public Instance Constructors #region Public Instance Methods - + /// /// Appends a to the buffer. /// @@ -79,19 +79,19 @@ public CyclicBuffer(int maxSize) /// /// public LoggingEvent Append(LoggingEvent loggingEvent) - { + { if (loggingEvent == null) { throw new ArgumentNullException("loggingEvent"); } - lock(this) + lock (this) { // save the discarded event LoggingEvent discardedLoggingEvent = m_events[m_last]; // overwrite the last event position - m_events[m_last] = loggingEvent; + m_events[m_last] = loggingEvent; if (++m_last == m_maxSize) { m_last = 0; @@ -129,12 +129,12 @@ public LoggingEvent Append(LoggingEvent loggingEvent) /// from the buffer. /// /// - public LoggingEvent PopOldest() + public LoggingEvent PopOldest() { - lock(this) + lock (this) { LoggingEvent ret = null; - if (m_numElems > 0) + if (m_numElems > 0) { m_numElems--; ret = m_events[m_first]; @@ -143,7 +143,7 @@ public LoggingEvent PopOldest() { m_first = 0; } - } + } return ret; } } @@ -159,7 +159,7 @@ public LoggingEvent PopOldest() /// public LoggingEvent[] PopAll() { - lock(this) + lock (this) { LoggingEvent[] ret = new LoggingEvent[m_numElems]; @@ -192,7 +192,7 @@ public LoggingEvent[] PopAll() /// public void Clear() { - lock(this) + lock (this) { // Set all the elements to null Array.Clear(m_events, 0, m_events.Length); @@ -276,11 +276,11 @@ public void Resize(int newSize) /// currently in the buffer, then null is returned. /// /// - public LoggingEvent this[int i] + public LoggingEvent this[int i] { get { - lock(this) + lock (this) { if (i < 0 || i >= m_numElems) { @@ -301,13 +301,13 @@ public LoggingEvent this[int i] /// Gets the maximum size of the buffer /// /// - public int MaxSize + public int MaxSize { - get - { - lock(this) + get + { + lock (this) { - return m_maxSize; + return m_maxSize; } } #if RESIZABLE_CYCLIC_BUFFER @@ -331,13 +331,13 @@ public int MaxSize /// public int Length { - get - { - lock(this) - { - return m_numElems; + get + { + lock (this) + { + return m_numElems; } - } + } } #endregion Public Instance Properties @@ -345,8 +345,8 @@ public int Length #region Private Instance Fields private LoggingEvent[] m_events; - private int m_first; - private int m_last; + private int m_first; + private int m_last; private int m_numElems; private int m_maxSize; diff --git a/src/log4net/Util/EmptyCollection.cs b/src/log4net/Util/EmptyCollection.cs index 2f019dd8..ab36d946 100644 --- a/src/log4net/Util/EmptyCollection.cs +++ b/src/log4net/Util/EmptyCollection.cs @@ -53,7 +53,7 @@ private EmptyCollection() } #endregion Private Instance Constructors - + #region Public Static Properties /// @@ -107,7 +107,7 @@ public void CopyTo(System.Array array, int index) /// public bool IsSynchronized { - get { return true; } + get { return true; } } /// @@ -172,7 +172,7 @@ public IEnumerator GetEnumerator() /// The singleton instance of the empty collection. /// private static readonly EmptyCollection s_instance = new EmptyCollection(); - + #endregion Private Static Fields } } diff --git a/src/log4net/Util/EmptyDictionary.cs b/src/log4net/Util/EmptyDictionary.cs index 1ccb67e2..a35d3f96 100644 --- a/src/log4net/Util/EmptyDictionary.cs +++ b/src/log4net/Util/EmptyDictionary.cs @@ -53,7 +53,7 @@ private EmptyDictionary() } #endregion Private Instance Constructors - + #region Public Static Properties /// @@ -107,7 +107,7 @@ public void CopyTo(System.Array array, int index) /// public bool IsSynchronized { - get { return true; } + get { return true; } } /// @@ -275,7 +275,7 @@ public bool IsFixedSize /// public bool IsReadOnly { - get { return true; } + get { return true; } } /// @@ -333,7 +333,7 @@ public object this[object key] /// The singleton instance of the empty dictionary. /// private static readonly EmptyDictionary s_instance = new EmptyDictionary(); - + #endregion Private Static Fields } } diff --git a/src/log4net/Util/FormattingInfo.cs b/src/log4net/Util/FormattingInfo.cs index 6e8ed637..6a6be4d6 100644 --- a/src/log4net/Util/FormattingInfo.cs +++ b/src/log4net/Util/FormattingInfo.cs @@ -47,7 +47,7 @@ public class FormattingInfo /// Initializes a new instance of the class. /// /// - public FormattingInfo() + public FormattingInfo() { } @@ -60,7 +60,7 @@ public FormattingInfo() /// with the specified parameters. /// /// - public FormattingInfo(int min, int max, bool leftAlign) + public FormattingInfo(int min, int max, bool leftAlign) { m_min = min; m_max = max; diff --git a/src/log4net/Util/GlobalContextProperties.cs b/src/log4net/Util/GlobalContextProperties.cs index c7c504ff..cfebd226 100644 --- a/src/log4net/Util/GlobalContextProperties.cs +++ b/src/log4net/Util/GlobalContextProperties.cs @@ -95,13 +95,13 @@ internal GlobalContextProperties() /// public override object this[string key] { - get - { + get + { return m_readOnlyProperties[key]; } set { - lock(m_syncRoot) + lock (m_syncRoot) { PropertiesDictionary mutableProps = new PropertiesDictionary(m_readOnlyProperties); @@ -128,7 +128,7 @@ public override object this[string key] /// public void Remove(string key) { - lock(m_syncRoot) + lock (m_syncRoot) { if (m_readOnlyProperties.Contains(key)) { @@ -146,7 +146,7 @@ public void Remove(string key) /// public void Clear() { - lock(m_syncRoot) + lock (m_syncRoot) { m_readOnlyProperties = new ReadOnlyPropertiesDictionary(); } diff --git a/src/log4net/Util/LevelMapping.cs b/src/log4net/Util/LevelMapping.cs index aee83b23..674ec3d9 100644 --- a/src/log4net/Util/LevelMapping.cs +++ b/src/log4net/Util/LevelMapping.cs @@ -46,14 +46,14 @@ public sealed class LevelMapping : IOptionHandler /// Initialise a new instance of . /// /// - public LevelMapping() + public LevelMapping() { } #endregion // Public Instance Constructors #region Public Instance Methods - + /// /// Add a to this mapping /// @@ -93,7 +93,7 @@ public LevelMappingEntry Lookup(Level level) { if (m_entries != null) { - foreach(LevelMappingEntry entry in m_entries) + foreach (LevelMappingEntry entry in m_entries) { if (level >= entry.Level) { @@ -130,12 +130,12 @@ public void ActivateOptions() // Reverse list so that highest level is first Array.Reverse(sortValues, 0, sortValues.Length); - foreach(LevelMappingEntry entry in sortValues) + foreach (LevelMappingEntry entry in sortValues) { entry.ActivateOptions(); } - m_entries = sortValues; + m_entries = sortValues; } #endregion // IOptionHandler Members diff --git a/src/log4net/Util/LevelMappingEntry.cs b/src/log4net/Util/LevelMappingEntry.cs index 4bbe0044..00901a5b 100644 --- a/src/log4net/Util/LevelMappingEntry.cs +++ b/src/log4net/Util/LevelMappingEntry.cs @@ -46,7 +46,7 @@ public abstract class LevelMappingEntry : IOptionHandler /// Default protected constructor /// /// - protected LevelMappingEntry() + protected LevelMappingEntry() { } @@ -93,7 +93,7 @@ public virtual void ActivateOptions() #region Private Instance Fields - private Level m_level; + private Level m_level; #endregion // Private Instance Fields } diff --git a/src/log4net/Util/LogLog.cs b/src/log4net/Util/LogLog.cs index 8c0f0a79..a54f0107 100644 --- a/src/log4net/Util/LogLog.cs +++ b/src/log4net/Util/LogLog.cs @@ -23,12 +23,12 @@ namespace log4net.Util { - /// - /// - /// - /// - /// - public delegate void LogReceivedEventHandler(object source, LogReceivedEventArgs e); + /// + /// + /// + /// + /// + public delegate void LogReceivedEventHandler(object source, LogReceivedEventArgs e); /// /// Outputs log statements from within the log4net assembly. @@ -49,101 +49,101 @@ namespace log4net.Util /// Gert Driesen public sealed class LogLog { - /// - /// The event raised when an internal message has been received. - /// - public static event LogReceivedEventHandler LogReceived; - - private readonly Type source; - private readonly DateTime timeStampUtc; - private readonly string prefix; - private readonly string message; - private readonly Exception exception; - - /// - /// The Type that generated the internal message. - /// - public Type Source - { - get { return source; } - } + /// + /// The event raised when an internal message has been received. + /// + public static event LogReceivedEventHandler LogReceived; - /// - /// The DateTime stamp of when the internal message was received. - /// - public DateTime TimeStamp - { - get { return timeStampUtc.ToLocalTime(); } - } + private readonly Type source; + private readonly DateTime timeStampUtc; + private readonly string prefix; + private readonly string message; + private readonly Exception exception; - /// - /// The UTC DateTime stamp of when the internal message was received. - /// - public DateTime TimeStampUtc - { - get { return timeStampUtc; } - } + /// + /// The Type that generated the internal message. + /// + public Type Source + { + get { return source; } + } - /// - /// A string indicating the severity of the internal message. - /// - /// - /// "log4net: ", - /// "log4net:ERROR ", - /// "log4net:WARN " - /// - public string Prefix - { - get { return prefix; } - } + /// + /// The DateTime stamp of when the internal message was received. + /// + public DateTime TimeStamp + { + get { return timeStampUtc.ToLocalTime(); } + } - /// - /// The internal log message. - /// - public string Message - { - get { return message; } - } + /// + /// The UTC DateTime stamp of when the internal message was received. + /// + public DateTime TimeStampUtc + { + get { return timeStampUtc; } + } - /// - /// The Exception related to the message. - /// - /// - /// Optional. Will be null if no Exception was passed. - /// - public Exception Exception - { - get { return exception; } - } + /// + /// A string indicating the severity of the internal message. + /// + /// + /// "log4net: ", + /// "log4net:ERROR ", + /// "log4net:WARN " + /// + public string Prefix + { + get { return prefix; } + } - /// - /// Formats Prefix, Source, and Message in the same format as the value - /// sent to Console.Out and Trace.Write. - /// - /// - public override string ToString() - { - return Prefix + Source.Name + ": " + Message; - } + /// + /// The internal log message. + /// + public string Message + { + get { return message; } + } - #region Private Instance Constructors + /// + /// The Exception related to the message. + /// + /// + /// Optional. Will be null if no Exception was passed. + /// + public Exception Exception + { + get { return exception; } + } - /// - /// Initializes a new instance of the class. - /// - /// - /// - /// - /// - public LogLog(Type source, string prefix, string message, Exception exception) - { - timeStampUtc = DateTime.UtcNow; - - this.source = source; - this.prefix = prefix; - this.message = message; - this.exception = exception; - } + /// + /// Formats Prefix, Source, and Message in the same format as the value + /// sent to Console.Out and Trace.Write. + /// + /// + public override string ToString() + { + return Prefix + Source.Name + ": " + Message; + } + + #region Private Instance Constructors + + /// + /// Initializes a new instance of the class. + /// + /// + /// + /// + /// + public LogLog(Type source, string prefix, string message, Exception exception) + { + timeStampUtc = DateTime.UtcNow; + + this.source = source; + this.prefix = prefix; + this.message = message; + this.exception = exception; + } #endregion Private Instance Constructors @@ -175,7 +175,7 @@ static LogLog() QuietMode = OptionConverter.ToBoolean(SystemInfo.GetAppSetting("log4net.Internal.Quiet"), false); EmitInternalMessages = OptionConverter.ToBoolean(SystemInfo.GetAppSetting("log4net.Internal.Emit"), true); } - catch(Exception ex) + catch (Exception ex) { // If an exception is thrown here then it looks like the config file does not // parse correctly. @@ -272,35 +272,35 @@ public static bool QuietMode set { s_quietMode = value; } } - /// - /// - /// - public static bool EmitInternalMessages - { - get { return s_emitInternalMessages; } - set { s_emitInternalMessages = value; } - } + /// + /// + /// + public static bool EmitInternalMessages + { + get { return s_emitInternalMessages; } + set { s_emitInternalMessages = value; } + } #endregion Public Static Properties #region Public Static Methods - /// - /// Raises the LogReceived event when an internal messages is received. - /// - /// - /// - /// - /// - public static void OnLogReceived(Type source, string prefix, string message, Exception exception) - { - if (LogReceived != null) - { - LogReceived(null, new LogReceivedEventArgs(new LogLog(source, prefix, message, exception))); - } - } + /// + /// Raises the LogReceived event when an internal messages is received. + /// + /// + /// + /// + /// + public static void OnLogReceived(Type source, string prefix, string message, Exception exception) + { + if (LogReceived != null) + { + LogReceived(null, new LogReceivedEventArgs(new LogLog(source, prefix, message, exception))); + } + } - /// + /// /// Test if LogLog.Debug is enabled for output. /// /// @@ -320,7 +320,7 @@ public static bool IsDebugEnabled /// Writes log4net internal debug messages to the /// standard output stream. /// - /// + /// /// The message to log. /// /// @@ -328,16 +328,16 @@ public static bool IsDebugEnabled /// the string "log4net: ". /// /// - public static void Debug(Type source, string message) + public static void Debug(Type source, string message) { - if (IsDebugEnabled) + if (IsDebugEnabled) { - if (EmitInternalMessages) - { - EmitOutLine(PREFIX + message); - } + if (EmitInternalMessages) + { + EmitOutLine(PREFIX + message); + } - OnLogReceived(source, PREFIX, message, null); + OnLogReceived(source, PREFIX, message, null); } } @@ -345,7 +345,7 @@ public static void Debug(Type source, string message) /// Writes log4net internal debug messages to the /// standard output stream. /// - /// The Type that generated this message. + /// The Type that generated this message. /// The message to log. /// An exception to log. /// @@ -354,23 +354,23 @@ public static void Debug(Type source, string message) /// the string "log4net: ". /// /// - public static void Debug(Type source, string message, Exception exception) + public static void Debug(Type source, string message, Exception exception) { - if (IsDebugEnabled) + if (IsDebugEnabled) { - if (EmitInternalMessages) - { - EmitOutLine(PREFIX + message); - if (exception != null) - { - EmitOutLine(exception.ToString()); - } - } - - OnLogReceived(source, PREFIX, message, exception); + if (EmitInternalMessages) + { + EmitOutLine(PREFIX + message); + if (exception != null) + { + EmitOutLine(exception.ToString()); + } + } + + OnLogReceived(source, PREFIX, message, exception); } } - + /// /// Test if LogLog.Warn is enabled for output. /// @@ -391,7 +391,7 @@ public static bool IsWarnEnabled /// Writes log4net internal warning messages to the /// standard error stream. /// - /// The Type that generated this message. + /// The Type that generated this message. /// The message to log. /// /// @@ -399,24 +399,24 @@ public static bool IsWarnEnabled /// the string "log4net:WARN ". /// /// - public static void Warn(Type source, string message) + public static void Warn(Type source, string message) { if (IsWarnEnabled) { - if (EmitInternalMessages) - { - EmitErrorLine(WARN_PREFIX + message); - } + if (EmitInternalMessages) + { + EmitErrorLine(WARN_PREFIX + message); + } - OnLogReceived(source, WARN_PREFIX, message, null); + OnLogReceived(source, WARN_PREFIX, message, null); } - } + } /// /// Writes log4net internal warning messages to the /// standard error stream. /// - /// The Type that generated this message. + /// The Type that generated this message. /// The message to log. /// An exception to log. /// @@ -425,22 +425,22 @@ public static void Warn(Type source, string message) /// the string "log4net:WARN ". /// /// - public static void Warn(Type source, string message, Exception exception) + public static void Warn(Type source, string message, Exception exception) { if (IsWarnEnabled) { - if (EmitInternalMessages) - { - EmitErrorLine(WARN_PREFIX + message); - if (exception != null) - { - EmitErrorLine(exception.ToString()); - } - } - - OnLogReceived(source, WARN_PREFIX, message, exception); + if (EmitInternalMessages) + { + EmitErrorLine(WARN_PREFIX + message); + if (exception != null) + { + EmitErrorLine(exception.ToString()); + } + } + + OnLogReceived(source, WARN_PREFIX, message, exception); } - } + } /// /// Test if LogLog.Error is enabled for output. @@ -462,7 +462,7 @@ public static bool IsErrorEnabled /// Writes log4net internal error messages to the /// standard error stream. /// - /// The Type that generated this message. + /// The Type that generated this message. /// The message to log. /// /// @@ -470,24 +470,24 @@ public static bool IsErrorEnabled /// the string "log4net:ERROR ". /// /// - public static void Error(Type source, string message) + public static void Error(Type source, string message) { if (IsErrorEnabled) { - if (EmitInternalMessages) - { - EmitErrorLine(ERR_PREFIX + message); - } + if (EmitInternalMessages) + { + EmitErrorLine(ERR_PREFIX + message); + } - OnLogReceived(source, ERR_PREFIX, message, null); + OnLogReceived(source, ERR_PREFIX, message, null); } - } + } /// /// Writes log4net internal error messages to the /// standard error stream. /// - /// The Type that generated this message. + /// The Type that generated this message. /// The message to log. /// An exception to log. /// @@ -496,22 +496,22 @@ public static void Error(Type source, string message) /// the string "log4net:ERROR ". /// /// - public static void Error(Type source, string message, Exception exception) + public static void Error(Type source, string message, Exception exception) { if (IsErrorEnabled) { - if (EmitInternalMessages) - { - EmitErrorLine(ERR_PREFIX + message); - if (exception != null) - { - EmitErrorLine(exception.ToString()); - } - } - - OnLogReceived(source, ERR_PREFIX, message, exception); + if (EmitInternalMessages) + { + EmitErrorLine(ERR_PREFIX + message); + if (exception != null) + { + EmitErrorLine(exception.ToString()); + } + } + + OnLogReceived(source, ERR_PREFIX, message, exception); } - } + } #endregion Public Static Methods @@ -595,81 +595,81 @@ private static void EmitErrorLine(string message) /// private static bool s_quietMode = false; - private static bool s_emitInternalMessages = true; + private static bool s_emitInternalMessages = true; - private const string PREFIX = "log4net: "; - private const string ERR_PREFIX = "log4net:ERROR "; - private const string WARN_PREFIX = "log4net:WARN "; + private const string PREFIX = "log4net: "; + private const string ERR_PREFIX = "log4net:ERROR "; + private const string WARN_PREFIX = "log4net:WARN "; #endregion Private Static Fields - /// - /// Subscribes to the LogLog.LogReceived event and stores messages - /// to the supplied IList instance. - /// - public class LogReceivedAdapter : IDisposable - { - private readonly IList items; - private readonly LogReceivedEventHandler handler; - - /// - /// - /// - /// - public LogReceivedAdapter(IList items) - { - this.items = items; - - handler = new LogReceivedEventHandler(LogLog_LogReceived); - - LogReceived += handler; - } - - void LogLog_LogReceived(object source, LogReceivedEventArgs e) - { - items.Add(e.LogLog); - } - - /// - /// - /// - public IList Items - { - get { return items; } - } - - /// - /// - /// - public void Dispose() - { - LogReceived -= handler; - } - } + /// + /// Subscribes to the LogLog.LogReceived event and stores messages + /// to the supplied IList instance. + /// + public class LogReceivedAdapter : IDisposable + { + private readonly IList items; + private readonly LogReceivedEventHandler handler; + + /// + /// + /// + /// + public LogReceivedAdapter(IList items) + { + this.items = items; + + handler = new LogReceivedEventHandler(LogLog_LogReceived); + + LogReceived += handler; + } + + void LogLog_LogReceived(object source, LogReceivedEventArgs e) + { + items.Add(e.LogLog); + } + + /// + /// + /// + public IList Items + { + get { return items; } + } + + /// + /// + /// + public void Dispose() + { + LogReceived -= handler; + } + } } + /// + /// + /// + public class LogReceivedEventArgs : EventArgs + { + private readonly LogLog loglog; + /// /// /// - public class LogReceivedEventArgs : EventArgs + /// + public LogReceivedEventArgs(LogLog loglog) { - private readonly LogLog loglog; - - /// - /// - /// - /// - public LogReceivedEventArgs(LogLog loglog) - { - this.loglog = loglog; - } + this.loglog = loglog; + } - /// - /// - /// - public LogLog LogLog - { - get { return loglog; } - } + /// + /// + /// + public LogLog LogLog + { + get { return loglog; } } + } } diff --git a/src/log4net/Util/LogicalThreadContextProperties.cs b/src/log4net/Util/LogicalThreadContextProperties.cs index 8a938943..21042205 100644 --- a/src/log4net/Util/LogicalThreadContextProperties.cs +++ b/src/log4net/Util/LogicalThreadContextProperties.cs @@ -64,12 +64,12 @@ public sealed class LogicalThreadContextProperties : ContextPropertiesBase #else private const string c_SlotName = "log4net.Util.LogicalThreadContextProperties"; #endif - + /// /// Flag used to disable this context if we don't have permission to access the CallContext. /// private bool m_disabled = false; - + #region Public Instance Constructors /// @@ -101,17 +101,17 @@ internal LogicalThreadContextProperties() /// public override object this[string key] { - get - { + get + { // Don't create the dictionary if it does not already exist PropertiesDictionary dictionary = GetProperties(false); if (dictionary != null) { - return dictionary[key]; + return dictionary[key]; } return null; } - set + set { // Force the dictionary to be created PropertiesDictionary props = GetProperties(true); @@ -198,12 +198,12 @@ internal PropertiesDictionary GetProperties(bool create) catch (SecurityException secEx) { m_disabled = true; - + // Thrown if we don't have permission to read or write the CallContext LogLog.Warn(declaringType, "SecurityException while accessing CallContext. Disabling LogicalThreadContextProperties", secEx); } } - + // Only get here is we are disabled because of a security exception if (create) { @@ -214,9 +214,9 @@ internal PropertiesDictionary GetProperties(bool create) #endregion Internal Instance Methods - #region Private Static Methods + #region Private Static Methods - /// + /// /// Gets the call context get data. /// /// The peroperties dictionary stored in the call context @@ -228,12 +228,12 @@ internal PropertiesDictionary GetProperties(bool create) #if NET_4_0 || MONO_4_0 || NETSTANDARD [System.Security.SecuritySafeCritical] #endif - private static PropertiesDictionary GetLogicalProperties() + private static PropertiesDictionary GetLogicalProperties() { #if NETSTANDARD return AsyncLocalDictionary.Value; #elif NET_2_0 || MONO_2_0 || MONO_3_5 || MONO_4_0 - return CallContext.LogicalGetData(c_SlotName) as PropertiesDictionary; + return CallContext.LogicalGetData(c_SlotName) as PropertiesDictionary; #else return CallContext.GetData(c_SlotName) as PropertiesDictionary; #endif @@ -251,7 +251,7 @@ private static PropertiesDictionary GetLogicalProperties() #if NET_4_0 || MONO_4_0 || NETSTANDARD [System.Security.SecuritySafeCritical] #endif - private static void SetLogicalProperties(PropertiesDictionary properties) + private static void SetLogicalProperties(PropertiesDictionary properties) { #if NETSTANDARD AsyncLocalDictionary.Value = properties; @@ -260,23 +260,23 @@ private static void SetLogicalProperties(PropertiesDictionary properties) #else CallContext.SetData(c_SlotName, properties); #endif - } + } - #endregion + #endregion - #region Private Static Fields + #region Private Static Fields - /// - /// The fully qualified type of the LogicalThreadContextProperties class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(LogicalThreadContextProperties); + /// + /// The fully qualified type of the LogicalThreadContextProperties class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(LogicalThreadContextProperties); - #endregion Private Static Fields - } + #endregion Private Static Fields + } } #endif diff --git a/src/log4net/Util/LogicalThreadContextStack.cs b/src/log4net/Util/LogicalThreadContextStack.cs index 45993ebc..bd7b0ab1 100644 --- a/src/log4net/Util/LogicalThreadContextStack.cs +++ b/src/log4net/Util/LogicalThreadContextStack.cs @@ -29,11 +29,11 @@ namespace log4net.Util /// /// Delegate type used for LogicalThreadContextStack's callbacks. /// - #if NET_2_0 || MONO_2_0 || NETSTANDARD +#if NET_2_0 || MONO_2_0 || NETSTANDARD public delegate void TwoArgAction(T1 t1, T2 t2); - #else +#else public delegate void TwoArgAction(string t1, LogicalThreadContextStack t2); - #endif +#endif /// /// Implementation of Stack for the @@ -63,11 +63,11 @@ public sealed class LogicalThreadContextStack : IFixingRequired /// The callback used to let the register a /// new instance of a . /// - #if NET_2_0 || MONO_2_0 || NETSTANDARD +#if NET_2_0 || MONO_2_0 || NETSTANDARD private TwoArgAction m_registerNew; - #else +#else private TwoArgAction m_registerNew; - #endif +#endif #endregion Private Instance Fields @@ -81,11 +81,11 @@ public sealed class LogicalThreadContextStack : IFixingRequired /// Initializes a new instance of the class. /// /// - #if NET_2_0 || MONO_2_0 || NETSTANDARD +#if NET_2_0 || MONO_2_0 || NETSTANDARD internal LogicalThreadContextStack(string propertyKey, TwoArgAction registerNew) - #else +#else internal LogicalThreadContextStack(string propertyKey, TwoArgAction registerNew) - #endif +#endif { m_propertyKey = propertyKey; m_registerNew = registerNew; diff --git a/src/log4net/Util/NativeError.cs b/src/log4net/Util/NativeError.cs index a17a40c5..e93cef18 100644 --- a/src/log4net/Util/NativeError.cs +++ b/src/log4net/Util/NativeError.cs @@ -28,7 +28,7 @@ using System.Globalization; using System.Runtime.InteropServices; -namespace log4net.Util +namespace log4net.Util { /// /// Represents a native error code and message. @@ -40,7 +40,7 @@ namespace log4net.Util /// /// Nicko Cadell /// Gert Driesen - public sealed class NativeError + public sealed class NativeError { #region Protected Instance Constructors @@ -56,7 +56,7 @@ public sealed class NativeError /// error number and message. /// /// - private NativeError(int number, string message) + private NativeError(int number, string message) { m_number = number; m_message = message; @@ -77,7 +77,7 @@ private NativeError(int number, string message) /// Gets the number of the native error. /// /// - public int Number + public int Number { get { return m_number; } } @@ -93,7 +93,7 @@ public int Number /// /// Gets the message of the native error. /// - public string Message + public string Message { get { return m_message; } } @@ -118,9 +118,9 @@ public string Message [System.Security.SecuritySafeCritical] #endif #if !NETCF && !NETSTANDARD1_3 - [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, UnmanagedCode = true)] + [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, UnmanagedCode = true)] #endif - public static NativeError GetLastError() + public static NativeError GetLastError() { int number = Marshal.GetLastWin32Error(); return new NativeError(number, NativeError.GetErrorMessage(number)); @@ -140,7 +140,7 @@ public static NativeError GetLastError() /// native Win32 FormatMessage function. /// /// - public static NativeError GetError(int number) + public static NativeError GetError(int number) { return new NativeError(number, NativeError.GetErrorMessage(number)); } @@ -162,43 +162,43 @@ public static NativeError GetError(int number) [System.Security.SecuritySafeCritical] #endif #if !NETCF && !NETSTANDARD1_3 - [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, UnmanagedCode = true)] + [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, UnmanagedCode = true)] #endif - public static string GetErrorMessage(int messageId) + public static string GetErrorMessage(int messageId) { // Win32 constants int FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100; // The function should allocates a buffer large enough to hold the formatted message int FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200; // Insert sequences in the message definition are to be ignored - int FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000; // The function should search the system message-table resource(s) for the requested message + int FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000; // The function should search the system message-table resource(s) for the requested message string msgBuf = ""; // buffer that will receive the message IntPtr sourcePtr = new IntPtr(); // Location of the message definition, will be ignored IntPtr argumentsPtr = new IntPtr(); // Pointer to array of values to insert, not supported as it requires unsafe code - if (messageId != 0) + if (messageId != 0) { // If the function succeeds, the return value is the number of TCHARs stored in the output buffer, excluding the terminating null character int messageSize = FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - ref sourcePtr, - messageId, - 0, - ref msgBuf, - 255, + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + ref sourcePtr, + messageId, + 0, + ref msgBuf, + 255, argumentsPtr); - if (messageSize > 0) + if (messageSize > 0) { // Remove trailing null-terminating characters (\r\n) from the message - msgBuf = msgBuf.TrimEnd(new char[] {'\r', '\n'}); + msgBuf = msgBuf.TrimEnd(new char[] { '\r', '\n' }); } - else + else { // A message could not be located. msgBuf = null; } - } - else + } + else { msgBuf = null; } @@ -219,7 +219,7 @@ public static string GetErrorMessage(int messageId) /// Return error information string /// /// - public override string ToString() + public override string ToString() { return string.Format(CultureInfo.InvariantCulture, "0x{0:x8}", this.Number) + (this.Message != null ? ": " + this.Message : ""); } @@ -265,14 +265,14 @@ public override string ToString() #if NETCF || NETSTANDARD [DllImport("CoreDll.dll", SetLastError=true, CharSet=CharSet.Unicode)] #else - [DllImport("Kernel32.dll", SetLastError=true, CharSet=CharSet.Auto)] + [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] #endif private static extern int FormatMessage( - int dwFlags, - ref IntPtr lpSource, + int dwFlags, + ref IntPtr lpSource, int dwMessageId, - int dwLanguageId, - ref String lpBuffer, + int dwLanguageId, + ref String lpBuffer, int nSize, IntPtr Arguments); diff --git a/src/log4net/Util/NullDictionaryEnumerator.cs b/src/log4net/Util/NullDictionaryEnumerator.cs index 53d15260..5f1d0552 100644 --- a/src/log4net/Util/NullDictionaryEnumerator.cs +++ b/src/log4net/Util/NullDictionaryEnumerator.cs @@ -52,7 +52,7 @@ private NullDictionaryEnumerator() #endregion Private Instance Constructors #region Public Static Properties - + /// /// Gets the singleton instance of the . /// @@ -87,11 +87,11 @@ public static NullDictionaryEnumerator Instance /// /// The collection is empty and /// cannot be positioned over a valid location. - public object Current + public object Current { - get { throw new InvalidOperationException(); } + get { throw new InvalidOperationException(); } } - + /// /// Test if the enumerator can advance, if so advance. /// @@ -107,7 +107,7 @@ public bool MoveNext() { return false; } - + /// /// Resets the enumerator back to the start. /// @@ -116,7 +116,7 @@ public bool MoveNext() /// As the enumerator is over an empty collection does nothing. /// /// - public void Reset() + public void Reset() { } @@ -140,9 +140,9 @@ public void Reset() /// /// The collection is empty and /// cannot be positioned over a valid location. - public object Key + public object Key { - get { throw new InvalidOperationException(); } + get { throw new InvalidOperationException(); } } /// @@ -162,9 +162,9 @@ public object Key /// /// The collection is empty and /// cannot be positioned over a valid location. - public object Value + public object Value { - get { throw new InvalidOperationException(); } + get { throw new InvalidOperationException(); } } /// @@ -183,11 +183,11 @@ public object Value /// /// The collection is empty and /// cannot be positioned over a valid location. - public DictionaryEntry Entry + public DictionaryEntry Entry { - get { throw new InvalidOperationException(); } + get { throw new InvalidOperationException(); } } - + #endregion Implementation of IDictionaryEnumerator #region Private Static Fields @@ -196,7 +196,7 @@ public DictionaryEntry Entry /// The singleton instance of the . /// private static readonly NullDictionaryEnumerator s_instance = new NullDictionaryEnumerator(); - + #endregion Private Static Fields } } diff --git a/src/log4net/Util/NullEnumerator.cs b/src/log4net/Util/NullEnumerator.cs index 05351f2e..4c57d11b 100644 --- a/src/log4net/Util/NullEnumerator.cs +++ b/src/log4net/Util/NullEnumerator.cs @@ -50,7 +50,7 @@ private NullEnumerator() } #endregion Private Instance Constructors - + #region Public Static Properties /// @@ -87,11 +87,11 @@ public static NullEnumerator Instance /// /// The collection is empty and /// cannot be positioned over a valid location. - public object Current + public object Current { - get { throw new InvalidOperationException(); } + get { throw new InvalidOperationException(); } } - + /// /// Test if the enumerator can advance, if so advance /// @@ -107,7 +107,7 @@ public bool MoveNext() { return false; } - + /// /// Resets the enumerator back to the start. /// @@ -116,7 +116,7 @@ public bool MoveNext() /// As the enumerator is over an empty collection does nothing. /// /// - public void Reset() + public void Reset() { } @@ -128,7 +128,7 @@ public void Reset() /// The singleton instance of the . /// private static readonly NullEnumerator s_instance = new NullEnumerator(); - + #endregion Private Static Fields } } diff --git a/src/log4net/Util/OnlyOnceErrorHandler.cs b/src/log4net/Util/OnlyOnceErrorHandler.cs index ba4f0d13..f5936073 100644 --- a/src/log4net/Util/OnlyOnceErrorHandler.cs +++ b/src/log4net/Util/OnlyOnceErrorHandler.cs @@ -101,48 +101,50 @@ public void Reset() /// Invokes if and only if this is the first error or the first error after has been called. /// /// - public void Error(string message, Exception e, ErrorCode errorCode) + public void Error(string message, Exception e, ErrorCode errorCode) { if (m_firstTime) { - FirstError(message, e, errorCode); + FirstError(message, e, errorCode); } } - /// - /// Log the very first error - /// - /// The error message. - /// The exception. - /// The internal error code. - /// - /// - /// Sends the error information to 's Error method. - /// - /// - public virtual void FirstError(string message, Exception e, ErrorCode errorCode) { - m_enabledDateUtc = DateTime.UtcNow; - m_errorCode = errorCode; - m_exception = e; - m_message = message; - m_firstTime = false; - - if (LogLog.InternalDebugging && !LogLog.QuietMode) { - LogLog.Error(declaringType, "[" + m_prefix + "] ErrorCode: " + errorCode.ToString() + ". " + message, e); - } - } - - /// + /// + /// Log the very first error + /// + /// The error message. + /// The exception. + /// The internal error code. + /// + /// + /// Sends the error information to 's Error method. + /// + /// + public virtual void FirstError(string message, Exception e, ErrorCode errorCode) + { + m_enabledDateUtc = DateTime.UtcNow; + m_errorCode = errorCode; + m_exception = e; + m_message = message; + m_firstTime = false; + + if (LogLog.InternalDebugging && !LogLog.QuietMode) + { + LogLog.Error(declaringType, "[" + m_prefix + "] ErrorCode: " + errorCode.ToString() + ". " + message, e); + } + } + + /// /// Log an Error /// /// The error message. /// The exception. /// - /// - /// Invokes if and only if this is the first error or the first error after has been called. - /// - /// - public void Error(string message, Exception e) + /// + /// Invokes if and only if this is the first error or the first error after has been called. + /// + /// + public void Error(string message, Exception e) { Error(message, e, ErrorCode.GenericFailure); } @@ -152,11 +154,11 @@ public void Error(string message, Exception e) /// /// The error message. /// - /// - /// Invokes if and only if this is the first error or the first error after has been called. - /// - /// - public void Error(string message) + /// + /// Invokes if and only if this is the first error or the first error after has been called. + /// + /// + public void Error(string message) { Error(message, null, ErrorCode.GenericFailure); } @@ -186,20 +188,20 @@ public bool IsEnabled /// public DateTime EnabledDate { - get - { - if (m_enabledDateUtc == DateTime.MinValue) return DateTime.MinValue; - return m_enabledDateUtc.ToLocalTime(); - } + get + { + if (m_enabledDateUtc == DateTime.MinValue) return DateTime.MinValue; + return m_enabledDateUtc.ToLocalTime(); + } } - /// - /// The UTC date the first error that trigged this error handler occured, or if it has not been triggered. - /// - public DateTime EnabledDateUtc - { - get { return m_enabledDateUtc; } - } + /// + /// The UTC date the first error that trigged this error handler occured, or if it has not been triggered. + /// + public DateTime EnabledDateUtc + { + get { return m_enabledDateUtc; } + } /// /// The message from the first error that trigged this error handler. @@ -269,13 +271,13 @@ public ErrorCode ErrorCode #region Private Static Fields - /// - /// The fully qualified type of the OnlyOnceErrorHandler class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// + /// + /// The fully qualified type of the OnlyOnceErrorHandler class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// private static readonly Type declaringType = typeof(OnlyOnceErrorHandler); #endregion diff --git a/src/log4net/Util/OptionConverter.cs b/src/log4net/Util/OptionConverter.cs index 77075b7b..8f4bcc75 100644 --- a/src/log4net/Util/OptionConverter.cs +++ b/src/log4net/Util/OptionConverter.cs @@ -70,7 +70,7 @@ private OptionConverter() /// Otherwise, is returned. /// /// - public static bool ToBoolean(string argValue, bool defaultValue) + public static bool ToBoolean(string argValue, bool defaultValue) { if (argValue != null && argValue.Length > 0) { @@ -78,7 +78,7 @@ public static bool ToBoolean(string argValue, bool defaultValue) { return bool.Parse(argValue); } - catch(Exception e) + catch (Exception e) { LogLog.Error(declaringType, "[" + argValue + "] is not in proper bool form.", e); } @@ -102,37 +102,37 @@ public static bool ToBoolean(string argValue, bool defaultValue) /// cannot be converted to a value. /// /// - public static long ToFileSize(string argValue, long defaultValue) + public static long ToFileSize(string argValue, long defaultValue) { if (argValue == null) { return defaultValue; } - + string s = argValue.Trim().ToUpperInvariant(); long multiplier = 1; int index; - - if ((index = s.IndexOf("KB")) != -1) - { + + if ((index = s.IndexOf("KB")) != -1) + { multiplier = 1024; s = s.Substring(0, index); } - else if ((index = s.IndexOf("MB")) != -1) + else if ((index = s.IndexOf("MB")) != -1) { multiplier = 1024 * 1024; s = s.Substring(0, index); } - else if ((index = s.IndexOf("GB")) != -1) + else if ((index = s.IndexOf("GB")) != -1) { multiplier = 1024 * 1024 * 1024; s = s.Substring(0, index); - } - if (s != null) + } + if (s != null) { // Try again to remove whitespace between the number and the size specifier s = s.Trim(); - + long longVal; if (SystemInfo.TryParse(s, out longVal)) { @@ -140,7 +140,7 @@ public static long ToFileSize(string argValue, long defaultValue) } else { - LogLog.Error(declaringType, "OptionConverter: ["+ s +"] is not in the correct file size syntax."); + LogLog.Error(declaringType, "OptionConverter: [" + s + "] is not in the correct file size syntax."); } } return defaultValue; @@ -200,14 +200,14 @@ public static object ConvertStringTo(Type target, string txt) // to an arbitrary type T there will be a static method defined on type T called Parse // that will take an argument of type string. i.e. T.Parse(string)->T we call this // method to convert the string to the type required by the property. - System.Reflection.MethodInfo meth = target.GetMethod("Parse", new Type[] {typeof(string)}); + System.Reflection.MethodInfo meth = target.GetMethod("Parse", new Type[] { typeof(string) }); if (meth != null) { // Call the Parse method #if NETSTANDARD1_3 return meth.Invoke(target, new[] { txt }); #else - return meth.Invoke(null, BindingFlags.InvokeMethod, null, new object[] {txt}, CultureInfo.InvariantCulture); + return meth.Invoke(null, BindingFlags.InvokeMethod, null, new object[] { txt }, CultureInfo.InvariantCulture); #endif } else @@ -219,20 +219,20 @@ public static object ConvertStringTo(Type target, string txt) return null; } -// /// -// /// Looks up the for the target type. -// /// -// /// The type to lookup the converter for. -// /// The converter for the specified type. -// public static IConvertFrom GetTypeConverter(Type target) -// { -// IConvertFrom converter = ConverterRegistry.GetConverter(target); -// if (converter == null) -// { -// throw new InvalidOperationException("No type converter defined for [" + target + "]"); -// } -// return converter; -// } + // /// + // /// Looks up the for the target type. + // /// + // /// The type to lookup the converter for. + // /// The converter for the specified type. + // public static IConvertFrom GetTypeConverter(Type target) + // { + // IConvertFrom converter = ConverterRegistry.GetConverter(target); + // if (converter == null) + // { + // throw new InvalidOperationException("No type converter defined for [" + target + "]"); + // } + // return converter; + // } /// /// Checks if there is an appropriate type conversion from the source type to the target type. @@ -325,37 +325,37 @@ public static object ConvertTypeTo(object sourceInstance, Type targetType) throw new ArgumentException("Cannot convert source object [" + sourceInstance.ToString() + "] to target type [" + targetType.Name + "]", "sourceInstance"); } -// /// -// /// Finds the value corresponding to in -// /// and then perform variable substitution -// /// on the found value. -// /// -// /// The key to lookup. -// /// The association to use for lookups. -// /// The substituted result. -// public static string FindAndSubst(string key, System.Collections.IDictionary props) -// { -// if (props == null) -// { -// throw new ArgumentNullException("props"); -// } -// -// string v = props[key] as string; -// if (v == null) -// { -// return null; -// } -// -// try -// { -// return SubstituteVariables(v, props); -// } -// catch(Exception e) -// { -// LogLog.Error(declaringType, "OptionConverter: Bad option value [" + v + "].", e); -// return v; -// } -// } + // /// + // /// Finds the value corresponding to in + // /// and then perform variable substitution + // /// on the found value. + // /// + // /// The key to lookup. + // /// The association to use for lookups. + // /// The substituted result. + // public static string FindAndSubst(string key, System.Collections.IDictionary props) + // { + // if (props == null) + // { + // throw new ArgumentNullException("props"); + // } + // + // string v = props[key] as string; + // if (v == null) + // { + // return null; + // } + // + // try + // { + // return SubstituteVariables(v, props); + // } + // catch(Exception e) + // { + // LogLog.Error(declaringType, "OptionConverter: Bad option value [" + v + "].", e); + // return v; + // } + // } /// /// Instantiates an object given a class name. @@ -374,30 +374,30 @@ public static object ConvertTypeTo(object sourceInstance, Type targetType) /// not be instantiated, then is returned. /// /// - public static object InstantiateByClassName(string className, Type superClass, object defaultValue) + public static object InstantiateByClassName(string className, Type superClass, object defaultValue) { - if (className != null) + if (className != null) { - try + try { #if NETSTANDARD1_3 Type classObj = SystemInfo.GetTypeFromString(superClass.GetTypeInfo().Assembly, className, true, true); #else Type classObj = SystemInfo.GetTypeFromString(className, true, true); #endif - if (!superClass.IsAssignableFrom(classObj)) + if (!superClass.IsAssignableFrom(classObj)) { LogLog.Error(declaringType, "OptionConverter: A [" + className + "] object is not assignable to a [" + superClass.FullName + "] variable."); - return defaultValue; + return defaultValue; } return Activator.CreateInstance(classObj); } - catch (Exception e) + catch (Exception e) { LogLog.Error(declaringType, "Could not instantiate class [" + className + "].", e); } } - return defaultValue; + return defaultValue; } /// @@ -443,48 +443,48 @@ public static object InstantiateByClassName(string className, Type superClass, o /// delimiter "${" which is not balanced by a stop delimiter "}". /// /// - public static string SubstituteVariables(string value, System.Collections.IDictionary props) + public static string SubstituteVariables(string value, System.Collections.IDictionary props) { StringBuilder buf = new StringBuilder(); int i = 0; int j, k; - - while(true) + + while (true) { j = value.IndexOf(DELIM_START, i); - if (j == -1) + if (j == -1) { if (i == 0) { return value; } - else + else { buf.Append(value.Substring(i, value.Length - i)); return buf.ToString(); } } - else + else { buf.Append(value.Substring(i, j - i)); k = value.IndexOf(DELIM_STOP, j); - if (k == -1) + if (k == -1) { throw new LogException("[" + value + "] has no closing brace. Opening brace at position [" + j + "]"); } - else + else { j += DELIM_START_LEN; string key = value.Substring(j, k - j); string replacement = props[key] as string; - if (replacement != null) + if (replacement != null) { buf.Append(replacement); } - i = k + DELIM_STOP_LEN; + i = k + DELIM_STOP_LEN; } } } @@ -502,7 +502,7 @@ public static string SubstituteVariables(string value, System.Collections.IDicti /// The enum string value. /// If true, ignore case; otherwise, regard case. /// An object of type whose value is represented by . - private static object ParseEnum(System.Type enumType, string value, bool ignoreCase) + private static object ParseEnum(System.Type enumType, string value, bool ignoreCase) { #if !NETCF return Enum.Parse(enumType, value, ignoreCase); @@ -543,25 +543,25 @@ private static object ParseEnum(System.Type enumType, string value, bool ignoreC } return Enum.ToObject(enumType, retVal); #endif - } + } #endregion Private Static Methods #region Private Static Fields - /// - /// The fully qualified type of the OptionConverter class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(OptionConverter); + /// + /// The fully qualified type of the OptionConverter class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(OptionConverter); private const string DELIM_START = "${"; - private const char DELIM_STOP = '}'; + private const char DELIM_STOP = '}'; private const int DELIM_START_LEN = 2; - private const int DELIM_STOP_LEN = 1; + private const int DELIM_STOP_LEN = 1; #endregion Private Static Fields } diff --git a/src/log4net/Util/PatternConverter.cs b/src/log4net/Util/PatternConverter.cs index 295a7495..8403ddd4 100644 --- a/src/log4net/Util/PatternConverter.cs +++ b/src/log4net/Util/PatternConverter.cs @@ -51,8 +51,8 @@ public abstract class PatternConverter /// Initializes a new instance of the class. /// /// - protected PatternConverter() - { + protected PatternConverter() + { } #endregion Protected Instance Constructors @@ -165,7 +165,7 @@ public virtual PatternConverter SetNext(PatternConverter patternConverter) /// apply those formattings before writing the output. /// /// - public virtual void Format(TextWriter writer, object state) + public virtual void Format(TextWriter writer, object state) { if (m_min < 0 && m_max == int.MaxValue) { @@ -174,35 +174,35 @@ public virtual void Format(TextWriter writer, object state) } else { - string msg = null; - int len; - lock (m_formatWriter) - { - m_formatWriter.Reset(c_renderBufferMaxCapacity, c_renderBufferSize); - - Convert(m_formatWriter, state); - - StringBuilder buf = m_formatWriter.GetStringBuilder(); - len = buf.Length; - if (len > m_max) - { - msg = buf.ToString(len - m_max, m_max); - len = m_max; - } - else - { - msg = buf.ToString(); - } - } - - if (len < m_min) + string msg = null; + int len; + lock (m_formatWriter) { - if (m_leftAlign) - { + m_formatWriter.Reset(c_renderBufferMaxCapacity, c_renderBufferSize); + + Convert(m_formatWriter, state); + + StringBuilder buf = m_formatWriter.GetStringBuilder(); + len = buf.Length; + if (len > m_max) + { + msg = buf.ToString(len - m_max, m_max); + len = m_max; + } + else + { + msg = buf.ToString(); + } + } + + if (len < m_min) + { + if (m_leftAlign) + { writer.Write(msg); SpacePad(writer, m_min - len); } - else + else { SpacePad(writer, m_min - len); writer.Write(msg); @@ -213,7 +213,7 @@ public virtual void Format(TextWriter writer, object state) writer.Write(msg); } } - } + } private static readonly string[] SPACES = { " ", " ", " ", " ", // 1,2,4,8 spaces " ", // 16 spaces @@ -229,22 +229,22 @@ public virtual void Format(TextWriter writer, object state) /// Fast space padding method. /// /// - protected static void SpacePad(TextWriter writer, int length) + protected static void SpacePad(TextWriter writer, int length) { - while(length >= 32) + while (length >= 32) { writer.Write(SPACES[5]); length -= 32; } - - for(int i = 4; i >= 0; i--) - { - if ((length & (1<= 0; i--) + { + if ((length & (1 << i)) != 0) { writer.Write(SPACES[i]); } } - } + } #endregion Public Instance Methods @@ -372,26 +372,26 @@ protected static void WriteObject(TextWriter writer, ILoggerRepository repositor // Don't have a repository to render with so just have to rely on ToString if (value == null) { - writer.Write( SystemInfo.NullText ); + writer.Write(SystemInfo.NullText); } else { - writer.Write( value.ToString() ); + writer.Write(value.ToString()); } } } #endregion - private PropertiesDictionary properties; + private PropertiesDictionary properties; - /// - /// - /// - public PropertiesDictionary Properties - { - get { return properties; } - set { properties = value; } - } + /// + /// + /// + public PropertiesDictionary Properties + { + get { return properties; } + set { properties = value; } + } } } diff --git a/src/log4net/Util/PatternParser.cs b/src/log4net/Util/PatternParser.cs index fc4c40b4..c639d5a1 100644 --- a/src/log4net/Util/PatternParser.cs +++ b/src/log4net/Util/PatternParser.cs @@ -52,7 +52,7 @@ public sealed class PatternParser /// with the specified pattern string. /// /// - public PatternParser(string pattern) + public PatternParser(string pattern) { m_pattern = pattern; } @@ -164,7 +164,7 @@ public int Compare(object x, object y) return s2.Length.CompareTo(s1.Length); } - + #endregion } @@ -183,7 +183,7 @@ public int Compare(object x, object y) private void ParseInternal(string pattern, string[] matches) { int offset = 0; - while(offset < pattern.Length) + while (offset < pattern.Length) { int i = pattern.IndexOf('%', offset); if (i < 0 || i == pattern.Length - 1) @@ -193,7 +193,7 @@ private void ParseInternal(string pattern, string[] matches) } else { - if (pattern[i+1] == '%') + if (pattern[i + 1] == '%') { // Escaped ProcessLiteral(pattern.Substring(offset, i - offset + 1)); @@ -257,7 +257,7 @@ private void ParseInternal(string pattern, string[] matches) int remainingStringLength = pattern.Length - offset; // Look for pattern - for(int m=0; mthe formatting info for the converter private void ProcessConverter(string converterName, string option, FormattingInfo formattingInfo) { - LogLog.Debug(declaringType, "Converter ["+converterName+"] Option ["+option+"] Format [min="+formattingInfo.Min+",max="+formattingInfo.Max+",leftAlign="+formattingInfo.LeftAlign+"]"); + LogLog.Debug(declaringType, "Converter [" + converterName + "] Option [" + option + "] Format [min=" + formattingInfo.Min + ",max=" + formattingInfo.Max + ",leftAlign=" + formattingInfo.LeftAlign + "]"); // Lookup the converter type - ConverterInfo converterInfo = (ConverterInfo)m_patternConverters[converterName]; + ConverterInfo converterInfo = (ConverterInfo)m_patternConverters[converterName]; if (converterInfo == null) { - LogLog.Error(declaringType, "Unknown converter name ["+converterName+"] in conversion pattern."); + LogLog.Error(declaringType, "Unknown converter name [" + converterName + "] in conversion pattern."); } else { @@ -336,20 +336,20 @@ private void ProcessConverter(string converterName, string option, FormattingInf PatternConverter pc = null; try { - pc = (PatternConverter)Activator.CreateInstance(converterInfo.Type); + pc = (PatternConverter)Activator.CreateInstance(converterInfo.Type); } - catch(Exception createInstanceEx) + catch (Exception createInstanceEx) { - LogLog.Error(declaringType, "Failed to create instance of Type [" + converterInfo.Type.FullName + "] using default constructor. Exception: " + createInstanceEx.ToString()); + LogLog.Error(declaringType, "Failed to create instance of Type [" + converterInfo.Type.FullName + "] using default constructor. Exception: " + createInstanceEx.ToString()); } // formattingInfo variable is an instance variable, occasionally reset // and used over and over again pc.FormattingInfo = formattingInfo; pc.Option = option; - pc.Properties = converterInfo.Properties; + pc.Properties = converterInfo.Properties; - IOptionHandler optionHandler = pc as IOptionHandler; + IOptionHandler optionHandler = pc as IOptionHandler; if (optionHandler != null) { optionHandler.ActivateOptions(); @@ -364,15 +364,15 @@ private void ProcessConverter(string converterName, string option, FormattingInf /// to the chain. /// /// The pattern converter to add. - private void AddConverter(PatternConverter pc) + private void AddConverter(PatternConverter pc) { // Add the pattern converter to the list. - if (m_head == null) + if (m_head == null) { m_head = m_tail = pc; } - else + else { // Set the next converter on the tail // Update the tail reference @@ -387,7 +387,7 @@ private void AddConverter(PatternConverter pc) #region Private Constants private const char ESCAPE_CHAR = '%'; - + #endregion Private Constants #region Private Instance Fields @@ -419,17 +419,17 @@ private void AddConverter(PatternConverter pc) #endregion Private Instance Fields - #region Private Static Fields + #region Private Static Fields - /// - /// The fully qualified type of the PatternParser class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(PatternParser); + /// + /// The fully qualified type of the PatternParser class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(PatternParser); - #endregion Private Static Fields + #endregion Private Static Fields } } diff --git a/src/log4net/Util/PatternString.cs b/src/log4net/Util/PatternString.cs index cb5c4461..d844b635 100644 --- a/src/log4net/Util/PatternString.cs +++ b/src/log4net/Util/PatternString.cs @@ -265,12 +265,12 @@ public class PatternString : IOptionHandler #endregion Static Fields #region Member Variables - + /// /// the pattern /// private string m_pattern; - + /// /// the head of the pattern converter chain /// @@ -352,7 +352,7 @@ public PatternString(string pattern) } #endregion - + /// /// Gets or sets the pattern formatting string /// @@ -368,7 +368,7 @@ public PatternString(string pattern) /// public string ConversionPattern { - get { return m_pattern; } + get { return m_pattern; } set { m_pattern = value; } } @@ -390,7 +390,7 @@ public string ConversionPattern /// must be called again. /// /// - public virtual void ActivateOptions() + public virtual void ActivateOptions() { m_head = CreatePatternParser(m_pattern).Parse(); } @@ -409,27 +409,27 @@ public virtual void ActivateOptions() /// custom conversion pattern name. /// /// - private PatternParser CreatePatternParser(string pattern) + private PatternParser CreatePatternParser(string pattern) { PatternParser patternParser = new PatternParser(pattern); // Add all the builtin patterns - foreach(DictionaryEntry entry in s_globalRulesRegistry) + foreach (DictionaryEntry entry in s_globalRulesRegistry) { - ConverterInfo converterInfo = new ConverterInfo(); - converterInfo.Name = (string)entry.Key; - converterInfo.Type = (Type)entry.Value; - patternParser.PatternConverters.Add(entry.Key, converterInfo); + ConverterInfo converterInfo = new ConverterInfo(); + converterInfo.Name = (string)entry.Key; + converterInfo.Type = (Type)entry.Value; + patternParser.PatternConverters.Add(entry.Key, converterInfo); } // Add the instance patterns - foreach(DictionaryEntry entry in m_instanceRulesRegistry) + foreach (DictionaryEntry entry in m_instanceRulesRegistry) { patternParser.PatternConverters[entry.Key] = entry.Value; } return patternParser; } - + /// /// Produces a formatted string as specified by the conversion pattern. /// @@ -439,7 +439,7 @@ private PatternParser CreatePatternParser(string pattern) /// Format the pattern to the . /// /// - public void Format(TextWriter writer) + public void Format(TextWriter writer) { if (writer == null) { @@ -449,7 +449,7 @@ public void Format(TextWriter writer) PatternConverter c = m_head; // loop through the chain of pattern converters - while(c != null) + while (c != null) { c.Format(writer, null); c = c.Next; @@ -465,7 +465,7 @@ public void Format(TextWriter writer) /// Format the pattern to a string. /// /// - public string Format() + public string Format() { using StringWriter writer = new StringWriter(System.Globalization.CultureInfo.InvariantCulture); Format(writer); @@ -484,13 +484,13 @@ public string Format() /// public void AddConverter(ConverterInfo converterInfo) { - if (converterInfo == null) throw new ArgumentNullException("converterInfo"); + if (converterInfo == null) throw new ArgumentNullException("converterInfo"); - if (!typeof(PatternConverter).IsAssignableFrom(converterInfo.Type)) - { - throw new ArgumentException("The converter type specified [" + converterInfo.Type + "] must be a subclass of log4net.Util.PatternConverter", "converterInfo"); - } - m_instanceRulesRegistry[converterInfo.Name] = converterInfo; + if (!typeof(PatternConverter).IsAssignableFrom(converterInfo.Type)) + { + throw new ArgumentException("The converter type specified [" + converterInfo.Type + "] must be a subclass of log4net.Util.PatternConverter", "converterInfo"); + } + m_instanceRulesRegistry[converterInfo.Name] = converterInfo; } /// @@ -508,11 +508,11 @@ public void AddConverter(string name, Type type) if (name == null) throw new ArgumentNullException("name"); if (type == null) throw new ArgumentNullException("type"); - ConverterInfo converterInfo = new ConverterInfo(); - converterInfo.Name = name; - converterInfo.Type = type; + ConverterInfo converterInfo = new ConverterInfo(); + converterInfo.Name = name; + converterInfo.Type = type; - AddConverter(converterInfo); + AddConverter(converterInfo); } } } diff --git a/src/log4net/Util/PatternStringConverters/AppDomainPatternConverter.cs b/src/log4net/Util/PatternStringConverters/AppDomainPatternConverter.cs index a874299a..4168df14 100644 --- a/src/log4net/Util/PatternStringConverters/AppDomainPatternConverter.cs +++ b/src/log4net/Util/PatternStringConverters/AppDomainPatternConverter.cs @@ -34,7 +34,7 @@ namespace log4net.Util.PatternStringConverters /// /// /// Nicko Cadell - internal sealed class AppDomainPatternConverter : PatternConverter + internal sealed class AppDomainPatternConverter : PatternConverter { /// /// Write the name of the current AppDomain to the output @@ -46,9 +46,9 @@ internal sealed class AppDomainPatternConverter : PatternConverter /// Writes name of the current AppDomain to the output . /// /// - protected override void Convert(TextWriter writer, object state) + protected override void Convert(TextWriter writer, object state) { - writer.Write( SystemInfo.ApplicationFriendlyName ); + writer.Write(SystemInfo.ApplicationFriendlyName); } } } diff --git a/src/log4net/Util/PatternStringConverters/AppSettingPatternConverter.cs b/src/log4net/Util/PatternStringConverters/AppSettingPatternConverter.cs index 75d5fb02..b3487ff6 100644 --- a/src/log4net/Util/PatternStringConverters/AppSettingPatternConverter.cs +++ b/src/log4net/Util/PatternStringConverters/AppSettingPatternConverter.cs @@ -26,83 +26,83 @@ namespace log4net.Util.PatternStringConverters { + /// + /// AppSetting pattern converter + /// + /// + /// + /// This pattern converter reads appSettings from the application configuration file. + /// + /// + /// If the is specified then that will be used to + /// lookup a single appSettings value. If no is specified + /// then all appSettings will be dumped as a list of key value pairs. + /// + /// + /// A typical use is to specify a base directory for log files, e.g. + /// + /// + /// + /// + /// ... + /// + /// + /// ]]> + /// + /// + /// + internal sealed class AppSettingPatternConverter : PatternConverter + { + private static IDictionary AppSettingsDictionary + { + get + { + if (_appSettingsHashTable == null) + { + Hashtable h = new Hashtable(); + foreach (string key in ConfigurationManager.AppSettings) + { + h.Add(key, ConfigurationManager.AppSettings[key]); + } + _appSettingsHashTable = h; + } + return _appSettingsHashTable; + } + + } + private static Hashtable _appSettingsHashTable; + /// - /// AppSetting pattern converter + /// Write the property value to the output /// + /// that will receive the formatted result. + /// null, state is not set /// /// - /// This pattern converter reads appSettings from the application configuration file. - /// - /// - /// If the is specified then that will be used to - /// lookup a single appSettings value. If no is specified - /// then all appSettings will be dumped as a list of key value pairs. + /// Writes out the value of a named property. The property name + /// should be set in the + /// property. /// /// - /// A typical use is to specify a base directory for log files, e.g. - /// - /// - /// - /// - /// ... - /// - /// - /// ]]> - /// + /// If the is set to null + /// then all the properties are written as key value pairs. /// /// - internal sealed class AppSettingPatternConverter : PatternConverter + protected override void Convert(TextWriter writer, object state) { - private static IDictionary AppSettingsDictionary - { - get - { - if (_appSettingsHashTable == null) - { - Hashtable h = new Hashtable(); - foreach(string key in ConfigurationManager.AppSettings) - { - h.Add(key, ConfigurationManager.AppSettings[key]); - } - _appSettingsHashTable = h; - } - return _appSettingsHashTable; - } - - } - private static Hashtable _appSettingsHashTable; - /// - /// Write the property value to the output - /// - /// that will receive the formatted result. - /// null, state is not set - /// - /// - /// Writes out the value of a named property. The property name - /// should be set in the - /// property. - /// - /// - /// If the is set to null - /// then all the properties are written as key value pairs. - /// - /// - protected override void Convert(TextWriter writer, object state) - { - - if (Option != null) - { - // Write the value for the specified key - WriteObject(writer, null, ConfigurationManager.AppSettings[Option]); - } - else - { - // Write all the key value pairs - WriteDictionary(writer, null, AppSettingsDictionary); - } - } + if (Option != null) + { + // Write the value for the specified key + WriteObject(writer, null, ConfigurationManager.AppSettings[Option]); + } + else + { + // Write all the key value pairs + WriteDictionary(writer, null, AppSettingsDictionary); + } } + } } #endif // !NETCF && NET_2_0 diff --git a/src/log4net/Util/PatternStringConverters/DatePatternConverter.cs b/src/log4net/Util/PatternStringConverters/DatePatternConverter.cs index 315ce0a2..8f77b5fa 100644 --- a/src/log4net/Util/PatternStringConverters/DatePatternConverter.cs +++ b/src/log4net/Util/PatternStringConverters/DatePatternConverter.cs @@ -91,7 +91,7 @@ internal class DatePatternConverter : PatternConverter, IOptionHandler /// /// protected IDateFormatter m_dateFormatter; - + #region Implementation of IOptionHandler /// @@ -118,7 +118,7 @@ public void ActivateOptions() { dateFormatStr = AbsoluteTimeDateFormatter.Iso8601TimeDateFormat; } - + if (SystemInfo.EqualsIgnoringCase(dateFormatStr, AbsoluteTimeDateFormatter.Iso8601TimeDateFormat)) { m_dateFormatter = new Iso8601DateFormatter(); @@ -133,15 +133,15 @@ public void ActivateOptions() } else { - try + try { m_dateFormatter = new SimpleDateFormatter(dateFormatStr); } - catch (Exception e) + catch (Exception e) { - LogLog.Error(declaringType, "Could not instantiate SimpleDateFormatter with ["+dateFormatStr+"]", e); + LogLog.Error(declaringType, "Could not instantiate SimpleDateFormatter with [" + dateFormatStr + "]", e); m_dateFormatter = new Iso8601DateFormatter(); - } + } } } @@ -161,29 +161,29 @@ public void ActivateOptions() /// The date and time passed is in the local time zone. /// /// - protected override void Convert(TextWriter writer, object state) + protected override void Convert(TextWriter writer, object state) { - try + try { m_dateFormatter.FormatDate(DateTime.Now, writer); } - catch (Exception ex) + catch (Exception ex) { LogLog.Error(declaringType, "Error occurred while converting date.", ex); } } - #region Private Static Fields + #region Private Static Fields - /// - /// The fully qualified type of the DatePatternConverter class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(DatePatternConverter); + /// + /// The fully qualified type of the DatePatternConverter class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(DatePatternConverter); - #endregion Private Static Fields + #endregion Private Static Fields } } diff --git a/src/log4net/Util/PatternStringConverters/EnvironmentFolderPathPatternConverter.cs b/src/log4net/Util/PatternStringConverters/EnvironmentFolderPathPatternConverter.cs index bd8d4b59..a66cdcec 100644 --- a/src/log4net/Util/PatternStringConverters/EnvironmentFolderPathPatternConverter.cs +++ b/src/log4net/Util/PatternStringConverters/EnvironmentFolderPathPatternConverter.cs @@ -24,75 +24,75 @@ namespace log4net.Util.PatternStringConverters { + /// + /// Write an folder path to the output + /// + /// + /// + /// Write an special path environment folder path to the output writer. + /// The value of the determines + /// the name of the variable to output. + /// should be a value in the enumeration. + /// + /// + /// Ron Grabowski + internal sealed class EnvironmentFolderPathPatternConverter : PatternConverter + { /// - /// Write an folder path to the output + /// Write an special path environment folder path to the output /// + /// the writer to write to + /// null, state is not set /// /// - /// Write an special path environment folder path to the output writer. - /// The value of the determines - /// the name of the variable to output. - /// should be a value in the enumeration. + /// Writes the special path environment folder path to the output . + /// The name of the special path environment folder path to output must be set + /// using the + /// property. /// /// - /// Ron Grabowski - internal sealed class EnvironmentFolderPathPatternConverter : PatternConverter + protected override void Convert(TextWriter writer, object state) { - /// - /// Write an special path environment folder path to the output - /// - /// the writer to write to - /// null, state is not set - /// - /// - /// Writes the special path environment folder path to the output . - /// The name of the special path environment folder path to output must be set - /// using the - /// property. - /// - /// - protected override void Convert(TextWriter writer, object state) + try + { + if (Option != null && Option.Length > 0) { - try - { - if (Option != null && Option.Length > 0) - { - Environment.SpecialFolder specialFolder = - (Environment.SpecialFolder)Enum.Parse(typeof(Environment.SpecialFolder), Option, true); + Environment.SpecialFolder specialFolder = + (Environment.SpecialFolder)Enum.Parse(typeof(Environment.SpecialFolder), Option, true); - string envFolderPathValue = Environment.GetFolderPath(specialFolder); - if (envFolderPathValue != null && envFolderPathValue.Length > 0) - { - writer.Write(envFolderPathValue); - } - } - } - catch (System.Security.SecurityException secEx) - { - // This security exception will occur if the caller does not have - // unrestricted environment permission. If this occurs the expansion - // will be skipped with the following warning message. - LogLog.Debug(declaringType, "Security exception while trying to expand environment variables. Error Ignored. No Expansion.", secEx); - } - catch (Exception ex) - { - LogLog.Error(declaringType, "Error occurred while converting environment variable.", ex); - } + string envFolderPathValue = Environment.GetFolderPath(specialFolder); + if (envFolderPathValue != null && envFolderPathValue.Length > 0) + { + writer.Write(envFolderPathValue); + } } + } + catch (System.Security.SecurityException secEx) + { + // This security exception will occur if the caller does not have + // unrestricted environment permission. If this occurs the expansion + // will be skipped with the following warning message. + LogLog.Debug(declaringType, "Security exception while trying to expand environment variables. Error Ignored. No Expansion.", secEx); + } + catch (Exception ex) + { + LogLog.Error(declaringType, "Error occurred while converting environment variable.", ex); + } + } - #region Private Static Fields + #region Private Static Fields - /// - /// The fully qualified type of the EnvironmentFolderPathPatternConverter class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(EnvironmentFolderPathPatternConverter); + /// + /// The fully qualified type of the EnvironmentFolderPathPatternConverter class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(EnvironmentFolderPathPatternConverter); - #endregion Private Static Fields - } + #endregion Private Static Fields + } } #endif // !NETCF && NET_2_0 \ No newline at end of file diff --git a/src/log4net/Util/PatternStringConverters/EnvironmentPatternConverter.cs b/src/log4net/Util/PatternStringConverters/EnvironmentPatternConverter.cs index 8b011a5a..7efb2a22 100644 --- a/src/log4net/Util/PatternStringConverters/EnvironmentPatternConverter.cs +++ b/src/log4net/Util/PatternStringConverters/EnvironmentPatternConverter.cs @@ -51,9 +51,9 @@ internal sealed class EnvironmentPatternConverter : PatternConverter /// property. /// /// - protected override void Convert(TextWriter writer, object state) + protected override void Convert(TextWriter writer, object state) { - try + try { if (this.Option != null && this.Option.Length > 0) { @@ -61,17 +61,17 @@ protected override void Convert(TextWriter writer, object state) string envValue = Environment.GetEnvironmentVariable(this.Option); #if NET_2_0 || NETSTANDARD2_0 - // If we didn't see it for the process, try a user level variable. - if (envValue == null) - { - envValue = Environment.GetEnvironmentVariable(this.Option, EnvironmentVariableTarget.User); - } + // If we didn't see it for the process, try a user level variable. + if (envValue == null) + { + envValue = Environment.GetEnvironmentVariable(this.Option, EnvironmentVariableTarget.User); + } - // If we still didn't find it, try a system level one. - if (envValue == null) - { - envValue = Environment.GetEnvironmentVariable(this.Option, EnvironmentVariableTarget.Machine); - } + // If we still didn't find it, try a system level one. + if (envValue == null) + { + envValue = Environment.GetEnvironmentVariable(this.Option, EnvironmentVariableTarget.Machine); + } #endif if (envValue != null && envValue.Length > 0) @@ -80,31 +80,31 @@ protected override void Convert(TextWriter writer, object state) } } } - catch(System.Security.SecurityException secEx) + catch (System.Security.SecurityException secEx) { // This security exception will occur if the caller does not have // unrestricted environment permission. If this occurs the expansion // will be skipped with the following warning message. LogLog.Debug(declaringType, "Security exception while trying to expand environment variables. Error Ignored. No Expansion.", secEx); } - catch (Exception ex) + catch (Exception ex) { LogLog.Error(declaringType, "Error occurred while converting environment variable.", ex); } } - #region Private Static Fields + #region Private Static Fields - /// - /// The fully qualified type of the EnvironmentPatternConverter class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(EnvironmentPatternConverter); + /// + /// The fully qualified type of the EnvironmentPatternConverter class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(EnvironmentPatternConverter); - #endregion Private Static Fields + #endregion Private Static Fields } } diff --git a/src/log4net/Util/PatternStringConverters/IdentityPatternConverter.cs b/src/log4net/Util/PatternStringConverters/IdentityPatternConverter.cs index f31ca0d9..8f6b926e 100644 --- a/src/log4net/Util/PatternStringConverters/IdentityPatternConverter.cs +++ b/src/log4net/Util/PatternStringConverters/IdentityPatternConverter.cs @@ -34,7 +34,7 @@ namespace log4net.Util.PatternStringConverters /// /// /// Nicko Cadell - internal sealed class IdentityPatternConverter : PatternConverter + internal sealed class IdentityPatternConverter : PatternConverter { /// /// Write the current thread identity to the output @@ -46,7 +46,7 @@ internal sealed class IdentityPatternConverter : PatternConverter /// Writes the current thread identity to the output . /// /// - protected override void Convert(TextWriter writer, object state) + protected override void Convert(TextWriter writer, object state) { #if (NETCF || SSCLI || NETSTANDARD1_3) // On compact framework there's no notion of current thread principals @@ -54,35 +54,35 @@ protected override void Convert(TextWriter writer, object state) #else try { - if (System.Threading.Thread.CurrentPrincipal != null && + if (System.Threading.Thread.CurrentPrincipal != null && System.Threading.Thread.CurrentPrincipal.Identity != null && System.Threading.Thread.CurrentPrincipal.Identity.Name != null) { - writer.Write( System.Threading.Thread.CurrentPrincipal.Identity.Name ); + writer.Write(System.Threading.Thread.CurrentPrincipal.Identity.Name); } } - catch(System.Security.SecurityException) + catch (System.Security.SecurityException) { // This security exception will occur if the caller does not have // some undefined set of SecurityPermission flags. LogLog.Debug(declaringType, "Security exception while trying to get current thread principal. Error Ignored."); - writer.Write( SystemInfo.NotAvailableText ); + writer.Write(SystemInfo.NotAvailableText); } #endif } - #region Private Static Fields + #region Private Static Fields - /// - /// The fully qualified type of the IdentityPatternConverter class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(IdentityPatternConverter); + /// + /// The fully qualified type of the IdentityPatternConverter class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(IdentityPatternConverter); - #endregion Private Static Fields + #endregion Private Static Fields } } diff --git a/src/log4net/Util/PatternStringConverters/LiteralPatternConverter.cs b/src/log4net/Util/PatternStringConverters/LiteralPatternConverter.cs index bcdf7e4d..c1adfb90 100644 --- a/src/log4net/Util/PatternStringConverters/LiteralPatternConverter.cs +++ b/src/log4net/Util/PatternStringConverters/LiteralPatternConverter.cs @@ -36,7 +36,7 @@ namespace log4net.Util.PatternStringConverters /// /// /// Nicko Cadell - internal class LiteralPatternConverter : PatternConverter + internal class LiteralPatternConverter : PatternConverter { /// /// Set the next converter in the chain @@ -84,7 +84,7 @@ public override PatternConverter SetNext(PatternConverter pc) /// to the output . /// /// - public override void Format(TextWriter writer, object state) + public override void Format(TextWriter writer, object state) { writer.Write(Option); } @@ -99,7 +99,7 @@ public override void Format(TextWriter writer, object state) /// This method is not used. /// /// - protected override void Convert(TextWriter writer, object state) + protected override void Convert(TextWriter writer, object state) { throw new InvalidOperationException("Should never get here because of the overridden Format method"); } diff --git a/src/log4net/Util/PatternStringConverters/ProcessIdPatternConverter.cs b/src/log4net/Util/PatternStringConverters/ProcessIdPatternConverter.cs index d4e197e4..55dbeebc 100644 --- a/src/log4net/Util/PatternStringConverters/ProcessIdPatternConverter.cs +++ b/src/log4net/Util/PatternStringConverters/ProcessIdPatternConverter.cs @@ -31,7 +31,7 @@ namespace log4net.Util.PatternStringConverters /// /// /// Nicko Cadell - internal sealed class ProcessIdPatternConverter : PatternConverter + internal sealed class ProcessIdPatternConverter : PatternConverter { /// /// Write the current process ID to the output @@ -46,7 +46,7 @@ internal sealed class ProcessIdPatternConverter : PatternConverter #if NET_4_0 || MONO_4_0 || NETSTANDARD [System.Security.SecuritySafeCritical] #endif - protected override void Convert(TextWriter writer, object state) + protected override void Convert(TextWriter writer, object state) { #if (NETCF || SSCLI) // On compact framework there is no System.Diagnostics.Process class @@ -54,30 +54,30 @@ protected override void Convert(TextWriter writer, object state) #else try { - writer.Write( System.Diagnostics.Process.GetCurrentProcess().Id ); + writer.Write(System.Diagnostics.Process.GetCurrentProcess().Id); } - catch(System.Security.SecurityException) + catch (System.Security.SecurityException) { // This security exception will occur if the caller does not have // some undefined set of SecurityPermission flags. LogLog.Debug(declaringType, "Security exception while trying to get current process id. Error Ignored."); - writer.Write( SystemInfo.NotAvailableText ); + writer.Write(SystemInfo.NotAvailableText); } #endif } - #region Private Static Fields + #region Private Static Fields - /// - /// The fully qualified type of the ProcessIdPatternConverter class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(ProcessIdPatternConverter); + /// + /// The fully qualified type of the ProcessIdPatternConverter class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(ProcessIdPatternConverter); - #endregion Private Static Fields + #endregion Private Static Fields } } diff --git a/src/log4net/Util/PatternStringConverters/PropertyPatternConverter.cs b/src/log4net/Util/PatternStringConverters/PropertyPatternConverter.cs index 76f4239f..99551162 100644 --- a/src/log4net/Util/PatternStringConverters/PropertyPatternConverter.cs +++ b/src/log4net/Util/PatternStringConverters/PropertyPatternConverter.cs @@ -39,7 +39,7 @@ namespace log4net.Util.PatternStringConverters /// /// /// Nicko Cadell - internal sealed class PropertyPatternConverter : PatternConverter + internal sealed class PropertyPatternConverter : PatternConverter { /// /// Write the property value to the output @@ -57,7 +57,7 @@ internal sealed class PropertyPatternConverter : PatternConverter /// then all the properties are written as key value pairs. /// /// - protected override void Convert(TextWriter writer, object state) + protected override void Convert(TextWriter writer, object state) { CompositeProperties compositeProperties = new CompositeProperties(); diff --git a/src/log4net/Util/PatternStringConverters/RandomStringPatternConverter.cs b/src/log4net/Util/PatternStringConverters/RandomStringPatternConverter.cs index 8b11c45c..0502dfc8 100644 --- a/src/log4net/Util/PatternStringConverters/RandomStringPatternConverter.cs +++ b/src/log4net/Util/PatternStringConverters/RandomStringPatternConverter.cs @@ -87,8 +87,8 @@ public void ActivateOptions() } else { - LogLog.Error(declaringType, "RandomStringPatternConverter: Could not convert Option ["+optionStr+"] to Length Int32"); - } + LogLog.Error(declaringType, "RandomStringPatternConverter: Could not convert Option [" + optionStr + "] to Length Int32"); + } } } @@ -104,13 +104,13 @@ public void ActivateOptions() /// Write a randoim string to the output . /// /// - protected override void Convert(TextWriter writer, object state) + protected override void Convert(TextWriter writer, object state) { - try + try { - lock(s_random) + lock (s_random) { - for(int i=0; i - /// The fully qualified type of the RandomStringPatternConverter class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(RandomStringPatternConverter); + /// + /// The fully qualified type of the RandomStringPatternConverter class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(RandomStringPatternConverter); - #endregion Private Static Fields + #endregion Private Static Fields } } diff --git a/src/log4net/Util/PatternStringConverters/UserNamePatternConverter.cs b/src/log4net/Util/PatternStringConverters/UserNamePatternConverter.cs index 896e51dc..a0f4789f 100644 --- a/src/log4net/Util/PatternStringConverters/UserNamePatternConverter.cs +++ b/src/log4net/Util/PatternStringConverters/UserNamePatternConverter.cs @@ -31,7 +31,7 @@ namespace log4net.Util.PatternStringConverters /// /// /// Nicko Cadell - internal sealed class UserNamePatternConverter : PatternConverter + internal sealed class UserNamePatternConverter : PatternConverter { /// /// Write the current threads username to the output @@ -43,7 +43,7 @@ internal sealed class UserNamePatternConverter : PatternConverter /// Write the current threads username to the output . /// /// - protected override void Convert(TextWriter writer, object state) + protected override void Convert(TextWriter writer, object state) { #if (NETCF || SSCLI || NETSTANDARD1_3) // On compact framework there's no notion of current Windows user @@ -55,31 +55,31 @@ protected override void Convert(TextWriter writer, object state) windowsIdentity = System.Security.Principal.WindowsIdentity.GetCurrent(); if (windowsIdentity != null && windowsIdentity.Name != null) { - writer.Write( windowsIdentity.Name ); + writer.Write(windowsIdentity.Name); } } - catch(System.Security.SecurityException) + catch (System.Security.SecurityException) { // This security exception will occur if the caller does not have // some undefined set of SecurityPermission flags. LogLog.Debug(declaringType, "Security exception while trying to get current windows identity. Error Ignored."); - writer.Write( SystemInfo.NotAvailableText ); + writer.Write(SystemInfo.NotAvailableText); } #endif } - #region Private Static Fields + #region Private Static Fields - /// - /// The fully qualified type of the UserNamePatternConverter class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(UserNamePatternConverter); + /// + /// The fully qualified type of the UserNamePatternConverter class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(UserNamePatternConverter); - #endregion Private Static Fields + #endregion Private Static Fields } } diff --git a/src/log4net/Util/PatternStringConverters/UtcDatePatternConverter.cs b/src/log4net/Util/PatternStringConverters/UtcDatePatternConverter.cs index 6c59484e..3a044505 100644 --- a/src/log4net/Util/PatternStringConverters/UtcDatePatternConverter.cs +++ b/src/log4net/Util/PatternStringConverters/UtcDatePatternConverter.cs @@ -60,27 +60,27 @@ internal class UtcDatePatternConverter : DatePatternConverter /// protected override void Convert(TextWriter writer, object state) { - try + try { m_dateFormatter.FormatDate(DateTime.UtcNow, writer); } - catch (Exception ex) + catch (Exception ex) { LogLog.Error(declaringType, "Error occurred while converting date.", ex); } } - #region Private Static Fields + #region Private Static Fields - /// - /// The fully qualified type of the UtcDatePatternConverter class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(UtcDatePatternConverter); + /// + /// The fully qualified type of the UtcDatePatternConverter class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(UtcDatePatternConverter); - #endregion Private Static Fields + #endregion Private Static Fields } } diff --git a/src/log4net/Util/PropertiesDictionary.cs b/src/log4net/Util/PropertiesDictionary.cs index ce72e981..6a37b60d 100644 --- a/src/log4net/Util/PropertiesDictionary.cs +++ b/src/log4net/Util/PropertiesDictionary.cs @@ -35,7 +35,7 @@ namespace log4net.Util /// /// Nicko Cadell /// Gert Driesen -#if NETCF +#if NETCF public sealed class PropertiesDictionary : ReadOnlyPropertiesDictionary, IDictionary #else [Serializable] diff --git a/src/log4net/Util/PropertyEntry.cs b/src/log4net/Util/PropertyEntry.cs index 3357d989..379a2854 100644 --- a/src/log4net/Util/PropertyEntry.cs +++ b/src/log4net/Util/PropertyEntry.cs @@ -21,60 +21,60 @@ namespace log4net.Util { + /// + /// A class to hold the key and data for a property set in the config file + /// + /// + /// + /// A class to hold the key and data for a property set in the config file + /// + /// + public class PropertyEntry + { + private string m_key = null; + private object m_value = null; + /// - /// A class to hold the key and data for a property set in the config file + /// Property Key /// + /// + /// Property Key + /// /// /// - /// A class to hold the key and data for a property set in the config file + /// Property Key. /// /// - public class PropertyEntry + public string Key { - private string m_key = null; - private object m_value = null; - - /// - /// Property Key - /// - /// - /// Property Key - /// - /// - /// - /// Property Key. - /// - /// - public string Key - { - get { return m_key; } - set { m_key = value; } - } + get { return m_key; } + set { m_key = value; } + } - /// - /// Property Value - /// - /// - /// Property Value - /// - /// - /// - /// Property Value. - /// - /// - public object Value - { - get { return m_value; } - set { m_value = value; } - } + /// + /// Property Value + /// + /// + /// Property Value + /// + /// + /// + /// Property Value. + /// + /// + public object Value + { + get { return m_value; } + set { m_value = value; } + } - /// - /// Override Object.ToString to return sensible debug info - /// - /// string info about this object - public override string ToString() - { - return "PropertyEntry(Key=" + m_key + ", Value=" + m_value + ")"; - } + /// + /// Override Object.ToString to return sensible debug info + /// + /// string info about this object + public override string ToString() + { + return "PropertyEntry(Key=" + m_key + ", Value=" + m_value + ")"; } + } } diff --git a/src/log4net/Util/QuietTextWriter.cs b/src/log4net/Util/QuietTextWriter.cs index f74c9c0b..884ce4bc 100644 --- a/src/log4net/Util/QuietTextWriter.cs +++ b/src/log4net/Util/QuietTextWriter.cs @@ -85,7 +85,7 @@ public IErrorHandler ErrorHandler } m_errorHandler = value; } - } + } /// /// Gets a value indicating whether this writer is closed. @@ -116,18 +116,18 @@ public bool Closed /// Writes a character to the underlying writer /// /// - public override void Write(char value) + public override void Write(char value) { - try + try { base.Write(value); - } - catch(Exception e) + } + catch (Exception e) { m_errorHandler.Error("Failed to write [" + value + "].", e, ErrorCode.WriteFailure); } } - + /// /// Writes a buffer to the underlying writer /// @@ -139,18 +139,18 @@ public override void Write(char value) /// Writes a buffer to the underlying writer /// /// - public override void Write(char[] buffer, int index, int count) + public override void Write(char[] buffer, int index, int count) { - try + try { base.Write(buffer, index, count); - } - catch(Exception e) + } + catch (Exception e) { m_errorHandler.Error("Failed to write buffer.", e, ErrorCode.WriteFailure); } } - + /// /// Writes a string to the output. /// @@ -160,13 +160,13 @@ public override void Write(char[] buffer, int index, int count) /// Writes a string to the output. /// /// - public override void Write(string value) + public override void Write(string value) { - try + try { base.Write(value); - } - catch(Exception e) + } + catch (Exception e) { m_errorHandler.Error("Failed to write [" + value + "].", e, ErrorCode.WriteFailure); } diff --git a/src/log4net/Util/ReadOnlyPropertiesDictionary.cs b/src/log4net/Util/ReadOnlyPropertiesDictionary.cs index 632ce8ca..c59be907 100644 --- a/src/log4net/Util/ReadOnlyPropertiesDictionary.cs +++ b/src/log4net/Util/ReadOnlyPropertiesDictionary.cs @@ -45,7 +45,8 @@ namespace log4net.Util #if NETCF public class ReadOnlyPropertiesDictionary : IDictionary #else - [Serializable] public class ReadOnlyPropertiesDictionary : ISerializable, IDictionary + [Serializable] + public class ReadOnlyPropertiesDictionary : ISerializable, IDictionary #endif { #region Private Instance Fields @@ -82,7 +83,7 @@ public ReadOnlyPropertiesDictionary() /// public ReadOnlyPropertiesDictionary(ReadOnlyPropertiesDictionary propertiesDictionary) { - foreach(DictionaryEntry entry in propertiesDictionary) + foreach (DictionaryEntry entry in propertiesDictionary) { InnerHashtable.Add(entry.Key, entry.Value); } @@ -106,7 +107,7 @@ public ReadOnlyPropertiesDictionary(ReadOnlyPropertiesDictionary propertiesDicti /// protected ReadOnlyPropertiesDictionary(SerializationInfo info, StreamingContext context) { - foreach(var entry in info) + foreach (var entry in info) { // The keys are stored as Xml encoded names InnerHashtable[XmlConvert.DecodeName(entry.Name)] = entry.Value; @@ -210,9 +211,9 @@ protected Hashtable InnerHashtable #if !NETCF && !NETSTANDARD1_3 [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, SerializationFormatter = true)] #endif - public virtual void GetObjectData(SerializationInfo info, StreamingContext context) + public virtual void GetObjectData(SerializationInfo info, StreamingContext context) { - foreach(DictionaryEntry entry in InnerHashtable.Clone() as IDictionary) + foreach (DictionaryEntry entry in InnerHashtable.Clone() as IDictionary) { var entryKey = entry.Key as string; if (entryKey is null) @@ -222,11 +223,11 @@ public virtual void GetObjectData(SerializationInfo info, StreamingContext conte var entryValue = entry.Value; - // If value is serializable then we add it to the list + // If value is serializable then we add it to the list #if NETSTANDARD1_3 var isSerializable = entryValue?.GetType().GetTypeInfo().IsSerializable ?? false; #else - var isSerializable = entryValue?.GetType().IsSerializable ?? false; + var isSerializable = entryValue?.GetType().IsSerializable ?? false; #endif if (!isSerializable) { diff --git a/src/log4net/Util/ReaderWriterLock.cs b/src/log4net/Util/ReaderWriterLock.cs index 7654d395..abac458a 100644 --- a/src/log4net/Util/ReaderWriterLock.cs +++ b/src/log4net/Util/ReaderWriterLock.cs @@ -72,7 +72,7 @@ public ReaderWriterLock() } #endregion Private Instance Constructors - + #region Public Methods /// diff --git a/src/log4net/Util/ReusableStringWriter.cs b/src/log4net/Util/ReusableStringWriter.cs index 3a7edee9..f335e2cf 100644 --- a/src/log4net/Util/ReusableStringWriter.cs +++ b/src/log4net/Util/ReusableStringWriter.cs @@ -46,7 +46,7 @@ public class ReusableStringWriter : StringWriter /// Create an instance of /// /// - public ReusableStringWriter(IFormatProvider formatProvider) : base(formatProvider) + public ReusableStringWriter(IFormatProvider formatProvider) : base(formatProvider) { } @@ -83,12 +83,12 @@ public void Reset(int maxCapacity, int defaultSize) StringBuilder sb = this.GetStringBuilder(); sb.Length = 0; - + // Check if over max size - if (sb.Capacity > maxCapacity) + if (sb.Capacity > maxCapacity) { sb.Capacity = defaultSize; - } + } } } } diff --git a/src/log4net/Util/SystemStringFormat.cs b/src/log4net/Util/SystemStringFormat.cs index 9b558f39..0d75e89b 100644 --- a/src/log4net/Util/SystemStringFormat.cs +++ b/src/log4net/Util/SystemStringFormat.cs @@ -112,9 +112,9 @@ private static string StringFormat(IFormatProvider provider, string format, para // Try to format the string return String.Format(provider, format, args); } - catch(Exception ex) + catch (Exception ex) { - log4net.Util.LogLog.Warn(declaringType, "Exception while rendering format ["+format+"]", 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 && !NETSTANDARD @@ -151,7 +151,7 @@ private static string StringFormatError(Exception formatException, string format return buf.ToString(); } - catch(Exception ex) + catch (Exception ex) { log4net.Util.LogLog.Error(declaringType, "INTERNAL ERROR during StringFormat error handling", ex); return "Exception during StringFormat. See Internal Log."; @@ -214,7 +214,7 @@ private static void RenderObject(Object obj, StringBuilder buffer) { buffer.Append(obj); } - catch(Exception ex) + catch (Exception ex) { buffer.Append(""); } @@ -229,17 +229,17 @@ private static void RenderObject(Object obj, StringBuilder buffer) #endregion StringFormat - #region Private Static Fields + #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 static readonly Type declaringType = typeof(SystemStringFormat); + /// + /// The fully qualified type of the SystemStringFormat class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(SystemStringFormat); - #endregion Private Static Fields + #endregion Private Static Fields } } diff --git a/src/log4net/Util/TextWriterAdapter.cs b/src/log4net/Util/TextWriterAdapter.cs index e130e58b..24304f05 100644 --- a/src/log4net/Util/TextWriterAdapter.cs +++ b/src/log4net/Util/TextWriterAdapter.cs @@ -59,7 +59,7 @@ public abstract class TextWriterAdapter : TextWriter /// messages to a . /// /// - protected TextWriterAdapter(TextWriter writer) : base(CultureInfo.InvariantCulture) + protected TextWriterAdapter(TextWriter writer) : base(CultureInfo.InvariantCulture) { m_writer = writer; } @@ -79,7 +79,7 @@ protected TextWriterAdapter(TextWriter writer) : base(CultureInfo.InvariantCult /// Gets or sets the underlying . /// /// - protected TextWriter Writer + protected TextWriter Writer { get { return m_writer; } set { m_writer = value; } @@ -88,7 +88,7 @@ protected TextWriter Writer #endregion Protected Instance Properties #region Public Properties - + /// /// The Encoding in which the output is written /// @@ -100,7 +100,7 @@ protected TextWriter Writer /// The Encoding in which the output is written /// /// - public override Encoding Encoding + public override Encoding Encoding { get { return m_writer.Encoding; } } @@ -116,7 +116,7 @@ public override Encoding Encoding /// Gets an object that controls formatting /// /// - public override IFormatProvider FormatProvider + public override IFormatProvider FormatProvider { get { return m_writer.FormatProvider; } } @@ -132,7 +132,7 @@ public override IFormatProvider FormatProvider /// Gets or sets the line terminator string used by the TextWriter /// /// - public override String NewLine + public override String NewLine { get { return m_writer.NewLine; } set { m_writer.NewLine = value; } @@ -154,7 +154,7 @@ public override String NewLine #else virtual #endif - public void Close() + public void Close() { m_writer.Close(); } @@ -185,7 +185,7 @@ protected override void Dispose(bool disposing) /// to the underlying device /// /// - public override void Flush() + public override void Flush() { m_writer.Flush(); } @@ -199,11 +199,11 @@ public override void Flush() /// Writes a character to the wrapped TextWriter /// /// - public override void Write(char value) + public override void Write(char value) { m_writer.Write(value); } - + /// /// Writes a character buffer to the wrapped TextWriter /// @@ -215,11 +215,11 @@ public override void Write(char value) /// Writes a character buffer to the wrapped TextWriter /// /// - public override void Write(char[] buffer, int index, int count) + public override void Write(char[] buffer, int index, int count) { m_writer.Write(buffer, index, count); } - + /// /// Writes a string to the wrapped TextWriter /// @@ -229,7 +229,7 @@ public override void Write(char[] buffer, int index, int count) /// Writes a string to the wrapped TextWriter /// /// - public override void Write(String value) + public override void Write(String value) { m_writer.Write(value); } diff --git a/src/log4net/Util/ThreadContextProperties.cs b/src/log4net/Util/ThreadContextProperties.cs index a35697b2..0fbeef6b 100644 --- a/src/log4net/Util/ThreadContextProperties.cs +++ b/src/log4net/Util/ThreadContextProperties.cs @@ -186,7 +186,7 @@ internal PropertiesDictionary GetProperties(bool create) #endif if (_dictionary == null && create) { - _dictionary = new PropertiesDictionary(); + _dictionary = new PropertiesDictionary(); #if NETCF System.Threading.Thread.SetData(s_threadLocalSlot, _dictionary); #endif diff --git a/src/log4net/Util/ThreadContextStack.cs b/src/log4net/Util/ThreadContextStack.cs index 2d51b817..37ed907a 100644 --- a/src/log4net/Util/ThreadContextStack.cs +++ b/src/log4net/Util/ThreadContextStack.cs @@ -102,7 +102,7 @@ public int Count /// syntax. /// /// - public void Clear() + public void Clear() { m_stack.Clear(); } @@ -118,7 +118,7 @@ public void Clear() /// empty string (not ) is returned. /// /// - public string Pop() + public string Pop() { Stack stack = m_stack; if (stack.Count > 0) @@ -151,10 +151,10 @@ public string Pop() /// } /// /// - public IDisposable Push(string message) + public IDisposable Push(string message) { Stack stack = m_stack; - stack.Push(new StackFrame(message, (stack.Count>0) ? (StackFrame)stack.Peek() : null)); + stack.Push(new StackFrame(message, (stack.Count > 0) ? (StackFrame)stack.Peek() : null)); return new AutoPopStackFrame(stack, stack.Count - 1); } @@ -187,7 +187,7 @@ public string Peek() /// Gets the current context information for this stack. /// /// The current context information. - internal string GetFullMessage() + internal string GetFullMessage() { Stack stack = m_stack; if (stack.Count > 0) @@ -213,7 +213,7 @@ internal Stack InternalStack get { return m_stack; } set { m_stack = value; } } - + #endregion Internal Methods /// @@ -252,14 +252,14 @@ object IFixingRequired.GetFixedObject() /// Inner class used to represent a single context frame in the stack. /// /// - private sealed class StackFrame + 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 @@ -275,15 +275,15 @@ private sealed class StackFrame /// with the specified message and parent context. /// /// - internal StackFrame(string message, StackFrame parent) + internal StackFrame(string message, StackFrame parent) { m_message = message; m_parent = parent; - if (parent == null) + if (parent == null) { m_fullMessage = message; - } + } } #endregion Internal Instance Constructors @@ -317,13 +317,13 @@ internal string Message /// internal string FullMessage { - get + get { if (m_fullMessage == null && m_parent != null) { m_fullMessage = string.Concat(m_parent.FullMessage, " ", m_message); } - return m_fullMessage; + return m_fullMessage; } } @@ -390,7 +390,7 @@ public void Dispose() { if (m_frameDepth >= 0 && m_frameStack != null) { - while(m_frameStack.Count > m_frameDepth) + while (m_frameStack.Count > m_frameDepth) { m_frameStack.Pop(); } diff --git a/src/log4net/Util/ThreadContextStacks.cs b/src/log4net/Util/ThreadContextStacks.cs index 20219daf..6997636c 100644 --- a/src/log4net/Util/ThreadContextStacks.cs +++ b/src/log4net/Util/ThreadContextStacks.cs @@ -67,7 +67,7 @@ internal ThreadContextStacks(ContextPropertiesBase properties) /// public ThreadContextStack this[string key] { - get + get { ThreadContextStack stack = null; @@ -95,7 +95,7 @@ public ThreadContextStack this[string key] { } - LogLog.Error(declaringType, "ThreadContextStacks: Request for stack named ["+key+"] failed because a property with the same name exists which is a ["+propertyValue.GetType().Name+"] with value ["+propertyValueString+"]"); + LogLog.Error(declaringType, "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(); } @@ -107,18 +107,18 @@ public ThreadContextStack this[string key] #endregion Public Instance Properties - #region Private Static Fields + #region Private Static Fields - /// - /// The fully qualified type of the ThreadContextStacks class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(ThreadContextStacks); + /// + /// The fully qualified type of the ThreadContextStacks class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(ThreadContextStacks); - #endregion Private Static Fields + #endregion Private Static Fields } } diff --git a/src/log4net/Util/Transform.cs b/src/log4net/Util/Transform.cs index 1689b34c..662720c2 100644 --- a/src/log4net/Util/Transform.cs +++ b/src/log4net/Util/Transform.cs @@ -72,7 +72,7 @@ public static void WriteEscapedXmlString(XmlWriter writer, string textData, stri // Write either escaped text or CDATA sections int weightCData = 12 * (1 + CountSubstrings(stringData, CDATA_END)); - int weightStringEscapes = 3*(CountSubstrings(stringData, "<") + CountSubstrings(stringData, ">")) + 4*CountSubstrings(stringData, "&"); + int weightStringEscapes = 3 * (CountSubstrings(stringData, "<") + CountSubstrings(stringData, ">")) + 4 * CountSubstrings(stringData, "&"); if (weightStringEscapes <= weightCData) { @@ -84,15 +84,15 @@ public static void WriteEscapedXmlString(XmlWriter writer, string textData, stri // Write string using CDATA section int end = stringData.IndexOf(CDATA_END); - - if (end < 0) + + if (end < 0) { writer.WriteCData(stringData); } else { int start = 0; - while (end > -1) + while (end > -1) { writer.WriteCData(stringData.Substring(start, end - start)); if (end == stringData.Length - 3) @@ -108,7 +108,7 @@ public static void WriteEscapedXmlString(XmlWriter writer, string textData, stri end = stringData.IndexOf(CDATA_END, start); } } - + if (start < stringData.Length) { writer.WriteCData(stringData.Substring(start)); @@ -169,7 +169,7 @@ private static int CountSubstrings(string text, string substring) return 0; } - while(offset < length) + while (offset < length) { int index = text.IndexOf(substring, offset); @@ -188,13 +188,13 @@ private static int CountSubstrings(string text, string substring) #region Private Static Fields - private const string CDATA_END = "]]>"; - private const string CDATA_UNESCAPABLE_TOKEN = "]]"; + private const string CDATA_END = "]]>"; + private const string CDATA_UNESCAPABLE_TOKEN = "]]"; - /// - /// Characters illegal in XML 1.0 - /// - private static Regex INVALIDCHARS=new Regex(@"[^\x09\x0A\x0D\x20-\uD7FF\uE000-\uFFFD]",RegexOptions.Compiled); + /// + /// Characters illegal in XML 1.0 + /// + private static Regex INVALIDCHARS = new Regex(@"[^\x09\x0A\x0D\x20-\uD7FF\uE000-\uFFFD]", RegexOptions.Compiled); #endregion Private Static Fields } } diff --git a/src/log4net/Util/TypeConverters/BooleanConverter.cs b/src/log4net/Util/TypeConverters/BooleanConverter.cs index 7ca64966..ca500018 100644 --- a/src/log4net/Util/TypeConverters/BooleanConverter.cs +++ b/src/log4net/Util/TypeConverters/BooleanConverter.cs @@ -65,11 +65,11 @@ public bool CanConvertFrom(Type sourceType) /// argument to a . /// /// - /// - /// The object cannot be converted to the - /// target type. To check for this condition use the - /// method. - /// + /// + /// The object cannot be converted to the + /// target type. To check for this condition use the + /// method. + /// public object ConvertFrom(object source) { string str = source as string; diff --git a/src/log4net/Util/TypeConverters/ConversionNotSupportedException.cs b/src/log4net/Util/TypeConverters/ConversionNotSupportedException.cs index ea59d980..61bd7501 100644 --- a/src/log4net/Util/TypeConverters/ConversionNotSupportedException.cs +++ b/src/log4net/Util/TypeConverters/ConversionNotSupportedException.cs @@ -42,7 +42,7 @@ namespace log4net.Util.TypeConverters #if NETSTANDARD1_3 public class ConversionNotSupportedException : Exception #else - public class ConversionNotSupportedException : ApplicationException + public class ConversionNotSupportedException : ApplicationException #endif { #region Public Instance Constructors @@ -69,10 +69,10 @@ public ConversionNotSupportedException() /// with the specified message. /// /// - public ConversionNotSupportedException(String message) : base(message) + public ConversionNotSupportedException(String message) : base(message) { } - + /// /// Constructor /// @@ -84,7 +84,7 @@ public ConversionNotSupportedException(String message) : base(message) /// with the specified message and inner exception. /// /// - public ConversionNotSupportedException(String message, Exception innerException) : base(message, innerException) + public ConversionNotSupportedException(String message, Exception innerException) : base(message, innerException) { } @@ -104,7 +104,7 @@ public ConversionNotSupportedException(String message, Exception innerException) /// with serialized data. /// /// - protected ConversionNotSupportedException(SerializationInfo info, StreamingContext context) : base(info, context) + protected ConversionNotSupportedException(SerializationInfo info, StreamingContext context) : base(info, context) { } #endif @@ -145,11 +145,11 @@ public static ConversionNotSupportedException Create(Type destinationType, objec { if (sourceValue == null) { - return new ConversionNotSupportedException("Cannot convert value [null] to type ["+destinationType+"]", innerException); + return new ConversionNotSupportedException("Cannot convert value [null] to type [" + destinationType + "]", innerException); } else { - return new ConversionNotSupportedException("Cannot convert from type ["+sourceValue.GetType()+"] value ["+sourceValue+"] to type ["+destinationType+"]", innerException); + return new ConversionNotSupportedException("Cannot convert from type [" + sourceValue.GetType() + "] value [" + sourceValue + "] to type [" + destinationType + "]", innerException); } } diff --git a/src/log4net/Util/TypeConverters/ConverterRegistry.cs b/src/log4net/Util/TypeConverters/ConverterRegistry.cs index bc0fa10c..ec3e59bc 100644 --- a/src/log4net/Util/TypeConverters/ConverterRegistry.cs +++ b/src/log4net/Util/TypeConverters/ConverterRegistry.cs @@ -54,7 +54,7 @@ public sealed class ConverterRegistry /// /// Initializes a new instance of the class. /// - private ConverterRegistry() + private ConverterRegistry() { } @@ -99,7 +99,7 @@ public static void AddConverter(Type destinationType, object converter) { if (destinationType != null && converter != null) { - lock(s_type2converter) + lock (s_type2converter) { s_type2converter[destinationType] = converter; } @@ -142,7 +142,7 @@ public static IConvertTo GetConvertTo(Type sourceType, Type destinationType) // TODO: Is destinationType required? We don't use it for anything. - lock(s_type2converter) + lock (s_type2converter) { // Lookup in the static registry IConvertTo converter = s_type2converter[sourceType] as IConvertTo; @@ -181,7 +181,7 @@ public static IConvertFrom GetConvertFrom(Type destinationType) // TODO: Support inheriting type converters. // i.e. getting a type converter for a base of destinationType - lock(s_type2converter) + lock (s_type2converter) { // Lookup in the static registry IConvertFrom converter = s_type2converter[destinationType] as IConvertFrom; @@ -201,7 +201,7 @@ public static IConvertFrom GetConvertFrom(Type destinationType) return converter; } } - + /// /// Lookups the type converter to use as specified by the attributes on the /// destination type. @@ -269,14 +269,14 @@ private static object CreateConverterInstance(Type converterType) // Create the type converter return Activator.CreateInstance(converterType); } - catch(Exception ex) + catch (Exception ex) { - LogLog.Error(declaringType, "Cannot CreateConverterInstance of type ["+converterType.FullName+"], Exception in call to Activator.CreateInstance", ex); + LogLog.Error(declaringType, "Cannot CreateConverterInstance of type [" + converterType.FullName + "], Exception in call to Activator.CreateInstance", ex); } } else { - LogLog.Error(declaringType, "Cannot CreateConverterInstance of type ["+converterType.FullName+"], type does not implement IConvertFrom or IConvertTo"); + LogLog.Error(declaringType, "Cannot CreateConverterInstance of type [" + converterType.FullName + "], type does not implement IConvertFrom or IConvertTo"); } return null; } @@ -285,14 +285,14 @@ private static object CreateConverterInstance(Type converterType) #region Private Static Fields - /// - /// The fully qualified type of the ConverterRegistry class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(ConverterRegistry); + /// + /// The fully qualified type of the ConverterRegistry class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(ConverterRegistry); /// /// Mapping from to type converter. diff --git a/src/log4net/Util/TypeConverters/EncodingConverter.cs b/src/log4net/Util/TypeConverters/EncodingConverter.cs index 27dd4bb0..45d54384 100644 --- a/src/log4net/Util/TypeConverters/EncodingConverter.cs +++ b/src/log4net/Util/TypeConverters/EncodingConverter.cs @@ -35,7 +35,7 @@ namespace log4net.Util.TypeConverters /// /// Nicko Cadell /// Gert Driesen - internal class EncodingConverter : IConvertFrom + internal class EncodingConverter : IConvertFrom { #region Implementation of IConvertFrom @@ -50,7 +50,7 @@ internal class EncodingConverter : IConvertFrom /// the type. /// /// - public bool CanConvertFrom(Type sourceType) + public bool CanConvertFrom(Type sourceType) { return (sourceType == typeof(string)); } @@ -71,10 +71,10 @@ public bool CanConvertFrom(Type sourceType) /// target type. To check for this condition use the /// method. /// - public object ConvertFrom(object source) + public object ConvertFrom(object source) { string str = source as string; - if (str != null) + if (str != null) { return Encoding.GetEncoding(str); } diff --git a/src/log4net/Util/TypeConverters/IPAddressConverter.cs b/src/log4net/Util/TypeConverters/IPAddressConverter.cs index 2c133a48..60c7bf6b 100644 --- a/src/log4net/Util/TypeConverters/IPAddressConverter.cs +++ b/src/log4net/Util/TypeConverters/IPAddressConverter.cs @@ -33,7 +33,7 @@ namespace log4net.Util.TypeConverters /// /// /// Nicko Cadell - internal class IPAddressConverter : IConvertFrom + internal class IPAddressConverter : IConvertFrom { #region Implementation of IConvertFrom @@ -48,7 +48,7 @@ internal class IPAddressConverter : IConvertFrom /// the type. /// /// - public bool CanConvertFrom(Type sourceType) + public bool CanConvertFrom(Type sourceType) { return (sourceType == typeof(string)); } @@ -70,10 +70,10 @@ public bool CanConvertFrom(Type sourceType) /// target type. To check for this condition use the /// method. /// - public object ConvertFrom(object source) + public object ConvertFrom(object source) { string str = source as string; - if (str != null && str.Length > 0) + if (str != null && str.Length > 0) { try { @@ -91,8 +91,8 @@ public object ConvertFrom(object source) // Try to resolve via DNS. This is a blocking call. // GetHostEntry works with either an IPAddress string or a host name IPHostEntry host = Dns.GetHostEntry(str); - if (host != null && - host.AddressList != null && + if (host != null && + host.AddressList != null && host.AddressList.Length > 0 && host.AddressList[0] != null) { @@ -130,7 +130,7 @@ public object ConvertFrom(object source) } #endif } - catch(Exception ex) + catch (Exception ex) { throw ConversionNotSupportedException.Create(typeof(IPAddress), source, ex); } @@ -143,6 +143,6 @@ public object ConvertFrom(object source) /// /// Valid characters in an IPv4 or IPv6 address string. (Does not support subnets) /// - private static readonly char[] validIpAddressChars = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','A','B','C','D','E','F','x','X','.',':','%'}; + private static readonly char[] validIpAddressChars = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'A', 'B', 'C', 'D', 'E', 'F', 'x', 'X', '.', ':', '%' }; } } diff --git a/src/log4net/Util/TypeConverters/PatternLayoutConverter.cs b/src/log4net/Util/TypeConverters/PatternLayoutConverter.cs index a3f594c7..4c342e85 100644 --- a/src/log4net/Util/TypeConverters/PatternLayoutConverter.cs +++ b/src/log4net/Util/TypeConverters/PatternLayoutConverter.cs @@ -77,7 +77,7 @@ public bool CanConvertFrom(System.Type sourceType) /// target type. To check for this condition use the /// method. /// - public object ConvertFrom(object source) + public object ConvertFrom(object source) { string str = source as string; if (str != null) diff --git a/src/log4net/Util/TypeConverters/PatternStringConverter.cs b/src/log4net/Util/TypeConverters/PatternStringConverter.cs index c414b636..2352aa9a 100644 --- a/src/log4net/Util/TypeConverters/PatternStringConverter.cs +++ b/src/log4net/Util/TypeConverters/PatternStringConverter.cs @@ -122,7 +122,7 @@ public bool CanConvertFrom(System.Type sourceType) /// target type. To check for this condition use the /// method. /// - public object ConvertFrom(object source) + public object ConvertFrom(object source) { string str = source as string; if (str != null) diff --git a/src/log4net/Util/TypeConverters/TypeConverter.cs b/src/log4net/Util/TypeConverters/TypeConverter.cs index 606abf0c..c5136e4d 100644 --- a/src/log4net/Util/TypeConverters/TypeConverter.cs +++ b/src/log4net/Util/TypeConverters/TypeConverter.cs @@ -36,7 +36,7 @@ namespace log4net.Util.TypeConverters /// /// /// Nicko Cadell - internal class TypeConverter : IConvertFrom + internal class TypeConverter : IConvertFrom { #region Implementation of IConvertFrom @@ -51,7 +51,7 @@ internal class TypeConverter : IConvertFrom /// the type. /// /// - public bool CanConvertFrom(Type sourceType) + public bool CanConvertFrom(Type sourceType) { return (sourceType == typeof(string)); } @@ -74,7 +74,7 @@ public bool CanConvertFrom(Type sourceType) /// target type. To check for this condition use the /// method. /// - public object ConvertFrom(object source) + public object ConvertFrom(object source) { string str = source as string; if (str != null) diff --git a/src/log4net/Util/TypeConverters/TypeConverterAttribute.cs b/src/log4net/Util/TypeConverters/TypeConverterAttribute.cs index d7f40fa0..137336a8 100644 --- a/src/log4net/Util/TypeConverters/TypeConverterAttribute.cs +++ b/src/log4net/Util/TypeConverters/TypeConverterAttribute.cs @@ -37,7 +37,7 @@ namespace log4net.Util.TypeConverters /// /// Nicko Cadell /// Gert Driesen - [AttributeUsage(AttributeTargets.Class|AttributeTargets.Interface|AttributeTargets.Enum)] + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Enum)] public sealed class TypeConverterAttribute : Attribute { #region Member Variables @@ -110,7 +110,7 @@ public TypeConverterAttribute(Type converterType) public string ConverterTypeName { get { return m_typeName; } - set { m_typeName = value ; } + set { m_typeName = value; } } } } diff --git a/src/log4net/Util/WindowsSecurityContext.cs b/src/log4net/Util/WindowsSecurityContext.cs index d58f47f4..bed14bca 100644 --- a/src/log4net/Util/WindowsSecurityContext.cs +++ b/src/log4net/Util/WindowsSecurityContext.cs @@ -279,8 +279,8 @@ public override IDisposable Impersonate(object state) #if NET_4_0 || MONO_4_0 [System.Security.SecuritySafeCritical] #endif - [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, UnmanagedCode = true)] - private static WindowsIdentity LogonUser(string userName, string domainName, string password) + [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, UnmanagedCode = true)] + private static WindowsIdentity LogonUser(string userName, string domainName, string password) { const int LOGON32_PROVIDER_DEFAULT = 0; //This parameter causes LogonUser to create a primary token. @@ -288,15 +288,15 @@ private static WindowsIdentity LogonUser(string userName, string domainName, str // Call LogonUser to obtain a handle to an access token. IntPtr tokenHandle = IntPtr.Zero; - if(!LogonUser(userName, domainName, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref tokenHandle)) + if (!LogonUser(userName, domainName, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref tokenHandle)) { NativeError error = NativeError.GetLastError(); - throw new Exception("Failed to LogonUser ["+userName+"] in Domain ["+domainName+"]. Error: "+ error.ToString()); + throw new Exception("Failed to LogonUser [" + userName + "] in Domain [" + domainName + "]. Error: " + error.ToString()); } const int SecurityImpersonation = 2; IntPtr dupeTokenHandle = IntPtr.Zero; - if(!DuplicateToken(tokenHandle, SecurityImpersonation, ref dupeTokenHandle)) + if (!DuplicateToken(tokenHandle, SecurityImpersonation, ref dupeTokenHandle)) { NativeError error = NativeError.GetLastError(); if (tokenHandle != IntPtr.Zero) @@ -309,7 +309,7 @@ private static WindowsIdentity LogonUser(string userName, string domainName, str WindowsIdentity identity = new WindowsIdentity(dupeTokenHandle); // Free the tokens. - if (dupeTokenHandle != IntPtr.Zero) + if (dupeTokenHandle != IntPtr.Zero) { CloseHandle(dupeTokenHandle); } @@ -323,13 +323,13 @@ private static WindowsIdentity LogonUser(string userName, string domainName, str #region Native Method Stubs - [DllImport("advapi32.dll", SetLastError=true)] + [DllImport("advapi32.dll", SetLastError = true)] private static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken); - [DllImport("kernel32.dll", CharSet=CharSet.Auto)] + [DllImport("kernel32.dll", CharSet = CharSet.Auto)] private static extern bool CloseHandle(IntPtr handle); - [DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)] + [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern bool DuplicateToken(IntPtr ExistingTokenHandle, int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle); #endregion From e1be2df92f1fd9dca4c5674c21f6b2fb136d928f Mon Sep 17 00:00:00 2001 From: Jan Friedrich Date: Tue, 5 Mar 2024 13:34:35 +0100 Subject: [PATCH 5/6] tabs to spaces (test project) --- .../Appender/AppenderCollectionTest.cs | 70 +- .../Appender/BufferingAppenderTest.cs | 168 +-- .../Appender/CountingAppender.cs | 112 +- .../Appender/EventLogAppenderTest.cs | 98 +- .../Appender/MemoryAppenderTest.cs | 20 +- .../Appender/RemotingAppenderTest.cs | 724 ++++----- .../Appender/RollingFileAppenderTest.cs | 22 +- .../Appender/SmtpPickupDirAppenderTest.cs | 430 +++--- src/log4net.Tests/Appender/StringAppender.cs | 88 +- .../Context/LogicalThreadContextTest.cs | 616 ++++---- src/log4net.Tests/Core/EvaluatorTest.cs | 222 +-- src/log4net.Tests/Core/FixingTest.cs | 240 +-- src/log4net.Tests/Core/ShutdownTest.cs | 70 +- src/log4net.Tests/Core/StringFormatTest.cs | 1328 ++++++++--------- src/log4net.Tests/Hierarchy/Hierarchy.cs | 2 +- src/log4net.Tests/Hierarchy/Logger.cs | 568 +++---- src/log4net.Tests/Layout/PatternLayoutTest.cs | 224 +-- src/log4net.Tests/Layout/XmlLayoutTest.cs | 408 ++--- src/log4net.Tests/Util/CyclicBufferTest.cs | 160 +- .../Util/EnvironmentPatternConverterTest.cs | 4 +- .../Util/PropertiesDictionaryTest.cs | 64 +- .../Util/RandomStringPatternConverterTest.cs | 104 +- src/log4net.Tests/Util/SystemInfoTest.cs | 204 +-- src/log4net.Tests/Utils.cs | 156 +- 24 files changed, 3051 insertions(+), 3051 deletions(-) diff --git a/src/log4net.Tests/Appender/AppenderCollectionTest.cs b/src/log4net.Tests/Appender/AppenderCollectionTest.cs index e22c3640..cf135f6a 100644 --- a/src/log4net.Tests/Appender/AppenderCollectionTest.cs +++ b/src/log4net.Tests/Appender/AppenderCollectionTest.cs @@ -22,44 +22,44 @@ namespace log4net.Tests.Appender { - /// - /// Used for internal unit testing the class. - /// - /// - /// Used for internal unit testing the class. - /// - /// Carlos Muñoz - [TestFixture] - public class AppenderCollectionTest - { - /// - /// Verifies that ToArray returns the elements of the - /// - [Test] - public void ToArrayTest() - { - AppenderCollection appenderCollection = new AppenderCollection(); - IAppender appender = new MemoryAppender(); - appenderCollection.Add(appender); + /// + /// Used for internal unit testing the class. + /// + /// + /// Used for internal unit testing the class. + /// + /// Carlos Muñoz + [TestFixture] + public class AppenderCollectionTest + { + /// + /// Verifies that ToArray returns the elements of the + /// + [Test] + public void ToArrayTest() + { + AppenderCollection appenderCollection = new AppenderCollection(); + IAppender appender = new MemoryAppender(); + appenderCollection.Add(appender); - IAppender[] appenderArray = appenderCollection.ToArray(); + IAppender[] appenderArray = appenderCollection.ToArray(); - Assert.AreEqual(1, appenderArray.Length); - Assert.AreEqual(appender, appenderArray[0]); - } + Assert.AreEqual(1, appenderArray.Length); + Assert.AreEqual(appender, appenderArray[0]); + } - [Test] - public void ReadOnlyToArrayTest() - { - AppenderCollection appenderCollection = new AppenderCollection(); - IAppender appender = new MemoryAppender(); - appenderCollection.Add(appender); - AppenderCollection readonlyAppenderCollection = AppenderCollection.ReadOnly(appenderCollection); + [Test] + public void ReadOnlyToArrayTest() + { + AppenderCollection appenderCollection = new AppenderCollection(); + IAppender appender = new MemoryAppender(); + appenderCollection.Add(appender); + AppenderCollection readonlyAppenderCollection = AppenderCollection.ReadOnly(appenderCollection); - IAppender[] appenderArray = readonlyAppenderCollection.ToArray(); + IAppender[] appenderArray = readonlyAppenderCollection.ToArray(); - Assert.AreEqual(1, appenderArray.Length); - Assert.AreEqual(appender, appenderArray[0]); - } - } + Assert.AreEqual(1, appenderArray.Length); + Assert.AreEqual(appender, appenderArray[0]); + } + } } \ No newline at end of file diff --git a/src/log4net.Tests/Appender/BufferingAppenderTest.cs b/src/log4net.Tests/Appender/BufferingAppenderTest.cs index ca656630..638ad697 100644 --- a/src/log4net.Tests/Appender/BufferingAppenderTest.cs +++ b/src/log4net.Tests/Appender/BufferingAppenderTest.cs @@ -25,88 +25,88 @@ namespace log4net.Tests.Appender { - /// - /// Used for internal unit testing the class. - /// - /// - /// Used for internal unit testing the class. - /// - [TestFixture] - public class BufferingAppenderTest - { - private BufferingForwardingAppender m_bufferingForwardingAppender; - private CountingAppender m_countingAppender; - private Repository.Hierarchy.Hierarchy m_hierarchy; - - - private void SetupRepository() - { - m_hierarchy = new Repository.Hierarchy.Hierarchy(); - - m_countingAppender = new CountingAppender(); - m_countingAppender.ActivateOptions(); - - m_bufferingForwardingAppender = new BufferingForwardingAppender(); - m_bufferingForwardingAppender.AddAppender(m_countingAppender); - - m_bufferingForwardingAppender.BufferSize = 0; - m_bufferingForwardingAppender.ClearFilters(); - m_bufferingForwardingAppender.Evaluator = null; - m_bufferingForwardingAppender.Fix = FixFlags.Partial; - m_bufferingForwardingAppender.Lossy = false; - m_bufferingForwardingAppender.LossyEvaluator = null; - m_bufferingForwardingAppender.Threshold = Level.All; - - m_bufferingForwardingAppender.ActivateOptions(); - - BasicConfigurator.Configure(m_hierarchy, m_bufferingForwardingAppender); - } - - /// - /// - [Test] - public void TestSetupAppender() - { - SetupRepository(); - - Assert.AreEqual(0, m_countingAppender.Counter, "Test empty appender"); - - ILogger logger = m_hierarchy.GetLogger("test"); - logger.Log(typeof(BufferingAppenderTest), Level.Warn, "Message logged", null); - - Assert.AreEqual(1, m_countingAppender.Counter, "Test 1 event logged"); - } - - /// - /// - [Test] - public void TestBufferSize5() - { - SetupRepository(); - - m_bufferingForwardingAppender.BufferSize = 5; - m_bufferingForwardingAppender.ActivateOptions(); - - Assert.AreEqual(m_countingAppender.Counter, 0); - - ILogger logger = m_hierarchy.GetLogger("test"); - - logger.Log(typeof(BufferingAppenderTest), Level.Warn, "Message 1", null); - Assert.AreEqual(0, m_countingAppender.Counter, "Test 1 event in buffer"); - logger.Log(typeof(BufferingAppenderTest), Level.Warn, "Message 2", null); - Assert.AreEqual(0, m_countingAppender.Counter, "Test 2 event in buffer"); - logger.Log(typeof(BufferingAppenderTest), Level.Warn, "Message 3", null); - Assert.AreEqual(0, m_countingAppender.Counter, "Test 3 event in buffer"); - logger.Log(typeof(BufferingAppenderTest), Level.Warn, "Message 4", null); - Assert.AreEqual(0, m_countingAppender.Counter, "Test 4 event in buffer"); - logger.Log(typeof(BufferingAppenderTest), Level.Warn, "Message 5", null); - Assert.AreEqual(0, m_countingAppender.Counter, "Test 5 event in buffer"); - logger.Log(typeof(BufferingAppenderTest), Level.Warn, "Message 6", null); - Assert.AreEqual(6, m_countingAppender.Counter, "Test 0 event in buffer. 6 event sent"); - logger.Log(typeof(BufferingAppenderTest), Level.Warn, "Message 7", null); - Assert.AreEqual(6, m_countingAppender.Counter, "Test 1 event in buffer. 6 event sent"); - logger.Log(typeof(BufferingAppenderTest), Level.Warn, "Message 8", null); - Assert.AreEqual(6, m_countingAppender.Counter, "Test 2 event in buffer. 6 event sent"); - } - } + /// + /// Used for internal unit testing the class. + /// + /// + /// Used for internal unit testing the class. + /// + [TestFixture] + public class BufferingAppenderTest + { + private BufferingForwardingAppender m_bufferingForwardingAppender; + private CountingAppender m_countingAppender; + private Repository.Hierarchy.Hierarchy m_hierarchy; + + + private void SetupRepository() + { + m_hierarchy = new Repository.Hierarchy.Hierarchy(); + + m_countingAppender = new CountingAppender(); + m_countingAppender.ActivateOptions(); + + m_bufferingForwardingAppender = new BufferingForwardingAppender(); + m_bufferingForwardingAppender.AddAppender(m_countingAppender); + + m_bufferingForwardingAppender.BufferSize = 0; + m_bufferingForwardingAppender.ClearFilters(); + m_bufferingForwardingAppender.Evaluator = null; + m_bufferingForwardingAppender.Fix = FixFlags.Partial; + m_bufferingForwardingAppender.Lossy = false; + m_bufferingForwardingAppender.LossyEvaluator = null; + m_bufferingForwardingAppender.Threshold = Level.All; + + m_bufferingForwardingAppender.ActivateOptions(); + + BasicConfigurator.Configure(m_hierarchy, m_bufferingForwardingAppender); + } + + /// + /// + [Test] + public void TestSetupAppender() + { + SetupRepository(); + + Assert.AreEqual(0, m_countingAppender.Counter, "Test empty appender"); + + ILogger logger = m_hierarchy.GetLogger("test"); + logger.Log(typeof(BufferingAppenderTest), Level.Warn, "Message logged", null); + + Assert.AreEqual(1, m_countingAppender.Counter, "Test 1 event logged"); + } + + /// + /// + [Test] + public void TestBufferSize5() + { + SetupRepository(); + + m_bufferingForwardingAppender.BufferSize = 5; + m_bufferingForwardingAppender.ActivateOptions(); + + Assert.AreEqual(m_countingAppender.Counter, 0); + + ILogger logger = m_hierarchy.GetLogger("test"); + + logger.Log(typeof(BufferingAppenderTest), Level.Warn, "Message 1", null); + Assert.AreEqual(0, m_countingAppender.Counter, "Test 1 event in buffer"); + logger.Log(typeof(BufferingAppenderTest), Level.Warn, "Message 2", null); + Assert.AreEqual(0, m_countingAppender.Counter, "Test 2 event in buffer"); + logger.Log(typeof(BufferingAppenderTest), Level.Warn, "Message 3", null); + Assert.AreEqual(0, m_countingAppender.Counter, "Test 3 event in buffer"); + logger.Log(typeof(BufferingAppenderTest), Level.Warn, "Message 4", null); + Assert.AreEqual(0, m_countingAppender.Counter, "Test 4 event in buffer"); + logger.Log(typeof(BufferingAppenderTest), Level.Warn, "Message 5", null); + Assert.AreEqual(0, m_countingAppender.Counter, "Test 5 event in buffer"); + logger.Log(typeof(BufferingAppenderTest), Level.Warn, "Message 6", null); + Assert.AreEqual(6, m_countingAppender.Counter, "Test 0 event in buffer. 6 event sent"); + logger.Log(typeof(BufferingAppenderTest), Level.Warn, "Message 7", null); + Assert.AreEqual(6, m_countingAppender.Counter, "Test 1 event in buffer. 6 event sent"); + logger.Log(typeof(BufferingAppenderTest), Level.Warn, "Message 8", null); + Assert.AreEqual(6, m_countingAppender.Counter, "Test 2 event in buffer. 6 event sent"); + } + } } \ No newline at end of file diff --git a/src/log4net.Tests/Appender/CountingAppender.cs b/src/log4net.Tests/Appender/CountingAppender.cs index 0e0aa15f..e39754aa 100644 --- a/src/log4net.Tests/Appender/CountingAppender.cs +++ b/src/log4net.Tests/Appender/CountingAppender.cs @@ -22,64 +22,64 @@ namespace log4net.Tests.Appender { - /// - /// Implements an Appender for test purposes that counts the - /// number of output calls to . - /// - /// - /// This appender is used in the unit tests. - /// - /// Nicko Cadell - /// Gert Driesen - public class CountingAppender : AppenderSkeleton - { - #region Public Instance Constructors - /// - /// Initializes a new instance of the class. - /// - public CountingAppender() - { - m_counter = 0; - } - #endregion Public Instance Constructors + /// + /// Implements an Appender for test purposes that counts the + /// number of output calls to . + /// + /// + /// This appender is used in the unit tests. + /// + /// Nicko Cadell + /// Gert Driesen + public class CountingAppender : AppenderSkeleton + { + #region Public Instance Constructors + /// + /// Initializes a new instance of the class. + /// + public CountingAppender() + { + m_counter = 0; + } + #endregion Public Instance Constructors - #region Public Instance Properties - /// - /// Returns the number of times has been called. - /// - /// - /// The number of times has been called. - /// - public int Counter - { - get { return m_counter; } - } - #endregion Public Instance Properties + #region Public Instance Properties + /// + /// Returns the number of times has been called. + /// + /// + /// The number of times has been called. + /// + public int Counter + { + get { return m_counter; } + } + #endregion Public Instance Properties - /// - /// Reset the counter to zero - /// - public void ResetCounter() - { - m_counter = 0; - } + /// + /// Reset the counter to zero + /// + public void ResetCounter() + { + m_counter = 0; + } - #region Override implementation of AppenderSkeleton - /// - /// Registers how many times the method has been called. - /// - /// The logging event. - protected override void Append(LoggingEvent logEvent) - { - m_counter++; - } - #endregion Override implementation of AppenderSkeleton + #region Override implementation of AppenderSkeleton + /// + /// Registers how many times the method has been called. + /// + /// The logging event. + protected override void Append(LoggingEvent logEvent) + { + m_counter++; + } + #endregion Override implementation of AppenderSkeleton - #region Private Instance Fields - /// - /// The number of times has been called. - /// - private int m_counter; - #endregion Private Instance Fields - } + #region Private Instance Fields + /// + /// The number of times has been called. + /// + private int m_counter; + #endregion Private Instance Fields + } } \ No newline at end of file diff --git a/src/log4net.Tests/Appender/EventLogAppenderTest.cs b/src/log4net.Tests/Appender/EventLogAppenderTest.cs index e055f2fd..7e2a5ccc 100644 --- a/src/log4net.Tests/Appender/EventLogAppenderTest.cs +++ b/src/log4net.Tests/Appender/EventLogAppenderTest.cs @@ -29,60 +29,60 @@ namespace log4net.Tests.Appender { - /// - /// Used for internal unit testing the class. - /// - /// - /// Used for internal unit testing the class. - /// - [TestFixture] - public class EventLogAppenderTest - { - /// - /// Verifies that for each event log level, the correct system - /// event log enumeration is returned - /// - [Test] - public void TestGetEntryTypeForExistingApplicationName() - { - EventLogAppender eventAppender = new EventLogAppender(); + /// + /// Used for internal unit testing the class. + /// + /// + /// Used for internal unit testing the class. + /// + [TestFixture] + public class EventLogAppenderTest + { + /// + /// Verifies that for each event log level, the correct system + /// event log enumeration is returned + /// + [Test] + public void TestGetEntryTypeForExistingApplicationName() + { + EventLogAppender eventAppender = new EventLogAppender(); eventAppender.ApplicationName = "Winlogon"; - eventAppender.ActivateOptions(); + eventAppender.ActivateOptions(); - Assert.AreEqual( - EventLogEntryType.Information, - GetEntryType(eventAppender, Level.All)); + Assert.AreEqual( + EventLogEntryType.Information, + GetEntryType(eventAppender, Level.All)); - Assert.AreEqual( - EventLogEntryType.Information, - GetEntryType(eventAppender, Level.Debug)); + Assert.AreEqual( + EventLogEntryType.Information, + GetEntryType(eventAppender, Level.Debug)); - Assert.AreEqual( - EventLogEntryType.Information, - GetEntryType(eventAppender, Level.Info)); + Assert.AreEqual( + EventLogEntryType.Information, + GetEntryType(eventAppender, Level.Info)); - Assert.AreEqual( - EventLogEntryType.Warning, - GetEntryType(eventAppender, Level.Warn)); + Assert.AreEqual( + EventLogEntryType.Warning, + GetEntryType(eventAppender, Level.Warn)); - Assert.AreEqual( - EventLogEntryType.Error, - GetEntryType(eventAppender, Level.Error)); + Assert.AreEqual( + EventLogEntryType.Error, + GetEntryType(eventAppender, Level.Error)); - Assert.AreEqual( - EventLogEntryType.Error, - GetEntryType(eventAppender, Level.Fatal)); + Assert.AreEqual( + EventLogEntryType.Error, + GetEntryType(eventAppender, Level.Fatal)); - Assert.AreEqual( - EventLogEntryType.Error, - GetEntryType(eventAppender, Level.Off)); - } + Assert.AreEqual( + EventLogEntryType.Error, + GetEntryType(eventAppender, Level.Off)); + } /// /// ActivateOption tries to create an event source if it doesn't exist but this is going to fail on more modern Windows versions unless the code is run with local administrator privileges. /// [Test] - [Ignore("seems to require administrator privileges or a specific environent when run")] + [Ignore("seems to require administrator privileges or a specific environent when run")] public void ActivateOptionsDisablesAppenderIfSourceDoesntExist() { EventLogAppender eventAppender = new EventLogAppender(); @@ -90,16 +90,16 @@ public void ActivateOptionsDisablesAppenderIfSourceDoesntExist() Assert.AreEqual(Level.Off, eventAppender.Threshold); } - // - // Helper functions to dig into the appender - // + // + // Helper functions to dig into the appender + // - private static EventLogEntryType GetEntryType(EventLogAppender appender, Level level) - { - return (EventLogEntryType)Utils.InvokeMethod(appender, "GetEntryType", level); - } + private static EventLogEntryType GetEntryType(EventLogAppender appender, Level level) + { + return (EventLogEntryType)Utils.InvokeMethod(appender, "GetEntryType", level); + } - } + } } #endif // NET_2_0 diff --git a/src/log4net.Tests/Appender/MemoryAppenderTest.cs b/src/log4net.Tests/Appender/MemoryAppenderTest.cs index 9b4e7a0d..ceb3bb02 100644 --- a/src/log4net.Tests/Appender/MemoryAppenderTest.cs +++ b/src/log4net.Tests/Appender/MemoryAppenderTest.cs @@ -70,21 +70,21 @@ public void TestThreadSafety() { thread.Join(); } - cEventsRead += memoryAppender.PopAllEvents().Length; + cEventsRead += memoryAppender.PopAllEvents().Length; Assert.AreEqual(cEventsExpected, cEventsRead, "Log events were lost."); } private static ThreadStart LogMessages(string repository) { - return () => { - var logger = LogManager.GetLogger(repository, "LoggerThread"); - for (var i = 0; i < cLogEntriesPerThread; i++) - { - logger.InfoFormat("Logging message {0}", i); - } - Interlocked.Decrement(ref cThreadsRunning); - }; - } + return () => { + var logger = LogManager.GetLogger(repository, "LoggerThread"); + for (var i = 0; i < cLogEntriesPerThread; i++) + { + logger.InfoFormat("Logging message {0}", i); + } + Interlocked.Decrement(ref cThreadsRunning); + }; + } } } #endif \ No newline at end of file diff --git a/src/log4net.Tests/Appender/RemotingAppenderTest.cs b/src/log4net.Tests/Appender/RemotingAppenderTest.cs index a4de297c..56cc1c33 100644 --- a/src/log4net.Tests/Appender/RemotingAppenderTest.cs +++ b/src/log4net.Tests/Appender/RemotingAppenderTest.cs @@ -38,250 +38,250 @@ namespace log4net.Tests.Appender { - /// - /// Used for internal unit testing the class. - /// - /// - /// Used for internal unit testing the class. - /// - [TestFixture] - public class RemotingAppenderTest - { - private IChannel m_remotingChannel = null; - - /// - /// Test that the Message property is correctly remoted - /// - [Test] - public void TestRemotedMessage() - { - // Setup the remoting appender - ConfigureRootAppender(FixFlags.Partial); - - RemoteLoggingSinkImpl.Instance.Reset(); - - Logger root; - root = ((Repository.Hierarchy.Hierarchy)LogManager.GetRepository()).Root; - - string testMessage = string.Format("test message [ {0} ]", (new Random()).Next()); - - // Log a message that will be remoted - root.Log(Level.Debug, testMessage, null); - - // Wait for the remoted object to be delivered - Thread.Sleep(2000); - - LoggingEvent[] events = RemoteLoggingSinkImpl.Instance.Events; - Assert.AreEqual(1, events.Length, "Expect to receive 1 remoted event"); - - Assert.AreEqual(testMessage, events[0].RenderedMessage, "Expect Message match after remoting event"); - } - - /// - /// Test that the LocationInfo property is not remoted when doing a Fix.Partial - /// - [Test] - public void TestPartialFix() - { - // Setup the remoting appender - ConfigureRootAppender(FixFlags.Partial); - - RemoteLoggingSinkImpl.Instance.Reset(); - - Logger root; - root = ((Repository.Hierarchy.Hierarchy)LogManager.GetRepository()).Root; - - // Log a message that will be remoted - root.Log(Level.Debug, "test message", null); - - // Wait for the remoted object to be delivered - Thread.Sleep(2000); - - LoggingEvent[] events = RemoteLoggingSinkImpl.Instance.Events; - Assert.AreEqual(1, events.Length, "Expect to receive 1 remoted event"); - - // Grab the event data - LoggingEventData eventData = GetLoggingEventData(events[0]); - - Assert.IsNull(eventData.LocationInfo, "Expect LocationInfo to be null because only doing a partial fix"); - } - - /// - /// Test that the LocationInfo property is remoted when doing a Fix.All - /// - [Test] - public void TestFullFix() - { - // Setup the remoting appender - ConfigureRootAppender(FixFlags.All); - - RemoteLoggingSinkImpl.Instance.Reset(); - - Logger root; - root = ((Repository.Hierarchy.Hierarchy)LogManager.GetRepository()).Root; - - // Log a message that will be remoted - root.Log(Level.Debug, "test message", null); - - // Wait for the remoted object to be delivered - Thread.Sleep(5000); - - WaitFor("Remote instance should have received a remoting event", () => RemoteLoggingSinkImpl.Instance.Events.Length > 0); - LoggingEvent[] events = RemoteLoggingSinkImpl.Instance.Events; - Assert.AreEqual(1, events.Length, "Expect to receive 1 remoted event"); - - // Grab the event data - LoggingEventData eventData = GetLoggingEventData(events[0]); - - Assert.IsNotNull(eventData.LocationInfo, "Expect LocationInfo to not be null because doing a full fix"); - } - - private void WaitFor( - string failMessage, - Func condition, - int maxWaitMilliseconds = 5000) - { - var start = DateTime.Now; - do - { - if (condition()) - { - return; - } - Thread.Sleep(100); - } while ((DateTime.Now - start).TotalMilliseconds < maxWaitMilliseconds); - throw new TimeoutException($"Condition not achieved within {maxWaitMilliseconds}ms: {failMessage}"); - } + /// + /// Used for internal unit testing the class. + /// + /// + /// Used for internal unit testing the class. + /// + [TestFixture] + public class RemotingAppenderTest + { + private IChannel m_remotingChannel = null; + + /// + /// Test that the Message property is correctly remoted + /// + [Test] + public void TestRemotedMessage() + { + // Setup the remoting appender + ConfigureRootAppender(FixFlags.Partial); + + RemoteLoggingSinkImpl.Instance.Reset(); + + Logger root; + root = ((Repository.Hierarchy.Hierarchy)LogManager.GetRepository()).Root; + + string testMessage = string.Format("test message [ {0} ]", (new Random()).Next()); + + // Log a message that will be remoted + root.Log(Level.Debug, testMessage, null); + + // Wait for the remoted object to be delivered + Thread.Sleep(2000); + + LoggingEvent[] events = RemoteLoggingSinkImpl.Instance.Events; + Assert.AreEqual(1, events.Length, "Expect to receive 1 remoted event"); + + Assert.AreEqual(testMessage, events[0].RenderedMessage, "Expect Message match after remoting event"); + } + + /// + /// Test that the LocationInfo property is not remoted when doing a Fix.Partial + /// + [Test] + public void TestPartialFix() + { + // Setup the remoting appender + ConfigureRootAppender(FixFlags.Partial); + + RemoteLoggingSinkImpl.Instance.Reset(); + + Logger root; + root = ((Repository.Hierarchy.Hierarchy)LogManager.GetRepository()).Root; + + // Log a message that will be remoted + root.Log(Level.Debug, "test message", null); + + // Wait for the remoted object to be delivered + Thread.Sleep(2000); + + LoggingEvent[] events = RemoteLoggingSinkImpl.Instance.Events; + Assert.AreEqual(1, events.Length, "Expect to receive 1 remoted event"); + + // Grab the event data + LoggingEventData eventData = GetLoggingEventData(events[0]); + + Assert.IsNull(eventData.LocationInfo, "Expect LocationInfo to be null because only doing a partial fix"); + } + + /// + /// Test that the LocationInfo property is remoted when doing a Fix.All + /// + [Test] + public void TestFullFix() + { + // Setup the remoting appender + ConfigureRootAppender(FixFlags.All); + + RemoteLoggingSinkImpl.Instance.Reset(); + + Logger root; + root = ((Repository.Hierarchy.Hierarchy)LogManager.GetRepository()).Root; + + // Log a message that will be remoted + root.Log(Level.Debug, "test message", null); + + // Wait for the remoted object to be delivered + Thread.Sleep(5000); + + WaitFor("Remote instance should have received a remoting event", () => RemoteLoggingSinkImpl.Instance.Events.Length > 0); + LoggingEvent[] events = RemoteLoggingSinkImpl.Instance.Events; + Assert.AreEqual(1, events.Length, "Expect to receive 1 remoted event"); + + // Grab the event data + LoggingEventData eventData = GetLoggingEventData(events[0]); + + Assert.IsNotNull(eventData.LocationInfo, "Expect LocationInfo to not be null because doing a full fix"); + } + + private void WaitFor( + string failMessage, + Func condition, + int maxWaitMilliseconds = 5000) + { + var start = DateTime.Now; + do + { + if (condition()) + { + return; + } + Thread.Sleep(100); + } while ((DateTime.Now - start).TotalMilliseconds < maxWaitMilliseconds); + throw new TimeoutException($"Condition not achieved within {maxWaitMilliseconds}ms: {failMessage}"); + } + + /// + /// Test that the Message property is correctly remoted + /// + [Test] + public void TestRemotedMessageNdcPushPop() + { + // Setup the remoting appender + ConfigureRootAppender(FixFlags.Partial); + + RemoteLoggingSinkImpl.Instance.Reset(); + + Logger root; + root = ((Repository.Hierarchy.Hierarchy)LogManager.GetRepository()).Root; + + string testMessage = string.Format("test message [ {0} ]", (new Random()).Next()); + + using(NDC.Push("value")) + { + } + + // Log a message that will be remoted + root.Log(Level.Debug, testMessage, null); + + // Wait for the remoted object to be delivered + Thread.Sleep(2000); - /// - /// Test that the Message property is correctly remoted - /// - [Test] - public void TestRemotedMessageNdcPushPop() - { - // Setup the remoting appender - ConfigureRootAppender(FixFlags.Partial); + LoggingEvent[] events = RemoteLoggingSinkImpl.Instance.Events; + Assert.AreEqual(1, events.Length, "Expect to receive 1 remoted event"); - RemoteLoggingSinkImpl.Instance.Reset(); + Assert.AreEqual(testMessage, events[0].RenderedMessage, "Expect Message match after remoting event"); + } - Logger root; - root = ((Repository.Hierarchy.Hierarchy)LogManager.GetRepository()).Root; + [Test] + public void TestNestedNdc() + { + // This test can suffer from timing and ordering issues as the RemotingAppender does dispatch events asynchronously - string testMessage = string.Format("test message [ {0} ]", (new Random()).Next()); + // Setup the remoting appender + ConfigureRootAppender(FixFlags.Partial); - using(NDC.Push("value")) - { - } + RemoteLoggingSinkImpl.Instance.Reset(); - // Log a message that will be remoted - root.Log(Level.Debug, testMessage, null); - - // Wait for the remoted object to be delivered - Thread.Sleep(2000); - - LoggingEvent[] events = RemoteLoggingSinkImpl.Instance.Events; - Assert.AreEqual(1, events.Length, "Expect to receive 1 remoted event"); + TestService t; + t = new TestService(); + t.Test(); - Assert.AreEqual(testMessage, events[0].RenderedMessage, "Expect Message match after remoting event"); - } + // Wait for the remoted objects to be delivered + Thread.Sleep(3000); - [Test] - public void TestNestedNdc() - { - // This test can suffer from timing and ordering issues as the RemotingAppender does dispatch events asynchronously + LoggingEvent[] events = RemoteLoggingSinkImpl.Instance.Events; + Assert.AreEqual(5, events.Length, "Expect to receive 5 remoted event"); - // Setup the remoting appender - ConfigureRootAppender(FixFlags.Partial); + Assert.AreEqual("begin test", events[0].RenderedMessage, "Verify event 1 RenderedMessage"); + Assert.AreEqual("feature", events[1].RenderedMessage, "Verify event 2 RenderedMessage"); + Assert.AreEqual("return", events[2].RenderedMessage, "Verify event 3 RenderedMessage"); + Assert.AreEqual("return", events[3].RenderedMessage, "Verify event 4 RenderedMessage"); + Assert.AreEqual("end test", events[4].RenderedMessage, "Verify event 5 RenderedMessage"); - RemoteLoggingSinkImpl.Instance.Reset(); - - TestService t; - t = new TestService(); - t.Test(); - - // Wait for the remoted objects to be delivered - Thread.Sleep(3000); - - LoggingEvent[] events = RemoteLoggingSinkImpl.Instance.Events; - Assert.AreEqual(5, events.Length, "Expect to receive 5 remoted event"); - - Assert.AreEqual("begin test", events[0].RenderedMessage, "Verify event 1 RenderedMessage"); - Assert.AreEqual("feature", events[1].RenderedMessage, "Verify event 2 RenderedMessage"); - Assert.AreEqual("return", events[2].RenderedMessage, "Verify event 3 RenderedMessage"); - Assert.AreEqual("return", events[3].RenderedMessage, "Verify event 4 RenderedMessage"); - Assert.AreEqual("end test", events[4].RenderedMessage, "Verify event 5 RenderedMessage"); - - Assert.IsNull(events[0].Properties["NDC"], "Verify event 1 Properties"); - Assert.AreEqual("test1", events[1].Properties["NDC"], "Verify event 2 Properties"); - Assert.AreEqual("test1 test2", events[2].Properties["NDC"], "Verify event 3 Properties"); - Assert.AreEqual("test1", events[3].Properties["NDC"], "Verify event 4 Properties"); - Assert.IsNull(events[4].Properties["NDC"], "Verify event 5 Properties"); - } - - - private void RegisterRemotingServerChannel() - { - if (m_remotingChannel == null) - { - BinaryClientFormatterSinkProvider clientSinkProvider = new BinaryClientFormatterSinkProvider(); - - BinaryServerFormatterSinkProvider serverSinkProvider = new BinaryServerFormatterSinkProvider(); - serverSinkProvider.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full; - - Hashtable channelProperties = new Hashtable(); - channelProperties["port"] = 8085; - - m_remotingChannel = new TcpChannel(channelProperties, clientSinkProvider, serverSinkProvider); - // Setup remoting server - try - { + Assert.IsNull(events[0].Properties["NDC"], "Verify event 1 Properties"); + Assert.AreEqual("test1", events[1].Properties["NDC"], "Verify event 2 Properties"); + Assert.AreEqual("test1 test2", events[2].Properties["NDC"], "Verify event 3 Properties"); + Assert.AreEqual("test1", events[3].Properties["NDC"], "Verify event 4 Properties"); + Assert.IsNull(events[4].Properties["NDC"], "Verify event 5 Properties"); + } + + + private void RegisterRemotingServerChannel() + { + if (m_remotingChannel == null) + { + BinaryClientFormatterSinkProvider clientSinkProvider = new BinaryClientFormatterSinkProvider(); + + BinaryServerFormatterSinkProvider serverSinkProvider = new BinaryServerFormatterSinkProvider(); + serverSinkProvider.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full; + + Hashtable channelProperties = new Hashtable(); + channelProperties["port"] = 8085; + + m_remotingChannel = new TcpChannel(channelProperties, clientSinkProvider, serverSinkProvider); + // Setup remoting server + try + { #if NET_2_0 || MONO_2_0 || MONO_3_5 || MONO_4_0 - ChannelServices.RegisterChannel(m_remotingChannel, false); + ChannelServices.RegisterChannel(m_remotingChannel, false); #else - ChannelServices.RegisterChannel(m_remotingChannel); + ChannelServices.RegisterChannel(m_remotingChannel); #endif - } - catch(Exception ex) - { - Assert.Fail("Failed to set up LoggingSink: {0}", ex); - } + } + catch(Exception ex) + { + Assert.Fail("Failed to set up LoggingSink: {0}", ex); + } - // Marshal the sink object - RemotingServices.Marshal(RemoteLoggingSinkImpl.Instance, "LoggingSink", typeof(RemotingAppender.IRemoteLoggingSink)); - } - } + // Marshal the sink object + RemotingServices.Marshal(RemoteLoggingSinkImpl.Instance, "LoggingSink", typeof(RemotingAppender.IRemoteLoggingSink)); + } + } /// - /// Shuts down any loggers in the hierarchy, along - /// with all appenders. - /// - private static void ResetRepository() - { - // Regular users should not use the clear method lightly! - LogManager.GetRepository().ResetConfiguration(); - LogManager.GetRepository().Shutdown(); - ((Repository.Hierarchy.Hierarchy)LogManager.GetRepository()).Clear(); - } - - /// - /// Any initialization that happens before each test can - /// go here - /// - [SetUp] - public void SetUp() - { - ResetRepository(); - RegisterRemotingServerChannel(); - } - - /// - /// Any steps that happen after each test go here - /// - [TearDown] - public void TearDown() - { - ResetRepository(); - } + /// Shuts down any loggers in the hierarchy, along + /// with all appenders. + /// + private static void ResetRepository() + { + // Regular users should not use the clear method lightly! + LogManager.GetRepository().ResetConfiguration(); + LogManager.GetRepository().Shutdown(); + ((Repository.Hierarchy.Hierarchy)LogManager.GetRepository()).Clear(); + } + + /// + /// Any initialization that happens before each test can + /// go here + /// + [SetUp] + public void SetUp() + { + ResetRepository(); + RegisterRemotingServerChannel(); + } + + /// + /// Any steps that happen after each test go here + /// + [TearDown] + public void TearDown() + { + ResetRepository(); + } /// /// Close down remoting infrastructure @@ -299,158 +299,158 @@ public void UnregisterRemotingServerChannel() { } } - /// - /// Configures the root appender for counting and rolling - /// - private static void ConfigureRootAppender(FixFlags fixFlags) - { - Logger root; - root = ((Repository.Hierarchy.Hierarchy)LogManager.GetRepository()).Root; - root.Level = Level.Debug; - root.AddAppender(CreateAppender(fixFlags)); - root.Repository.Configured = true; - } - - private static RemotingAppender CreateAppender(FixFlags fixFlags) - { - RemotingAppender appender = new RemotingAppender(); - appender.Sink = "tcp://localhost:8085/LoggingSink"; - appender.Lossy = false; - appender.BufferSize = 1; - appender.Fix = fixFlags; - - appender.ActivateOptions(); - - return appender; - } - - public class RemoteLoggingSinkImpl : MarshalByRefObject, RemotingAppender.IRemoteLoggingSink - { - public static readonly RemoteLoggingSinkImpl Instance = new RemoteLoggingSinkImpl(); - - private ArrayList m_events = new ArrayList(); - - #region Public Instance Constructors - private RemoteLoggingSinkImpl() - { - } - #endregion Public Instance Constructors - - #region Implementation of IRemoteLoggingSink - /// - /// Logs the events to to an internal buffer - /// - /// The events to log. - /// - /// Logs the events to to an internal buffer. The logged events can - /// be retrieved via the property. To clear - /// the buffer call the method. - /// - public void LogEvents(LoggingEvent[] events) - { - m_events.AddRange(events); - } - #endregion Implementation of IRemoteLoggingSink - - #region Override implementation of MarshalByRefObject - /// - /// Obtains a lifetime service object to control the lifetime - /// policy for this instance. - /// - /// - /// null to indicate that this instance should live - /// forever. - /// - public override object InitializeLifetimeService() - { - return null; - } - #endregion Override implementation of MarshalByRefObject - - public void Reset() - { - m_events.Clear(); - } - - public LoggingEvent[] Events - { - get { return (LoggingEvent[])m_events.ToArray(typeof(LoggingEvent)); } - } - } - - // - // Helper functions to dig into the appender - // - - private static LoggingEventData GetLoggingEventData(LoggingEvent loggingEvent) - { - return (LoggingEventData)Utils.GetField(loggingEvent, "m_data"); - } - } + /// + /// Configures the root appender for counting and rolling + /// + private static void ConfigureRootAppender(FixFlags fixFlags) + { + Logger root; + root = ((Repository.Hierarchy.Hierarchy)LogManager.GetRepository()).Root; + root.Level = Level.Debug; + root.AddAppender(CreateAppender(fixFlags)); + root.Repository.Configured = true; + } + + private static RemotingAppender CreateAppender(FixFlags fixFlags) + { + RemotingAppender appender = new RemotingAppender(); + appender.Sink = "tcp://localhost:8085/LoggingSink"; + appender.Lossy = false; + appender.BufferSize = 1; + appender.Fix = fixFlags; + + appender.ActivateOptions(); + + return appender; + } + + public class RemoteLoggingSinkImpl : MarshalByRefObject, RemotingAppender.IRemoteLoggingSink + { + public static readonly RemoteLoggingSinkImpl Instance = new RemoteLoggingSinkImpl(); + + private ArrayList m_events = new ArrayList(); + + #region Public Instance Constructors + private RemoteLoggingSinkImpl() + { + } + #endregion Public Instance Constructors + + #region Implementation of IRemoteLoggingSink + /// + /// Logs the events to to an internal buffer + /// + /// The events to log. + /// + /// Logs the events to to an internal buffer. The logged events can + /// be retrieved via the property. To clear + /// the buffer call the method. + /// + public void LogEvents(LoggingEvent[] events) + { + m_events.AddRange(events); + } + #endregion Implementation of IRemoteLoggingSink + + #region Override implementation of MarshalByRefObject + /// + /// Obtains a lifetime service object to control the lifetime + /// policy for this instance. + /// + /// + /// null to indicate that this instance should live + /// forever. + /// + public override object InitializeLifetimeService() + { + return null; + } + #endregion Override implementation of MarshalByRefObject + + public void Reset() + { + m_events.Clear(); + } + + public LoggingEvent[] Events + { + get { return (LoggingEvent[])m_events.ToArray(typeof(LoggingEvent)); } + } + } + + // + // Helper functions to dig into the appender + // + + private static LoggingEventData GetLoggingEventData(LoggingEvent loggingEvent) + { + return (LoggingEventData)Utils.GetField(loggingEvent, "m_data"); + } + } } // helper for TestNestedNdc namespace log4net.Tests.Appender.Remoting.UserInterfaces { - public class TestService - { - private static ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - public void Test() - { - log.Info("begin test"); - Thread.Sleep(100); - - Feature f = new Feature(); - f.Test(); - log.Info("end test"); - Thread.Sleep(100); - } - } + public class TestService + { + private static ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + public void Test() + { + log.Info("begin test"); + Thread.Sleep(100); + + Feature f = new Feature(); + f.Test(); + log.Info("end test"); + Thread.Sleep(100); + } + } } // helper for TestNestedNdc namespace log4net.Tests.Appender.Remoting { - public class Feature - { - private static ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - public void Test() - { - using(NDC.Push("test1")) - { - log.Info("feature"); - Thread.Sleep(100); - - Dal d = new Dal(); - d.Test(); - log.Info("return"); - Thread.Sleep(100); - } - } - } + public class Feature + { + private static ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + public void Test() + { + using(NDC.Push("test1")) + { + log.Info("feature"); + Thread.Sleep(100); + + Dal d = new Dal(); + d.Test(); + log.Info("return"); + Thread.Sleep(100); + } + } + } } // helper for TestNestedNdc namespace log4net.Tests.Appender.Remoting.Data { - public class Dal - { - private static ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - public void Test() - { - using(NDC.Push("test2")) - { - log.Info("return"); - Thread.Sleep(100); - } - } - } + public class Dal + { + private static ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + public void Test() + { + using(NDC.Push("test2")) + { + log.Info("return"); + Thread.Sleep(100); + } + } + } } #endif // NET_2_0 \ No newline at end of file diff --git a/src/log4net.Tests/Appender/RollingFileAppenderTest.cs b/src/log4net.Tests/Appender/RollingFileAppenderTest.cs index d6cee4b9..883a9c0b 100644 --- a/src/log4net.Tests/Appender/RollingFileAppenderTest.cs +++ b/src/log4net.Tests/Appender/RollingFileAppenderTest.cs @@ -463,7 +463,7 @@ private static void VerifyFileConditions(string sBaseFileName, RollFileEntry[] f ArrayList alExisting = GetExistingFiles(sBaseFileName); if (null != fileEntries) { - // AssertEquals( "File count mismatch", alExisting.Count, fileEntries.Length ); + // AssertEquals( "File count mismatch", alExisting.Count, fileEntries.Length ); foreach (RollFileEntry rollFile in fileEntries) { string sFileName = rollFile.FileName; @@ -552,7 +552,7 @@ private void LogMessage(RollConditions entry, string sMessageToLog) // { // DumpFileEntry( file ); // } - // // System.Diagnostics.Debug.WriteLine(""); + // // System.Diagnostics.Debug.WriteLine(""); //} /// @@ -569,15 +569,15 @@ private void RollFromTableEntries(string sBaseFileName, RollConditions[] entries { RollConditions entry = entries[i]; - // System.Diagnostics.Debug.WriteLine( i + ": Entry " + i + " pre/post conditions"); - // DumpTableEntry( entry ); - // System.Diagnostics.Debug.WriteLine( i + ": Testing entry pre-conditions"); + // System.Diagnostics.Debug.WriteLine( i + ": Entry " + i + " pre/post conditions"); + // DumpTableEntry( entry ); + // System.Diagnostics.Debug.WriteLine( i + ": Testing entry pre-conditions"); VerifyPreConditions(sBaseFileName, entry); - // System.Diagnostics.Debug.WriteLine( i + ": Logging message"); + // System.Diagnostics.Debug.WriteLine( i + ": Logging message"); LogMessage(entry, sMessageToLog); - // System.Diagnostics.Debug.WriteLine( i + ": Testing entry post-conditions"); + // System.Diagnostics.Debug.WriteLine( i + ": Testing entry post-conditions"); VerifyPostConditions(sBaseFileName, entry); - // System.Diagnostics.Debug.WriteLine( i + ": Finished validating entry\n"); + // System.Diagnostics.Debug.WriteLine( i + ": Finished validating entry\n"); } } @@ -678,7 +678,7 @@ private static string GetBackupGroup(string sBackupGroups, int iGroup) //{ // if (0 == stats.NumberOfFileRolls ) // { - // return null; // first round has no previous backups + // return null; // first round has no previous backups // } // string sGroup; // if (0 == stats.MessagesThisFile ) @@ -1651,7 +1651,7 @@ public void TestExclusiveLockLocks() catch (IOException e1) { #if MONO - Assert.AreEqual("Sharing violation on path ", e1.Message.Substring(0, 26), "Unexpected exception"); + Assert.AreEqual("Sharing violation on path ", e1.Message.Substring(0, 26), "Unexpected exception"); #else Assert.AreEqual("The process cannot access the file ", e1.Message.Substring(0, 35), "Unexpected exception"); @@ -1977,7 +1977,7 @@ public void VerifyInitializeRollBackups(int iBackups, int iMaxSizeRollBackups) SetFieldCurSizeRollBackups(rfa, 0); InitializeRollBackups(rfa, sBaseFile, arrFiles); - // iBackups / Meaning + // iBackups / Meaning // 0 = none // 1 = file.log // 2 = file.log.1 diff --git a/src/log4net.Tests/Appender/SmtpPickupDirAppenderTest.cs b/src/log4net.Tests/Appender/SmtpPickupDirAppenderTest.cs index 6fbb0827..6cd5a9ed 100644 --- a/src/log4net.Tests/Appender/SmtpPickupDirAppenderTest.cs +++ b/src/log4net.Tests/Appender/SmtpPickupDirAppenderTest.cs @@ -31,219 +31,219 @@ namespace log4net.Tests.Appender { - /// - /// Used for internal unit testing the class. - /// - [TestFixture] - public class SmtpPickupDirAppenderTest - { - private readonly string _testPickupDir; - - private class SilentErrorHandler : IErrorHandler - { - private StringBuilder m_buffer = new StringBuilder(); - - public string Message - { - get { return m_buffer.ToString(); } - } - - public void Error(string message) - { - m_buffer.Append(message + "\n"); - } - - public void Error(string message, Exception e) - { - m_buffer.Append(message + "\n" + e.Message + "\n"); - } - - public void Error(string message, Exception e, ErrorCode errorCode) - { - m_buffer.Append(message + "\n" + e.Message + "\n"); - } - } - - public SmtpPickupDirAppenderTest() - { - _testPickupDir = Path.Combine(Directory.GetCurrentDirectory(), "SmtpPickupDirAppenderTest_PickupDir"); - } - /// - /// Sets up variables used for the tests - /// - private void InitializePickupDir() - { - Directory.CreateDirectory(_testPickupDir); - } - - /// - /// Shuts down any loggers in the hierarchy, along - /// with all appenders, and deletes any test files used - /// for logging. - /// - private void ResetLogger() - { - // Regular users should not use the clear method lightly! - Utils.GetRepository().ResetConfiguration(); - Utils.GetRepository().Shutdown(); - ((Repository.Hierarchy.Hierarchy)Utils.GetRepository()).Clear(); - } - - /// - /// Any initialization that happens before each test can - /// go here - /// - [SetUp] - public void SetUp() - { - ResetLogger(); - DeleteTestFiles(); - InitializePickupDir(); - } - - /// - /// Any steps that happen after each test go here - /// - [TearDown] - public void TearDown() - { - ResetLogger(); - DeleteTestFiles(); - } - - /// - /// Removes all test files that exist - /// - private void DeleteTestFiles() - { - if (Directory.Exists(_testPickupDir)) - { - Directory.Delete(_testPickupDir, true); - } - } - - /// - /// Creates a logger hierarchy, configures a SMTP pickup dir appender and returns an ILogger - /// - /// The appender to use - /// A configured ILogger - private ILogger CreateLogger(SmtpPickupDirAppender appender) - { - Repository.Hierarchy.Hierarchy h = (Repository.Hierarchy.Hierarchy)LogManager.CreateRepository("TestRepository"); - - PatternLayout layout = new PatternLayout(); - layout.ConversionPattern = "%m%n"; - layout.ActivateOptions(); - - appender.Layout = layout; - appender.ActivateOptions(); - - h.Root.AddAppender(appender); - h.Configured = true; - - ILogger log = h.GetLogger("Logger"); - return log; - } - - /// - /// Create an appender to use for the logger - /// - /// The error handler to use. - /// - private SmtpPickupDirAppender CreateSmtpPickupDirAppender(IErrorHandler handler) - { - SmtpPickupDirAppender appender = new SmtpPickupDirAppender(); - appender.PickupDir = _testPickupDir; - appender.ErrorHandler = handler; - return appender; - } - - /// - /// Destroys the logger hierarchy created by - /// - private static void DestroyLogger() - { - Repository.Hierarchy.Hierarchy h = (Repository.Hierarchy.Hierarchy)LogManager.GetRepository("TestRepository"); - h.ResetConfiguration(); - //Replace the repository selector so that we can recreate the hierarchy with the same name if necessary - LoggerManager.RepositorySelector = new DefaultRepositorySelector(typeof(log4net.Repository.Hierarchy.Hierarchy)); - } - - /// - /// Tests if the sent message contained the date header. - /// - [Test] - public void TestOutputContainsSentDate() - { - SilentErrorHandler sh = new SilentErrorHandler(); - SmtpPickupDirAppender appender = CreateSmtpPickupDirAppender(sh); - ILogger log = CreateLogger(appender); - log.Log(GetType(), Level.Info, "This is a message", null); - log.Log(GetType(), Level.Info, "This is a message 2", null); - DestroyLogger(); - - Assert.AreEqual(1, Directory.GetFiles(_testPickupDir).Length); - string[] fileContent = File.ReadAllLines((Directory.GetFiles(_testPickupDir)[0])); - bool hasDateHeader = false; - const string dateHeaderStart = "Date: "; - foreach (string line in fileContent) - { - if(line.StartsWith(dateHeaderStart)) - { - string datePart = line.Substring(dateHeaderStart.Length); - DateTime date = DateTime.ParseExact(datePart, "r", System.Globalization.CultureInfo.InvariantCulture); - double diff = Math.Abs( (DateTime.UtcNow - date).TotalMilliseconds); - Assert.LessOrEqual(diff, 1000, "Times should be equal, allowing a diff of one second to make test robust"); - hasDateHeader = true; - } - } - Assert.IsTrue(hasDateHeader, "Output must contains a date header"); - - Assert.AreEqual("", sh.Message, "Unexpected error message"); - } - - /// - /// Verifies that file extension is applied to output file name. - /// - [Test] - public void TestConfigurableFileExtension() - { - const string fileExtension = "eml"; - SilentErrorHandler sh = new SilentErrorHandler(); - SmtpPickupDirAppender appender = CreateSmtpPickupDirAppender(sh); - appender.FileExtension = fileExtension; - ILogger log = CreateLogger(appender); - log.Log(GetType(), Level.Info, "This is a message", null); - log.Log(GetType(), Level.Info, "This is a message 2", null); - DestroyLogger(); - - Assert.AreEqual(1, Directory.GetFiles(_testPickupDir).Length); - FileInfo fileInfo = new FileInfo(Directory.GetFiles(_testPickupDir)[0]); - Assert.AreEqual("." + fileExtension, fileInfo.Extension); - Assert.DoesNotThrow(delegate { new Guid(fileInfo.Name.Substring(0, fileInfo.Name.Length - fileInfo.Extension.Length)); }); // Assert that filename before extension is a guid - - Assert.AreEqual("", sh.Message, "Unexpected error message"); - } - - /// - /// Verifies that logging a message actually produces output - /// - [Test] - public void TestDefaultFileNameIsAGuid() - { - SilentErrorHandler sh = new SilentErrorHandler(); - SmtpPickupDirAppender appender = CreateSmtpPickupDirAppender(sh); - ILogger log = CreateLogger(appender); - log.Log(GetType(), Level.Info, "This is a message", null); - log.Log(GetType(), Level.Info, "This is a message 2", null); - DestroyLogger(); - - Assert.AreEqual(1, Directory.GetFiles(_testPickupDir).Length); - FileInfo fileInfo = new FileInfo(Directory.GetFiles(_testPickupDir)[0]); - Assert.IsEmpty(fileInfo.Extension); - Assert.DoesNotThrow(delegate { new Guid(fileInfo.Name); }); // Assert that filename is a guid - - Assert.AreEqual("", sh.Message, "Unexpected error message"); - } - } + /// + /// Used for internal unit testing the class. + /// + [TestFixture] + public class SmtpPickupDirAppenderTest + { + private readonly string _testPickupDir; + + private class SilentErrorHandler : IErrorHandler + { + private StringBuilder m_buffer = new StringBuilder(); + + public string Message + { + get { return m_buffer.ToString(); } + } + + public void Error(string message) + { + m_buffer.Append(message + "\n"); + } + + public void Error(string message, Exception e) + { + m_buffer.Append(message + "\n" + e.Message + "\n"); + } + + public void Error(string message, Exception e, ErrorCode errorCode) + { + m_buffer.Append(message + "\n" + e.Message + "\n"); + } + } + + public SmtpPickupDirAppenderTest() + { + _testPickupDir = Path.Combine(Directory.GetCurrentDirectory(), "SmtpPickupDirAppenderTest_PickupDir"); + } + /// + /// Sets up variables used for the tests + /// + private void InitializePickupDir() + { + Directory.CreateDirectory(_testPickupDir); + } + + /// + /// Shuts down any loggers in the hierarchy, along + /// with all appenders, and deletes any test files used + /// for logging. + /// + private void ResetLogger() + { + // Regular users should not use the clear method lightly! + Utils.GetRepository().ResetConfiguration(); + Utils.GetRepository().Shutdown(); + ((Repository.Hierarchy.Hierarchy)Utils.GetRepository()).Clear(); + } + + /// + /// Any initialization that happens before each test can + /// go here + /// + [SetUp] + public void SetUp() + { + ResetLogger(); + DeleteTestFiles(); + InitializePickupDir(); + } + + /// + /// Any steps that happen after each test go here + /// + [TearDown] + public void TearDown() + { + ResetLogger(); + DeleteTestFiles(); + } + + /// + /// Removes all test files that exist + /// + private void DeleteTestFiles() + { + if (Directory.Exists(_testPickupDir)) + { + Directory.Delete(_testPickupDir, true); + } + } + + /// + /// Creates a logger hierarchy, configures a SMTP pickup dir appender and returns an ILogger + /// + /// The appender to use + /// A configured ILogger + private ILogger CreateLogger(SmtpPickupDirAppender appender) + { + Repository.Hierarchy.Hierarchy h = (Repository.Hierarchy.Hierarchy)LogManager.CreateRepository("TestRepository"); + + PatternLayout layout = new PatternLayout(); + layout.ConversionPattern = "%m%n"; + layout.ActivateOptions(); + + appender.Layout = layout; + appender.ActivateOptions(); + + h.Root.AddAppender(appender); + h.Configured = true; + + ILogger log = h.GetLogger("Logger"); + return log; + } + + /// + /// Create an appender to use for the logger + /// + /// The error handler to use. + /// + private SmtpPickupDirAppender CreateSmtpPickupDirAppender(IErrorHandler handler) + { + SmtpPickupDirAppender appender = new SmtpPickupDirAppender(); + appender.PickupDir = _testPickupDir; + appender.ErrorHandler = handler; + return appender; + } + + /// + /// Destroys the logger hierarchy created by + /// + private static void DestroyLogger() + { + Repository.Hierarchy.Hierarchy h = (Repository.Hierarchy.Hierarchy)LogManager.GetRepository("TestRepository"); + h.ResetConfiguration(); + //Replace the repository selector so that we can recreate the hierarchy with the same name if necessary + LoggerManager.RepositorySelector = new DefaultRepositorySelector(typeof(log4net.Repository.Hierarchy.Hierarchy)); + } + + /// + /// Tests if the sent message contained the date header. + /// + [Test] + public void TestOutputContainsSentDate() + { + SilentErrorHandler sh = new SilentErrorHandler(); + SmtpPickupDirAppender appender = CreateSmtpPickupDirAppender(sh); + ILogger log = CreateLogger(appender); + log.Log(GetType(), Level.Info, "This is a message", null); + log.Log(GetType(), Level.Info, "This is a message 2", null); + DestroyLogger(); + + Assert.AreEqual(1, Directory.GetFiles(_testPickupDir).Length); + string[] fileContent = File.ReadAllLines((Directory.GetFiles(_testPickupDir)[0])); + bool hasDateHeader = false; + const string dateHeaderStart = "Date: "; + foreach (string line in fileContent) + { + if(line.StartsWith(dateHeaderStart)) + { + string datePart = line.Substring(dateHeaderStart.Length); + DateTime date = DateTime.ParseExact(datePart, "r", System.Globalization.CultureInfo.InvariantCulture); + double diff = Math.Abs( (DateTime.UtcNow - date).TotalMilliseconds); + Assert.LessOrEqual(diff, 1000, "Times should be equal, allowing a diff of one second to make test robust"); + hasDateHeader = true; + } + } + Assert.IsTrue(hasDateHeader, "Output must contains a date header"); + + Assert.AreEqual("", sh.Message, "Unexpected error message"); + } + + /// + /// Verifies that file extension is applied to output file name. + /// + [Test] + public void TestConfigurableFileExtension() + { + const string fileExtension = "eml"; + SilentErrorHandler sh = new SilentErrorHandler(); + SmtpPickupDirAppender appender = CreateSmtpPickupDirAppender(sh); + appender.FileExtension = fileExtension; + ILogger log = CreateLogger(appender); + log.Log(GetType(), Level.Info, "This is a message", null); + log.Log(GetType(), Level.Info, "This is a message 2", null); + DestroyLogger(); + + Assert.AreEqual(1, Directory.GetFiles(_testPickupDir).Length); + FileInfo fileInfo = new FileInfo(Directory.GetFiles(_testPickupDir)[0]); + Assert.AreEqual("." + fileExtension, fileInfo.Extension); + Assert.DoesNotThrow(delegate { new Guid(fileInfo.Name.Substring(0, fileInfo.Name.Length - fileInfo.Extension.Length)); }); // Assert that filename before extension is a guid + + Assert.AreEqual("", sh.Message, "Unexpected error message"); + } + + /// + /// Verifies that logging a message actually produces output + /// + [Test] + public void TestDefaultFileNameIsAGuid() + { + SilentErrorHandler sh = new SilentErrorHandler(); + SmtpPickupDirAppender appender = CreateSmtpPickupDirAppender(sh); + ILogger log = CreateLogger(appender); + log.Log(GetType(), Level.Info, "This is a message", null); + log.Log(GetType(), Level.Info, "This is a message 2", null); + DestroyLogger(); + + Assert.AreEqual(1, Directory.GetFiles(_testPickupDir).Length); + FileInfo fileInfo = new FileInfo(Directory.GetFiles(_testPickupDir)[0]); + Assert.IsEmpty(fileInfo.Extension); + Assert.DoesNotThrow(delegate { new Guid(fileInfo.Name); }); // Assert that filename is a guid + + Assert.AreEqual("", sh.Message, "Unexpected error message"); + } + } } \ No newline at end of file diff --git a/src/log4net.Tests/Appender/StringAppender.cs b/src/log4net.Tests/Appender/StringAppender.cs index 977099c5..83602f88 100644 --- a/src/log4net.Tests/Appender/StringAppender.cs +++ b/src/log4net.Tests/Appender/StringAppender.cs @@ -24,53 +24,53 @@ namespace log4net.Tests.Appender { - /// - /// Write events to a string - /// - /// Nicko Cadell - public class StringAppender : AppenderSkeleton - { - private StringBuilder m_buf = new StringBuilder(); + /// + /// Write events to a string + /// + /// Nicko Cadell + public class StringAppender : AppenderSkeleton + { + private StringBuilder m_buf = new StringBuilder(); - /// - /// Initializes a new instance of the class. - /// - public StringAppender() - { - } + /// + /// Initializes a new instance of the class. + /// + public StringAppender() + { + } - /// - /// Get the string logged so far - /// - /// - public string GetString() - { - return m_buf.ToString(); - } + /// + /// Get the string logged so far + /// + /// + public string GetString() + { + return m_buf.ToString(); + } - /// - /// Reset the string - /// - public void Reset() - { - m_buf.Length = 0; - } + /// + /// Reset the string + /// + public void Reset() + { + m_buf.Length = 0; + } - /// - /// - /// the event to log - protected override void Append(LoggingEvent loggingEvent) - { - m_buf.Append(RenderLoggingEvent(loggingEvent)); - } + /// + /// + /// the event to log + protected override void Append(LoggingEvent loggingEvent) + { + m_buf.Append(RenderLoggingEvent(loggingEvent)); + } - /// - /// This appender requires a to be set. - /// - /// true - protected override bool RequiresLayout - { - get { return true; } - } - } + /// + /// This appender requires a to be set. + /// + /// true + protected override bool RequiresLayout + { + get { return true; } + } + } } \ No newline at end of file diff --git a/src/log4net.Tests/Context/LogicalThreadContextTest.cs b/src/log4net.Tests/Context/LogicalThreadContextTest.cs index 103e00bf..ca8a7c11 100644 --- a/src/log4net.Tests/Context/LogicalThreadContextTest.cs +++ b/src/log4net.Tests/Context/LogicalThreadContextTest.cs @@ -32,313 +32,313 @@ namespace log4net.Tests.Context { - /// - /// Used for internal unit testing the class. - /// - /// - /// Used for internal unit testing the class. - /// - [TestFixture] - public class LogicalThreadContextTest - { - [TearDown] - public void TearDown() - { - Utils.RemovePropertyFromAllContexts(); - } - - [Test] - public void TestLogicalThreadPropertiesPatternBasicGetSet() - { - StringAppender stringAppender = new StringAppender(); - stringAppender.Layout = new PatternLayout("%property{" + Utils.PROPERTY_KEY + "}"); - - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - BasicConfigurator.Configure(rep, stringAppender); - - ILog log1 = LogManager.GetLogger(rep.Name, "TestLogicalThreadPropertiesPattern"); - - log1.Info("TestMessage"); - Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test no logical thread properties value set"); - stringAppender.Reset(); - - LogicalThreadContext.Properties[Utils.PROPERTY_KEY] = "val1"; - - log1.Info("TestMessage"); - Assert.AreEqual("val1", stringAppender.GetString(), "Test logical thread properties value set"); - stringAppender.Reset(); - - LogicalThreadContext.Properties.Remove(Utils.PROPERTY_KEY); - - log1.Info("TestMessage"); - Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test logical thread properties value removed"); - stringAppender.Reset(); - } - - [Test] - public async Task TestLogicalThreadPropertiesPatternAsyncAwait() - { - StringAppender stringAppender = new StringAppender(); - stringAppender.Layout = new PatternLayout("%property{" + Utils.PROPERTY_KEY + "}"); - - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - BasicConfigurator.Configure(rep, stringAppender); - - ILog log1 = LogManager.GetLogger(rep.Name, "TestLogicalThreadPropertiesPattern"); - - log1.Info("TestMessage"); - Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test no logical thread stack value set"); - stringAppender.Reset(); - - string testValueForCurrentContext = "Outer"; - LogicalThreadContext.Properties[Utils.PROPERTY_KEY] = testValueForCurrentContext; - - log1.Info("TestMessage"); - Assert.AreEqual(testValueForCurrentContext, stringAppender.GetString(), "Test logical thread properties value set"); - stringAppender.Reset(); - - var strings = await Task.WhenAll(Enumerable.Range(0, 10).Select(x => SomeWorkProperties(x.ToString()))); - - // strings should be ["00AA0BB0", "01AA1BB1", "02AA2BB2", ...] - for (int i = 0; i < strings.Length; i++) - { - Assert.AreEqual(string.Format("{0}{1}AA{1}BB{1}", testValueForCurrentContext, i), strings[i], "Test logical thread properties expected sequence"); - } - - log1.Info("TestMessage"); - Assert.AreEqual(testValueForCurrentContext, stringAppender.GetString(), "Test logical thread properties value set"); - stringAppender.Reset(); - - LogicalThreadContext.Properties.Remove(Utils.PROPERTY_KEY); - - log1.Info("TestMessage"); - Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test logical thread properties value removed"); - stringAppender.Reset(); - } - - [Test] - public void TestLogicalThreadStackPattern() - { - StringAppender stringAppender = new StringAppender(); - stringAppender.Layout = new PatternLayout("%property{" + Utils.PROPERTY_KEY + "}"); - - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - BasicConfigurator.Configure(rep, stringAppender); - - ILog log1 = LogManager.GetLogger(rep.Name, "TestThreadStackPattern"); - - log1.Info("TestMessage"); - Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test no logical thread stack value set"); - stringAppender.Reset(); - - using (LogicalThreadContext.Stacks[Utils.PROPERTY_KEY].Push("val1")) - { - log1.Info("TestMessage"); - Assert.AreEqual("val1", stringAppender.GetString(), "Test logical thread stack value set"); - stringAppender.Reset(); - } - - log1.Info("TestMessage"); - Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test logical thread stack value removed"); - stringAppender.Reset(); - } - - [Test] - public void TestLogicalThreadStackPattern2() - { - StringAppender stringAppender = new StringAppender(); - stringAppender.Layout = new PatternLayout("%property{" + Utils.PROPERTY_KEY + "}"); - - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - BasicConfigurator.Configure(rep, stringAppender); - - ILog log1 = LogManager.GetLogger(rep.Name, "TestThreadStackPattern"); - - log1.Info("TestMessage"); - Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test no logical thread stack value set"); - stringAppender.Reset(); - - using (LogicalThreadContext.Stacks[Utils.PROPERTY_KEY].Push("val1")) - { - log1.Info("TestMessage"); - Assert.AreEqual("val1", stringAppender.GetString(), "Test logical thread stack value set"); - stringAppender.Reset(); - - using (LogicalThreadContext.Stacks[Utils.PROPERTY_KEY].Push("val2")) - { - log1.Info("TestMessage"); - Assert.AreEqual("val1 val2", stringAppender.GetString(), "Test logical thread stack value pushed 2nd val"); - stringAppender.Reset(); - } - } - - log1.Info("TestMessage"); - Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test logical thread stack value removed"); - stringAppender.Reset(); - } - - [Test] - public void TestLogicalThreadStackPatternNullVal() - { - StringAppender stringAppender = new StringAppender(); - stringAppender.Layout = new PatternLayout("%property{" + Utils.PROPERTY_KEY + "}"); - - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - BasicConfigurator.Configure(rep, stringAppender); - - ILog log1 = LogManager.GetLogger(rep.Name, "TestThreadStackPattern"); - - log1.Info("TestMessage"); - Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test no logical thread stack value set"); - stringAppender.Reset(); - - using (LogicalThreadContext.Stacks[Utils.PROPERTY_KEY].Push(null)) - { - log1.Info("TestMessage"); - Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test logical thread stack value set"); - stringAppender.Reset(); - } - - log1.Info("TestMessage"); - Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test logical thread stack value removed"); - stringAppender.Reset(); - } - - [Test] - public void TestLogicalThreadStackPatternNullVal2() - { - StringAppender stringAppender = new StringAppender(); - stringAppender.Layout = new PatternLayout("%property{" + Utils.PROPERTY_KEY + "}"); - - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - BasicConfigurator.Configure(rep, stringAppender); - - ILog log1 = LogManager.GetLogger(rep.Name, "TestThreadStackPattern"); - - log1.Info("TestMessage"); - Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test no logical thread stack value set"); - stringAppender.Reset(); - - using (LogicalThreadContext.Stacks[Utils.PROPERTY_KEY].Push("val1")) - { - log1.Info("TestMessage"); - Assert.AreEqual("val1", stringAppender.GetString(), "Test logical thread stack value set"); - stringAppender.Reset(); - - using (LogicalThreadContext.Stacks[Utils.PROPERTY_KEY].Push(null)) - { - log1.Info("TestMessage"); - Assert.AreEqual("val1 ", stringAppender.GetString(), "Test logical thread stack value pushed null"); - stringAppender.Reset(); - } - } - - log1.Info("TestMessage"); - Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test logical thread stack value removed"); - stringAppender.Reset(); - } - - [Test] - public async Task TestLogicalThreadStackPatternAsyncAwait() - { - StringAppender stringAppender = new StringAppender(); - stringAppender.Layout = new PatternLayout("%property{" + Utils.PROPERTY_KEY + "}"); - - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - BasicConfigurator.Configure(rep, stringAppender); - - ILog log1 = LogManager.GetLogger(rep.Name, "TestLogicalThreadStackPattern"); - - log1.Info("TestMessage"); - Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test no logical thread stack value set"); - stringAppender.Reset(); - - string testValueForCurrentContext = "Outer"; - string[] strings = null; - using (LogicalThreadContext.Stacks[Utils.PROPERTY_KEY].Push(testValueForCurrentContext)) - { - log1.Info("TestMessage"); - Assert.AreEqual(testValueForCurrentContext, stringAppender.GetString(), "Test logical thread stack value set"); - stringAppender.Reset(); - - strings = await Task.WhenAll(Enumerable.Range(0, 10).Select(x => SomeWorkStack(x.ToString()))); - } - - // strings should be ["Outer 0 AOuter 0 AOuter 0Outer 0 BOuter 0 B Outer 0", ...] - for (int i = 0; i < strings.Length; i++) - { - Assert.AreEqual(string.Format("{0} {1} A{0} {1} A{0} {1}{0} {1} B{0} {1} B{0} {1}", testValueForCurrentContext, i), strings[i], "Test logical thread properties expected sequence"); - } - - log1.Info("TestMessage"); - Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test logical thread properties value removed"); - stringAppender.Reset(); - } - - static async Task SomeWorkProperties(string propertyName) - { - StringAppender stringAppender = new StringAppender(); - stringAppender.Layout = new PatternLayout("%property{" + Utils.PROPERTY_KEY + "}"); - - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - BasicConfigurator.Configure(rep, stringAppender); - - ILog log = LogManager.GetLogger(rep.Name, "TestLogicalThreadStackPattern"); - log.Info("TestMessage"); - - // set a new one - LogicalThreadContext.Properties[Utils.PROPERTY_KEY] = propertyName; - log.Info("TestMessage"); - - await MoreWorkProperties(log, "A"); - log.Info("TestMessage"); - await MoreWorkProperties(log, "B"); - log.Info("TestMessage"); - return stringAppender.GetString(); - } - - static async Task MoreWorkProperties(ILog log, string propertyName) - { - LogicalThreadContext.Properties[Utils.PROPERTY_KEY] = propertyName; - log.Info("TestMessage"); - await Task.Delay(1); - log.Info("TestMessage"); - } - - static async Task SomeWorkStack(string stackName) - { - StringAppender stringAppender = new StringAppender(); - stringAppender.Layout = new PatternLayout("%property{" + Utils.PROPERTY_KEY + "}"); - - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - BasicConfigurator.Configure(rep, stringAppender); - - ILog log = LogManager.GetLogger(rep.Name, "TestLogicalThreadStackPattern"); - - using (LogicalThreadContext.Stacks[Utils.PROPERTY_KEY].Push(stackName)) - { - log.Info("TestMessage"); - Assert.AreEqual(string.Format("Outer {0}", stackName), stringAppender.GetString(), "Test logical thread stack value set"); - stringAppender.Reset(); - - await MoreWorkStack(log, "A"); - log.Info("TestMessage"); - await MoreWorkStack(log, "B"); - log.Info("TestMessage"); - } - - return stringAppender.GetString(); - } - - static async Task MoreWorkStack(ILog log, string stackName) - { - using (LogicalThreadContext.Stacks[Utils.PROPERTY_KEY].Push(stackName)) - { - log.Info("TestMessage"); - await Task.Delay(1); - log.Info("TestMessage"); - } - } - } + /// + /// Used for internal unit testing the class. + /// + /// + /// Used for internal unit testing the class. + /// + [TestFixture] + public class LogicalThreadContextTest + { + [TearDown] + public void TearDown() + { + Utils.RemovePropertyFromAllContexts(); + } + + [Test] + public void TestLogicalThreadPropertiesPatternBasicGetSet() + { + StringAppender stringAppender = new StringAppender(); + stringAppender.Layout = new PatternLayout("%property{" + Utils.PROPERTY_KEY + "}"); + + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + BasicConfigurator.Configure(rep, stringAppender); + + ILog log1 = LogManager.GetLogger(rep.Name, "TestLogicalThreadPropertiesPattern"); + + log1.Info("TestMessage"); + Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test no logical thread properties value set"); + stringAppender.Reset(); + + LogicalThreadContext.Properties[Utils.PROPERTY_KEY] = "val1"; + + log1.Info("TestMessage"); + Assert.AreEqual("val1", stringAppender.GetString(), "Test logical thread properties value set"); + stringAppender.Reset(); + + LogicalThreadContext.Properties.Remove(Utils.PROPERTY_KEY); + + log1.Info("TestMessage"); + Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test logical thread properties value removed"); + stringAppender.Reset(); + } + + [Test] + public async Task TestLogicalThreadPropertiesPatternAsyncAwait() + { + StringAppender stringAppender = new StringAppender(); + stringAppender.Layout = new PatternLayout("%property{" + Utils.PROPERTY_KEY + "}"); + + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + BasicConfigurator.Configure(rep, stringAppender); + + ILog log1 = LogManager.GetLogger(rep.Name, "TestLogicalThreadPropertiesPattern"); + + log1.Info("TestMessage"); + Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test no logical thread stack value set"); + stringAppender.Reset(); + + string testValueForCurrentContext = "Outer"; + LogicalThreadContext.Properties[Utils.PROPERTY_KEY] = testValueForCurrentContext; + + log1.Info("TestMessage"); + Assert.AreEqual(testValueForCurrentContext, stringAppender.GetString(), "Test logical thread properties value set"); + stringAppender.Reset(); + + var strings = await Task.WhenAll(Enumerable.Range(0, 10).Select(x => SomeWorkProperties(x.ToString()))); + + // strings should be ["00AA0BB0", "01AA1BB1", "02AA2BB2", ...] + for (int i = 0; i < strings.Length; i++) + { + Assert.AreEqual(string.Format("{0}{1}AA{1}BB{1}", testValueForCurrentContext, i), strings[i], "Test logical thread properties expected sequence"); + } + + log1.Info("TestMessage"); + Assert.AreEqual(testValueForCurrentContext, stringAppender.GetString(), "Test logical thread properties value set"); + stringAppender.Reset(); + + LogicalThreadContext.Properties.Remove(Utils.PROPERTY_KEY); + + log1.Info("TestMessage"); + Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test logical thread properties value removed"); + stringAppender.Reset(); + } + + [Test] + public void TestLogicalThreadStackPattern() + { + StringAppender stringAppender = new StringAppender(); + stringAppender.Layout = new PatternLayout("%property{" + Utils.PROPERTY_KEY + "}"); + + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + BasicConfigurator.Configure(rep, stringAppender); + + ILog log1 = LogManager.GetLogger(rep.Name, "TestThreadStackPattern"); + + log1.Info("TestMessage"); + Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test no logical thread stack value set"); + stringAppender.Reset(); + + using (LogicalThreadContext.Stacks[Utils.PROPERTY_KEY].Push("val1")) + { + log1.Info("TestMessage"); + Assert.AreEqual("val1", stringAppender.GetString(), "Test logical thread stack value set"); + stringAppender.Reset(); + } + + log1.Info("TestMessage"); + Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test logical thread stack value removed"); + stringAppender.Reset(); + } + + [Test] + public void TestLogicalThreadStackPattern2() + { + StringAppender stringAppender = new StringAppender(); + stringAppender.Layout = new PatternLayout("%property{" + Utils.PROPERTY_KEY + "}"); + + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + BasicConfigurator.Configure(rep, stringAppender); + + ILog log1 = LogManager.GetLogger(rep.Name, "TestThreadStackPattern"); + + log1.Info("TestMessage"); + Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test no logical thread stack value set"); + stringAppender.Reset(); + + using (LogicalThreadContext.Stacks[Utils.PROPERTY_KEY].Push("val1")) + { + log1.Info("TestMessage"); + Assert.AreEqual("val1", stringAppender.GetString(), "Test logical thread stack value set"); + stringAppender.Reset(); + + using (LogicalThreadContext.Stacks[Utils.PROPERTY_KEY].Push("val2")) + { + log1.Info("TestMessage"); + Assert.AreEqual("val1 val2", stringAppender.GetString(), "Test logical thread stack value pushed 2nd val"); + stringAppender.Reset(); + } + } + + log1.Info("TestMessage"); + Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test logical thread stack value removed"); + stringAppender.Reset(); + } + + [Test] + public void TestLogicalThreadStackPatternNullVal() + { + StringAppender stringAppender = new StringAppender(); + stringAppender.Layout = new PatternLayout("%property{" + Utils.PROPERTY_KEY + "}"); + + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + BasicConfigurator.Configure(rep, stringAppender); + + ILog log1 = LogManager.GetLogger(rep.Name, "TestThreadStackPattern"); + + log1.Info("TestMessage"); + Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test no logical thread stack value set"); + stringAppender.Reset(); + + using (LogicalThreadContext.Stacks[Utils.PROPERTY_KEY].Push(null)) + { + log1.Info("TestMessage"); + Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test logical thread stack value set"); + stringAppender.Reset(); + } + + log1.Info("TestMessage"); + Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test logical thread stack value removed"); + stringAppender.Reset(); + } + + [Test] + public void TestLogicalThreadStackPatternNullVal2() + { + StringAppender stringAppender = new StringAppender(); + stringAppender.Layout = new PatternLayout("%property{" + Utils.PROPERTY_KEY + "}"); + + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + BasicConfigurator.Configure(rep, stringAppender); + + ILog log1 = LogManager.GetLogger(rep.Name, "TestThreadStackPattern"); + + log1.Info("TestMessage"); + Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test no logical thread stack value set"); + stringAppender.Reset(); + + using (LogicalThreadContext.Stacks[Utils.PROPERTY_KEY].Push("val1")) + { + log1.Info("TestMessage"); + Assert.AreEqual("val1", stringAppender.GetString(), "Test logical thread stack value set"); + stringAppender.Reset(); + + using (LogicalThreadContext.Stacks[Utils.PROPERTY_KEY].Push(null)) + { + log1.Info("TestMessage"); + Assert.AreEqual("val1 ", stringAppender.GetString(), "Test logical thread stack value pushed null"); + stringAppender.Reset(); + } + } + + log1.Info("TestMessage"); + Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test logical thread stack value removed"); + stringAppender.Reset(); + } + + [Test] + public async Task TestLogicalThreadStackPatternAsyncAwait() + { + StringAppender stringAppender = new StringAppender(); + stringAppender.Layout = new PatternLayout("%property{" + Utils.PROPERTY_KEY + "}"); + + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + BasicConfigurator.Configure(rep, stringAppender); + + ILog log1 = LogManager.GetLogger(rep.Name, "TestLogicalThreadStackPattern"); + + log1.Info("TestMessage"); + Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test no logical thread stack value set"); + stringAppender.Reset(); + + string testValueForCurrentContext = "Outer"; + string[] strings = null; + using (LogicalThreadContext.Stacks[Utils.PROPERTY_KEY].Push(testValueForCurrentContext)) + { + log1.Info("TestMessage"); + Assert.AreEqual(testValueForCurrentContext, stringAppender.GetString(), "Test logical thread stack value set"); + stringAppender.Reset(); + + strings = await Task.WhenAll(Enumerable.Range(0, 10).Select(x => SomeWorkStack(x.ToString()))); + } + + // strings should be ["Outer 0 AOuter 0 AOuter 0Outer 0 BOuter 0 B Outer 0", ...] + for (int i = 0; i < strings.Length; i++) + { + Assert.AreEqual(string.Format("{0} {1} A{0} {1} A{0} {1}{0} {1} B{0} {1} B{0} {1}", testValueForCurrentContext, i), strings[i], "Test logical thread properties expected sequence"); + } + + log1.Info("TestMessage"); + Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test logical thread properties value removed"); + stringAppender.Reset(); + } + + static async Task SomeWorkProperties(string propertyName) + { + StringAppender stringAppender = new StringAppender(); + stringAppender.Layout = new PatternLayout("%property{" + Utils.PROPERTY_KEY + "}"); + + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + BasicConfigurator.Configure(rep, stringAppender); + + ILog log = LogManager.GetLogger(rep.Name, "TestLogicalThreadStackPattern"); + log.Info("TestMessage"); + + // set a new one + LogicalThreadContext.Properties[Utils.PROPERTY_KEY] = propertyName; + log.Info("TestMessage"); + + await MoreWorkProperties(log, "A"); + log.Info("TestMessage"); + await MoreWorkProperties(log, "B"); + log.Info("TestMessage"); + return stringAppender.GetString(); + } + + static async Task MoreWorkProperties(ILog log, string propertyName) + { + LogicalThreadContext.Properties[Utils.PROPERTY_KEY] = propertyName; + log.Info("TestMessage"); + await Task.Delay(1); + log.Info("TestMessage"); + } + + static async Task SomeWorkStack(string stackName) + { + StringAppender stringAppender = new StringAppender(); + stringAppender.Layout = new PatternLayout("%property{" + Utils.PROPERTY_KEY + "}"); + + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + BasicConfigurator.Configure(rep, stringAppender); + + ILog log = LogManager.GetLogger(rep.Name, "TestLogicalThreadStackPattern"); + + using (LogicalThreadContext.Stacks[Utils.PROPERTY_KEY].Push(stackName)) + { + log.Info("TestMessage"); + Assert.AreEqual(string.Format("Outer {0}", stackName), stringAppender.GetString(), "Test logical thread stack value set"); + stringAppender.Reset(); + + await MoreWorkStack(log, "A"); + log.Info("TestMessage"); + await MoreWorkStack(log, "B"); + log.Info("TestMessage"); + } + + return stringAppender.GetString(); + } + + static async Task MoreWorkStack(ILog log, string stackName) + { + using (LogicalThreadContext.Stacks[Utils.PROPERTY_KEY].Push(stackName)) + { + log.Info("TestMessage"); + await Task.Delay(1); + log.Info("TestMessage"); + } + } + } } #endif diff --git a/src/log4net.Tests/Core/EvaluatorTest.cs b/src/log4net.Tests/Core/EvaluatorTest.cs index 0dbc5dc4..30a31de2 100644 --- a/src/log4net.Tests/Core/EvaluatorTest.cs +++ b/src/log4net.Tests/Core/EvaluatorTest.cs @@ -27,118 +27,118 @@ namespace log4net.Tests.Core { - [TestFixture] - public class EvaluatorTest - { - private BufferingForwardingAppender m_bufferingForwardingAppender; - private CountingAppender m_countingAppender; - private Repository.Hierarchy.Hierarchy m_hierarchy; - - [SetUp] - public void SetupRepository() - { - m_hierarchy = new Repository.Hierarchy.Hierarchy(); - - m_countingAppender = new CountingAppender(); - m_countingAppender.ActivateOptions(); - - m_bufferingForwardingAppender = new BufferingForwardingAppender(); - m_bufferingForwardingAppender.AddAppender(m_countingAppender); - - m_bufferingForwardingAppender.BufferSize = 5; - m_bufferingForwardingAppender.ClearFilters(); - m_bufferingForwardingAppender.Fix = FixFlags.Partial; - m_bufferingForwardingAppender.Lossy = false; - m_bufferingForwardingAppender.LossyEvaluator = null; - m_bufferingForwardingAppender.Threshold = Level.All; - } - - [Test] - public void TestLevelEvaluator() - { - m_bufferingForwardingAppender.Evaluator = new LevelEvaluator(Level.Info); - m_bufferingForwardingAppender.ActivateOptions(); - log4net.Config.BasicConfigurator.Configure(m_hierarchy, m_bufferingForwardingAppender); - - ILogger logger = m_hierarchy.GetLogger("TestLevelEvaluator"); - - logger.Log(typeof(EvaluatorTest), Level.Debug, "Debug message logged", null); - logger.Log(typeof(EvaluatorTest), Level.Debug, "Debug message logged", null); - Assert.AreEqual(0, m_countingAppender.Counter, "Test 2 events buffered"); - - logger.Log(typeof(EvaluatorTest), Level.Info, "Info message logged", null); - Assert.AreEqual(3, m_countingAppender.Counter, "Test 3 events flushed on Info message."); - } + [TestFixture] + public class EvaluatorTest + { + private BufferingForwardingAppender m_bufferingForwardingAppender; + private CountingAppender m_countingAppender; + private Repository.Hierarchy.Hierarchy m_hierarchy; + + [SetUp] + public void SetupRepository() + { + m_hierarchy = new Repository.Hierarchy.Hierarchy(); + + m_countingAppender = new CountingAppender(); + m_countingAppender.ActivateOptions(); + + m_bufferingForwardingAppender = new BufferingForwardingAppender(); + m_bufferingForwardingAppender.AddAppender(m_countingAppender); + + m_bufferingForwardingAppender.BufferSize = 5; + m_bufferingForwardingAppender.ClearFilters(); + m_bufferingForwardingAppender.Fix = FixFlags.Partial; + m_bufferingForwardingAppender.Lossy = false; + m_bufferingForwardingAppender.LossyEvaluator = null; + m_bufferingForwardingAppender.Threshold = Level.All; + } + + [Test] + public void TestLevelEvaluator() + { + m_bufferingForwardingAppender.Evaluator = new LevelEvaluator(Level.Info); + m_bufferingForwardingAppender.ActivateOptions(); + log4net.Config.BasicConfigurator.Configure(m_hierarchy, m_bufferingForwardingAppender); + + ILogger logger = m_hierarchy.GetLogger("TestLevelEvaluator"); + + logger.Log(typeof(EvaluatorTest), Level.Debug, "Debug message logged", null); + logger.Log(typeof(EvaluatorTest), Level.Debug, "Debug message logged", null); + Assert.AreEqual(0, m_countingAppender.Counter, "Test 2 events buffered"); + + logger.Log(typeof(EvaluatorTest), Level.Info, "Info message logged", null); + Assert.AreEqual(3, m_countingAppender.Counter, "Test 3 events flushed on Info message."); + } #if !NETSTANDARD1_3 - [Test] - public void TestExceptionEvaluator() - { - m_bufferingForwardingAppender.Evaluator = new ExceptionEvaluator(typeof(ApplicationException), true); - m_bufferingForwardingAppender.ActivateOptions(); - log4net.Config.BasicConfigurator.Configure(m_hierarchy, m_bufferingForwardingAppender); - - ILogger logger = m_hierarchy.GetLogger("TestExceptionEvaluator"); - - logger.Log(typeof(EvaluatorTest), Level.Warn, "Warn message logged", null); - logger.Log(typeof(EvaluatorTest), Level.Warn, "Warn message logged", null); - Assert.AreEqual(0, m_countingAppender.Counter, "Test 2 events buffered"); - - logger.Log(typeof(EvaluatorTest), Level.Warn, "Warn message logged", new ApplicationException()); - Assert.AreEqual(3, m_countingAppender.Counter, "Test 3 events flushed on ApplicationException message."); - } - - [Test] - public void TestExceptionEvaluatorTriggerOnSubClass() - { - m_bufferingForwardingAppender.Evaluator = new ExceptionEvaluator(typeof(Exception), true); - m_bufferingForwardingAppender.ActivateOptions(); - log4net.Config.BasicConfigurator.Configure(m_hierarchy, m_bufferingForwardingAppender); - - ILogger logger = m_hierarchy.GetLogger("TestExceptionEvaluatorTriggerOnSubClass"); - - logger.Log(typeof(EvaluatorTest), Level.Warn, "Warn message logged", null); - logger.Log(typeof(EvaluatorTest), Level.Warn, "Warn message logged", null); - Assert.AreEqual(0, m_countingAppender.Counter, "Test 2 events buffered"); - - logger.Log(typeof(EvaluatorTest), Level.Warn, "Warn message logged", new ApplicationException()); - Assert.AreEqual(3, m_countingAppender.Counter, "Test 3 events flushed on ApplicationException message."); - } - - [Test] - public void TestExceptionEvaluatorNoTriggerOnSubClass() - { - m_bufferingForwardingAppender.Evaluator = new ExceptionEvaluator(typeof(Exception), false); - m_bufferingForwardingAppender.ActivateOptions(); - log4net.Config.BasicConfigurator.Configure(m_hierarchy, m_bufferingForwardingAppender); - - ILogger logger = m_hierarchy.GetLogger("TestExceptionEvaluatorNoTriggerOnSubClass"); - - logger.Log(typeof(EvaluatorTest), Level.Warn, "Warn message logged", null); - logger.Log(typeof(EvaluatorTest), Level.Warn, "Warn message logged", null); - Assert.AreEqual(0, m_countingAppender.Counter, "Test 2 events buffered"); - - logger.Log(typeof(EvaluatorTest), Level.Warn, "Warn message logged", new ApplicationException()); - Assert.AreEqual(0, m_countingAppender.Counter, "Test 3 events buffered"); - } - - [Test] - public void TestInvalidExceptionEvaluator() - { - // warning: String is not a subclass of Exception - m_bufferingForwardingAppender.Evaluator = new ExceptionEvaluator(typeof(String), false); - m_bufferingForwardingAppender.ActivateOptions(); - log4net.Config.BasicConfigurator.Configure(m_hierarchy, m_bufferingForwardingAppender); - - ILogger logger = m_hierarchy.GetLogger("TestExceptionEvaluatorNoTriggerOnSubClass"); - - logger.Log(typeof(EvaluatorTest), Level.Warn, "Warn message logged", null); - logger.Log(typeof(EvaluatorTest), Level.Warn, "Warn message logged", null); - Assert.AreEqual(0, m_countingAppender.Counter, "Test 2 events buffered"); - - logger.Log(typeof(EvaluatorTest), Level.Warn, "Warn message logged", new ApplicationException()); - Assert.AreEqual(0, m_countingAppender.Counter, "Test 3 events buffered"); - } + [Test] + public void TestExceptionEvaluator() + { + m_bufferingForwardingAppender.Evaluator = new ExceptionEvaluator(typeof(ApplicationException), true); + m_bufferingForwardingAppender.ActivateOptions(); + log4net.Config.BasicConfigurator.Configure(m_hierarchy, m_bufferingForwardingAppender); + + ILogger logger = m_hierarchy.GetLogger("TestExceptionEvaluator"); + + logger.Log(typeof(EvaluatorTest), Level.Warn, "Warn message logged", null); + logger.Log(typeof(EvaluatorTest), Level.Warn, "Warn message logged", null); + Assert.AreEqual(0, m_countingAppender.Counter, "Test 2 events buffered"); + + logger.Log(typeof(EvaluatorTest), Level.Warn, "Warn message logged", new ApplicationException()); + Assert.AreEqual(3, m_countingAppender.Counter, "Test 3 events flushed on ApplicationException message."); + } + + [Test] + public void TestExceptionEvaluatorTriggerOnSubClass() + { + m_bufferingForwardingAppender.Evaluator = new ExceptionEvaluator(typeof(Exception), true); + m_bufferingForwardingAppender.ActivateOptions(); + log4net.Config.BasicConfigurator.Configure(m_hierarchy, m_bufferingForwardingAppender); + + ILogger logger = m_hierarchy.GetLogger("TestExceptionEvaluatorTriggerOnSubClass"); + + logger.Log(typeof(EvaluatorTest), Level.Warn, "Warn message logged", null); + logger.Log(typeof(EvaluatorTest), Level.Warn, "Warn message logged", null); + Assert.AreEqual(0, m_countingAppender.Counter, "Test 2 events buffered"); + + logger.Log(typeof(EvaluatorTest), Level.Warn, "Warn message logged", new ApplicationException()); + Assert.AreEqual(3, m_countingAppender.Counter, "Test 3 events flushed on ApplicationException message."); + } + + [Test] + public void TestExceptionEvaluatorNoTriggerOnSubClass() + { + m_bufferingForwardingAppender.Evaluator = new ExceptionEvaluator(typeof(Exception), false); + m_bufferingForwardingAppender.ActivateOptions(); + log4net.Config.BasicConfigurator.Configure(m_hierarchy, m_bufferingForwardingAppender); + + ILogger logger = m_hierarchy.GetLogger("TestExceptionEvaluatorNoTriggerOnSubClass"); + + logger.Log(typeof(EvaluatorTest), Level.Warn, "Warn message logged", null); + logger.Log(typeof(EvaluatorTest), Level.Warn, "Warn message logged", null); + Assert.AreEqual(0, m_countingAppender.Counter, "Test 2 events buffered"); + + logger.Log(typeof(EvaluatorTest), Level.Warn, "Warn message logged", new ApplicationException()); + Assert.AreEqual(0, m_countingAppender.Counter, "Test 3 events buffered"); + } + + [Test] + public void TestInvalidExceptionEvaluator() + { + // warning: String is not a subclass of Exception + m_bufferingForwardingAppender.Evaluator = new ExceptionEvaluator(typeof(String), false); + m_bufferingForwardingAppender.ActivateOptions(); + log4net.Config.BasicConfigurator.Configure(m_hierarchy, m_bufferingForwardingAppender); + + ILogger logger = m_hierarchy.GetLogger("TestExceptionEvaluatorNoTriggerOnSubClass"); + + logger.Log(typeof(EvaluatorTest), Level.Warn, "Warn message logged", null); + logger.Log(typeof(EvaluatorTest), Level.Warn, "Warn message logged", null); + Assert.AreEqual(0, m_countingAppender.Counter, "Test 2 events buffered"); + + logger.Log(typeof(EvaluatorTest), Level.Warn, "Warn message logged", new ApplicationException()); + Assert.AreEqual(0, m_countingAppender.Counter, "Test 3 events buffered"); + } #endif - } + } } diff --git a/src/log4net.Tests/Core/FixingTest.cs b/src/log4net.Tests/Core/FixingTest.cs index d122344f..6c5dbb8b 100644 --- a/src/log4net.Tests/Core/FixingTest.cs +++ b/src/log4net.Tests/Core/FixingTest.cs @@ -29,16 +29,16 @@ namespace log4net.Tests.Core { - /// - /// - [TestFixture] - public class FixingTest - { + /// + /// + [TestFixture] + public class FixingTest + { const string TEST_REPOSITORY = "Test Repository"; [OneTimeSetUp] - public void CreateRepository() - { + public void CreateRepository() + { bool exists = false; Repository.ILoggerRepository[] repositories = LogManager.GetAllRepositories(); if (repositories != null) { @@ -53,121 +53,121 @@ public void CreateRepository() LogManager.CreateRepository(TEST_REPOSITORY); } - // write-once - if (Thread.CurrentThread.Name == null) - { - Thread.CurrentThread.Name = "Log4Net Test thread"; - } - } - - [Test] - public void All_ShouldContainAllFlags() - { - // Arrange - // Act - var allFlags = Enum.GetValues(typeof(FixFlags)).Cast() - .Except(new[] { FixFlags.None }) - .ToArray(); - // Assert - foreach (var flag in allFlags) - { - Expect(FixFlags.All & flag) - .To.Equal(flag, () => $"FixFlags.All does not contain {flag}"); - } - } - - [Test] - public void TestUnfixedValues() - { - LoggingEventData loggingEventData = BuildStandardEventData(); - - // LoggingEvents occur at distinct points in time - LoggingEvent loggingEvent = new LoggingEvent( - loggingEventData.LocationInfo.GetType(), - LogManager.GetRepository(TEST_REPOSITORY), - loggingEventData.LoggerName, - loggingEventData.Level, - loggingEventData.Message, - new Exception("This is the exception")); - - AssertExpectedLoggingEvent(loggingEvent, loggingEventData); - - Assert.AreEqual(FixFlags.None, loggingEvent.Fix, "Fixed Fields is incorrect"); - } - - [Test] - public void TestAllFixedValues() - { - LoggingEventData loggingEventData = BuildStandardEventData(); - - // LoggingEvents occur at distinct points in time - LoggingEvent loggingEvent = new LoggingEvent( - loggingEventData.LocationInfo.GetType(), - LogManager.GetRepository(TEST_REPOSITORY), - loggingEventData.LoggerName, - loggingEventData.Level, - loggingEventData.Message, - new Exception("This is the exception")); - - AssertExpectedLoggingEvent(loggingEvent, loggingEventData); - - loggingEvent.Fix = FixFlags.All; - - Assert.AreEqual(FixFlags.LocationInfo | FixFlags.UserName | FixFlags.Identity | FixFlags.Partial | FixFlags.Message | FixFlags.ThreadName | FixFlags.Exception | FixFlags.Domain | FixFlags.Properties, loggingEvent.Fix, "Fixed Fields is incorrect"); - } - - [Test] - public void TestNoFixedValues() - { - LoggingEventData loggingEventData = BuildStandardEventData(); - - // LoggingEvents occur at distinct points in time - LoggingEvent loggingEvent = new LoggingEvent( - loggingEventData.LocationInfo.GetType(), - LogManager.GetRepository(TEST_REPOSITORY), - loggingEventData.LoggerName, - loggingEventData.Level, - loggingEventData.Message, - new Exception("This is the exception")); - - AssertExpectedLoggingEvent(loggingEvent, loggingEventData); - - loggingEvent.Fix = FixFlags.None; - - Assert.AreEqual(FixFlags.None, loggingEvent.Fix, "Fixed Fields is incorrect"); - } - - private static LoggingEventData BuildStandardEventData() - { - LoggingEventData loggingEventData = new LoggingEventData(); - loggingEventData.LoggerName = typeof(FixingTest).FullName; - loggingEventData.Level = Level.Warn; - loggingEventData.Message = "Logging event works"; - loggingEventData.Domain = "ReallySimpleApp"; - loggingEventData.LocationInfo = new LocationInfo(typeof(FixingTest).Name, "Main", "Class1.cs", "29"); //Completely arbitary - loggingEventData.ThreadName = Thread.CurrentThread.Name; - loggingEventData.TimeStampUtc = DateTime.UtcNow.Date; - loggingEventData.ExceptionString = "Exception occured here"; - loggingEventData.UserName = "TestUser"; - return loggingEventData; - } - - private static void AssertExpectedLoggingEvent(LoggingEvent loggingEvent, LoggingEventData loggingEventData) - { - Assert.AreEqual("ReallySimpleApp", loggingEventData.Domain, "Domain is incorrect"); - Assert.AreEqual("System.Exception: This is the exception", loggingEvent.GetExceptionString(), "Exception is incorrect"); - Assert.AreEqual(null, loggingEventData.Identity, "Identity is incorrect"); - Assert.AreEqual(Level.Warn, loggingEventData.Level, "Level is incorrect"); + // write-once + if (Thread.CurrentThread.Name == null) + { + Thread.CurrentThread.Name = "Log4Net Test thread"; + } + } + + [Test] + public void All_ShouldContainAllFlags() + { + // Arrange + // Act + var allFlags = Enum.GetValues(typeof(FixFlags)).Cast() + .Except(new[] { FixFlags.None }) + .ToArray(); + // Assert + foreach (var flag in allFlags) + { + Expect(FixFlags.All & flag) + .To.Equal(flag, () => $"FixFlags.All does not contain {flag}"); + } + } + + [Test] + public void TestUnfixedValues() + { + LoggingEventData loggingEventData = BuildStandardEventData(); + + // LoggingEvents occur at distinct points in time + LoggingEvent loggingEvent = new LoggingEvent( + loggingEventData.LocationInfo.GetType(), + LogManager.GetRepository(TEST_REPOSITORY), + loggingEventData.LoggerName, + loggingEventData.Level, + loggingEventData.Message, + new Exception("This is the exception")); + + AssertExpectedLoggingEvent(loggingEvent, loggingEventData); + + Assert.AreEqual(FixFlags.None, loggingEvent.Fix, "Fixed Fields is incorrect"); + } + + [Test] + public void TestAllFixedValues() + { + LoggingEventData loggingEventData = BuildStandardEventData(); + + // LoggingEvents occur at distinct points in time + LoggingEvent loggingEvent = new LoggingEvent( + loggingEventData.LocationInfo.GetType(), + LogManager.GetRepository(TEST_REPOSITORY), + loggingEventData.LoggerName, + loggingEventData.Level, + loggingEventData.Message, + new Exception("This is the exception")); + + AssertExpectedLoggingEvent(loggingEvent, loggingEventData); + + loggingEvent.Fix = FixFlags.All; + + Assert.AreEqual(FixFlags.LocationInfo | FixFlags.UserName | FixFlags.Identity | FixFlags.Partial | FixFlags.Message | FixFlags.ThreadName | FixFlags.Exception | FixFlags.Domain | FixFlags.Properties, loggingEvent.Fix, "Fixed Fields is incorrect"); + } + + [Test] + public void TestNoFixedValues() + { + LoggingEventData loggingEventData = BuildStandardEventData(); + + // LoggingEvents occur at distinct points in time + LoggingEvent loggingEvent = new LoggingEvent( + loggingEventData.LocationInfo.GetType(), + LogManager.GetRepository(TEST_REPOSITORY), + loggingEventData.LoggerName, + loggingEventData.Level, + loggingEventData.Message, + new Exception("This is the exception")); + + AssertExpectedLoggingEvent(loggingEvent, loggingEventData); + + loggingEvent.Fix = FixFlags.None; + + Assert.AreEqual(FixFlags.None, loggingEvent.Fix, "Fixed Fields is incorrect"); + } + + private static LoggingEventData BuildStandardEventData() + { + LoggingEventData loggingEventData = new LoggingEventData(); + loggingEventData.LoggerName = typeof(FixingTest).FullName; + loggingEventData.Level = Level.Warn; + loggingEventData.Message = "Logging event works"; + loggingEventData.Domain = "ReallySimpleApp"; + loggingEventData.LocationInfo = new LocationInfo(typeof(FixingTest).Name, "Main", "Class1.cs", "29"); //Completely arbitary + loggingEventData.ThreadName = Thread.CurrentThread.Name; + loggingEventData.TimeStampUtc = DateTime.UtcNow.Date; + loggingEventData.ExceptionString = "Exception occured here"; + loggingEventData.UserName = "TestUser"; + return loggingEventData; + } + + private static void AssertExpectedLoggingEvent(LoggingEvent loggingEvent, LoggingEventData loggingEventData) + { + Assert.AreEqual("ReallySimpleApp", loggingEventData.Domain, "Domain is incorrect"); + Assert.AreEqual("System.Exception: This is the exception", loggingEvent.GetExceptionString(), "Exception is incorrect"); + Assert.AreEqual(null, loggingEventData.Identity, "Identity is incorrect"); + Assert.AreEqual(Level.Warn, loggingEventData.Level, "Level is incorrect"); #if !NETSTANDARD1_3 // NETSTANDARD1_3: LocationInfo can't get method names - Assert.AreEqual("get_LocationInformation", loggingEvent.LocationInformation.MethodName, "Location Info is incorrect"); + Assert.AreEqual("get_LocationInformation", loggingEvent.LocationInformation.MethodName, "Location Info is incorrect"); #endif - Assert.AreEqual("log4net.Tests.Core.FixingTest", loggingEventData.LoggerName, "LoggerName is incorrect"); - Assert.AreEqual(LogManager.GetRepository(TEST_REPOSITORY), loggingEvent.Repository, "Repository is incorrect"); - Assert.AreEqual(Thread.CurrentThread.Name, loggingEventData.ThreadName, "ThreadName is incorrect"); + Assert.AreEqual("log4net.Tests.Core.FixingTest", loggingEventData.LoggerName, "LoggerName is incorrect"); + Assert.AreEqual(LogManager.GetRepository(TEST_REPOSITORY), loggingEvent.Repository, "Repository is incorrect"); + Assert.AreEqual(Thread.CurrentThread.Name, loggingEventData.ThreadName, "ThreadName is incorrect"); // This test is redundant as loggingEventData.TimeStamp is a value type and cannot be null // Assert.IsNotNull(loggingEventData.TimeStampUtc, "TimeStamp is incorrect"); - Assert.AreEqual("TestUser", loggingEventData.UserName, "UserName is incorrect"); - Assert.AreEqual("Logging event works", loggingEvent.RenderedMessage, "Message is incorrect"); - } - } + Assert.AreEqual("TestUser", loggingEventData.UserName, "UserName is incorrect"); + Assert.AreEqual("Logging event works", loggingEvent.RenderedMessage, "Message is incorrect"); + } + } } \ No newline at end of file diff --git a/src/log4net.Tests/Core/ShutdownTest.cs b/src/log4net.Tests/Core/ShutdownTest.cs index 720a321b..075a469c 100644 --- a/src/log4net.Tests/Core/ShutdownTest.cs +++ b/src/log4net.Tests/Core/ShutdownTest.cs @@ -28,46 +28,46 @@ namespace log4net.Tests.Core { - /// - /// - [TestFixture] - public class ShutdownTest - { - /// - /// Test that a repository can be shutdown and reconfigured - /// - [Test] - public void TestShutdownAndReconfigure() - { - // Create unique repository - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + /// + /// + [TestFixture] + public class ShutdownTest + { + /// + /// Test that a repository can be shutdown and reconfigured + /// + [Test] + public void TestShutdownAndReconfigure() + { + // Create unique repository + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - // Create appender and configure repos - StringAppender stringAppender = new StringAppender(); - stringAppender.Layout = new PatternLayout("%m"); - BasicConfigurator.Configure(rep, stringAppender); + // Create appender and configure repos + StringAppender stringAppender = new StringAppender(); + stringAppender.Layout = new PatternLayout("%m"); + BasicConfigurator.Configure(rep, stringAppender); - // Get logger from repos - ILog log1 = LogManager.GetLogger(rep.Name, "logger1"); + // Get logger from repos + ILog log1 = LogManager.GetLogger(rep.Name, "logger1"); - log1.Info("TestMessage1"); - Assert.AreEqual("TestMessage1", stringAppender.GetString(), "Test logging configured"); - stringAppender.Reset(); + log1.Info("TestMessage1"); + Assert.AreEqual("TestMessage1", stringAppender.GetString(), "Test logging configured"); + stringAppender.Reset(); - rep.Shutdown(); + rep.Shutdown(); - log1.Info("TestMessage2"); - Assert.AreEqual("", stringAppender.GetString(), "Test not logging while shutdown"); - stringAppender.Reset(); + log1.Info("TestMessage2"); + Assert.AreEqual("", stringAppender.GetString(), "Test not logging while shutdown"); + stringAppender.Reset(); - // Create new appender and configure - stringAppender = new StringAppender(); - stringAppender.Layout = new PatternLayout("%m"); - BasicConfigurator.Configure(rep, stringAppender); + // Create new appender and configure + stringAppender = new StringAppender(); + stringAppender.Layout = new PatternLayout("%m"); + BasicConfigurator.Configure(rep, stringAppender); - log1.Info("TestMessage3"); - Assert.AreEqual("TestMessage3", stringAppender.GetString(), "Test logging re-configured"); - stringAppender.Reset(); - } - } + log1.Info("TestMessage3"); + Assert.AreEqual("TestMessage3", stringAppender.GetString(), "Test logging re-configured"); + stringAppender.Reset(); + } + } } \ No newline at end of file diff --git a/src/log4net.Tests/Core/StringFormatTest.cs b/src/log4net.Tests/Core/StringFormatTest.cs index 16c7b5aa..7aaf9b1d 100644 --- a/src/log4net.Tests/Core/StringFormatTest.cs +++ b/src/log4net.Tests/Core/StringFormatTest.cs @@ -31,681 +31,681 @@ namespace log4net.Tests.Core { - /// - /// Used for internal unit testing the class. - /// - /// - /// Used for internal unit testing the class. - /// - [TestFixture] - public class StringFormatTest - { + /// + /// Used for internal unit testing the class. + /// + /// + /// Used for internal unit testing the class. + /// + [TestFixture] + public class StringFormatTest + { #if !NETSTANDARD1_3 - private CultureInfo _currentCulture; - private CultureInfo _currentUICulture; - - [SetUp] - public void SetUp() - { - // set correct thread culture - _currentCulture = System.Threading.Thread.CurrentThread.CurrentCulture; - _currentUICulture = System.Threading.Thread.CurrentThread.CurrentUICulture; - System.Threading.Thread.CurrentThread.CurrentCulture = System.Threading.Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.InvariantCulture; - } - - [TearDown] - public void TearDown() - { - // restore previous culture - System.Threading.Thread.CurrentThread.CurrentCulture = _currentCulture; - System.Threading.Thread.CurrentThread.CurrentUICulture = _currentUICulture; - } + private CultureInfo _currentCulture; + private CultureInfo _currentUICulture; + + [SetUp] + public void SetUp() + { + // set correct thread culture + _currentCulture = System.Threading.Thread.CurrentThread.CurrentCulture; + _currentUICulture = System.Threading.Thread.CurrentThread.CurrentUICulture; + System.Threading.Thread.CurrentThread.CurrentCulture = System.Threading.Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.InvariantCulture; + } + + [TearDown] + public void TearDown() + { + // restore previous culture + System.Threading.Thread.CurrentThread.CurrentCulture = _currentCulture; + System.Threading.Thread.CurrentThread.CurrentUICulture = _currentUICulture; + } #endif - [Test] - public void TestFormatString() - { - StringAppender stringAppender = new StringAppender(); - stringAppender.Layout = new PatternLayout("%message"); + [Test] + public void TestFormatString() + { + StringAppender stringAppender = new StringAppender(); + stringAppender.Layout = new PatternLayout("%message"); - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - BasicConfigurator.Configure(rep, stringAppender); + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + BasicConfigurator.Configure(rep, stringAppender); - ILog log1 = LogManager.GetLogger(rep.Name, "TestFormatString"); + ILog log1 = LogManager.GetLogger(rep.Name, "TestFormatString"); - // *** - log1.Info("TestMessage"); - Assert.AreEqual("TestMessage", stringAppender.GetString(), "Test simple INFO event"); - stringAppender.Reset(); + // *** + log1.Info("TestMessage"); + Assert.AreEqual("TestMessage", stringAppender.GetString(), "Test simple INFO event"); + stringAppender.Reset(); - // *** - log1.DebugFormat("Before {0} After", "Middle"); - Assert.AreEqual("Before Middle After", stringAppender.GetString(), "Test simple formatted DEBUG event"); - stringAppender.Reset(); + // *** + log1.DebugFormat("Before {0} After", "Middle"); + Assert.AreEqual("Before Middle After", stringAppender.GetString(), "Test simple formatted DEBUG event"); + stringAppender.Reset(); - // *** - log1.InfoFormat("Before {0} After", "Middle"); - Assert.AreEqual("Before Middle After", stringAppender.GetString(), "Test simple formatted INFO event"); - stringAppender.Reset(); + // *** + log1.InfoFormat("Before {0} After", "Middle"); + Assert.AreEqual("Before Middle After", stringAppender.GetString(), "Test simple formatted INFO event"); + stringAppender.Reset(); - // *** - log1.WarnFormat("Before {0} After", "Middle"); - Assert.AreEqual("Before Middle After", stringAppender.GetString(), "Test simple formatted WARN event"); - stringAppender.Reset(); + // *** + log1.WarnFormat("Before {0} After", "Middle"); + Assert.AreEqual("Before Middle After", stringAppender.GetString(), "Test simple formatted WARN event"); + stringAppender.Reset(); - // *** - log1.ErrorFormat("Before {0} After", "Middle"); - Assert.AreEqual("Before Middle After", stringAppender.GetString(), "Test simple formatted ERROR event"); - stringAppender.Reset(); + // *** + log1.ErrorFormat("Before {0} After", "Middle"); + Assert.AreEqual("Before Middle After", stringAppender.GetString(), "Test simple formatted ERROR event"); + stringAppender.Reset(); - // *** - log1.FatalFormat("Before {0} After", "Middle"); - Assert.AreEqual("Before Middle After", stringAppender.GetString(), "Test simple formatted FATAL event"); - stringAppender.Reset(); + // *** + log1.FatalFormat("Before {0} After", "Middle"); + Assert.AreEqual("Before Middle After", stringAppender.GetString(), "Test simple formatted FATAL event"); + stringAppender.Reset(); - - // *** - log1.InfoFormat("Before {0} After {1}", "Middle", "End"); - Assert.AreEqual("Before Middle After End", stringAppender.GetString(), "Test simple formatted INFO event 2"); - stringAppender.Reset(); - - // *** - log1.InfoFormat("IGNORE THIS WARNING - EXCEPTION EXPECTED Before {0} After {1} {2}", "Middle", "End"); - Assert.AreEqual(STRING_FORMAT_ERROR, stringAppender.GetString(), "Test formatting error"); - stringAppender.Reset(); - } - - private const string STRING_FORMAT_ERROR = "Exception during StringFormat: Index (zero based) must be greater than or equal to zero and less than the size of the argument list. IGNORE THIS WARNING - EXCEPTION EXPECTED Before {0} After {1} {2}{Middle, End}"; - - - [Test] - public void TestLogFormatApi_Debug() - { - StringAppender stringAppender = new StringAppender(); - stringAppender.Layout = new PatternLayout("%level:%message"); - - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - BasicConfigurator.Configure(rep, stringAppender); - - ILog log1 = LogManager.GetLogger(rep.Name, "TestLogFormatApi_Debug"); - - // *** - log1.Debug("TestMessage"); - Assert.AreEqual("DEBUG:TestMessage", stringAppender.GetString(), "Test simple DEBUG event 1"); - stringAppender.Reset(); - - // *** - log1.Debug("TestMessage", null); - Assert.AreEqual("DEBUG:TestMessage", stringAppender.GetString(), "Test simple DEBUG event 2"); - stringAppender.Reset(); - - // *** - log1.Debug("TestMessage", new Exception("Exception message")); - Assert.AreEqual("DEBUG:TestMessageSystem.Exception: Exception message" + Environment.NewLine, stringAppender.GetString(), "Test simple DEBUG event 3"); - stringAppender.Reset(); - - // *** - log1.DebugFormat("a{0}", "1"); - Assert.AreEqual("DEBUG:a1", stringAppender.GetString(), "Test formatted DEBUG event with 1 parm"); - stringAppender.Reset(); - - // *** - log1.DebugFormat("a{0}b{1}", "1", "2"); - Assert.AreEqual("DEBUG:a1b2", stringAppender.GetString(), "Test formatted DEBUG event with 2 parm"); - stringAppender.Reset(); - - // *** - log1.DebugFormat("a{0}b{1}c{2}", "1", "2", "3"); - Assert.AreEqual("DEBUG:a1b2c3", stringAppender.GetString(), "Test formatted DEBUG event with 3 parm"); - stringAppender.Reset(); - - - // *** - log1.DebugFormat("a{0}b{1}c{2}d{3}e{4}f", "Q", "W", "E", "R", "T", "Y"); - Assert.AreEqual("DEBUG:aQbWcEdReTf", stringAppender.GetString(), "Test formatted DEBUG event with 5 parms (only 4 used)"); - stringAppender.Reset(); - - // *** - log1.DebugFormat(null, "Before {0} After {1}", "Middle", "End"); - Assert.AreEqual("DEBUG:Before Middle After End", stringAppender.GetString(), "Test formatting with null provider"); - stringAppender.Reset(); - - // *** - log1.DebugFormat(new CultureInfo("en"), "Before {0} After {1}", "Middle", "End"); - Assert.AreEqual("DEBUG:Before Middle After End", stringAppender.GetString(), "Test formatting with 'en' provider"); - stringAppender.Reset(); - } - - [Test] - public void TestLogFormatApi_NoDebug() - { - StringAppender stringAppender = new StringAppender(); - stringAppender.Threshold = Level.Info; - stringAppender.Layout = new PatternLayout("%level:%message"); - - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - BasicConfigurator.Configure(rep, stringAppender); - - ILog log1 = LogManager.GetLogger(rep.Name, "TestLogFormatApi_Debug"); - - // *** - log1.Debug("TestMessage"); - Assert.AreEqual("", stringAppender.GetString(), "Test simple DEBUG event 1"); - stringAppender.Reset(); - - // *** - log1.Debug("TestMessage", null); - Assert.AreEqual("", stringAppender.GetString(), "Test simple DEBUG event 2"); - stringAppender.Reset(); - - // *** - log1.Debug("TestMessage", new Exception("Exception message")); - Assert.AreEqual("", stringAppender.GetString(), "Test simple DEBUG event 3"); - stringAppender.Reset(); - - // *** - log1.DebugFormat("a{0}", "1"); - Assert.AreEqual("", stringAppender.GetString(), "Test formatted DEBUG event with 1 parm"); - stringAppender.Reset(); - - // *** - log1.DebugFormat("a{0}b{1}", "1", "2"); - Assert.AreEqual("", stringAppender.GetString(), "Test formatted DEBUG event with 2 parm"); - stringAppender.Reset(); - - // *** - log1.DebugFormat("a{0}b{1}c{2}", "1", "2", "3"); - Assert.AreEqual("", stringAppender.GetString(), "Test formatted DEBUG event with 3 parm"); - stringAppender.Reset(); - - - // *** - log1.DebugFormat("a{0}b{1}c{2}d{3}e{4}f", "Q", "W", "E", "R", "T", "Y"); - Assert.AreEqual("", stringAppender.GetString(), "Test formatted DEBUG event with 5 parms (only 4 used)"); - stringAppender.Reset(); - - // *** - log1.DebugFormat(null, "Before {0} After {1}", "Middle", "End"); - Assert.AreEqual("", stringAppender.GetString(), "Test formatting with null provider"); - stringAppender.Reset(); - - // *** - log1.DebugFormat(new CultureInfo("en"), "Before {0} After {1}", "Middle", "End"); - Assert.AreEqual("", stringAppender.GetString(), "Test formatting with 'en' provider"); - stringAppender.Reset(); - } - - - [Test] - public void TestLogFormatApi_Info() - { - StringAppender stringAppender = new StringAppender(); - stringAppender.Layout = new PatternLayout("%level:%message"); - - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - BasicConfigurator.Configure(rep, stringAppender); - - ILog log1 = LogManager.GetLogger(rep.Name, "TestLogFormatApi_Info"); - - // *** - log1.Info("TestMessage"); - Assert.AreEqual("INFO:TestMessage", stringAppender.GetString(), "Test simple INFO event 1"); - stringAppender.Reset(); - - // *** - log1.Info("TestMessage", null); - Assert.AreEqual("INFO:TestMessage", stringAppender.GetString(), "Test simple INFO event 2"); - stringAppender.Reset(); - - // *** - log1.Info("TestMessage", new Exception("Exception message")); - Assert.AreEqual("INFO:TestMessageSystem.Exception: Exception message" + Environment.NewLine, stringAppender.GetString(), "Test simple INFO event 3"); - stringAppender.Reset(); - - // *** - log1.InfoFormat("a{0}", "1"); - Assert.AreEqual("INFO:a1", stringAppender.GetString(), "Test formatted INFO event with 1 parm"); - stringAppender.Reset(); - - // *** - log1.InfoFormat("a{0}b{1}", "1", "2"); - Assert.AreEqual("INFO:a1b2", stringAppender.GetString(), "Test formatted INFO event with 2 parm"); - stringAppender.Reset(); - - // *** - log1.InfoFormat("a{0}b{1}c{2}", "1", "2", "3"); - Assert.AreEqual("INFO:a1b2c3", stringAppender.GetString(), "Test formatted INFO event with 3 parm"); - stringAppender.Reset(); - - - // *** - log1.InfoFormat("a{0}b{1}c{2}d{3}e{4}f", "Q", "W", "E", "R", "T", "Y"); - Assert.AreEqual("INFO:aQbWcEdReTf", stringAppender.GetString(), "Test formatted INFO event with 5 parms (only 4 used)"); - stringAppender.Reset(); - - // *** - log1.InfoFormat(null, "Before {0} After {1}", "Middle", "End"); - Assert.AreEqual("INFO:Before Middle After End", stringAppender.GetString(), "Test formatting with null provider"); - stringAppender.Reset(); - - // *** - log1.InfoFormat(new CultureInfo("en"), "Before {0} After {1}", "Middle", "End"); - Assert.AreEqual("INFO:Before Middle After End", stringAppender.GetString(), "Test formatting with 'en' provider"); - stringAppender.Reset(); - } - - [Test] - public void TestLogFormatApi_NoInfo() - { - StringAppender stringAppender = new StringAppender(); - stringAppender.Threshold = Level.Warn; - stringAppender.Layout = new PatternLayout("%level:%message"); - - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - BasicConfigurator.Configure(rep, stringAppender); - - ILog log1 = LogManager.GetLogger(rep.Name, "TestLogFormatApi_Info"); - - // *** - log1.Info("TestMessage"); - Assert.AreEqual("", stringAppender.GetString(), "Test simple INFO event 1"); - stringAppender.Reset(); - - // *** - log1.Info("TestMessage", null); - Assert.AreEqual("", stringAppender.GetString(), "Test simple INFO event 2"); - stringAppender.Reset(); - - // *** - log1.Info("TestMessage", new Exception("Exception message")); - Assert.AreEqual("", stringAppender.GetString(), "Test simple INFO event 3"); - stringAppender.Reset(); - - // *** - log1.InfoFormat("a{0}", "1"); - Assert.AreEqual("", stringAppender.GetString(), "Test formatted INFO event with 1 parm"); - stringAppender.Reset(); - - // *** - log1.InfoFormat("a{0}b{1}", "1", "2"); - Assert.AreEqual("", stringAppender.GetString(), "Test formatted INFO event with 2 parm"); - stringAppender.Reset(); - - // *** - log1.InfoFormat("a{0}b{1}c{2}", "1", "2", "3"); - Assert.AreEqual("", stringAppender.GetString(), "Test formatted INFO event with 3 parm"); - stringAppender.Reset(); - - - // *** - log1.InfoFormat("a{0}b{1}c{2}d{3}e{4}f", "Q", "W", "E", "R", "T", "Y"); - Assert.AreEqual("", stringAppender.GetString(), "Test formatted INFO event with 5 parms (only 4 used)"); - stringAppender.Reset(); - - // *** - log1.InfoFormat(null, "Before {0} After {1}", "Middle", "End"); - Assert.AreEqual("", stringAppender.GetString(), "Test formatting with null provider"); - stringAppender.Reset(); - - // *** - log1.InfoFormat(new CultureInfo("en"), "Before {0} After {1}", "Middle", "End"); - Assert.AreEqual("", stringAppender.GetString(), "Test formatting with 'en' provider"); - stringAppender.Reset(); - } - - - [Test] - public void TestLogFormatApi_Warn() - { - StringAppender stringAppender = new StringAppender(); - stringAppender.Layout = new PatternLayout("%level:%message"); - - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - BasicConfigurator.Configure(rep, stringAppender); - - ILog log1 = LogManager.GetLogger(rep.Name, "TestLogFormatApi_Warn"); - - // *** - log1.Warn("TestMessage"); - Assert.AreEqual("WARN:TestMessage", stringAppender.GetString(), "Test simple WARN event 1"); - stringAppender.Reset(); - - // *** - log1.Warn("TestMessage", null); - Assert.AreEqual("WARN:TestMessage", stringAppender.GetString(), "Test simple WARN event 2"); - stringAppender.Reset(); - - // *** - log1.Warn("TestMessage", new Exception("Exception message")); - Assert.AreEqual("WARN:TestMessageSystem.Exception: Exception message" + Environment.NewLine, stringAppender.GetString(), "Test simple WARN event 3"); - stringAppender.Reset(); - - // *** - log1.WarnFormat("a{0}", "1"); - Assert.AreEqual("WARN:a1", stringAppender.GetString(), "Test formatted WARN event with 1 parm"); - stringAppender.Reset(); - - // *** - log1.WarnFormat("a{0}b{1}", "1", "2"); - Assert.AreEqual("WARN:a1b2", stringAppender.GetString(), "Test formatted WARN event with 2 parm"); - stringAppender.Reset(); - - // *** - log1.WarnFormat("a{0}b{1}c{2}", "1", "2", "3"); - Assert.AreEqual("WARN:a1b2c3", stringAppender.GetString(), "Test formatted WARN event with 3 parm"); - stringAppender.Reset(); - - - // *** - log1.WarnFormat("a{0}b{1}c{2}d{3}e{4}f", "Q", "W", "E", "R", "T", "Y"); - Assert.AreEqual("WARN:aQbWcEdReTf", stringAppender.GetString(), "Test formatted WARN event with 5 parms (only 4 used)"); - stringAppender.Reset(); - - // *** - log1.WarnFormat(null, "Before {0} After {1}", "Middle", "End"); - Assert.AreEqual("WARN:Before Middle After End", stringAppender.GetString(), "Test formatting with null provider"); - stringAppender.Reset(); - - // *** - log1.WarnFormat(new CultureInfo("en"), "Before {0} After {1}", "Middle", "End"); - Assert.AreEqual("WARN:Before Middle After End", stringAppender.GetString(), "Test formatting with 'en' provider"); - stringAppender.Reset(); - } - - [Test] - public void TestLogFormatApi_NoWarn() - { - StringAppender stringAppender = new StringAppender(); - stringAppender.Threshold = Level.Error; - stringAppender.Layout = new PatternLayout("%level:%message"); - - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - BasicConfigurator.Configure(rep, stringAppender); - - ILog log1 = LogManager.GetLogger(rep.Name, "TestLogFormatApi_Warn"); - - // *** - log1.Warn("TestMessage"); - Assert.AreEqual("", stringAppender.GetString(), "Test simple WARN event 1"); - stringAppender.Reset(); - - // *** - log1.Warn("TestMessage", null); - Assert.AreEqual("", stringAppender.GetString(), "Test simple WARN event 2"); - stringAppender.Reset(); - - // *** - log1.Warn("TestMessage", new Exception("Exception message")); - Assert.AreEqual("", stringAppender.GetString(), "Test simple WARN event 3"); - stringAppender.Reset(); - - // *** - log1.WarnFormat("a{0}", "1"); - Assert.AreEqual("", stringAppender.GetString(), "Test formatted WARN event with 1 parm"); - stringAppender.Reset(); - - // *** - log1.WarnFormat("a{0}b{1}", "1", "2"); - Assert.AreEqual("", stringAppender.GetString(), "Test formatted WARN event with 2 parm"); - stringAppender.Reset(); - - // *** - log1.WarnFormat("a{0}b{1}c{2}", "1", "2", "3"); - Assert.AreEqual("", stringAppender.GetString(), "Test formatted WARN event with 3 parm"); - stringAppender.Reset(); - - - // *** - log1.WarnFormat("a{0}b{1}c{2}d{3}e{4}f", "Q", "W", "E", "R", "T", "Y"); - Assert.AreEqual("", stringAppender.GetString(), "Test formatted WARN event with 5 parms (only 4 used)"); - stringAppender.Reset(); - - // *** - log1.WarnFormat(null, "Before {0} After {1}", "Middle", "End"); - Assert.AreEqual("", stringAppender.GetString(), "Test formatting with null provider"); - stringAppender.Reset(); - - // *** - log1.WarnFormat(new CultureInfo("en"), "Before {0} After {1}", "Middle", "End"); - Assert.AreEqual("", stringAppender.GetString(), "Test formatting with 'en' provider"); - stringAppender.Reset(); - } - - - [Test] - public void TestLogFormatApi_Error() - { - StringAppender stringAppender = new StringAppender(); - stringAppender.Layout = new PatternLayout("%level:%message"); - - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - BasicConfigurator.Configure(rep, stringAppender); - - ILog log1 = LogManager.GetLogger(rep.Name, "TestLogFormatApi_Error"); - - // *** - log1.Error("TestMessage"); - Assert.AreEqual("ERROR:TestMessage", stringAppender.GetString(), "Test simple ERROR event 1"); - stringAppender.Reset(); - - // *** - log1.Error("TestMessage", null); - Assert.AreEqual("ERROR:TestMessage", stringAppender.GetString(), "Test simple ERROR event 2"); - stringAppender.Reset(); - - // *** - log1.Error("TestMessage", new Exception("Exception message")); - Assert.AreEqual("ERROR:TestMessageSystem.Exception: Exception message" + Environment.NewLine, stringAppender.GetString(), "Test simple ERROR event 3"); - stringAppender.Reset(); - - // *** - log1.ErrorFormat("a{0}", "1"); - Assert.AreEqual("ERROR:a1", stringAppender.GetString(), "Test formatted ERROR event with 1 parm"); - stringAppender.Reset(); - - // *** - log1.ErrorFormat("a{0}b{1}", "1", "2"); - Assert.AreEqual("ERROR:a1b2", stringAppender.GetString(), "Test formatted ERROR event with 2 parm"); - stringAppender.Reset(); - - // *** - log1.ErrorFormat("a{0}b{1}c{2}", "1", "2", "3"); - Assert.AreEqual("ERROR:a1b2c3", stringAppender.GetString(), "Test formatted ERROR event with 3 parm"); - stringAppender.Reset(); - - - // *** - log1.ErrorFormat("a{0}b{1}c{2}d{3}e{4}f", "Q", "W", "E", "R", "T", "Y"); - Assert.AreEqual("ERROR:aQbWcEdReTf", stringAppender.GetString(), "Test formatted ERROR event with 5 parms (only 4 used)"); - stringAppender.Reset(); - - // *** - log1.ErrorFormat(null, "Before {0} After {1}", "Middle", "End"); - Assert.AreEqual("ERROR:Before Middle After End", stringAppender.GetString(), "Test formatting with null provider"); - stringAppender.Reset(); - - // *** - log1.ErrorFormat(new CultureInfo("en"), "Before {0} After {1}", "Middle", "End"); - Assert.AreEqual("ERROR:Before Middle After End", stringAppender.GetString(), "Test formatting with 'en' provider"); - stringAppender.Reset(); - } - - [Test] - public void TestLogFormatApi_NoError() - { - StringAppender stringAppender = new StringAppender(); - stringAppender.Threshold = Level.Fatal; - stringAppender.Layout = new PatternLayout("%level:%message"); - - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - BasicConfigurator.Configure(rep, stringAppender); - - ILog log1 = LogManager.GetLogger(rep.Name, "TestLogFormatApi_Error"); - - // *** - log1.Error("TestMessage"); - Assert.AreEqual("", stringAppender.GetString(), "Test simple ERROR event 1"); - stringAppender.Reset(); - - // *** - log1.Error("TestMessage", null); - Assert.AreEqual("", stringAppender.GetString(), "Test simple ERROR event 2"); - stringAppender.Reset(); - - // *** - log1.Error("TestMessage", new Exception("Exception message")); - Assert.AreEqual("", stringAppender.GetString(), "Test simple ERROR event 3"); - stringAppender.Reset(); - - // *** - log1.ErrorFormat("a{0}", "1"); - Assert.AreEqual("", stringAppender.GetString(), "Test formatted ERROR event with 1 parm"); - stringAppender.Reset(); - - // *** - log1.ErrorFormat("a{0}b{1}", "1", "2"); - Assert.AreEqual("", stringAppender.GetString(), "Test formatted ERROR event with 2 parm"); - stringAppender.Reset(); - - // *** - log1.ErrorFormat("a{0}b{1}c{2}", "1", "2", "3"); - Assert.AreEqual("", stringAppender.GetString(), "Test formatted ERROR event with 3 parm"); - stringAppender.Reset(); - - - // *** - log1.ErrorFormat("a{0}b{1}c{2}d{3}e{4}f", "Q", "W", "E", "R", "T", "Y"); - Assert.AreEqual("", stringAppender.GetString(), "Test formatted ERROR event with 5 parms (only 4 used)"); - stringAppender.Reset(); - - // *** - log1.ErrorFormat(null, "Before {0} After {1}", "Middle", "End"); - Assert.AreEqual("", stringAppender.GetString(), "Test formatting with null provider"); - stringAppender.Reset(); - - // *** - log1.ErrorFormat(new CultureInfo("en"), "Before {0} After {1}", "Middle", "End"); - Assert.AreEqual("", stringAppender.GetString(), "Test formatting with 'en' provider"); - stringAppender.Reset(); - } - - - [Test] - public void TestLogFormatApi_Fatal() - { - StringAppender stringAppender = new StringAppender(); - stringAppender.Layout = new PatternLayout("%level:%message"); - - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - BasicConfigurator.Configure(rep, stringAppender); - - ILog log1 = LogManager.GetLogger(rep.Name, "TestLogFormatApi_Fatal"); - - // *** - log1.Fatal("TestMessage"); - Assert.AreEqual("FATAL:TestMessage", stringAppender.GetString(), "Test simple FATAL event 1"); - stringAppender.Reset(); - - // *** - log1.Fatal("TestMessage", null); - Assert.AreEqual("FATAL:TestMessage", stringAppender.GetString(), "Test simple FATAL event 2"); - stringAppender.Reset(); - - // *** - log1.Fatal("TestMessage", new Exception("Exception message")); - Assert.AreEqual("FATAL:TestMessageSystem.Exception: Exception message" + Environment.NewLine, stringAppender.GetString(), "Test simple FATAL event 3"); - stringAppender.Reset(); - - // *** - log1.FatalFormat("a{0}", "1"); - Assert.AreEqual("FATAL:a1", stringAppender.GetString(), "Test formatted FATAL event with 1 parm"); - stringAppender.Reset(); - - // *** - log1.FatalFormat("a{0}b{1}", "1", "2"); - Assert.AreEqual("FATAL:a1b2", stringAppender.GetString(), "Test formatted FATAL event with 2 parm"); - stringAppender.Reset(); - - // *** - log1.FatalFormat("a{0}b{1}c{2}", "1", "2", "3"); - Assert.AreEqual("FATAL:a1b2c3", stringAppender.GetString(), "Test formatted FATAL event with 3 parm"); - stringAppender.Reset(); - - - // *** - log1.FatalFormat("a{0}b{1}c{2}d{3}e{4}f", "Q", "W", "E", "R", "T", "Y"); - Assert.AreEqual("FATAL:aQbWcEdReTf", stringAppender.GetString(), "Test formatted FATAL event with 5 parms (only 4 used)"); - stringAppender.Reset(); - - // *** - log1.FatalFormat(null, "Before {0} After {1}", "Middle", "End"); - Assert.AreEqual("FATAL:Before Middle After End", stringAppender.GetString(), "Test formatting with null provider"); - stringAppender.Reset(); - - // *** - log1.FatalFormat(new CultureInfo("en"), "Before {0} After {1}", "Middle", "End"); - Assert.AreEqual("FATAL:Before Middle After End", stringAppender.GetString(), "Test formatting with 'en' provider"); - stringAppender.Reset(); - } - - [Test] - public void TestLogFormatApi_NoFatal() - { - StringAppender stringAppender = new StringAppender(); - stringAppender.Threshold = Level.Off; - stringAppender.Layout = new PatternLayout("%level:%message"); - - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - BasicConfigurator.Configure(rep, stringAppender); - - ILog log1 = LogManager.GetLogger(rep.Name, "TestLogFormatApi_Fatal"); - - // *** - log1.Fatal("TestMessage"); - Assert.AreEqual("", stringAppender.GetString(), "Test simple FATAL event 1"); - stringAppender.Reset(); - - // *** - log1.Fatal("TestMessage", null); - Assert.AreEqual("", stringAppender.GetString(), "Test simple FATAL event 2"); - stringAppender.Reset(); - - // *** - log1.Fatal("TestMessage", new Exception("Exception message")); - Assert.AreEqual("", stringAppender.GetString(), "Test simple FATAL event 3"); - stringAppender.Reset(); - - // *** - log1.FatalFormat("a{0}", "1"); - Assert.AreEqual("", stringAppender.GetString(), "Test formatted FATAL event with 1 parm"); - stringAppender.Reset(); - - // *** - log1.FatalFormat("a{0}b{1}", "1", "2"); - Assert.AreEqual("", stringAppender.GetString(), "Test formatted FATAL event with 2 parm"); - stringAppender.Reset(); - - // *** - log1.FatalFormat("a{0}b{1}c{2}", "1", "2", "3"); - Assert.AreEqual("", stringAppender.GetString(), "Test formatted FATAL event with 3 parm"); - stringAppender.Reset(); - - - // *** - log1.FatalFormat("a{0}b{1}c{2}d{3}e{4}f", "Q", "W", "E", "R", "T", "Y"); - Assert.AreEqual("", stringAppender.GetString(), "Test formatted FATAL event with 5 parms (only 4 used)"); - stringAppender.Reset(); - - // *** - log1.FatalFormat(null, "Before {0} After {1}", "Middle", "End"); - Assert.AreEqual("", stringAppender.GetString(), "Test formatting with null provider"); - stringAppender.Reset(); - - // *** - log1.FatalFormat(new CultureInfo("en"), "Before {0} After {1}", "Middle", "End"); - Assert.AreEqual("", stringAppender.GetString(), "Test formatting with 'en' provider"); - stringAppender.Reset(); - } - } + + // *** + log1.InfoFormat("Before {0} After {1}", "Middle", "End"); + Assert.AreEqual("Before Middle After End", stringAppender.GetString(), "Test simple formatted INFO event 2"); + stringAppender.Reset(); + + // *** + log1.InfoFormat("IGNORE THIS WARNING - EXCEPTION EXPECTED Before {0} After {1} {2}", "Middle", "End"); + Assert.AreEqual(STRING_FORMAT_ERROR, stringAppender.GetString(), "Test formatting error"); + stringAppender.Reset(); + } + + private const string STRING_FORMAT_ERROR = "Exception during StringFormat: Index (zero based) must be greater than or equal to zero and less than the size of the argument list. IGNORE THIS WARNING - EXCEPTION EXPECTED Before {0} After {1} {2}{Middle, End}"; + + + [Test] + public void TestLogFormatApi_Debug() + { + StringAppender stringAppender = new StringAppender(); + stringAppender.Layout = new PatternLayout("%level:%message"); + + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + BasicConfigurator.Configure(rep, stringAppender); + + ILog log1 = LogManager.GetLogger(rep.Name, "TestLogFormatApi_Debug"); + + // *** + log1.Debug("TestMessage"); + Assert.AreEqual("DEBUG:TestMessage", stringAppender.GetString(), "Test simple DEBUG event 1"); + stringAppender.Reset(); + + // *** + log1.Debug("TestMessage", null); + Assert.AreEqual("DEBUG:TestMessage", stringAppender.GetString(), "Test simple DEBUG event 2"); + stringAppender.Reset(); + + // *** + log1.Debug("TestMessage", new Exception("Exception message")); + Assert.AreEqual("DEBUG:TestMessageSystem.Exception: Exception message" + Environment.NewLine, stringAppender.GetString(), "Test simple DEBUG event 3"); + stringAppender.Reset(); + + // *** + log1.DebugFormat("a{0}", "1"); + Assert.AreEqual("DEBUG:a1", stringAppender.GetString(), "Test formatted DEBUG event with 1 parm"); + stringAppender.Reset(); + + // *** + log1.DebugFormat("a{0}b{1}", "1", "2"); + Assert.AreEqual("DEBUG:a1b2", stringAppender.GetString(), "Test formatted DEBUG event with 2 parm"); + stringAppender.Reset(); + + // *** + log1.DebugFormat("a{0}b{1}c{2}", "1", "2", "3"); + Assert.AreEqual("DEBUG:a1b2c3", stringAppender.GetString(), "Test formatted DEBUG event with 3 parm"); + stringAppender.Reset(); + + + // *** + log1.DebugFormat("a{0}b{1}c{2}d{3}e{4}f", "Q", "W", "E", "R", "T", "Y"); + Assert.AreEqual("DEBUG:aQbWcEdReTf", stringAppender.GetString(), "Test formatted DEBUG event with 5 parms (only 4 used)"); + stringAppender.Reset(); + + // *** + log1.DebugFormat(null, "Before {0} After {1}", "Middle", "End"); + Assert.AreEqual("DEBUG:Before Middle After End", stringAppender.GetString(), "Test formatting with null provider"); + stringAppender.Reset(); + + // *** + log1.DebugFormat(new CultureInfo("en"), "Before {0} After {1}", "Middle", "End"); + Assert.AreEqual("DEBUG:Before Middle After End", stringAppender.GetString(), "Test formatting with 'en' provider"); + stringAppender.Reset(); + } + + [Test] + public void TestLogFormatApi_NoDebug() + { + StringAppender stringAppender = new StringAppender(); + stringAppender.Threshold = Level.Info; + stringAppender.Layout = new PatternLayout("%level:%message"); + + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + BasicConfigurator.Configure(rep, stringAppender); + + ILog log1 = LogManager.GetLogger(rep.Name, "TestLogFormatApi_Debug"); + + // *** + log1.Debug("TestMessage"); + Assert.AreEqual("", stringAppender.GetString(), "Test simple DEBUG event 1"); + stringAppender.Reset(); + + // *** + log1.Debug("TestMessage", null); + Assert.AreEqual("", stringAppender.GetString(), "Test simple DEBUG event 2"); + stringAppender.Reset(); + + // *** + log1.Debug("TestMessage", new Exception("Exception message")); + Assert.AreEqual("", stringAppender.GetString(), "Test simple DEBUG event 3"); + stringAppender.Reset(); + + // *** + log1.DebugFormat("a{0}", "1"); + Assert.AreEqual("", stringAppender.GetString(), "Test formatted DEBUG event with 1 parm"); + stringAppender.Reset(); + + // *** + log1.DebugFormat("a{0}b{1}", "1", "2"); + Assert.AreEqual("", stringAppender.GetString(), "Test formatted DEBUG event with 2 parm"); + stringAppender.Reset(); + + // *** + log1.DebugFormat("a{0}b{1}c{2}", "1", "2", "3"); + Assert.AreEqual("", stringAppender.GetString(), "Test formatted DEBUG event with 3 parm"); + stringAppender.Reset(); + + + // *** + log1.DebugFormat("a{0}b{1}c{2}d{3}e{4}f", "Q", "W", "E", "R", "T", "Y"); + Assert.AreEqual("", stringAppender.GetString(), "Test formatted DEBUG event with 5 parms (only 4 used)"); + stringAppender.Reset(); + + // *** + log1.DebugFormat(null, "Before {0} After {1}", "Middle", "End"); + Assert.AreEqual("", stringAppender.GetString(), "Test formatting with null provider"); + stringAppender.Reset(); + + // *** + log1.DebugFormat(new CultureInfo("en"), "Before {0} After {1}", "Middle", "End"); + Assert.AreEqual("", stringAppender.GetString(), "Test formatting with 'en' provider"); + stringAppender.Reset(); + } + + + [Test] + public void TestLogFormatApi_Info() + { + StringAppender stringAppender = new StringAppender(); + stringAppender.Layout = new PatternLayout("%level:%message"); + + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + BasicConfigurator.Configure(rep, stringAppender); + + ILog log1 = LogManager.GetLogger(rep.Name, "TestLogFormatApi_Info"); + + // *** + log1.Info("TestMessage"); + Assert.AreEqual("INFO:TestMessage", stringAppender.GetString(), "Test simple INFO event 1"); + stringAppender.Reset(); + + // *** + log1.Info("TestMessage", null); + Assert.AreEqual("INFO:TestMessage", stringAppender.GetString(), "Test simple INFO event 2"); + stringAppender.Reset(); + + // *** + log1.Info("TestMessage", new Exception("Exception message")); + Assert.AreEqual("INFO:TestMessageSystem.Exception: Exception message" + Environment.NewLine, stringAppender.GetString(), "Test simple INFO event 3"); + stringAppender.Reset(); + + // *** + log1.InfoFormat("a{0}", "1"); + Assert.AreEqual("INFO:a1", stringAppender.GetString(), "Test formatted INFO event with 1 parm"); + stringAppender.Reset(); + + // *** + log1.InfoFormat("a{0}b{1}", "1", "2"); + Assert.AreEqual("INFO:a1b2", stringAppender.GetString(), "Test formatted INFO event with 2 parm"); + stringAppender.Reset(); + + // *** + log1.InfoFormat("a{0}b{1}c{2}", "1", "2", "3"); + Assert.AreEqual("INFO:a1b2c3", stringAppender.GetString(), "Test formatted INFO event with 3 parm"); + stringAppender.Reset(); + + + // *** + log1.InfoFormat("a{0}b{1}c{2}d{3}e{4}f", "Q", "W", "E", "R", "T", "Y"); + Assert.AreEqual("INFO:aQbWcEdReTf", stringAppender.GetString(), "Test formatted INFO event with 5 parms (only 4 used)"); + stringAppender.Reset(); + + // *** + log1.InfoFormat(null, "Before {0} After {1}", "Middle", "End"); + Assert.AreEqual("INFO:Before Middle After End", stringAppender.GetString(), "Test formatting with null provider"); + stringAppender.Reset(); + + // *** + log1.InfoFormat(new CultureInfo("en"), "Before {0} After {1}", "Middle", "End"); + Assert.AreEqual("INFO:Before Middle After End", stringAppender.GetString(), "Test formatting with 'en' provider"); + stringAppender.Reset(); + } + + [Test] + public void TestLogFormatApi_NoInfo() + { + StringAppender stringAppender = new StringAppender(); + stringAppender.Threshold = Level.Warn; + stringAppender.Layout = new PatternLayout("%level:%message"); + + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + BasicConfigurator.Configure(rep, stringAppender); + + ILog log1 = LogManager.GetLogger(rep.Name, "TestLogFormatApi_Info"); + + // *** + log1.Info("TestMessage"); + Assert.AreEqual("", stringAppender.GetString(), "Test simple INFO event 1"); + stringAppender.Reset(); + + // *** + log1.Info("TestMessage", null); + Assert.AreEqual("", stringAppender.GetString(), "Test simple INFO event 2"); + stringAppender.Reset(); + + // *** + log1.Info("TestMessage", new Exception("Exception message")); + Assert.AreEqual("", stringAppender.GetString(), "Test simple INFO event 3"); + stringAppender.Reset(); + + // *** + log1.InfoFormat("a{0}", "1"); + Assert.AreEqual("", stringAppender.GetString(), "Test formatted INFO event with 1 parm"); + stringAppender.Reset(); + + // *** + log1.InfoFormat("a{0}b{1}", "1", "2"); + Assert.AreEqual("", stringAppender.GetString(), "Test formatted INFO event with 2 parm"); + stringAppender.Reset(); + + // *** + log1.InfoFormat("a{0}b{1}c{2}", "1", "2", "3"); + Assert.AreEqual("", stringAppender.GetString(), "Test formatted INFO event with 3 parm"); + stringAppender.Reset(); + + + // *** + log1.InfoFormat("a{0}b{1}c{2}d{3}e{4}f", "Q", "W", "E", "R", "T", "Y"); + Assert.AreEqual("", stringAppender.GetString(), "Test formatted INFO event with 5 parms (only 4 used)"); + stringAppender.Reset(); + + // *** + log1.InfoFormat(null, "Before {0} After {1}", "Middle", "End"); + Assert.AreEqual("", stringAppender.GetString(), "Test formatting with null provider"); + stringAppender.Reset(); + + // *** + log1.InfoFormat(new CultureInfo("en"), "Before {0} After {1}", "Middle", "End"); + Assert.AreEqual("", stringAppender.GetString(), "Test formatting with 'en' provider"); + stringAppender.Reset(); + } + + + [Test] + public void TestLogFormatApi_Warn() + { + StringAppender stringAppender = new StringAppender(); + stringAppender.Layout = new PatternLayout("%level:%message"); + + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + BasicConfigurator.Configure(rep, stringAppender); + + ILog log1 = LogManager.GetLogger(rep.Name, "TestLogFormatApi_Warn"); + + // *** + log1.Warn("TestMessage"); + Assert.AreEqual("WARN:TestMessage", stringAppender.GetString(), "Test simple WARN event 1"); + stringAppender.Reset(); + + // *** + log1.Warn("TestMessage", null); + Assert.AreEqual("WARN:TestMessage", stringAppender.GetString(), "Test simple WARN event 2"); + stringAppender.Reset(); + + // *** + log1.Warn("TestMessage", new Exception("Exception message")); + Assert.AreEqual("WARN:TestMessageSystem.Exception: Exception message" + Environment.NewLine, stringAppender.GetString(), "Test simple WARN event 3"); + stringAppender.Reset(); + + // *** + log1.WarnFormat("a{0}", "1"); + Assert.AreEqual("WARN:a1", stringAppender.GetString(), "Test formatted WARN event with 1 parm"); + stringAppender.Reset(); + + // *** + log1.WarnFormat("a{0}b{1}", "1", "2"); + Assert.AreEqual("WARN:a1b2", stringAppender.GetString(), "Test formatted WARN event with 2 parm"); + stringAppender.Reset(); + + // *** + log1.WarnFormat("a{0}b{1}c{2}", "1", "2", "3"); + Assert.AreEqual("WARN:a1b2c3", stringAppender.GetString(), "Test formatted WARN event with 3 parm"); + stringAppender.Reset(); + + + // *** + log1.WarnFormat("a{0}b{1}c{2}d{3}e{4}f", "Q", "W", "E", "R", "T", "Y"); + Assert.AreEqual("WARN:aQbWcEdReTf", stringAppender.GetString(), "Test formatted WARN event with 5 parms (only 4 used)"); + stringAppender.Reset(); + + // *** + log1.WarnFormat(null, "Before {0} After {1}", "Middle", "End"); + Assert.AreEqual("WARN:Before Middle After End", stringAppender.GetString(), "Test formatting with null provider"); + stringAppender.Reset(); + + // *** + log1.WarnFormat(new CultureInfo("en"), "Before {0} After {1}", "Middle", "End"); + Assert.AreEqual("WARN:Before Middle After End", stringAppender.GetString(), "Test formatting with 'en' provider"); + stringAppender.Reset(); + } + + [Test] + public void TestLogFormatApi_NoWarn() + { + StringAppender stringAppender = new StringAppender(); + stringAppender.Threshold = Level.Error; + stringAppender.Layout = new PatternLayout("%level:%message"); + + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + BasicConfigurator.Configure(rep, stringAppender); + + ILog log1 = LogManager.GetLogger(rep.Name, "TestLogFormatApi_Warn"); + + // *** + log1.Warn("TestMessage"); + Assert.AreEqual("", stringAppender.GetString(), "Test simple WARN event 1"); + stringAppender.Reset(); + + // *** + log1.Warn("TestMessage", null); + Assert.AreEqual("", stringAppender.GetString(), "Test simple WARN event 2"); + stringAppender.Reset(); + + // *** + log1.Warn("TestMessage", new Exception("Exception message")); + Assert.AreEqual("", stringAppender.GetString(), "Test simple WARN event 3"); + stringAppender.Reset(); + + // *** + log1.WarnFormat("a{0}", "1"); + Assert.AreEqual("", stringAppender.GetString(), "Test formatted WARN event with 1 parm"); + stringAppender.Reset(); + + // *** + log1.WarnFormat("a{0}b{1}", "1", "2"); + Assert.AreEqual("", stringAppender.GetString(), "Test formatted WARN event with 2 parm"); + stringAppender.Reset(); + + // *** + log1.WarnFormat("a{0}b{1}c{2}", "1", "2", "3"); + Assert.AreEqual("", stringAppender.GetString(), "Test formatted WARN event with 3 parm"); + stringAppender.Reset(); + + + // *** + log1.WarnFormat("a{0}b{1}c{2}d{3}e{4}f", "Q", "W", "E", "R", "T", "Y"); + Assert.AreEqual("", stringAppender.GetString(), "Test formatted WARN event with 5 parms (only 4 used)"); + stringAppender.Reset(); + + // *** + log1.WarnFormat(null, "Before {0} After {1}", "Middle", "End"); + Assert.AreEqual("", stringAppender.GetString(), "Test formatting with null provider"); + stringAppender.Reset(); + + // *** + log1.WarnFormat(new CultureInfo("en"), "Before {0} After {1}", "Middle", "End"); + Assert.AreEqual("", stringAppender.GetString(), "Test formatting with 'en' provider"); + stringAppender.Reset(); + } + + + [Test] + public void TestLogFormatApi_Error() + { + StringAppender stringAppender = new StringAppender(); + stringAppender.Layout = new PatternLayout("%level:%message"); + + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + BasicConfigurator.Configure(rep, stringAppender); + + ILog log1 = LogManager.GetLogger(rep.Name, "TestLogFormatApi_Error"); + + // *** + log1.Error("TestMessage"); + Assert.AreEqual("ERROR:TestMessage", stringAppender.GetString(), "Test simple ERROR event 1"); + stringAppender.Reset(); + + // *** + log1.Error("TestMessage", null); + Assert.AreEqual("ERROR:TestMessage", stringAppender.GetString(), "Test simple ERROR event 2"); + stringAppender.Reset(); + + // *** + log1.Error("TestMessage", new Exception("Exception message")); + Assert.AreEqual("ERROR:TestMessageSystem.Exception: Exception message" + Environment.NewLine, stringAppender.GetString(), "Test simple ERROR event 3"); + stringAppender.Reset(); + + // *** + log1.ErrorFormat("a{0}", "1"); + Assert.AreEqual("ERROR:a1", stringAppender.GetString(), "Test formatted ERROR event with 1 parm"); + stringAppender.Reset(); + + // *** + log1.ErrorFormat("a{0}b{1}", "1", "2"); + Assert.AreEqual("ERROR:a1b2", stringAppender.GetString(), "Test formatted ERROR event with 2 parm"); + stringAppender.Reset(); + + // *** + log1.ErrorFormat("a{0}b{1}c{2}", "1", "2", "3"); + Assert.AreEqual("ERROR:a1b2c3", stringAppender.GetString(), "Test formatted ERROR event with 3 parm"); + stringAppender.Reset(); + + + // *** + log1.ErrorFormat("a{0}b{1}c{2}d{3}e{4}f", "Q", "W", "E", "R", "T", "Y"); + Assert.AreEqual("ERROR:aQbWcEdReTf", stringAppender.GetString(), "Test formatted ERROR event with 5 parms (only 4 used)"); + stringAppender.Reset(); + + // *** + log1.ErrorFormat(null, "Before {0} After {1}", "Middle", "End"); + Assert.AreEqual("ERROR:Before Middle After End", stringAppender.GetString(), "Test formatting with null provider"); + stringAppender.Reset(); + + // *** + log1.ErrorFormat(new CultureInfo("en"), "Before {0} After {1}", "Middle", "End"); + Assert.AreEqual("ERROR:Before Middle After End", stringAppender.GetString(), "Test formatting with 'en' provider"); + stringAppender.Reset(); + } + + [Test] + public void TestLogFormatApi_NoError() + { + StringAppender stringAppender = new StringAppender(); + stringAppender.Threshold = Level.Fatal; + stringAppender.Layout = new PatternLayout("%level:%message"); + + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + BasicConfigurator.Configure(rep, stringAppender); + + ILog log1 = LogManager.GetLogger(rep.Name, "TestLogFormatApi_Error"); + + // *** + log1.Error("TestMessage"); + Assert.AreEqual("", stringAppender.GetString(), "Test simple ERROR event 1"); + stringAppender.Reset(); + + // *** + log1.Error("TestMessage", null); + Assert.AreEqual("", stringAppender.GetString(), "Test simple ERROR event 2"); + stringAppender.Reset(); + + // *** + log1.Error("TestMessage", new Exception("Exception message")); + Assert.AreEqual("", stringAppender.GetString(), "Test simple ERROR event 3"); + stringAppender.Reset(); + + // *** + log1.ErrorFormat("a{0}", "1"); + Assert.AreEqual("", stringAppender.GetString(), "Test formatted ERROR event with 1 parm"); + stringAppender.Reset(); + + // *** + log1.ErrorFormat("a{0}b{1}", "1", "2"); + Assert.AreEqual("", stringAppender.GetString(), "Test formatted ERROR event with 2 parm"); + stringAppender.Reset(); + + // *** + log1.ErrorFormat("a{0}b{1}c{2}", "1", "2", "3"); + Assert.AreEqual("", stringAppender.GetString(), "Test formatted ERROR event with 3 parm"); + stringAppender.Reset(); + + + // *** + log1.ErrorFormat("a{0}b{1}c{2}d{3}e{4}f", "Q", "W", "E", "R", "T", "Y"); + Assert.AreEqual("", stringAppender.GetString(), "Test formatted ERROR event with 5 parms (only 4 used)"); + stringAppender.Reset(); + + // *** + log1.ErrorFormat(null, "Before {0} After {1}", "Middle", "End"); + Assert.AreEqual("", stringAppender.GetString(), "Test formatting with null provider"); + stringAppender.Reset(); + + // *** + log1.ErrorFormat(new CultureInfo("en"), "Before {0} After {1}", "Middle", "End"); + Assert.AreEqual("", stringAppender.GetString(), "Test formatting with 'en' provider"); + stringAppender.Reset(); + } + + + [Test] + public void TestLogFormatApi_Fatal() + { + StringAppender stringAppender = new StringAppender(); + stringAppender.Layout = new PatternLayout("%level:%message"); + + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + BasicConfigurator.Configure(rep, stringAppender); + + ILog log1 = LogManager.GetLogger(rep.Name, "TestLogFormatApi_Fatal"); + + // *** + log1.Fatal("TestMessage"); + Assert.AreEqual("FATAL:TestMessage", stringAppender.GetString(), "Test simple FATAL event 1"); + stringAppender.Reset(); + + // *** + log1.Fatal("TestMessage", null); + Assert.AreEqual("FATAL:TestMessage", stringAppender.GetString(), "Test simple FATAL event 2"); + stringAppender.Reset(); + + // *** + log1.Fatal("TestMessage", new Exception("Exception message")); + Assert.AreEqual("FATAL:TestMessageSystem.Exception: Exception message" + Environment.NewLine, stringAppender.GetString(), "Test simple FATAL event 3"); + stringAppender.Reset(); + + // *** + log1.FatalFormat("a{0}", "1"); + Assert.AreEqual("FATAL:a1", stringAppender.GetString(), "Test formatted FATAL event with 1 parm"); + stringAppender.Reset(); + + // *** + log1.FatalFormat("a{0}b{1}", "1", "2"); + Assert.AreEqual("FATAL:a1b2", stringAppender.GetString(), "Test formatted FATAL event with 2 parm"); + stringAppender.Reset(); + + // *** + log1.FatalFormat("a{0}b{1}c{2}", "1", "2", "3"); + Assert.AreEqual("FATAL:a1b2c3", stringAppender.GetString(), "Test formatted FATAL event with 3 parm"); + stringAppender.Reset(); + + + // *** + log1.FatalFormat("a{0}b{1}c{2}d{3}e{4}f", "Q", "W", "E", "R", "T", "Y"); + Assert.AreEqual("FATAL:aQbWcEdReTf", stringAppender.GetString(), "Test formatted FATAL event with 5 parms (only 4 used)"); + stringAppender.Reset(); + + // *** + log1.FatalFormat(null, "Before {0} After {1}", "Middle", "End"); + Assert.AreEqual("FATAL:Before Middle After End", stringAppender.GetString(), "Test formatting with null provider"); + stringAppender.Reset(); + + // *** + log1.FatalFormat(new CultureInfo("en"), "Before {0} After {1}", "Middle", "End"); + Assert.AreEqual("FATAL:Before Middle After End", stringAppender.GetString(), "Test formatting with 'en' provider"); + stringAppender.Reset(); + } + + [Test] + public void TestLogFormatApi_NoFatal() + { + StringAppender stringAppender = new StringAppender(); + stringAppender.Threshold = Level.Off; + stringAppender.Layout = new PatternLayout("%level:%message"); + + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + BasicConfigurator.Configure(rep, stringAppender); + + ILog log1 = LogManager.GetLogger(rep.Name, "TestLogFormatApi_Fatal"); + + // *** + log1.Fatal("TestMessage"); + Assert.AreEqual("", stringAppender.GetString(), "Test simple FATAL event 1"); + stringAppender.Reset(); + + // *** + log1.Fatal("TestMessage", null); + Assert.AreEqual("", stringAppender.GetString(), "Test simple FATAL event 2"); + stringAppender.Reset(); + + // *** + log1.Fatal("TestMessage", new Exception("Exception message")); + Assert.AreEqual("", stringAppender.GetString(), "Test simple FATAL event 3"); + stringAppender.Reset(); + + // *** + log1.FatalFormat("a{0}", "1"); + Assert.AreEqual("", stringAppender.GetString(), "Test formatted FATAL event with 1 parm"); + stringAppender.Reset(); + + // *** + log1.FatalFormat("a{0}b{1}", "1", "2"); + Assert.AreEqual("", stringAppender.GetString(), "Test formatted FATAL event with 2 parm"); + stringAppender.Reset(); + + // *** + log1.FatalFormat("a{0}b{1}c{2}", "1", "2", "3"); + Assert.AreEqual("", stringAppender.GetString(), "Test formatted FATAL event with 3 parm"); + stringAppender.Reset(); + + + // *** + log1.FatalFormat("a{0}b{1}c{2}d{3}e{4}f", "Q", "W", "E", "R", "T", "Y"); + Assert.AreEqual("", stringAppender.GetString(), "Test formatted FATAL event with 5 parms (only 4 used)"); + stringAppender.Reset(); + + // *** + log1.FatalFormat(null, "Before {0} After {1}", "Middle", "End"); + Assert.AreEqual("", stringAppender.GetString(), "Test formatting with null provider"); + stringAppender.Reset(); + + // *** + log1.FatalFormat(new CultureInfo("en"), "Before {0} After {1}", "Middle", "End"); + Assert.AreEqual("", stringAppender.GetString(), "Test formatting with 'en' provider"); + stringAppender.Reset(); + } + } } \ No newline at end of file diff --git a/src/log4net.Tests/Hierarchy/Hierarchy.cs b/src/log4net.Tests/Hierarchy/Hierarchy.cs index 3755d7bb..7daa95ec 100644 --- a/src/log4net.Tests/Hierarchy/Hierarchy.cs +++ b/src/log4net.Tests/Hierarchy/Hierarchy.cs @@ -100,7 +100,7 @@ public void AddingMultipleAppenders2() } [Test] - // LOG4NET-343 + // LOG4NET-343 public void LoggerNameCanConsistOfASingleDot() { XmlDocument log4netConfig = new XmlDocument(); diff --git a/src/log4net.Tests/Hierarchy/Logger.cs b/src/log4net.Tests/Hierarchy/Logger.cs index aa51d896..3d383f7f 100644 --- a/src/log4net.Tests/Hierarchy/Logger.cs +++ b/src/log4net.Tests/Hierarchy/Logger.cs @@ -30,291 +30,291 @@ namespace log4net.Tests.Hierarchy { - /// - /// Used for internal unit testing the class. - /// - /// - /// Internal unit test. Uses the NUnit test harness. - /// - [TestFixture] - public class LoggerTest - { - private Logger log; - - // A short message. - private static string MSG = "M"; - - /// - /// Any initialization that happens before each test can - /// go here - /// - [SetUp] - public void SetUp() - { - } - - /// - /// Any steps that happen after each test go here - /// - [TearDown] - public void TearDown() - { - // Regular users should not use the clear method lightly! - Utils.GetRepository().ResetConfiguration(); - Utils.GetRepository().Shutdown(); - ((Repository.Hierarchy.Hierarchy)Utils.GetRepository()).Clear(); - } - - /// - /// Add an appender and see if it can be retrieved. - /// - [Test] - public void TestAppender1() - { - log = (Logger)Utils.GetLogger("test").Logger; - CountingAppender a1 = new CountingAppender(); - a1.Name = "testAppender1"; - log.AddAppender(a1); - - IEnumerator enumAppenders = ((IEnumerable)log.Appenders).GetEnumerator(); - Assert.IsTrue(enumAppenders.MoveNext()); - CountingAppender aHat = (CountingAppender)enumAppenders.Current; - Assert.AreEqual(a1, aHat); - } - - /// - /// Add an appender X, Y, remove X and check if Y is the only - /// remaining appender. - /// - [Test] - public void TestAppender2() - { - CountingAppender a1 = new CountingAppender(); - a1.Name = "testAppender2.1"; - CountingAppender a2 = new CountingAppender(); - a2.Name = "testAppender2.2"; - - log = (Logger)Utils.GetLogger("test").Logger; - log.AddAppender(a1); - log.AddAppender(a2); - - CountingAppender aHat = (CountingAppender)log.GetAppender(a1.Name); - Assert.AreEqual(a1, aHat); - - aHat = (CountingAppender)log.GetAppender(a2.Name); - Assert.AreEqual(a2, aHat); - - log.RemoveAppender("testAppender2.1"); - - IEnumerator enumAppenders = ((IEnumerable)log.Appenders).GetEnumerator(); - Assert.IsTrue(enumAppenders.MoveNext()); - aHat = (CountingAppender)enumAppenders.Current; - Assert.AreEqual(a2, aHat); - Assert.IsTrue(!enumAppenders.MoveNext()); - - aHat = (CountingAppender)log.GetAppender(a2.Name); - Assert.AreEqual(a2, aHat); - } - - /// - /// Test if logger a.b inherits its appender from a. - /// - [Test] - public void TestAdditivity1() - { - Logger a = (Logger)Utils.GetLogger("a").Logger; - Logger ab = (Logger)Utils.GetLogger("a.b").Logger; - CountingAppender ca = new CountingAppender(); - - a.AddAppender(ca); - a.Repository.Configured = true; - - Assert.AreEqual(ca.Counter, 0); - ab.Log(Level.Debug, MSG, null); - Assert.AreEqual(ca.Counter, 1); - ab.Log(Level.Info, MSG, null); - Assert.AreEqual(ca.Counter, 2); - ab.Log(Level.Warn, MSG, null); - Assert.AreEqual(ca.Counter, 3); - ab.Log(Level.Error, MSG, null); - Assert.AreEqual(ca.Counter, 4); - } - - /// - /// Test multiple additivity. - /// - [Test] - public void TestAdditivity2() - { - Logger a = (Logger)Utils.GetLogger("a").Logger; - Logger ab = (Logger)Utils.GetLogger("a.b").Logger; - Logger abc = (Logger)Utils.GetLogger("a.b.c").Logger; - Logger x = (Logger)Utils.GetLogger("x").Logger; - - CountingAppender ca1 = new CountingAppender(); - CountingAppender ca2 = new CountingAppender(); - - a.AddAppender(ca1); - abc.AddAppender(ca2); - a.Repository.Configured = true; - - Assert.AreEqual(ca1.Counter, 0); - Assert.AreEqual(ca2.Counter, 0); - - ab.Log(Level.Debug, MSG, null); - Assert.AreEqual(ca1.Counter, 1); - Assert.AreEqual(ca2.Counter, 0); - - abc.Log(Level.Debug, MSG, null); - Assert.AreEqual(ca1.Counter, 2); - Assert.AreEqual(ca2.Counter, 1); - - x.Log(Level.Debug, MSG, null); - Assert.AreEqual(ca1.Counter, 2); - Assert.AreEqual(ca2.Counter, 1); - } - - /// - /// Test additivity flag. - /// - [Test] - public void TestAdditivity3() - { - Logger root = ((Repository.Hierarchy.Hierarchy)Utils.GetRepository()).Root; - Logger a = (Logger)Utils.GetLogger("a").Logger; - Logger ab = (Logger)Utils.GetLogger("a.b").Logger; - Logger abc = (Logger)Utils.GetLogger("a.b.c").Logger; - - CountingAppender caRoot = new CountingAppender(); - CountingAppender caA = new CountingAppender(); - CountingAppender caABC = new CountingAppender(); - - root.AddAppender(caRoot); - a.AddAppender(caA); - abc.AddAppender(caABC); - a.Repository.Configured = true; - - Assert.AreEqual(caRoot.Counter, 0); - Assert.AreEqual(caA.Counter, 0); - Assert.AreEqual(caABC.Counter, 0); - - ab.Additivity = false; - - a.Log(Level.Debug, MSG, null); - Assert.AreEqual(caRoot.Counter, 1); - Assert.AreEqual(caA.Counter, 1); - Assert.AreEqual(caABC.Counter, 0); - - ab.Log(Level.Debug, MSG, null); - Assert.AreEqual(caRoot.Counter, 1); - Assert.AreEqual(caA.Counter, 1); - Assert.AreEqual(caABC.Counter, 0); - - abc.Log(Level.Debug, MSG, null); - Assert.AreEqual(caRoot.Counter, 1); - Assert.AreEqual(caA.Counter, 1); - Assert.AreEqual(caABC.Counter, 1); - } - - /// - /// Test the ability to disable a level of message - /// - [Test] - public void TestDisable1() - { - CountingAppender caRoot = new CountingAppender(); - Logger root = ((Repository.Hierarchy.Hierarchy)Utils.GetRepository()).Root; - root.AddAppender(caRoot); - - Repository.Hierarchy.Hierarchy h = ((Repository.Hierarchy.Hierarchy)Utils.GetRepository()); - h.Threshold = Level.Info; - h.Configured = true; - - Assert.AreEqual(caRoot.Counter, 0); - - root.Log(Level.Debug, MSG, null); - Assert.AreEqual(caRoot.Counter, 0); - root.Log(Level.Info, MSG, null); - Assert.AreEqual(caRoot.Counter, 1); - root.Log(Level.Warn, MSG, null); - Assert.AreEqual(caRoot.Counter, 2); - root.Log(Level.Warn, MSG, null); - Assert.AreEqual(caRoot.Counter, 3); - - h.Threshold = Level.Warn; - root.Log(Level.Debug, MSG, null); - Assert.AreEqual(caRoot.Counter, 3); - root.Log(Level.Info, MSG, null); - Assert.AreEqual(caRoot.Counter, 3); - root.Log(Level.Warn, MSG, null); - Assert.AreEqual(caRoot.Counter, 4); - root.Log(Level.Error, MSG, null); - Assert.AreEqual(caRoot.Counter, 5); - root.Log(Level.Error, MSG, null); - Assert.AreEqual(caRoot.Counter, 6); - - h.Threshold = Level.Off; - root.Log(Level.Debug, MSG, null); - Assert.AreEqual(caRoot.Counter, 6); - root.Log(Level.Info, MSG, null); - Assert.AreEqual(caRoot.Counter, 6); - root.Log(Level.Warn, MSG, null); - Assert.AreEqual(caRoot.Counter, 6); - root.Log(Level.Error, MSG, null); - Assert.AreEqual(caRoot.Counter, 6); - root.Log(Level.Fatal, MSG, null); - Assert.AreEqual(caRoot.Counter, 6); - root.Log(Level.Fatal, MSG, null); - Assert.AreEqual(caRoot.Counter, 6); - } - - /// - /// Tests the Exists method of the Logger class - /// - [Test] - public void TestExists() - { - object a = Utils.GetLogger("a"); - object a_b = Utils.GetLogger("a.b"); - object a_b_c = Utils.GetLogger("a.b.c"); - - object t; + /// + /// Used for internal unit testing the class. + /// + /// + /// Internal unit test. Uses the NUnit test harness. + /// + [TestFixture] + public class LoggerTest + { + private Logger log; + + // A short message. + private static string MSG = "M"; + + /// + /// Any initialization that happens before each test can + /// go here + /// + [SetUp] + public void SetUp() + { + } + + /// + /// Any steps that happen after each test go here + /// + [TearDown] + public void TearDown() + { + // Regular users should not use the clear method lightly! + Utils.GetRepository().ResetConfiguration(); + Utils.GetRepository().Shutdown(); + ((Repository.Hierarchy.Hierarchy)Utils.GetRepository()).Clear(); + } + + /// + /// Add an appender and see if it can be retrieved. + /// + [Test] + public void TestAppender1() + { + log = (Logger)Utils.GetLogger("test").Logger; + CountingAppender a1 = new CountingAppender(); + a1.Name = "testAppender1"; + log.AddAppender(a1); + + IEnumerator enumAppenders = ((IEnumerable)log.Appenders).GetEnumerator(); + Assert.IsTrue(enumAppenders.MoveNext()); + CountingAppender aHat = (CountingAppender)enumAppenders.Current; + Assert.AreEqual(a1, aHat); + } + + /// + /// Add an appender X, Y, remove X and check if Y is the only + /// remaining appender. + /// + [Test] + public void TestAppender2() + { + CountingAppender a1 = new CountingAppender(); + a1.Name = "testAppender2.1"; + CountingAppender a2 = new CountingAppender(); + a2.Name = "testAppender2.2"; + + log = (Logger)Utils.GetLogger("test").Logger; + log.AddAppender(a1); + log.AddAppender(a2); + + CountingAppender aHat = (CountingAppender)log.GetAppender(a1.Name); + Assert.AreEqual(a1, aHat); + + aHat = (CountingAppender)log.GetAppender(a2.Name); + Assert.AreEqual(a2, aHat); + + log.RemoveAppender("testAppender2.1"); + + IEnumerator enumAppenders = ((IEnumerable)log.Appenders).GetEnumerator(); + Assert.IsTrue(enumAppenders.MoveNext()); + aHat = (CountingAppender)enumAppenders.Current; + Assert.AreEqual(a2, aHat); + Assert.IsTrue(!enumAppenders.MoveNext()); + + aHat = (CountingAppender)log.GetAppender(a2.Name); + Assert.AreEqual(a2, aHat); + } + + /// + /// Test if logger a.b inherits its appender from a. + /// + [Test] + public void TestAdditivity1() + { + Logger a = (Logger)Utils.GetLogger("a").Logger; + Logger ab = (Logger)Utils.GetLogger("a.b").Logger; + CountingAppender ca = new CountingAppender(); + + a.AddAppender(ca); + a.Repository.Configured = true; + + Assert.AreEqual(ca.Counter, 0); + ab.Log(Level.Debug, MSG, null); + Assert.AreEqual(ca.Counter, 1); + ab.Log(Level.Info, MSG, null); + Assert.AreEqual(ca.Counter, 2); + ab.Log(Level.Warn, MSG, null); + Assert.AreEqual(ca.Counter, 3); + ab.Log(Level.Error, MSG, null); + Assert.AreEqual(ca.Counter, 4); + } + + /// + /// Test multiple additivity. + /// + [Test] + public void TestAdditivity2() + { + Logger a = (Logger)Utils.GetLogger("a").Logger; + Logger ab = (Logger)Utils.GetLogger("a.b").Logger; + Logger abc = (Logger)Utils.GetLogger("a.b.c").Logger; + Logger x = (Logger)Utils.GetLogger("x").Logger; + + CountingAppender ca1 = new CountingAppender(); + CountingAppender ca2 = new CountingAppender(); + + a.AddAppender(ca1); + abc.AddAppender(ca2); + a.Repository.Configured = true; + + Assert.AreEqual(ca1.Counter, 0); + Assert.AreEqual(ca2.Counter, 0); + + ab.Log(Level.Debug, MSG, null); + Assert.AreEqual(ca1.Counter, 1); + Assert.AreEqual(ca2.Counter, 0); + + abc.Log(Level.Debug, MSG, null); + Assert.AreEqual(ca1.Counter, 2); + Assert.AreEqual(ca2.Counter, 1); + + x.Log(Level.Debug, MSG, null); + Assert.AreEqual(ca1.Counter, 2); + Assert.AreEqual(ca2.Counter, 1); + } + + /// + /// Test additivity flag. + /// + [Test] + public void TestAdditivity3() + { + Logger root = ((Repository.Hierarchy.Hierarchy)Utils.GetRepository()).Root; + Logger a = (Logger)Utils.GetLogger("a").Logger; + Logger ab = (Logger)Utils.GetLogger("a.b").Logger; + Logger abc = (Logger)Utils.GetLogger("a.b.c").Logger; + + CountingAppender caRoot = new CountingAppender(); + CountingAppender caA = new CountingAppender(); + CountingAppender caABC = new CountingAppender(); + + root.AddAppender(caRoot); + a.AddAppender(caA); + abc.AddAppender(caABC); + a.Repository.Configured = true; + + Assert.AreEqual(caRoot.Counter, 0); + Assert.AreEqual(caA.Counter, 0); + Assert.AreEqual(caABC.Counter, 0); + + ab.Additivity = false; + + a.Log(Level.Debug, MSG, null); + Assert.AreEqual(caRoot.Counter, 1); + Assert.AreEqual(caA.Counter, 1); + Assert.AreEqual(caABC.Counter, 0); + + ab.Log(Level.Debug, MSG, null); + Assert.AreEqual(caRoot.Counter, 1); + Assert.AreEqual(caA.Counter, 1); + Assert.AreEqual(caABC.Counter, 0); + + abc.Log(Level.Debug, MSG, null); + Assert.AreEqual(caRoot.Counter, 1); + Assert.AreEqual(caA.Counter, 1); + Assert.AreEqual(caABC.Counter, 1); + } + + /// + /// Test the ability to disable a level of message + /// + [Test] + public void TestDisable1() + { + CountingAppender caRoot = new CountingAppender(); + Logger root = ((Repository.Hierarchy.Hierarchy)Utils.GetRepository()).Root; + root.AddAppender(caRoot); + + Repository.Hierarchy.Hierarchy h = ((Repository.Hierarchy.Hierarchy)Utils.GetRepository()); + h.Threshold = Level.Info; + h.Configured = true; + + Assert.AreEqual(caRoot.Counter, 0); + + root.Log(Level.Debug, MSG, null); + Assert.AreEqual(caRoot.Counter, 0); + root.Log(Level.Info, MSG, null); + Assert.AreEqual(caRoot.Counter, 1); + root.Log(Level.Warn, MSG, null); + Assert.AreEqual(caRoot.Counter, 2); + root.Log(Level.Warn, MSG, null); + Assert.AreEqual(caRoot.Counter, 3); + + h.Threshold = Level.Warn; + root.Log(Level.Debug, MSG, null); + Assert.AreEqual(caRoot.Counter, 3); + root.Log(Level.Info, MSG, null); + Assert.AreEqual(caRoot.Counter, 3); + root.Log(Level.Warn, MSG, null); + Assert.AreEqual(caRoot.Counter, 4); + root.Log(Level.Error, MSG, null); + Assert.AreEqual(caRoot.Counter, 5); + root.Log(Level.Error, MSG, null); + Assert.AreEqual(caRoot.Counter, 6); + + h.Threshold = Level.Off; + root.Log(Level.Debug, MSG, null); + Assert.AreEqual(caRoot.Counter, 6); + root.Log(Level.Info, MSG, null); + Assert.AreEqual(caRoot.Counter, 6); + root.Log(Level.Warn, MSG, null); + Assert.AreEqual(caRoot.Counter, 6); + root.Log(Level.Error, MSG, null); + Assert.AreEqual(caRoot.Counter, 6); + root.Log(Level.Fatal, MSG, null); + Assert.AreEqual(caRoot.Counter, 6); + root.Log(Level.Fatal, MSG, null); + Assert.AreEqual(caRoot.Counter, 6); + } + + /// + /// Tests the Exists method of the Logger class + /// + [Test] + public void TestExists() + { + object a = Utils.GetLogger("a"); + object a_b = Utils.GetLogger("a.b"); + object a_b_c = Utils.GetLogger("a.b.c"); + + object t; #if NETSTANDARD1_3 - Assert.IsNull(LogManager.Exists(GetType().GetTypeInfo().Assembly, "xx")); - t = LogManager.Exists(GetType().GetTypeInfo().Assembly, "a"); - Assert.AreSame(a, t); - t = LogManager.Exists(GetType().GetTypeInfo().Assembly, "a.b"); - Assert.AreSame(a_b, t); - t = LogManager.Exists(GetType().GetTypeInfo().Assembly, "a.b.c"); - Assert.AreSame(a_b_c, t); + Assert.IsNull(LogManager.Exists(GetType().GetTypeInfo().Assembly, "xx")); + t = LogManager.Exists(GetType().GetTypeInfo().Assembly, "a"); + Assert.AreSame(a, t); + t = LogManager.Exists(GetType().GetTypeInfo().Assembly, "a.b"); + Assert.AreSame(a_b, t); + t = LogManager.Exists(GetType().GetTypeInfo().Assembly, "a.b.c"); + Assert.AreSame(a_b_c, t); #else - t = LogManager.Exists("xx"); - Assert.IsNull(t); - t = LogManager.Exists("a"); - Assert.AreSame(a, t); - t = LogManager.Exists("a.b"); - Assert.AreSame(a_b, t); - t = LogManager.Exists("a.b.c"); - Assert.AreSame(a_b_c, t); + t = LogManager.Exists("xx"); + Assert.IsNull(t); + t = LogManager.Exists("a"); + Assert.AreSame(a, t); + t = LogManager.Exists("a.b"); + Assert.AreSame(a_b, t); + t = LogManager.Exists("a.b.c"); + Assert.AreSame(a_b_c, t); #endif - } - - /// - /// Tests the chained level for a hierarchy - /// - [Test] - public void TestHierarchy1() - { - Repository.Hierarchy.Hierarchy h = new Repository.Hierarchy.Hierarchy(); - h.Root.Level = Level.Error; - - Logger a0 = (Logger)h.GetLogger("a"); - Assert.AreEqual("a", a0.Name); - Assert.IsNull(a0.Level); - Assert.AreSame(Level.Error, a0.EffectiveLevel); - - Logger a1 = (Logger)h.GetLogger("a"); - Assert.AreSame(a0, a1); - } - } + } + + /// + /// Tests the chained level for a hierarchy + /// + [Test] + public void TestHierarchy1() + { + Repository.Hierarchy.Hierarchy h = new Repository.Hierarchy.Hierarchy(); + h.Root.Level = Level.Error; + + Logger a0 = (Logger)h.GetLogger("a"); + Assert.AreEqual("a", a0.Name); + Assert.IsNull(a0.Level); + Assert.AreSame(Level.Error, a0.EffectiveLevel); + + Logger a1 = (Logger)h.GetLogger("a"); + Assert.AreSame(a0, a1); + } + } } \ No newline at end of file diff --git a/src/log4net.Tests/Layout/PatternLayoutTest.cs b/src/log4net.Tests/Layout/PatternLayoutTest.cs index 9c768caf..d2937d5b 100644 --- a/src/log4net.Tests/Layout/PatternLayoutTest.cs +++ b/src/log4net.Tests/Layout/PatternLayoutTest.cs @@ -35,35 +35,35 @@ namespace log4net.Tests.Layout { - /// - /// Used for internal unit testing the class. - /// - /// - /// Used for internal unit testing the class. - /// - [TestFixture] - public class PatternLayoutTest - { + /// + /// Used for internal unit testing the class. + /// + /// + /// Used for internal unit testing the class. + /// + [TestFixture] + public class PatternLayoutTest + { #if !NETSTANDARD1_3 - private CultureInfo _currentCulture; - private CultureInfo _currentUICulture; - - [SetUp] - public void SetUp() - { - // set correct thread culture - _currentCulture = System.Threading.Thread.CurrentThread.CurrentCulture; - _currentUICulture = System.Threading.Thread.CurrentThread.CurrentUICulture; - System.Threading.Thread.CurrentThread.CurrentCulture = System.Threading.Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.InvariantCulture; - } + private CultureInfo _currentCulture; + private CultureInfo _currentUICulture; + + [SetUp] + public void SetUp() + { + // set correct thread culture + _currentCulture = System.Threading.Thread.CurrentThread.CurrentCulture; + _currentUICulture = System.Threading.Thread.CurrentThread.CurrentUICulture; + System.Threading.Thread.CurrentThread.CurrentCulture = System.Threading.Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.InvariantCulture; + } [TearDown] public void TearDown() { - Utils.RemovePropertyFromAllContexts(); - // restore previous culture - System.Threading.Thread.CurrentThread.CurrentCulture = _currentCulture; - System.Threading.Thread.CurrentThread.CurrentUICulture = _currentUICulture; + Utils.RemovePropertyFromAllContexts(); + // restore previous culture + System.Threading.Thread.CurrentThread.CurrentCulture = _currentCulture; + System.Threading.Thread.CurrentThread.CurrentUICulture = _currentUICulture; } #endif @@ -76,32 +76,32 @@ protected virtual PatternLayout NewPatternLayout(string pattern) { } [Test] - public void TestThreadPropertiesPattern() - { - StringAppender stringAppender = new StringAppender(); + public void TestThreadPropertiesPattern() + { + StringAppender stringAppender = new StringAppender(); stringAppender.Layout = NewPatternLayout("%property{" + Utils.PROPERTY_KEY + "}"); - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - BasicConfigurator.Configure(rep, stringAppender); + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + BasicConfigurator.Configure(rep, stringAppender); - ILog log1 = LogManager.GetLogger(rep.Name, "TestThreadProperiesPattern"); + ILog log1 = LogManager.GetLogger(rep.Name, "TestThreadProperiesPattern"); - log1.Info("TestMessage"); - Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test no thread properties value set"); - stringAppender.Reset(); + log1.Info("TestMessage"); + Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test no thread properties value set"); + stringAppender.Reset(); - ThreadContext.Properties[Utils.PROPERTY_KEY] = "val1"; + ThreadContext.Properties[Utils.PROPERTY_KEY] = "val1"; - log1.Info("TestMessage"); - Assert.AreEqual("val1", stringAppender.GetString(), "Test thread properties value set"); - stringAppender.Reset(); + log1.Info("TestMessage"); + Assert.AreEqual("val1", stringAppender.GetString(), "Test thread properties value set"); + stringAppender.Reset(); - ThreadContext.Properties.Remove(Utils.PROPERTY_KEY); + ThreadContext.Properties.Remove(Utils.PROPERTY_KEY); - log1.Info("TestMessage"); - Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test thread properties value removed"); - stringAppender.Reset(); - } + log1.Info("TestMessage"); + Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test thread properties value removed"); + stringAppender.Reset(); + } #if !NETSTANDARD1_3 [Test] @@ -121,55 +121,55 @@ public void TestStackTracePattern() } #endif - [Test] - public void TestGlobalPropertiesPattern() - { - StringAppender stringAppender = new StringAppender(); + [Test] + public void TestGlobalPropertiesPattern() + { + StringAppender stringAppender = new StringAppender(); stringAppender.Layout = NewPatternLayout("%property{" + Utils.PROPERTY_KEY + "}"); - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - BasicConfigurator.Configure(rep, stringAppender); + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + BasicConfigurator.Configure(rep, stringAppender); - ILog log1 = LogManager.GetLogger(rep.Name, "TestGlobalProperiesPattern"); + ILog log1 = LogManager.GetLogger(rep.Name, "TestGlobalProperiesPattern"); - log1.Info("TestMessage"); - Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test no global properties value set"); - stringAppender.Reset(); + log1.Info("TestMessage"); + Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test no global properties value set"); + stringAppender.Reset(); - GlobalContext.Properties[Utils.PROPERTY_KEY] = "val1"; + GlobalContext.Properties[Utils.PROPERTY_KEY] = "val1"; - log1.Info("TestMessage"); - Assert.AreEqual("val1", stringAppender.GetString(), "Test global properties value set"); - stringAppender.Reset(); + log1.Info("TestMessage"); + Assert.AreEqual("val1", stringAppender.GetString(), "Test global properties value set"); + stringAppender.Reset(); - GlobalContext.Properties.Remove(Utils.PROPERTY_KEY); + GlobalContext.Properties.Remove(Utils.PROPERTY_KEY); - log1.Info("TestMessage"); - Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test global properties value removed"); - stringAppender.Reset(); - } + log1.Info("TestMessage"); + Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test global properties value removed"); + stringAppender.Reset(); + } - [Test] - public void TestAddingCustomPattern() - { - StringAppender stringAppender = new StringAppender(); - PatternLayout layout = NewPatternLayout(); + [Test] + public void TestAddingCustomPattern() + { + StringAppender stringAppender = new StringAppender(); + PatternLayout layout = NewPatternLayout(); - layout.AddConverter("TestAddingCustomPattern", typeof(TestMessagePatternConverter)); - layout.ConversionPattern = "%TestAddingCustomPattern"; - layout.ActivateOptions(); + layout.AddConverter("TestAddingCustomPattern", typeof(TestMessagePatternConverter)); + layout.ConversionPattern = "%TestAddingCustomPattern"; + layout.ActivateOptions(); - stringAppender.Layout = layout; + stringAppender.Layout = layout; - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - BasicConfigurator.Configure(rep, stringAppender); + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + BasicConfigurator.Configure(rep, stringAppender); - ILog log1 = LogManager.GetLogger(rep.Name, "TestAddingCustomPattern"); + ILog log1 = LogManager.GetLogger(rep.Name, "TestAddingCustomPattern"); - log1.Info("TestMessage"); - Assert.AreEqual("TestMessage", stringAppender.GetString(), "%TestAddingCustomPattern not registered"); - stringAppender.Reset(); - } + log1.Info("TestMessage"); + Assert.AreEqual("TestMessage", stringAppender.GetString(), "%TestAddingCustomPattern not registered"); + stringAppender.Reset(); + } [Test] public void NamedPatternConverterWithoutPrecisionShouldReturnFullName() @@ -312,41 +312,41 @@ public void NamedPatternConverterWithPrecision2ShouldStripLessLeadingStuffIfPres } /// - /// Converter to include event message - /// - private class TestMessagePatternConverter : PatternLayoutConverter - { - /// - /// Convert the pattern to the rendered message - /// - /// that will receive the formatted result. - /// the event being logged - /// the relevant location information - protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) - { - loggingEvent.WriteRenderedMessage(writer); - } - } - - [Test] - public void TestExceptionPattern() - { - StringAppender stringAppender = new StringAppender(); - PatternLayout layout = NewPatternLayout("%exception{stacktrace}"); - stringAppender.Layout = layout; - - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - BasicConfigurator.Configure(rep, stringAppender); - - ILog log1 = LogManager.GetLogger(rep.Name, "TestExceptionPattern"); - - Exception exception = new Exception("Oh no!"); - log1.Info("TestMessage", exception); - - Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString()); - - stringAppender.Reset(); - } + /// Converter to include event message + /// + private class TestMessagePatternConverter : PatternLayoutConverter + { + /// + /// Convert the pattern to the rendered message + /// + /// that will receive the formatted result. + /// the event being logged + /// the relevant location information + protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) + { + loggingEvent.WriteRenderedMessage(writer); + } + } + + [Test] + public void TestExceptionPattern() + { + StringAppender stringAppender = new StringAppender(); + PatternLayout layout = NewPatternLayout("%exception{stacktrace}"); + stringAppender.Layout = layout; + + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + BasicConfigurator.Configure(rep, stringAppender); + + ILog log1 = LogManager.GetLogger(rep.Name, "TestExceptionPattern"); + + Exception exception = new Exception("Oh no!"); + log1.Info("TestMessage", exception); + + Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString()); + + stringAppender.Reset(); + } private class MessageAsNamePatternConverter : NamedPatternConverter { diff --git a/src/log4net.Tests/Layout/XmlLayoutTest.cs b/src/log4net.Tests/Layout/XmlLayoutTest.cs index 39ca33d5..17cd67eb 100644 --- a/src/log4net.Tests/Layout/XmlLayoutTest.cs +++ b/src/log4net.Tests/Layout/XmlLayoutTest.cs @@ -33,277 +33,277 @@ namespace log4net.Tests.Layout { - [TestFixture] - public class XmlLayoutTest - { + [TestFixture] + public class XmlLayoutTest + { #if !NETSTANDARD1_3 - private CultureInfo _currentCulture; - private CultureInfo _currentUICulture; - - [SetUp] - public void SetUp() - { - // set correct thread culture - _currentCulture = System.Threading.Thread.CurrentThread.CurrentCulture; - _currentUICulture = System.Threading.Thread.CurrentThread.CurrentUICulture; - System.Threading.Thread.CurrentThread.CurrentCulture = System.Threading.Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.InvariantCulture; - } - - [TearDown] - public void TearDown() - { - // restore previous culture - System.Threading.Thread.CurrentThread.CurrentCulture = _currentCulture; - System.Threading.Thread.CurrentThread.CurrentUICulture = _currentUICulture; - } + private CultureInfo _currentCulture; + private CultureInfo _currentUICulture; + + [SetUp] + public void SetUp() + { + // set correct thread culture + _currentCulture = System.Threading.Thread.CurrentThread.CurrentCulture; + _currentUICulture = System.Threading.Thread.CurrentThread.CurrentUICulture; + System.Threading.Thread.CurrentThread.CurrentCulture = System.Threading.Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.InvariantCulture; + } + + [TearDown] + public void TearDown() + { + // restore previous culture + System.Threading.Thread.CurrentThread.CurrentCulture = _currentCulture; + System.Threading.Thread.CurrentThread.CurrentUICulture = _currentUICulture; + } #endif - /// - /// Build a basic object with some default values. - /// - /// A useful LoggingEventData object - private LoggingEventData CreateBaseEvent() - { - LoggingEventData ed = new LoggingEventData(); - ed.Domain = "Tests"; - ed.ExceptionString = ""; - ed.Identity = "TestRunner"; - ed.Level = Level.Info; - ed.LocationInfo = new LocationInfo(GetType()); - ed.LoggerName = "TestLogger"; - ed.Message = "Test message"; - ed.ThreadName = "TestThread"; - ed.TimeStampUtc = DateTime.Today.ToUniversalTime(); - ed.UserName = "TestRunner"; - ed.Properties = new PropertiesDictionary(); - - return ed; - } - - private static string CreateEventNode(string message) - { - return String.Format("{1}" + Environment.NewLine, + /// + /// Build a basic object with some default values. + /// + /// A useful LoggingEventData object + private LoggingEventData CreateBaseEvent() + { + LoggingEventData ed = new LoggingEventData(); + ed.Domain = "Tests"; + ed.ExceptionString = ""; + ed.Identity = "TestRunner"; + ed.Level = Level.Info; + ed.LocationInfo = new LocationInfo(GetType()); + ed.LoggerName = "TestLogger"; + ed.Message = "Test message"; + ed.ThreadName = "TestThread"; + ed.TimeStampUtc = DateTime.Today.ToUniversalTime(); + ed.UserName = "TestRunner"; + ed.Properties = new PropertiesDictionary(); + + return ed; + } + + private static string CreateEventNode(string message) + { + return String.Format("{1}" + Environment.NewLine, #if NET_2_0 || MONO_2_0 || MONO_3_5 || MONO_4_0 || NETSTANDARD - XmlConvert.ToString(DateTime.Today, XmlDateTimeSerializationMode.Local), + XmlConvert.ToString(DateTime.Today, XmlDateTimeSerializationMode.Local), #else - XmlConvert.ToString(DateTime.Today), + XmlConvert.ToString(DateTime.Today), #endif - message); - } + message); + } - private static string CreateEventNode(string key, string value) - { - return String.Format("Test message" + Environment.NewLine, + private static string CreateEventNode(string key, string value) + { + return String.Format("Test message" + Environment.NewLine, #if NET_2_0 || MONO_2_0 || MONO_3_5 || MONO_4_0 || NETSTANDARD - XmlConvert.ToString(DateTime.Today, XmlDateTimeSerializationMode.Local), + XmlConvert.ToString(DateTime.Today, XmlDateTimeSerializationMode.Local), #else - XmlConvert.ToString(DateTime.Today), + XmlConvert.ToString(DateTime.Today), #endif - key, - value); - } + key, + value); + } - [Test] - public void TestBasicEventLogging() - { - TextWriter writer = new StringWriter(); - XmlLayout layout = new XmlLayout(); - LoggingEventData evt = CreateBaseEvent(); + [Test] + public void TestBasicEventLogging() + { + TextWriter writer = new StringWriter(); + XmlLayout layout = new XmlLayout(); + LoggingEventData evt = CreateBaseEvent(); - layout.Format(writer, new LoggingEvent(evt)); + layout.Format(writer, new LoggingEvent(evt)); - string expected = CreateEventNode("Test message"); + string expected = CreateEventNode("Test message"); - Assert.AreEqual(expected, writer.ToString()); - } + Assert.AreEqual(expected, writer.ToString()); + } - [Test] - public void TestIllegalCharacterMasking() - { - TextWriter writer = new StringWriter(); - XmlLayout layout = new XmlLayout(); - LoggingEventData evt = CreateBaseEvent(); + [Test] + public void TestIllegalCharacterMasking() + { + TextWriter writer = new StringWriter(); + XmlLayout layout = new XmlLayout(); + LoggingEventData evt = CreateBaseEvent(); - evt.Message = "This is a masked char->\uFFFF"; + evt.Message = "This is a masked char->\uFFFF"; - layout.Format(writer, new LoggingEvent(evt)); + layout.Format(writer, new LoggingEvent(evt)); - string expected = CreateEventNode("This is a masked char->?"); + string expected = CreateEventNode("This is a masked char->?"); - Assert.AreEqual(expected, writer.ToString()); - } + Assert.AreEqual(expected, writer.ToString()); + } - [Test] - public void TestCDATAEscaping1() - { - TextWriter writer = new StringWriter(); - XmlLayout layout = new XmlLayout(); - LoggingEventData evt = CreateBaseEvent(); + [Test] + public void TestCDATAEscaping1() + { + TextWriter writer = new StringWriter(); + XmlLayout layout = new XmlLayout(); + LoggingEventData evt = CreateBaseEvent(); - //The &'s trigger the use of a cdata block - evt.Message = "&&&&&&&Escape this ]]>. End here."; + //The &'s trigger the use of a cdata block + evt.Message = "&&&&&&&Escape this ]]>. End here."; - layout.Format(writer, new LoggingEvent(evt)); + layout.Format(writer, new LoggingEvent(evt)); - string expected = CreateEventNode("]]. End here.]]>"); + string expected = CreateEventNode("]]. End here.]]>"); - Assert.AreEqual(expected, writer.ToString()); - } + Assert.AreEqual(expected, writer.ToString()); + } - [Test] - public void TestCDATAEscaping2() - { - TextWriter writer = new StringWriter(); - XmlLayout layout = new XmlLayout(); - LoggingEventData evt = CreateBaseEvent(); + [Test] + public void TestCDATAEscaping2() + { + TextWriter writer = new StringWriter(); + XmlLayout layout = new XmlLayout(); + LoggingEventData evt = CreateBaseEvent(); - //The &'s trigger the use of a cdata block - evt.Message = "&&&&&&&Escape the end ]]>"; + //The &'s trigger the use of a cdata block + evt.Message = "&&&&&&&Escape the end ]]>"; - layout.Format(writer, new LoggingEvent(evt)); + layout.Format(writer, new LoggingEvent(evt)); - string expected = CreateEventNode("]]>"); + string expected = CreateEventNode("]]>"); - Assert.AreEqual(expected, writer.ToString()); - } + Assert.AreEqual(expected, writer.ToString()); + } - [Test] - public void TestCDATAEscaping3() - { - TextWriter writer = new StringWriter(); - XmlLayout layout = new XmlLayout(); - LoggingEventData evt = CreateBaseEvent(); + [Test] + public void TestCDATAEscaping3() + { + TextWriter writer = new StringWriter(); + XmlLayout layout = new XmlLayout(); + LoggingEventData evt = CreateBaseEvent(); - //The &'s trigger the use of a cdata block - evt.Message = "]]>&&&&&&&Escape the begining"; + //The &'s trigger the use of a cdata block + evt.Message = "]]>&&&&&&&Escape the begining"; - layout.Format(writer, new LoggingEvent(evt)); + layout.Format(writer, new LoggingEvent(evt)); - string expected = CreateEventNode("]]&&&&&&&Escape the begining]]>"); + string expected = CreateEventNode("]]&&&&&&&Escape the begining]]>"); - Assert.AreEqual(expected, writer.ToString()); - } + Assert.AreEqual(expected, writer.ToString()); + } - [Test] - public void TestBase64EventLogging() - { - TextWriter writer = new StringWriter(); - XmlLayout layout = new XmlLayout(); - LoggingEventData evt = CreateBaseEvent(); + [Test] + public void TestBase64EventLogging() + { + TextWriter writer = new StringWriter(); + XmlLayout layout = new XmlLayout(); + LoggingEventData evt = CreateBaseEvent(); - layout.Base64EncodeMessage = true; - layout.Format(writer, new LoggingEvent(evt)); + layout.Base64EncodeMessage = true; + layout.Format(writer, new LoggingEvent(evt)); - string expected = CreateEventNode("VGVzdCBtZXNzYWdl"); + string expected = CreateEventNode("VGVzdCBtZXNzYWdl"); - Assert.AreEqual(expected, writer.ToString()); - } + Assert.AreEqual(expected, writer.ToString()); + } - [Test] - public void TestPropertyEventLogging() - { - LoggingEventData evt = CreateBaseEvent(); - evt.Properties["Property1"] = "prop1"; + [Test] + public void TestPropertyEventLogging() + { + LoggingEventData evt = CreateBaseEvent(); + evt.Properties["Property1"] = "prop1"; - XmlLayout layout = new XmlLayout(); - StringAppender stringAppender = new StringAppender(); - stringAppender.Layout = layout; + XmlLayout layout = new XmlLayout(); + StringAppender stringAppender = new StringAppender(); + stringAppender.Layout = layout; - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - BasicConfigurator.Configure(rep, stringAppender); - ILog log1 = LogManager.GetLogger(rep.Name, "TestThreadProperiesPattern"); + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + BasicConfigurator.Configure(rep, stringAppender); + ILog log1 = LogManager.GetLogger(rep.Name, "TestThreadProperiesPattern"); - log1.Logger.Log(new LoggingEvent(evt)); + log1.Logger.Log(new LoggingEvent(evt)); - string expected = CreateEventNode("Property1", "prop1"); + string expected = CreateEventNode("Property1", "prop1"); - Assert.AreEqual(expected, stringAppender.GetString()); - } + Assert.AreEqual(expected, stringAppender.GetString()); + } - [Test] - public void TestBase64PropertyEventLogging() - { - LoggingEventData evt = CreateBaseEvent(); - evt.Properties["Property1"] = "prop1"; + [Test] + public void TestBase64PropertyEventLogging() + { + LoggingEventData evt = CreateBaseEvent(); + evt.Properties["Property1"] = "prop1"; - XmlLayout layout = new XmlLayout(); - layout.Base64EncodeProperties = true; - StringAppender stringAppender = new StringAppender(); - stringAppender.Layout = layout; + XmlLayout layout = new XmlLayout(); + layout.Base64EncodeProperties = true; + StringAppender stringAppender = new StringAppender(); + stringAppender.Layout = layout; - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - BasicConfigurator.Configure(rep, stringAppender); - ILog log1 = LogManager.GetLogger(rep.Name, "TestThreadProperiesPattern"); + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + BasicConfigurator.Configure(rep, stringAppender); + ILog log1 = LogManager.GetLogger(rep.Name, "TestThreadProperiesPattern"); - log1.Logger.Log(new LoggingEvent(evt)); + log1.Logger.Log(new LoggingEvent(evt)); - string expected = CreateEventNode("Property1", "cHJvcDE="); + string expected = CreateEventNode("Property1", "cHJvcDE="); - Assert.AreEqual(expected, stringAppender.GetString()); - } + Assert.AreEqual(expected, stringAppender.GetString()); + } - [Test] - public void TestPropertyCharacterEscaping() - { - LoggingEventData evt = CreateBaseEvent(); - evt.Properties["Property1"] = "prop1 \"quoted\""; + [Test] + public void TestPropertyCharacterEscaping() + { + LoggingEventData evt = CreateBaseEvent(); + evt.Properties["Property1"] = "prop1 \"quoted\""; - XmlLayout layout = new XmlLayout(); - StringAppender stringAppender = new StringAppender(); - stringAppender.Layout = layout; + XmlLayout layout = new XmlLayout(); + StringAppender stringAppender = new StringAppender(); + stringAppender.Layout = layout; - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - BasicConfigurator.Configure(rep, stringAppender); - ILog log1 = LogManager.GetLogger(rep.Name, "TestThreadProperiesPattern"); + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + BasicConfigurator.Configure(rep, stringAppender); + ILog log1 = LogManager.GetLogger(rep.Name, "TestThreadProperiesPattern"); - log1.Logger.Log(new LoggingEvent(evt)); + log1.Logger.Log(new LoggingEvent(evt)); - string expected = CreateEventNode("Property1", "prop1 "quoted""); + string expected = CreateEventNode("Property1", "prop1 "quoted""); - Assert.AreEqual(expected, stringAppender.GetString()); - } + Assert.AreEqual(expected, stringAppender.GetString()); + } - [Test] - public void TestPropertyIllegalCharacterMasking() - { - LoggingEventData evt = CreateBaseEvent(); - evt.Properties["Property1"] = "mask this ->\uFFFF"; + [Test] + public void TestPropertyIllegalCharacterMasking() + { + LoggingEventData evt = CreateBaseEvent(); + evt.Properties["Property1"] = "mask this ->\uFFFF"; - XmlLayout layout = new XmlLayout(); - StringAppender stringAppender = new StringAppender(); - stringAppender.Layout = layout; + XmlLayout layout = new XmlLayout(); + StringAppender stringAppender = new StringAppender(); + stringAppender.Layout = layout; - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - BasicConfigurator.Configure(rep, stringAppender); - ILog log1 = LogManager.GetLogger(rep.Name, "TestThreadProperiesPattern"); + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + BasicConfigurator.Configure(rep, stringAppender); + ILog log1 = LogManager.GetLogger(rep.Name, "TestThreadProperiesPattern"); - log1.Logger.Log(new LoggingEvent(evt)); + log1.Logger.Log(new LoggingEvent(evt)); - string expected = CreateEventNode("Property1", "mask this ->?"); + string expected = CreateEventNode("Property1", "mask this ->?"); - Assert.AreEqual(expected, stringAppender.GetString()); - } + Assert.AreEqual(expected, stringAppender.GetString()); + } - [Test] - public void TestPropertyIllegalCharacterMaskingInName() - { - LoggingEventData evt = CreateBaseEvent(); - evt.Properties["Property\uFFFF"] = "mask this ->\uFFFF"; + [Test] + public void TestPropertyIllegalCharacterMaskingInName() + { + LoggingEventData evt = CreateBaseEvent(); + evt.Properties["Property\uFFFF"] = "mask this ->\uFFFF"; - XmlLayout layout = new XmlLayout(); - StringAppender stringAppender = new StringAppender(); - stringAppender.Layout = layout; + XmlLayout layout = new XmlLayout(); + StringAppender stringAppender = new StringAppender(); + stringAppender.Layout = layout; - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - BasicConfigurator.Configure(rep, stringAppender); - ILog log1 = LogManager.GetLogger(rep.Name, "TestThreadProperiesPattern"); + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + BasicConfigurator.Configure(rep, stringAppender); + ILog log1 = LogManager.GetLogger(rep.Name, "TestThreadProperiesPattern"); - log1.Logger.Log(new LoggingEvent(evt)); + log1.Logger.Log(new LoggingEvent(evt)); - string expected = CreateEventNode("Property?", "mask this ->?"); + string expected = CreateEventNode("Property?", "mask this ->?"); - Assert.AreEqual(expected, stringAppender.GetString()); - } + Assert.AreEqual(expected, stringAppender.GetString()); + } #if NET_4_0 || MONO_4_0 || NETSTANDARD [Test] @@ -368,5 +368,5 @@ public void BracketsInStackTracesAreEscapedProperly() { } } #endif - } + } } \ No newline at end of file diff --git a/src/log4net.Tests/Util/CyclicBufferTest.cs b/src/log4net.Tests/Util/CyclicBufferTest.cs index 3ea79321..0d81c48b 100644 --- a/src/log4net.Tests/Util/CyclicBufferTest.cs +++ b/src/log4net.Tests/Util/CyclicBufferTest.cs @@ -26,84 +26,84 @@ namespace log4net.Tests.Util { - /// - /// Used for internal unit testing the class. - /// - /// - /// Used for internal unit testing the class. - /// - [TestFixture] - public class CyclicBufferTest - { - [Test] - public void TestConstructorSize0() - { - Assert.Throws(() => new CyclicBuffer(0)); - } - - [Test] - public void TestSize1() - { - CyclicBuffer cb = new CyclicBuffer(1); - - Assert.AreEqual(0, cb.Length, "Empty Buffer should have length 0"); - Assert.AreEqual(1, cb.MaxSize, "Buffer should have max size 1"); - - LoggingEvent event1 = new LoggingEvent(null, null, null, null, null, null); - LoggingEvent event2 = new LoggingEvent(null, null, null, null, null, null); - - LoggingEvent discardedEvent = cb.Append(event1); - - Assert.IsNull(discardedEvent, "No event should be discarded untill the buffer is full"); - Assert.AreEqual(1, cb.Length, "Buffer should have length 1"); - Assert.AreEqual(1, cb.MaxSize, "Buffer should still have max size 1"); - - - discardedEvent = cb.Append(event2); - - Assert.AreSame(event1, discardedEvent, "Expect event1 to now be discarded"); - Assert.AreEqual(1, cb.Length, "Buffer should still have length 1"); - Assert.AreEqual(1, cb.MaxSize, "Buffer should really still have max size 1"); - - LoggingEvent[] discardedEvents = cb.PopAll(); - - Assert.AreEqual(1, discardedEvents.Length, "Poped events length should be 1"); - Assert.AreSame(event2, discardedEvents[0], "Expect event2 to now be popped"); - Assert.AreEqual(0, cb.Length, "Buffer should be back to length 0"); - Assert.AreEqual(1, cb.MaxSize, "Buffer should really really still have max size 1"); - } - - [Test] - public void TestSize2() - { - CyclicBuffer cb = new CyclicBuffer(2); - - Assert.AreEqual(0, cb.Length, "Empty Buffer should have length 0"); - Assert.AreEqual(2, cb.MaxSize, "Buffer should have max size 2"); - - LoggingEvent event1 = new LoggingEvent(null, null, null, null, null, null); - LoggingEvent event2 = new LoggingEvent(null, null, null, null, null, null); - LoggingEvent event3 = new LoggingEvent(null, null, null, null, null, null); - - LoggingEvent discardedEvent; - - discardedEvent = cb.Append(event1); - Assert.IsNull(discardedEvent, "No event should be discarded after append 1"); - discardedEvent = cb.Append(event2); - Assert.IsNull(discardedEvent, "No event should be discarded after append 2"); - - discardedEvent = cb.Append(event3); - Assert.AreSame(event1, discardedEvent, "Expect event1 to now be discarded"); - - discardedEvent = cb.PopOldest(); - Assert.AreSame(event2, discardedEvent, "Expect event2 to now be discarded"); - - LoggingEvent[] discardedEvents = cb.PopAll(); - - Assert.AreEqual(1, discardedEvents.Length, "Poped events length should be 1"); - Assert.AreSame(event3, discardedEvents[0], "Expect event3 to now be popped"); - Assert.AreEqual(0, cb.Length, "Buffer should be back to length 0"); - Assert.AreEqual(2, cb.MaxSize, "Buffer should really really still have max size 2"); - } - } + /// + /// Used for internal unit testing the class. + /// + /// + /// Used for internal unit testing the class. + /// + [TestFixture] + public class CyclicBufferTest + { + [Test] + public void TestConstructorSize0() + { + Assert.Throws(() => new CyclicBuffer(0)); + } + + [Test] + public void TestSize1() + { + CyclicBuffer cb = new CyclicBuffer(1); + + Assert.AreEqual(0, cb.Length, "Empty Buffer should have length 0"); + Assert.AreEqual(1, cb.MaxSize, "Buffer should have max size 1"); + + LoggingEvent event1 = new LoggingEvent(null, null, null, null, null, null); + LoggingEvent event2 = new LoggingEvent(null, null, null, null, null, null); + + LoggingEvent discardedEvent = cb.Append(event1); + + Assert.IsNull(discardedEvent, "No event should be discarded untill the buffer is full"); + Assert.AreEqual(1, cb.Length, "Buffer should have length 1"); + Assert.AreEqual(1, cb.MaxSize, "Buffer should still have max size 1"); + + + discardedEvent = cb.Append(event2); + + Assert.AreSame(event1, discardedEvent, "Expect event1 to now be discarded"); + Assert.AreEqual(1, cb.Length, "Buffer should still have length 1"); + Assert.AreEqual(1, cb.MaxSize, "Buffer should really still have max size 1"); + + LoggingEvent[] discardedEvents = cb.PopAll(); + + Assert.AreEqual(1, discardedEvents.Length, "Poped events length should be 1"); + Assert.AreSame(event2, discardedEvents[0], "Expect event2 to now be popped"); + Assert.AreEqual(0, cb.Length, "Buffer should be back to length 0"); + Assert.AreEqual(1, cb.MaxSize, "Buffer should really really still have max size 1"); + } + + [Test] + public void TestSize2() + { + CyclicBuffer cb = new CyclicBuffer(2); + + Assert.AreEqual(0, cb.Length, "Empty Buffer should have length 0"); + Assert.AreEqual(2, cb.MaxSize, "Buffer should have max size 2"); + + LoggingEvent event1 = new LoggingEvent(null, null, null, null, null, null); + LoggingEvent event2 = new LoggingEvent(null, null, null, null, null, null); + LoggingEvent event3 = new LoggingEvent(null, null, null, null, null, null); + + LoggingEvent discardedEvent; + + discardedEvent = cb.Append(event1); + Assert.IsNull(discardedEvent, "No event should be discarded after append 1"); + discardedEvent = cb.Append(event2); + Assert.IsNull(discardedEvent, "No event should be discarded after append 2"); + + discardedEvent = cb.Append(event3); + Assert.AreSame(event1, discardedEvent, "Expect event1 to now be discarded"); + + discardedEvent = cb.PopOldest(); + Assert.AreSame(event2, discardedEvent, "Expect event2 to now be discarded"); + + LoggingEvent[] discardedEvents = cb.PopAll(); + + Assert.AreEqual(1, discardedEvents.Length, "Poped events length should be 1"); + Assert.AreSame(event3, discardedEvents[0], "Expect event3 to now be popped"); + Assert.AreEqual(0, cb.Length, "Buffer should be back to length 0"); + Assert.AreEqual(2, cb.MaxSize, "Buffer should really really still have max size 2"); + } + } } \ No newline at end of file diff --git a/src/log4net.Tests/Util/EnvironmentPatternConverterTest.cs b/src/log4net.Tests/Util/EnvironmentPatternConverterTest.cs index cced28c1..e475ae5a 100644 --- a/src/log4net.Tests/Util/EnvironmentPatternConverterTest.cs +++ b/src/log4net.Tests/Util/EnvironmentPatternConverterTest.cs @@ -50,8 +50,8 @@ public void SystemLevelEnvironmentVariable() converter.Option = ENVIRONMENT_VARIABLE_NAME; - StringWriter sw = new StringWriter(); - converter.Convert(sw, null); + StringWriter sw = new StringWriter(); + converter.Convert(sw, null); Assert.AreEqual(SYSTEM_LEVEL_VALUE, sw.ToString(), "System level environment variable not expended correctly."); diff --git a/src/log4net.Tests/Util/PropertiesDictionaryTest.cs b/src/log4net.Tests/Util/PropertiesDictionaryTest.cs index e44f4a8c..04d66c8c 100644 --- a/src/log4net.Tests/Util/PropertiesDictionaryTest.cs +++ b/src/log4net.Tests/Util/PropertiesDictionaryTest.cs @@ -28,44 +28,44 @@ namespace log4net.Tests.Util { - /// - /// Used for internal unit testing the class. - /// - /// - /// Used for internal unit testing the class. - /// - [TestFixture] - public class PropertiesDictionaryTest - { - [Test] - public void TestSerialization() - { - PropertiesDictionary pd = new PropertiesDictionary(); + /// + /// Used for internal unit testing the class. + /// + /// + /// Used for internal unit testing the class. + /// + [TestFixture] + public class PropertiesDictionaryTest + { + [Test] + public void TestSerialization() + { + PropertiesDictionary pd = new PropertiesDictionary(); - for(int i = 0; i < 10; i++) - { - pd[i.ToString()] = i; - } + for(int i = 0; i < 10; i++) + { + pd[i.ToString()] = i; + } - Assert.AreEqual(10, pd.Count, "Dictionary should have 10 items"); + Assert.AreEqual(10, pd.Count, "Dictionary should have 10 items"); - // Serialize the properties into a memory stream - BinaryFormatter formatter = new BinaryFormatter(); - MemoryStream memory = new MemoryStream(); - formatter.Serialize(memory, pd); + // Serialize the properties into a memory stream + BinaryFormatter formatter = new BinaryFormatter(); + MemoryStream memory = new MemoryStream(); + formatter.Serialize(memory, pd); - // Deserialize the stream into a new properties dictionary - memory.Position = 0; - PropertiesDictionary pd2 = (PropertiesDictionary)formatter.Deserialize(memory); + // Deserialize the stream into a new properties dictionary + memory.Position = 0; + PropertiesDictionary pd2 = (PropertiesDictionary)formatter.Deserialize(memory); - Assert.AreEqual(10, pd2.Count, "Deserialized Dictionary should have 10 items"); + Assert.AreEqual(10, pd2.Count, "Deserialized Dictionary should have 10 items"); - foreach(string key in pd.GetKeys()) - { - Assert.AreEqual(pd[key], pd2[key], "Check Value Persisted for key [{0}]", key); - } - } - } + foreach(string key in pd.GetKeys()) + { + Assert.AreEqual(pd[key], pd2[key], "Check Value Persisted for key [{0}]", key); + } + } + } } #endif diff --git a/src/log4net.Tests/Util/RandomStringPatternConverterTest.cs b/src/log4net.Tests/Util/RandomStringPatternConverterTest.cs index e586a9d9..adb3e406 100644 --- a/src/log4net.Tests/Util/RandomStringPatternConverterTest.cs +++ b/src/log4net.Tests/Util/RandomStringPatternConverterTest.cs @@ -23,68 +23,68 @@ namespace log4net.Tests.Util { - /// - /// Used for internal unit testing the class. - /// - /// - /// Used for internal unit testing the class. - /// - [TestFixture] - public class RandomStringPatternConverterTest - { - [Test] - public void TestConvert() - { - RandomStringPatternConverter converter = new RandomStringPatternConverter(); + /// + /// Used for internal unit testing the class. + /// + /// + /// Used for internal unit testing the class. + /// + [TestFixture] + public class RandomStringPatternConverterTest + { + [Test] + public void TestConvert() + { + RandomStringPatternConverter converter = new RandomStringPatternConverter(); - // Check default string length - StringWriter sw = new StringWriter(); - converter.Convert(sw, null); + // Check default string length + StringWriter sw = new StringWriter(); + converter.Convert(sw, null); - Assert.AreEqual(4, sw.ToString().Length, "Default string length should be 4"); + Assert.AreEqual(4, sw.ToString().Length, "Default string length should be 4"); - // Set string length to 7 - converter.Option = "7"; - converter.ActivateOptions(); + // Set string length to 7 + converter.Option = "7"; + converter.ActivateOptions(); - sw = new StringWriter(); - converter.Convert(sw, null); + sw = new StringWriter(); + converter.Convert(sw, null); - string string1 = sw.ToString(); - Assert.AreEqual(7, string1.Length, "string length should be 7"); + string string1 = sw.ToString(); + Assert.AreEqual(7, string1.Length, "string length should be 7"); - // Check for duplicate result - sw = new StringWriter(); - converter.Convert(sw, null); + // Check for duplicate result + sw = new StringWriter(); + converter.Convert(sw, null); - string string2 = sw.ToString(); - Assert.IsTrue(string1 != string2, "strings should be different"); - } + string string2 = sw.ToString(); + Assert.IsTrue(string1 != string2, "strings should be different"); + } - private class RandomStringPatternConverter - { - private object target = null; + private class RandomStringPatternConverter + { + private object target = null; - public RandomStringPatternConverter() - { - target = Utils.CreateInstance("log4net.Util.PatternStringConverters.RandomStringPatternConverter,log4net"); - } + public RandomStringPatternConverter() + { + target = Utils.CreateInstance("log4net.Util.PatternStringConverters.RandomStringPatternConverter,log4net"); + } - public string Option - { - get { return Utils.GetProperty(target, "Option") as string; } - set { Utils.SetProperty(target, "Option", value); } - } + public string Option + { + get { return Utils.GetProperty(target, "Option") as string; } + set { Utils.SetProperty(target, "Option", value); } + } - public void Convert(TextWriter writer, object state) - { - Utils.InvokeMethod(target, "Convert", writer, state); - } + public void Convert(TextWriter writer, object state) + { + Utils.InvokeMethod(target, "Convert", writer, state); + } - public void ActivateOptions() - { - Utils.InvokeMethod(target, "ActivateOptions"); - } - } - } + public void ActivateOptions() + { + Utils.InvokeMethod(target, "ActivateOptions"); + } + } + } } \ No newline at end of file diff --git a/src/log4net.Tests/Util/SystemInfoTest.cs b/src/log4net.Tests/Util/SystemInfoTest.cs index ee2b518f..b943e09b 100644 --- a/src/log4net.Tests/Util/SystemInfoTest.cs +++ b/src/log4net.Tests/Util/SystemInfoTest.cs @@ -30,145 +30,145 @@ namespace log4net.Tests.Util { - /// - /// Used for internal unit testing the class. - /// - [TestFixture] - public class SystemInfoTest - { + /// + /// Used for internal unit testing the class. + /// + [TestFixture] + public class SystemInfoTest + { #if NET_4_0 || MONO_4_0 || NETSTANDARD - /// - /// It's "does not throw not supported exception" NOT - /// "returns 'Dynamic Assembly' string for dynamic assemblies" by purpose. - /// can be JITted and inlined in different release configurations, - /// thus we cannot determine what the exact result of this test will be. - /// In 'Debug' GetCallingAssembly should return dynamic assembly named: 'Anonymously Hosted DynamicMethods Assembly' - /// whereas in 'Release' this will be inlined and the result will be something like 'X:\Y\Z\log4net.Tests.dll'. - /// Therefore simple check against dynamic assembly - /// in to avoid 'Debug' release. - /// - [Test] - public void TestAssemblyLocationInfoDoesNotThrowNotSupportedExceptionForDynamicAssembly() - { - var systemInfoAssemblyLocationMethod = GetAssemblyLocationInfoMethodCall(); - - Assert.DoesNotThrow(() => systemInfoAssemblyLocationMethod()); - } - - private static Func GetAssemblyLocationInfoMethodCall() - { - var method = typeof(SystemInfoTest).GetMethod("TestAssemblyLocationInfoMethod", new Type[0]); - var methodCall = Expression.Call(null, method, new Expression[0]); - return Expression.Lambda>(methodCall, new ParameterExpression[0]).Compile(); - } - - public static string TestAssemblyLocationInfoMethod() - { + /// + /// It's "does not throw not supported exception" NOT + /// "returns 'Dynamic Assembly' string for dynamic assemblies" by purpose. + /// can be JITted and inlined in different release configurations, + /// thus we cannot determine what the exact result of this test will be. + /// In 'Debug' GetCallingAssembly should return dynamic assembly named: 'Anonymously Hosted DynamicMethods Assembly' + /// whereas in 'Release' this will be inlined and the result will be something like 'X:\Y\Z\log4net.Tests.dll'. + /// Therefore simple check against dynamic assembly + /// in to avoid 'Debug' release. + /// + [Test] + public void TestAssemblyLocationInfoDoesNotThrowNotSupportedExceptionForDynamicAssembly() + { + var systemInfoAssemblyLocationMethod = GetAssemblyLocationInfoMethodCall(); + + Assert.DoesNotThrow(() => systemInfoAssemblyLocationMethod()); + } + + private static Func GetAssemblyLocationInfoMethodCall() + { + var method = typeof(SystemInfoTest).GetMethod("TestAssemblyLocationInfoMethod", new Type[0]); + var methodCall = Expression.Call(null, method, new Expression[0]); + return Expression.Lambda>(methodCall, new ParameterExpression[0]).Compile(); + } + + public static string TestAssemblyLocationInfoMethod() + { #if NETSTANDARD1_3 - return SystemInfo.AssemblyLocationInfo(typeof(SystemInfoTest).GetTypeInfo().Assembly); + return SystemInfo.AssemblyLocationInfo(typeof(SystemInfoTest).GetTypeInfo().Assembly); #else - return SystemInfo.AssemblyLocationInfo(Assembly.GetCallingAssembly()); + return SystemInfo.AssemblyLocationInfo(Assembly.GetCallingAssembly()); #endif - } + } #endif - [Test] - public void TestGetTypeFromStringFullyQualified() - { - Type t; + [Test] + public void TestGetTypeFromStringFullyQualified() + { + Type t; - t = GetTypeFromString("log4net.Tests.Util.SystemInfoTest,log4net.Tests", false, false); - Assert.AreSame(typeof(SystemInfoTest), t, "Test explicit case sensitive type load"); + t = GetTypeFromString("log4net.Tests.Util.SystemInfoTest,log4net.Tests", false, false); + Assert.AreSame(typeof(SystemInfoTest), t, "Test explicit case sensitive type load"); - t = GetTypeFromString("LOG4NET.TESTS.UTIL.SYSTEMINFOTEST,log4net.Tests", false, true); - Assert.AreSame(typeof(SystemInfoTest), t, "Test explicit case in-sensitive type load caps"); + t = GetTypeFromString("LOG4NET.TESTS.UTIL.SYSTEMINFOTEST,log4net.Tests", false, true); + Assert.AreSame(typeof(SystemInfoTest), t, "Test explicit case in-sensitive type load caps"); - t = GetTypeFromString("log4net.tests.util.systeminfotest,log4net.Tests", false, true); - Assert.AreSame(typeof(SystemInfoTest), t, "Test explicit case in-sensitive type load lower"); - } + t = GetTypeFromString("log4net.tests.util.systeminfotest,log4net.Tests", false, true); + Assert.AreSame(typeof(SystemInfoTest), t, "Test explicit case in-sensitive type load lower"); + } #if !NETSTANDARD1_3 - [Test][Platform(Include="Win")] - public void TestGetTypeFromStringCaseInsensitiveOnAssemblyName() - { - Type t; + [Test][Platform(Include="Win")] + public void TestGetTypeFromStringCaseInsensitiveOnAssemblyName() + { + Type t; - t = GetTypeFromString("LOG4NET.TESTS.UTIL.SYSTEMINFOTEST,LOG4NET.TESTS", false, true); - Assert.AreSame(typeof(SystemInfoTest), t, "Test explicit case in-sensitive type load caps"); + t = GetTypeFromString("LOG4NET.TESTS.UTIL.SYSTEMINFOTEST,LOG4NET.TESTS", false, true); + Assert.AreSame(typeof(SystemInfoTest), t, "Test explicit case in-sensitive type load caps"); - t = GetTypeFromString("log4net.tests.util.systeminfotest,log4net.tests", false, true); - Assert.AreSame(typeof(SystemInfoTest), t, "Test explicit case in-sensitive type load lower"); - } + t = GetTypeFromString("log4net.tests.util.systeminfotest,log4net.tests", false, true); + Assert.AreSame(typeof(SystemInfoTest), t, "Test explicit case in-sensitive type load lower"); + } #endif - [Test] - public void TestGetTypeFromStringRelative() - { - Type t; + [Test] + public void TestGetTypeFromStringRelative() + { + Type t; - t = GetTypeFromString("log4net.Tests.Util.SystemInfoTest", false, false); - Assert.AreSame(typeof(SystemInfoTest), t, "Test explicit case sensitive type load"); + t = GetTypeFromString("log4net.Tests.Util.SystemInfoTest", false, false); + Assert.AreSame(typeof(SystemInfoTest), t, "Test explicit case sensitive type load"); - t = GetTypeFromString("LOG4NET.TESTS.UTIL.SYSTEMINFOTEST", false, true); - Assert.AreSame(typeof(SystemInfoTest), t, "Test explicit case in-sensitive type load caps"); + t = GetTypeFromString("LOG4NET.TESTS.UTIL.SYSTEMINFOTEST", false, true); + Assert.AreSame(typeof(SystemInfoTest), t, "Test explicit case in-sensitive type load caps"); - t = GetTypeFromString("log4net.tests.util.systeminfotest", false, true); - Assert.AreSame(typeof(SystemInfoTest), t, "Test explicit case in-sensitive type load lower"); - } + t = GetTypeFromString("log4net.tests.util.systeminfotest", false, true); + Assert.AreSame(typeof(SystemInfoTest), t, "Test explicit case in-sensitive type load lower"); + } #if !NETSTANDARD1_3 - [Test] - public void TestGetTypeFromStringSearch() - { - Type t; + [Test] + public void TestGetTypeFromStringSearch() + { + Type t; - t = GetTypeFromString("log4net.Util.SystemInfo", false, false); - Assert.AreSame(typeof(SystemInfo), t, + t = GetTypeFromString("log4net.Util.SystemInfo", false, false); + Assert.AreSame(typeof(SystemInfo), t, string.Format("Test explicit case sensitive type load found {0} rather than {1}", t.AssemblyQualifiedName, typeof(SystemInfo).AssemblyQualifiedName)); - t = GetTypeFromString("LOG4NET.UTIL.SYSTEMINFO", false, true); - Assert.AreSame(typeof(SystemInfo), t, "Test explicit case in-sensitive type load caps"); + t = GetTypeFromString("LOG4NET.UTIL.SYSTEMINFO", false, true); + Assert.AreSame(typeof(SystemInfo), t, "Test explicit case in-sensitive type load caps"); - t = GetTypeFromString("log4net.util.systeminfo", false, true); - Assert.AreSame(typeof(SystemInfo), t, "Test explicit case in-sensitive type load lower"); - } + t = GetTypeFromString("log4net.util.systeminfo", false, true); + Assert.AreSame(typeof(SystemInfo), t, "Test explicit case in-sensitive type load lower"); + } #endif - [Test] - public void TestGetTypeFromStringFails1() - { - Type t; + [Test] + public void TestGetTypeFromStringFails1() + { + Type t; - t = GetTypeFromString("LOG4NET.TESTS.UTIL.SYSTEMINFOTEST,LOG4NET.TESTS", false, false); - Assert.AreSame(null, t, "Test explicit case sensitive fails type load"); + t = GetTypeFromString("LOG4NET.TESTS.UTIL.SYSTEMINFOTEST,LOG4NET.TESTS", false, false); + Assert.AreSame(null, t, "Test explicit case sensitive fails type load"); - Assert.Throws(() => GetTypeFromString("LOG4NET.TESTS.UTIL.SYSTEMINFOTEST,LOG4NET.TESTS", true, false)); - } + Assert.Throws(() => GetTypeFromString("LOG4NET.TESTS.UTIL.SYSTEMINFOTEST,LOG4NET.TESTS", true, false)); + } - [Test] - public void TestGetTypeFromStringFails2() - { - Type t; + [Test] + public void TestGetTypeFromStringFails2() + { + Type t; - t = GetTypeFromString("LOG4NET.TESTS.UTIL.SYSTEMINFOTEST", false, false); - Assert.AreSame(null, t, "Test explicit case sensitive fails type load"); + t = GetTypeFromString("LOG4NET.TESTS.UTIL.SYSTEMINFOTEST", false, false); + Assert.AreSame(null, t, "Test explicit case sensitive fails type load"); Assert.Throws(() => GetTypeFromString("LOG4NET.TESTS.UTIL.SYSTEMINFOTEST", true, false)); - } + } - // Wraps SystemInfo.GetTypeFromString because the method relies on GetCallingAssembly, which is - // unavailable in CoreFX. As a workaround, only overloads which explicitly take a Type or Assembly - // are exposed for NETSTANDARD1_3. - private Type GetTypeFromString(string typeName, bool throwOnError, bool ignoreCase) - { + // Wraps SystemInfo.GetTypeFromString because the method relies on GetCallingAssembly, which is + // unavailable in CoreFX. As a workaround, only overloads which explicitly take a Type or Assembly + // are exposed for NETSTANDARD1_3. + private Type GetTypeFromString(string typeName, bool throwOnError, bool ignoreCase) + { #if NETSTANDARD1_3 - return SystemInfo.GetTypeFromString(GetType().GetTypeInfo().Assembly, typeName, throwOnError, ignoreCase); + return SystemInfo.GetTypeFromString(GetType().GetTypeInfo().Assembly, typeName, throwOnError, ignoreCase); #else - return SystemInfo.GetTypeFromString(typeName, throwOnError, ignoreCase); + return SystemInfo.GetTypeFromString(typeName, throwOnError, ignoreCase); #endif - } + } [Test] public void EqualsIgnoringCase_BothNull_true() @@ -205,5 +205,5 @@ public void EqualsIgnoringCase_DifferentStrings_false() { Assert.False(SystemInfo.EqualsIgnoringCase("foo", "foobar")); } - } + } } diff --git a/src/log4net.Tests/Utils.cs b/src/log4net.Tests/Utils.cs index ea1bc825..d4ad6316 100644 --- a/src/log4net.Tests/Utils.cs +++ b/src/log4net.Tests/Utils.cs @@ -23,96 +23,96 @@ namespace log4net.Tests { - /// - /// Summary description for Class1. - /// - public class Utils - { - private Utils() - { - } - - public static object CreateInstance(string targetType) - { - return CreateInstance(Type.GetType(targetType, true, true)); - } - - public static object CreateInstance(Type targetType) - { + /// + /// Summary description for Class1. + /// + public class Utils + { + private Utils() + { + } + + public static object CreateInstance(string targetType) + { + return CreateInstance(Type.GetType(targetType, true, true)); + } + + public static object CreateInstance(Type targetType) + { #if NETSTANDARD1_3 - return targetType.GetConstructor(new Type[0]).Invoke(null); + return targetType.GetConstructor(new Type[0]).Invoke(null); #else - return targetType.GetConstructor(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, null, new Type[0], null).Invoke(null); + return targetType.GetConstructor(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, null, new Type[0], null).Invoke(null); #endif - } + } - public static object InvokeMethod(object target, string name, params object[] args) - { + public static object InvokeMethod(object target, string name, params object[] args) + { #if NETSTANDARD1_3 - return target.GetType().GetTypeInfo().GetDeclaredMethod(name).Invoke(target, args); + return target.GetType().GetTypeInfo().GetDeclaredMethod(name).Invoke(target, args); #else - return target.GetType().GetMethod(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance, null, GetTypesArray(args), null).Invoke(target, args); + return target.GetType().GetMethod(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance, null, GetTypesArray(args), null).Invoke(target, args); #endif - } + } - public static object InvokeMethod(Type target, string name, params object[] args) - { + public static object InvokeMethod(Type target, string name, params object[] args) + { #if NETSTANDARD1_3 - return target.GetTypeInfo().GetDeclaredMethod(name).Invoke(null, args); + return target.GetTypeInfo().GetDeclaredMethod(name).Invoke(null, args); #else - return target.GetMethod(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static, null, GetTypesArray(args), null).Invoke(null, args); + return target.GetMethod(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static, null, GetTypesArray(args), null).Invoke(null, args); #endif - } - - public static object GetField(object target, string name) - { - return target.GetType().GetField(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance).GetValue(target); - } - - public static void SetField(object target, string name, object val) - { - target.GetType().GetField(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance).SetValue(target, val); - } - - public static object GetProperty(object target, string name) - { - return target.GetType().GetProperty(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance).GetValue(target, null); - } - - public static void SetProperty(object target, string name, object val) - { - target.GetType().GetProperty(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance).SetValue(target, val, null); - } - - public static object GetProperty(object target, string name, params object[] index) - { - return target.GetType().GetProperty(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance).GetValue(target, index); - } - - public static void SetProperty(object target, string name, object val, params object[] index) - { - target.GetType().GetProperty(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance).SetValue(target, val, index); - } - - private static Type[] GetTypesArray(object[] args) - { - Type[] types = new Type[args.Length]; - - for(int i = 0; i < args.Length; i++) - { - if (args[i] == null) - { - types[i] = typeof(object); - } - else - { - types[i] = args[i].GetType(); - } - } - - return types; - } + } + + public static object GetField(object target, string name) + { + return target.GetType().GetField(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance).GetValue(target); + } + + public static void SetField(object target, string name, object val) + { + target.GetType().GetField(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance).SetValue(target, val); + } + + public static object GetProperty(object target, string name) + { + return target.GetType().GetProperty(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance).GetValue(target, null); + } + + public static void SetProperty(object target, string name, object val) + { + target.GetType().GetProperty(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance).SetValue(target, val, null); + } + + public static object GetProperty(object target, string name, params object[] index) + { + return target.GetType().GetProperty(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance).GetValue(target, index); + } + + public static void SetProperty(object target, string name, object val, params object[] index) + { + target.GetType().GetProperty(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance).SetValue(target, val, index); + } + + private static Type[] GetTypesArray(object[] args) + { + Type[] types = new Type[args.Length]; + + for(int i = 0; i < args.Length; i++) + { + if (args[i] == null) + { + types[i] = typeof(object); + } + else + { + types[i] = args[i].GetType(); + } + } + + return types; + } internal const string PROPERTY_KEY = "prop1"; From 788cf6edf3905b13674afb7070a2a4a4870d8455 Mon Sep 17 00:00:00 2001 From: Jan Friedrich Date: Tue, 5 Mar 2024 13:35:29 +0100 Subject: [PATCH 6/6] format documents (test project) --- .../Appender/AdoNet/Log4NetCommand.cs | 232 +- .../Appender/AdoNet/Log4NetConnection.cs | 164 +- .../Appender/AdoNet/Log4NetParameter.cs | 148 +- .../AdoNet/Log4NetParameterCollection.cs | 62 +- .../Appender/AdoNet/Log4NetTransaction.cs | 54 +- .../Appender/AdoNetAppenderTest.cs | 306 +- .../Appender/DebugAppenderTest.cs | 210 +- .../Appender/EventLogAppenderTest.cs | 24 +- .../Appender/MemoryAppenderTest.cs | 91 +- .../Appender/RemotingAppenderTest.cs | 44 +- .../Appender/RollingFileAppenderTest.cs | 3810 ++++++++--------- .../Appender/SmtpPickupDirAppenderTest.cs | 4 +- .../Appender/TraceAppenderTest.cs | 134 +- .../Context/ThreadContextTest.cs | 406 +- src/log4net.Tests/Core/FixingTest.cs | 38 +- src/log4net.Tests/Filter/FilterTest.cs | 109 +- src/log4net.Tests/Hierarchy/Hierarchy.cs | 128 +- .../Layout/DynamicPatternLayoutTest.cs | 26 +- src/log4net.Tests/Layout/PatternLayoutTest.cs | 348 +- src/log4net.Tests/Layout/XmlLayoutTest.cs | 117 +- .../LoggerRepository/ConfigurationMessages.cs | 84 +- .../NUnitTestRunnerInitializer.cs | 18 +- src/log4net.Tests/Signing.cs | 26 +- .../Util/EnvironmentPatternConverterTest.cs | 130 +- src/log4net.Tests/Util/LogLogTest.cs | 152 +- .../Util/PatternConverterTest.cs | 172 +- src/log4net.Tests/Util/PatternStringTest.cs | 124 +- .../Util/PropertiesDictionaryTest.cs | 4 +- src/log4net.Tests/Util/SystemInfoTest.cs | 75 +- src/log4net.Tests/Util/TransformTest.cs | 31 +- src/log4net.Tests/Utils.cs | 33 +- 31 files changed, 3671 insertions(+), 3633 deletions(-) diff --git a/src/log4net.Tests/Appender/AdoNet/Log4NetCommand.cs b/src/log4net.Tests/Appender/AdoNet/Log4NetCommand.cs index 98beb8e2..9cf82a85 100644 --- a/src/log4net.Tests/Appender/AdoNet/Log4NetCommand.cs +++ b/src/log4net.Tests/Appender/AdoNet/Log4NetCommand.cs @@ -24,121 +24,121 @@ namespace log4net.Tests.Appender.AdoNet { - public class Log4NetCommand : IDbCommand - { - #region AdoNetAppender - - private static Log4NetCommand mostRecentInstance; - - private IDbTransaction transaction; - private string commandText; - private readonly IDataParameterCollection parameters; - private CommandType commandType; - private int executeNonQueryCount; - - public Log4NetCommand() - { - mostRecentInstance = this; - - parameters = new Log4NetParameterCollection(); - } - - public void Dispose() - { - // empty - } - - public IDbTransaction Transaction - { - get { return transaction; } - set { transaction = value; } - } - - public int ExecuteNonQuery() - { - executeNonQueryCount++; - return 0; - } - - public int ExecuteNonQueryCount - { - get { return executeNonQueryCount; } - } - - public IDbDataParameter CreateParameter() - { - return new Log4NetParameter(); - } - - public string CommandText - { - get { return commandText; } - set { commandText = value; } - } - - public CommandType CommandType - { - get { return commandType; } - set { commandType = value; } - } - - public void Prepare() - { - // empty - } - - public IDataParameterCollection Parameters - { - get { return parameters; } - } - - public static Log4NetCommand MostRecentInstance - { - get { return mostRecentInstance; } - } - - #endregion - - #region Not Implemented - - public void Cancel() - { - throw new NotImplementedException(); - } - - public IDataReader ExecuteReader() - { - throw new NotImplementedException(); - } - - public IDataReader ExecuteReader(CommandBehavior behavior) - { - throw new NotImplementedException(); - } - - public object ExecuteScalar() - { - throw new NotImplementedException(); - } - - public IDbConnection Connection - { - get { throw new NotImplementedException(); } - set { throw new NotImplementedException(); } - } - - public int CommandTimeout - { - get { throw new NotImplementedException(); } - set { throw new NotImplementedException(); } - } - - public UpdateRowSource UpdatedRowSource - { - get { throw new NotImplementedException(); } - set { throw new NotImplementedException(); } - } - - #endregion + public class Log4NetCommand : IDbCommand + { + #region AdoNetAppender + + private static Log4NetCommand mostRecentInstance; + + private IDbTransaction transaction; + private string commandText; + private readonly IDataParameterCollection parameters; + private CommandType commandType; + private int executeNonQueryCount; + + public Log4NetCommand() + { + mostRecentInstance = this; + + parameters = new Log4NetParameterCollection(); + } + + public void Dispose() + { + // empty + } + + public IDbTransaction Transaction + { + get { return transaction; } + set { transaction = value; } + } + + public int ExecuteNonQuery() + { + executeNonQueryCount++; + return 0; + } + + public int ExecuteNonQueryCount + { + get { return executeNonQueryCount; } + } + + public IDbDataParameter CreateParameter() + { + return new Log4NetParameter(); + } + + public string CommandText + { + get { return commandText; } + set { commandText = value; } } + + public CommandType CommandType + { + get { return commandType; } + set { commandType = value; } + } + + public void Prepare() + { + // empty + } + + public IDataParameterCollection Parameters + { + get { return parameters; } + } + + public static Log4NetCommand MostRecentInstance + { + get { return mostRecentInstance; } + } + + #endregion + + #region Not Implemented + + public void Cancel() + { + throw new NotImplementedException(); + } + + public IDataReader ExecuteReader() + { + throw new NotImplementedException(); + } + + public IDataReader ExecuteReader(CommandBehavior behavior) + { + throw new NotImplementedException(); + } + + public object ExecuteScalar() + { + throw new NotImplementedException(); + } + + public IDbConnection Connection + { + get { throw new NotImplementedException(); } + set { throw new NotImplementedException(); } + } + + public int CommandTimeout + { + get { throw new NotImplementedException(); } + set { throw new NotImplementedException(); } + } + + public UpdateRowSource UpdatedRowSource + { + get { throw new NotImplementedException(); } + set { throw new NotImplementedException(); } + } + + #endregion + } } diff --git a/src/log4net.Tests/Appender/AdoNet/Log4NetConnection.cs b/src/log4net.Tests/Appender/AdoNet/Log4NetConnection.cs index 33bbcce0..cabcb0ae 100644 --- a/src/log4net.Tests/Appender/AdoNet/Log4NetConnection.cs +++ b/src/log4net.Tests/Appender/AdoNet/Log4NetConnection.cs @@ -24,88 +24,88 @@ namespace log4net.Tests.Appender.AdoNet { - public class Log4NetConnection : IDbConnection + public class Log4NetConnection : IDbConnection + { + #region AdoNetAppender + + private static Log4NetConnection mostRecentInstance; + + private bool open; + private string connectionString; + + public Log4NetConnection() + { + mostRecentInstance = this; + } + + public void Close() + { + open = false; + } + + public ConnectionState State + { + get + { + return open ? ConnectionState.Open : ConnectionState.Closed; + } + } + + public string ConnectionString + { + get { return connectionString; } + set { connectionString = value; } + } + + public IDbTransaction BeginTransaction() + { + return new Log4NetTransaction(); + } + + public IDbCommand CreateCommand() + { + return new Log4NetCommand(); + } + + public void Open() { - #region AdoNetAppender - - private static Log4NetConnection mostRecentInstance; - - private bool open; - private string connectionString; - - public Log4NetConnection() - { - mostRecentInstance = this; - } - - public void Close() - { - open = false; - } - - public ConnectionState State - { - get - { - return open ? ConnectionState.Open : ConnectionState.Closed; - } - } - - public string ConnectionString - { - get { return connectionString; } - set { connectionString = value; } - } - - public IDbTransaction BeginTransaction() - { - return new Log4NetTransaction(); - } - - public IDbCommand CreateCommand() - { - return new Log4NetCommand(); - } - - public void Open() - { - open = true; - } - - public static Log4NetConnection MostRecentInstance - { - get { return mostRecentInstance; } - } - - #endregion - - #region Not Implemented - - public IDbTransaction BeginTransaction(IsolationLevel il) - { - throw new NotImplementedException(); - } - - public void ChangeDatabase(string databaseName) - { - throw new NotImplementedException(); - } - - public int ConnectionTimeout - { - get { throw new NotImplementedException(); } - } - - public string Database - { - get { throw new NotImplementedException(); } - } - - public void Dispose() - { - throw new NotImplementedException(); - } - - #endregion + open = true; } + + public static Log4NetConnection MostRecentInstance + { + get { return mostRecentInstance; } + } + + #endregion + + #region Not Implemented + + public IDbTransaction BeginTransaction(IsolationLevel il) + { + throw new NotImplementedException(); + } + + public void ChangeDatabase(string databaseName) + { + throw new NotImplementedException(); + } + + public int ConnectionTimeout + { + get { throw new NotImplementedException(); } + } + + public string Database + { + get { throw new NotImplementedException(); } + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + #endregion + } } diff --git a/src/log4net.Tests/Appender/AdoNet/Log4NetParameter.cs b/src/log4net.Tests/Appender/AdoNet/Log4NetParameter.cs index 4eb038d3..d79621a6 100644 --- a/src/log4net.Tests/Appender/AdoNet/Log4NetParameter.cs +++ b/src/log4net.Tests/Appender/AdoNet/Log4NetParameter.cs @@ -24,80 +24,80 @@ namespace log4net.Tests.Appender.AdoNet { - public class Log4NetParameter : IDbDataParameter + public class Log4NetParameter : IDbDataParameter + { + #region AdoNetAppender + + private string parameterName; + private byte precision; + private byte scale; + private int size; + private DbType dbType; + private object value; + + public string ParameterName { - #region AdoNetAppender - - private string parameterName; - private byte precision; - private byte scale; - private int size; - private DbType dbType; - private object value; - - public string ParameterName - { - get { return parameterName; } - set { parameterName = value; } - } - - public byte Precision - { - get { return precision; } - set { precision = value; } - } - - public byte Scale - { - get { return scale; } - set { scale = value; } - } - - public int Size - { - get { return size; } - set { size = value; } - } - - public DbType DbType - { - get { return dbType; } - set { dbType = value; } - } - - public object Value - { - get { return value; } - set { this.value = value; } - } - - #endregion - - #region Not Implemented - - public ParameterDirection Direction - { - get { throw new NotImplementedException(); } - set { throw new NotImplementedException(); } - } - - public bool IsNullable - { - get { throw new NotImplementedException(); } - } - - public string SourceColumn - { - get { throw new NotImplementedException(); } - set { throw new NotImplementedException(); } - } - - public DataRowVersion SourceVersion - { - get { throw new NotImplementedException(); } - set { throw new NotImplementedException(); } - } - - #endregion + get { return parameterName; } + set { parameterName = value; } } + + public byte Precision + { + get { return precision; } + set { precision = value; } + } + + public byte Scale + { + get { return scale; } + set { scale = value; } + } + + public int Size + { + get { return size; } + set { size = value; } + } + + public DbType DbType + { + get { return dbType; } + set { dbType = value; } + } + + public object Value + { + get { return value; } + set { this.value = value; } + } + + #endregion + + #region Not Implemented + + public ParameterDirection Direction + { + get { throw new NotImplementedException(); } + set { throw new NotImplementedException(); } + } + + public bool IsNullable + { + get { throw new NotImplementedException(); } + } + + public string SourceColumn + { + get { throw new NotImplementedException(); } + set { throw new NotImplementedException(); } + } + + public DataRowVersion SourceVersion + { + get { throw new NotImplementedException(); } + set { throw new NotImplementedException(); } + } + + #endregion + } } diff --git a/src/log4net.Tests/Appender/AdoNet/Log4NetParameterCollection.cs b/src/log4net.Tests/Appender/AdoNet/Log4NetParameterCollection.cs index 8b0d0415..c0107698 100644 --- a/src/log4net.Tests/Appender/AdoNet/Log4NetParameterCollection.cs +++ b/src/log4net.Tests/Appender/AdoNet/Log4NetParameterCollection.cs @@ -25,45 +25,45 @@ namespace log4net.Tests.Appender.AdoNet { - public class Log4NetParameterCollection : CollectionBase, IDataParameterCollection - { - #region AdoNetAppender - - private readonly Hashtable parameterNameToIndex = new Hashtable(); + public class Log4NetParameterCollection : CollectionBase, IDataParameterCollection + { + #region AdoNetAppender - protected override void OnInsertComplete(int index, object value) - { - base.OnInsertComplete(index, value); + private readonly Hashtable parameterNameToIndex = new Hashtable(); - IDataParameter param = (IDataParameter)value; - parameterNameToIndex[param.ParameterName] = index; - } + protected override void OnInsertComplete(int index, object value) + { + base.OnInsertComplete(index, value); - public int IndexOf(string parameterName) - { - return (int)parameterNameToIndex[parameterName]; - } + IDataParameter param = (IDataParameter)value; + parameterNameToIndex[param.ParameterName] = index; + } - public object this[string parameterName] - { - get { return InnerList[IndexOf(parameterName)]; } - set { InnerList[IndexOf(parameterName)] = value; } - } + public int IndexOf(string parameterName) + { + return (int)parameterNameToIndex[parameterName]; + } - #endregion + public object this[string parameterName] + { + get { return InnerList[IndexOf(parameterName)]; } + set { InnerList[IndexOf(parameterName)] = value; } + } - #region Not Implemented + #endregion - public void RemoveAt(string parameterName) - { - throw new NotImplementedException(); - } + #region Not Implemented - public bool Contains(string parameterName) - { - throw new NotImplementedException(); - } + public void RemoveAt(string parameterName) + { + throw new NotImplementedException(); + } - #endregion + public bool Contains(string parameterName) + { + throw new NotImplementedException(); } + + #endregion + } } diff --git a/src/log4net.Tests/Appender/AdoNet/Log4NetTransaction.cs b/src/log4net.Tests/Appender/AdoNet/Log4NetTransaction.cs index d52e3643..ab415ae9 100644 --- a/src/log4net.Tests/Appender/AdoNet/Log4NetTransaction.cs +++ b/src/log4net.Tests/Appender/AdoNet/Log4NetTransaction.cs @@ -24,39 +24,39 @@ namespace log4net.Tests.Appender.AdoNet { - public class Log4NetTransaction : IDbTransaction - { - #region AdoNetAppender - - public void Commit() - { - // empty - } + public class Log4NetTransaction : IDbTransaction + { + #region AdoNetAppender - public void Rollback() - { - // empty - } + public void Commit() + { + // empty + } - #endregion + public void Rollback() + { + // empty + } - #region Not Implemented + #endregion - public IDbConnection Connection - { - get { throw new NotImplementedException(); } - } + #region Not Implemented - public IsolationLevel IsolationLevel - { - get { throw new NotImplementedException(); } - } + public IDbConnection Connection + { + get { throw new NotImplementedException(); } + } - public void Dispose() - { - throw new NotImplementedException(); - } + public IsolationLevel IsolationLevel + { + get { throw new NotImplementedException(); } + } - #endregion + public void Dispose() + { + throw new NotImplementedException(); } + + #endregion + } } diff --git a/src/log4net.Tests/Appender/AdoNetAppenderTest.cs b/src/log4net.Tests/Appender/AdoNetAppenderTest.cs index 1b48f269..1b4eedf2 100644 --- a/src/log4net.Tests/Appender/AdoNetAppenderTest.cs +++ b/src/log4net.Tests/Appender/AdoNetAppenderTest.cs @@ -38,67 +38,67 @@ namespace log4net.Tests.Appender { - [TestFixture] - public class AdoNetAppenderTest + [TestFixture] + public class AdoNetAppenderTest + { + [Test] + public void NoBufferingTest() { - [Test] - public void NoBufferingTest() - { - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - AdoNetAppender adoNetAppender = new AdoNetAppender(); - adoNetAppender.BufferSize = -1; + AdoNetAppender adoNetAppender = new AdoNetAppender(); + adoNetAppender.BufferSize = -1; #if NETSTANDARD1_3 adoNetAppender.ConnectionType = typeof(Log4NetConnection).AssemblyQualifiedName; #else - adoNetAppender.ConnectionType = "log4net.Tests.Appender.AdoNet.Log4NetConnection"; + adoNetAppender.ConnectionType = "log4net.Tests.Appender.AdoNet.Log4NetConnection"; #endif - adoNetAppender.ActivateOptions(); + adoNetAppender.ActivateOptions(); - BasicConfigurator.Configure(rep, adoNetAppender); + BasicConfigurator.Configure(rep, adoNetAppender); - ILog log = LogManager.GetLogger(rep.Name, "NoBufferingTest"); - log.Debug("Message"); - Assert.NotNull(Log4NetCommand.MostRecentInstance); - Assert.AreEqual(1, Log4NetCommand.MostRecentInstance.ExecuteNonQueryCount); - } + ILog log = LogManager.GetLogger(rep.Name, "NoBufferingTest"); + log.Debug("Message"); + Assert.NotNull(Log4NetCommand.MostRecentInstance); + Assert.AreEqual(1, Log4NetCommand.MostRecentInstance.ExecuteNonQueryCount); + } - [Test] - public void BufferingTest() - { - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + [Test] + public void BufferingTest() + { + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - int bufferSize = 5; + int bufferSize = 5; - AdoNetAppender adoNetAppender = new AdoNetAppender(); - adoNetAppender.BufferSize = bufferSize; + AdoNetAppender adoNetAppender = new AdoNetAppender(); + adoNetAppender.BufferSize = bufferSize; #if NETSTANDARD1_3 adoNetAppender.ConnectionType = typeof(Log4NetConnection).AssemblyQualifiedName; #else - adoNetAppender.ConnectionType = "log4net.Tests.Appender.AdoNet.Log4NetConnection"; + adoNetAppender.ConnectionType = "log4net.Tests.Appender.AdoNet.Log4NetConnection"; #endif - adoNetAppender.ActivateOptions(); - - BasicConfigurator.Configure(rep, adoNetAppender); - - ILog log = LogManager.GetLogger(rep.Name, "BufferingTest"); - for (int i = 0; i < bufferSize; i++) - { - log.Debug("Message"); - Assert.IsNull(Log4NetCommand.MostRecentInstance); - } - log.Debug("Message"); - Assert.NotNull(Log4NetCommand.MostRecentInstance); - Assert.AreEqual(bufferSize+1, Log4NetCommand.MostRecentInstance.ExecuteNonQueryCount); - } + adoNetAppender.ActivateOptions(); + + BasicConfigurator.Configure(rep, adoNetAppender); + + ILog log = LogManager.GetLogger(rep.Name, "BufferingTest"); + for (int i = 0; i < bufferSize; i++) + { + log.Debug("Message"); + Assert.IsNull(Log4NetCommand.MostRecentInstance); + } + log.Debug("Message"); + Assert.NotNull(Log4NetCommand.MostRecentInstance); + Assert.AreEqual(bufferSize + 1, Log4NetCommand.MostRecentInstance.ExecuteNonQueryCount); + } #if !NETSTANDARD1_3 - [Test] - public void WebsiteExample() - { - XmlDocument log4netConfig = new XmlDocument(); - #region Load log4netConfig - log4netConfig.LoadXml(@" + [Test] + public void WebsiteExample() + { + XmlDocument log4netConfig = new XmlDocument(); + #region Load log4netConfig + log4netConfig.LoadXml(@" @@ -154,41 +154,41 @@ public void WebsiteExample() "); - #endregion - - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - XmlConfigurator.Configure(rep, log4netConfig["log4net"]); - ILog log = LogManager.GetLogger(rep.Name, "WebsiteExample"); - log.Debug("Message"); - - IDbCommand command = Log4NetCommand.MostRecentInstance; - - Assert.NotNull(command); - Assert.AreEqual( - "INSERT INTO Log ([Date],[Thread],[Level],[Logger],[Message],[Exception]) VALUES (@log_date, @thread, @log_level, @logger, @message, @exception)", - command.CommandText); - - Assert.AreEqual(6, command.Parameters.Count); - - IDbDataParameter param = (IDbDataParameter)command.Parameters["@message"]; - Assert.AreEqual("Message", param.Value); - - param = (IDbDataParameter)command.Parameters["@log_level"]; - Assert.AreEqual(Level.Debug.ToString(), param.Value); - - param = (IDbDataParameter)command.Parameters["@logger"]; - Assert.AreEqual("WebsiteExample", param.Value); - - param = (IDbDataParameter)command.Parameters["@exception"]; - Assert.IsEmpty((string)param.Value); - } - - [Test] - public void BufferingWebsiteExample() - { - XmlDocument log4netConfig = new XmlDocument(); - #region Load log4netConfig - log4netConfig.LoadXml(@" + #endregion + + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + XmlConfigurator.Configure(rep, log4netConfig["log4net"]); + ILog log = LogManager.GetLogger(rep.Name, "WebsiteExample"); + log.Debug("Message"); + + IDbCommand command = Log4NetCommand.MostRecentInstance; + + Assert.NotNull(command); + Assert.AreEqual( + "INSERT INTO Log ([Date],[Thread],[Level],[Logger],[Message],[Exception]) VALUES (@log_date, @thread, @log_level, @logger, @message, @exception)", + command.CommandText); + + Assert.AreEqual(6, command.Parameters.Count); + + IDbDataParameter param = (IDbDataParameter)command.Parameters["@message"]; + Assert.AreEqual("Message", param.Value); + + param = (IDbDataParameter)command.Parameters["@log_level"]; + Assert.AreEqual(Level.Debug.ToString(), param.Value); + + param = (IDbDataParameter)command.Parameters["@logger"]; + Assert.AreEqual("WebsiteExample", param.Value); + + param = (IDbDataParameter)command.Parameters["@exception"]; + Assert.IsEmpty((string)param.Value); + } + + [Test] + public void BufferingWebsiteExample() + { + XmlDocument log4netConfig = new XmlDocument(); + #region Load log4netConfig + log4netConfig.LoadXml(@" @@ -244,46 +244,46 @@ public void BufferingWebsiteExample() "); - #endregion + #endregion - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - XmlConfigurator.Configure(rep, log4netConfig["log4net"]); - ILog log = LogManager.GetLogger(rep.Name, "WebsiteExample"); + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + XmlConfigurator.Configure(rep, log4netConfig["log4net"]); + ILog log = LogManager.GetLogger(rep.Name, "WebsiteExample"); - for (int i = 0; i < 3; i++) - { - log.Debug("Message"); - } + for (int i = 0; i < 3; i++) + { + log.Debug("Message"); + } - IDbCommand command = Log4NetCommand.MostRecentInstance; + IDbCommand command = Log4NetCommand.MostRecentInstance; - Assert.NotNull(command); - Assert.AreEqual( - "INSERT INTO Log ([Date],[Thread],[Level],[Logger],[Message],[Exception]) VALUES (@log_date, @thread, @log_level, @logger, @message, @exception)", - command.CommandText); + Assert.NotNull(command); + Assert.AreEqual( + "INSERT INTO Log ([Date],[Thread],[Level],[Logger],[Message],[Exception]) VALUES (@log_date, @thread, @log_level, @logger, @message, @exception)", + command.CommandText); - Assert.AreEqual(6, command.Parameters.Count); + Assert.AreEqual(6, command.Parameters.Count); - IDbDataParameter param = (IDbDataParameter)command.Parameters["@message"]; - Assert.AreEqual("Message", param.Value); + IDbDataParameter param = (IDbDataParameter)command.Parameters["@message"]; + Assert.AreEqual("Message", param.Value); - param = (IDbDataParameter)command.Parameters["@log_level"]; - Assert.AreEqual(Level.Debug.ToString(), param.Value); + param = (IDbDataParameter)command.Parameters["@log_level"]; + Assert.AreEqual(Level.Debug.ToString(), param.Value); - param = (IDbDataParameter)command.Parameters["@logger"]; - Assert.AreEqual("WebsiteExample", param.Value); + param = (IDbDataParameter)command.Parameters["@logger"]; + Assert.AreEqual("WebsiteExample", param.Value); - param = (IDbDataParameter)command.Parameters["@exception"]; - Assert.IsEmpty((string)param.Value); - } + param = (IDbDataParameter)command.Parameters["@exception"]; + Assert.IsEmpty((string)param.Value); + } #endif - [Test] - public void NullPropertyXmlConfig() - { - XmlDocument log4netConfig = new XmlDocument(); - #region Load log4netConfig - log4netConfig.LoadXml(@" + [Test] + public void NullPropertyXmlConfig() + { + XmlDocument log4netConfig = new XmlDocument(); + #region Load log4netConfig + log4netConfig.LoadXml(@" @@ -304,54 +304,54 @@ public void NullPropertyXmlConfig() "); - #endregion - - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - XmlConfigurator.Configure(rep, log4netConfig["log4net"]); - ILog log = LogManager.GetLogger(rep.Name, "NullPropertyXmlConfig"); - - log.Debug("Message"); - IDbCommand command = Log4NetCommand.MostRecentInstance; - Assert.NotNull(command); - - IDbDataParameter param = (IDbDataParameter)command.Parameters["@productId"]; - Assert.AreNotEqual(SystemInfo.NullText, param.Value); - Assert.AreEqual(DBNull.Value, param.Value); - } - - [Test] - public void NullPropertyProgmaticConfig() - { - AdoNetAppenderParameter productIdParam = new AdoNetAppenderParameter(); - productIdParam.ParameterName = "@productId"; - productIdParam.DbType = DbType.String; - productIdParam.Size = 50; - RawPropertyLayout rawPropertyLayout = new RawPropertyLayout(); - rawPropertyLayout.Key = "ProductId"; - productIdParam.Layout = rawPropertyLayout; - - AdoNetAppender appender = new AdoNetAppender(); + #endregion + + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + XmlConfigurator.Configure(rep, log4netConfig["log4net"]); + ILog log = LogManager.GetLogger(rep.Name, "NullPropertyXmlConfig"); + + log.Debug("Message"); + IDbCommand command = Log4NetCommand.MostRecentInstance; + Assert.NotNull(command); + + IDbDataParameter param = (IDbDataParameter)command.Parameters["@productId"]; + Assert.AreNotEqual(SystemInfo.NullText, param.Value); + Assert.AreEqual(DBNull.Value, param.Value); + } + + [Test] + public void NullPropertyProgmaticConfig() + { + AdoNetAppenderParameter productIdParam = new AdoNetAppenderParameter(); + productIdParam.ParameterName = "@productId"; + productIdParam.DbType = DbType.String; + productIdParam.Size = 50; + RawPropertyLayout rawPropertyLayout = new RawPropertyLayout(); + rawPropertyLayout.Key = "ProductId"; + productIdParam.Layout = rawPropertyLayout; + + AdoNetAppender appender = new AdoNetAppender(); #if NETSTANDARD1_3 appender.ConnectionType = typeof(Log4NetConnection).AssemblyQualifiedName; #else - appender.ConnectionType = typeof(Log4NetConnection).FullName; + appender.ConnectionType = typeof(Log4NetConnection).FullName; #endif - appender.BufferSize = -1; - appender.CommandText = "INSERT INTO Log ([productId]) VALUES (@productId)"; - appender.AddParameter(productIdParam); - appender.ActivateOptions(); - - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - BasicConfigurator.Configure(rep, appender); - ILog log = LogManager.GetLogger(rep.Name, "NullPropertyProgmaticConfig"); - - log.Debug("Message"); - IDbCommand command = Log4NetCommand.MostRecentInstance; - Assert.NotNull(command); - - IDbDataParameter param = (IDbDataParameter)command.Parameters["@productId"]; - Assert.AreNotEqual(SystemInfo.NullText, param.Value); - Assert.AreEqual(DBNull.Value, param.Value); - } + appender.BufferSize = -1; + appender.CommandText = "INSERT INTO Log ([productId]) VALUES (@productId)"; + appender.AddParameter(productIdParam); + appender.ActivateOptions(); + + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + BasicConfigurator.Configure(rep, appender); + ILog log = LogManager.GetLogger(rep.Name, "NullPropertyProgmaticConfig"); + + log.Debug("Message"); + IDbCommand command = Log4NetCommand.MostRecentInstance; + Assert.NotNull(command); + + IDbDataParameter param = (IDbDataParameter)command.Parameters["@productId"]; + Assert.AreNotEqual(SystemInfo.NullText, param.Value); + Assert.AreEqual(DBNull.Value, param.Value); } + } } diff --git a/src/log4net.Tests/Appender/DebugAppenderTest.cs b/src/log4net.Tests/Appender/DebugAppenderTest.cs index 89983abb..8cc26083 100644 --- a/src/log4net.Tests/Appender/DebugAppenderTest.cs +++ b/src/log4net.Tests/Appender/DebugAppenderTest.cs @@ -31,145 +31,145 @@ namespace log4net.Tests.Appender { - [TestFixture] - public class DebugAppenderTest + [TestFixture] + public class DebugAppenderTest + { + [Test] + public void NullCategoryTest() { - [Test] - public void NullCategoryTest() - { - CategoryTraceListener categoryTraceListener = new CategoryTraceListener(); - Debug.Listeners.Add(categoryTraceListener); + CategoryTraceListener categoryTraceListener = new CategoryTraceListener(); + Debug.Listeners.Add(categoryTraceListener); - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - DebugAppender debugAppender = new DebugAppender(); - debugAppender.Layout = new SimpleLayout(); - debugAppender.ActivateOptions(); + DebugAppender debugAppender = new DebugAppender(); + debugAppender.Layout = new SimpleLayout(); + debugAppender.ActivateOptions(); - debugAppender.Category = null; + debugAppender.Category = null; - TestErrorHandler testErrHandler = new TestErrorHandler(); - debugAppender.ErrorHandler = testErrHandler; + TestErrorHandler testErrHandler = new TestErrorHandler(); + debugAppender.ErrorHandler = testErrHandler; - BasicConfigurator.Configure(rep, debugAppender); + BasicConfigurator.Configure(rep, debugAppender); - ILog log = LogManager.GetLogger(rep.Name, GetType()); - log.Debug("Message"); + ILog log = LogManager.GetLogger(rep.Name, GetType()); + log.Debug("Message"); - Assert.AreEqual( - null, - categoryTraceListener.Category); + Assert.AreEqual( + null, + categoryTraceListener.Category); - Assert.IsFalse(testErrHandler.ErrorOccured); + Assert.IsFalse(testErrHandler.ErrorOccured); - Debug.Listeners.Remove(categoryTraceListener); - } - - [Test] - public void EmptyStringCategoryTest() - { - CategoryTraceListener categoryTraceListener = new CategoryTraceListener(); - Debug.Listeners.Add(categoryTraceListener); - - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - - DebugAppender debugAppender = new DebugAppender(); - debugAppender.Layout = new SimpleLayout(); - debugAppender.ActivateOptions(); - - debugAppender.Category = new PatternLayout(""); - - BasicConfigurator.Configure(rep, debugAppender); + Debug.Listeners.Remove(categoryTraceListener); + } - ILog log = LogManager.GetLogger(rep.Name, GetType()); - log.Debug("Message"); + [Test] + public void EmptyStringCategoryTest() + { + CategoryTraceListener categoryTraceListener = new CategoryTraceListener(); + Debug.Listeners.Add(categoryTraceListener); - Assert.AreEqual( - null, - categoryTraceListener.Category); + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - Debug.Listeners.Remove(categoryTraceListener); - } + DebugAppender debugAppender = new DebugAppender(); + debugAppender.Layout = new SimpleLayout(); + debugAppender.ActivateOptions(); - [Test] - public void DefaultCategoryTest() - { - CategoryTraceListener categoryTraceListener = new CategoryTraceListener(); - Debug.Listeners.Add(categoryTraceListener); + debugAppender.Category = new PatternLayout(""); - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + BasicConfigurator.Configure(rep, debugAppender); - DebugAppender debugAppender = new DebugAppender(); - debugAppender.Layout = new SimpleLayout(); - debugAppender.ActivateOptions(); + ILog log = LogManager.GetLogger(rep.Name, GetType()); + log.Debug("Message"); - BasicConfigurator.Configure(rep, debugAppender); + Assert.AreEqual( + null, + categoryTraceListener.Category); - ILog log = LogManager.GetLogger(rep.Name, GetType()); - log.Debug("Message"); + Debug.Listeners.Remove(categoryTraceListener); + } - Assert.AreEqual( - GetType().ToString(), - categoryTraceListener.Category); + [Test] + public void DefaultCategoryTest() + { + CategoryTraceListener categoryTraceListener = new CategoryTraceListener(); + Debug.Listeners.Add(categoryTraceListener); - Debug.Listeners.Remove(categoryTraceListener); - } + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - [Test] - public void MethodNameCategoryTest() - { - CategoryTraceListener categoryTraceListener = new CategoryTraceListener(); - Debug.Listeners.Add(categoryTraceListener); + DebugAppender debugAppender = new DebugAppender(); + debugAppender.Layout = new SimpleLayout(); + debugAppender.ActivateOptions(); - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + BasicConfigurator.Configure(rep, debugAppender); - DebugAppender debugAppender = new DebugAppender(); - PatternLayout methodLayout = new PatternLayout("%method"); - methodLayout.ActivateOptions(); - debugAppender.Category = methodLayout; - debugAppender.Layout = new SimpleLayout(); - debugAppender.ActivateOptions(); + ILog log = LogManager.GetLogger(rep.Name, GetType()); + log.Debug("Message"); - BasicConfigurator.Configure(rep, debugAppender); + Assert.AreEqual( + GetType().ToString(), + categoryTraceListener.Category); - ILog log = LogManager.GetLogger(rep.Name, GetType()); - log.Debug("Message"); + Debug.Listeners.Remove(categoryTraceListener); + } - Assert.AreEqual( - System.Reflection.MethodInfo.GetCurrentMethod().Name, - categoryTraceListener.Category); + [Test] + public void MethodNameCategoryTest() + { + CategoryTraceListener categoryTraceListener = new CategoryTraceListener(); + Debug.Listeners.Add(categoryTraceListener); - Debug.Listeners.Remove(categoryTraceListener); - } + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - private class TestErrorHandler : IErrorHandler - { - private bool m_errorOccured = false; + DebugAppender debugAppender = new DebugAppender(); + PatternLayout methodLayout = new PatternLayout("%method"); + methodLayout.ActivateOptions(); + debugAppender.Category = methodLayout; + debugAppender.Layout = new SimpleLayout(); + debugAppender.ActivateOptions(); - public bool ErrorOccured - { - get { return m_errorOccured; } - } - #region IErrorHandler Members + BasicConfigurator.Configure(rep, debugAppender); - public void Error(string message, Exception e, ErrorCode errorCode) - { - m_errorOccured = true; - } + ILog log = LogManager.GetLogger(rep.Name, GetType()); + log.Debug("Message"); - public void Error(string message, Exception e) - { - Error(message, e, ErrorCode.GenericFailure); - } + Assert.AreEqual( + System.Reflection.MethodInfo.GetCurrentMethod().Name, + categoryTraceListener.Category); - public void Error(string message) - { - Error(message, null, ErrorCode.GenericFailure); - } + Debug.Listeners.Remove(categoryTraceListener); + } - #endregion - } + private class TestErrorHandler : IErrorHandler + { + private bool m_errorOccured = false; + + public bool ErrorOccured + { + get { return m_errorOccured; } + } + #region IErrorHandler Members + + public void Error(string message, Exception e, ErrorCode errorCode) + { + m_errorOccured = true; + } + + public void Error(string message, Exception e) + { + Error(message, e, ErrorCode.GenericFailure); + } + + public void Error(string message) + { + Error(message, null, ErrorCode.GenericFailure); + } + + #endregion } + } } #endif diff --git a/src/log4net.Tests/Appender/EventLogAppenderTest.cs b/src/log4net.Tests/Appender/EventLogAppenderTest.cs index 7e2a5ccc..63e77715 100644 --- a/src/log4net.Tests/Appender/EventLogAppenderTest.cs +++ b/src/log4net.Tests/Appender/EventLogAppenderTest.cs @@ -46,7 +46,7 @@ public class EventLogAppenderTest public void TestGetEntryTypeForExistingApplicationName() { EventLogAppender eventAppender = new EventLogAppender(); - eventAppender.ApplicationName = "Winlogon"; + eventAppender.ApplicationName = "Winlogon"; eventAppender.ActivateOptions(); Assert.AreEqual( @@ -78,17 +78,17 @@ public void TestGetEntryTypeForExistingApplicationName() GetEntryType(eventAppender, Level.Off)); } - /// - /// ActivateOption tries to create an event source if it doesn't exist but this is going to fail on more modern Windows versions unless the code is run with local administrator privileges. - /// - [Test] - [Ignore("seems to require administrator privileges or a specific environent when run")] - public void ActivateOptionsDisablesAppenderIfSourceDoesntExist() - { - EventLogAppender eventAppender = new EventLogAppender(); - eventAppender.ActivateOptions(); - Assert.AreEqual(Level.Off, eventAppender.Threshold); - } + /// + /// ActivateOption tries to create an event source if it doesn't exist but this is going to fail on more modern Windows versions unless the code is run with local administrator privileges. + /// + [Test] + [Ignore("seems to require administrator privileges or a specific environent when run")] + public void ActivateOptionsDisablesAppenderIfSourceDoesntExist() + { + EventLogAppender eventAppender = new EventLogAppender(); + eventAppender.ActivateOptions(); + Assert.AreEqual(Level.Off, eventAppender.Threshold); + } // // Helper functions to dig into the appender diff --git a/src/log4net.Tests/Appender/MemoryAppenderTest.cs b/src/log4net.Tests/Appender/MemoryAppenderTest.cs index ceb3bb02..7bb755bc 100644 --- a/src/log4net.Tests/Appender/MemoryAppenderTest.cs +++ b/src/log4net.Tests/Appender/MemoryAppenderTest.cs @@ -32,59 +32,60 @@ namespace log4net.Tests.Appender { - [TestFixture] - public class MemoryAppenderTest - { - private static int cThreadsRunning; - private const int cThreadsMax = 10; - private const int cLogEntriesPerThread = 100; - private const long cEventsExpected = cLogEntriesPerThread * cThreadsMax; + [TestFixture] + public class MemoryAppenderTest + { + private static int cThreadsRunning; + private const int cThreadsMax = 10; + private const int cLogEntriesPerThread = 100; + private const long cEventsExpected = cLogEntriesPerThread * cThreadsMax; - [Test] - public void TestThreadSafety() - { - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - var memoryAppender = new MemoryAppender(); - var patternLayout = new PatternLayout(); - memoryAppender.Layout = patternLayout; - memoryAppender.ActivateOptions(); - BasicConfigurator.Configure(rep, memoryAppender); + [Test] + public void TestThreadSafety() + { + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + var memoryAppender = new MemoryAppender(); + var patternLayout = new PatternLayout(); + memoryAppender.Layout = patternLayout; + memoryAppender.ActivateOptions(); + BasicConfigurator.Configure(rep, memoryAppender); - cThreadsRunning = cThreadsMax; - var threads = Enumerable.Range(0, cThreadsMax) - .Select(i => new Thread(LogMessages(rep.Name))) - .ToList(); + cThreadsRunning = cThreadsMax; + var threads = Enumerable.Range(0, cThreadsMax) + .Select(i => new Thread(LogMessages(rep.Name))) + .ToList(); - foreach (var thread in threads) - { - thread.Start(); - } + foreach (var thread in threads) + { + thread.Start(); + } - long cEventsRead = 0; - while (cThreadsRunning > 0) - { - var events = memoryAppender.PopAllEvents(); - cEventsRead += events.Length; - } - foreach (var thread in threads) - { - thread.Join(); - } + long cEventsRead = 0; + while (cThreadsRunning > 0) + { + var events = memoryAppender.PopAllEvents(); + cEventsRead += events.Length; + } + foreach (var thread in threads) + { + thread.Join(); + } cEventsRead += memoryAppender.PopAllEvents().Length; - Assert.AreEqual(cEventsExpected, cEventsRead, "Log events were lost."); - } + Assert.AreEqual(cEventsExpected, cEventsRead, "Log events were lost."); + } - private static ThreadStart LogMessages(string repository) - { - return () => { - var logger = LogManager.GetLogger(repository, "LoggerThread"); - for (var i = 0; i < cLogEntriesPerThread; i++) + private static ThreadStart LogMessages(string repository) { - logger.InfoFormat("Logging message {0}", i); - } - Interlocked.Decrement(ref cThreadsRunning); + return () => + { + var logger = LogManager.GetLogger(repository, "LoggerThread"); + for (var i = 0; i < cLogEntriesPerThread; i++) + { + logger.InfoFormat("Logging message {0}", i); + } + Interlocked.Decrement(ref cThreadsRunning); }; - } } + } } #endif \ No newline at end of file diff --git a/src/log4net.Tests/Appender/RemotingAppenderTest.cs b/src/log4net.Tests/Appender/RemotingAppenderTest.cs index 56cc1c33..49a739f2 100644 --- a/src/log4net.Tests/Appender/RemotingAppenderTest.cs +++ b/src/log4net.Tests/Appender/RemotingAppenderTest.cs @@ -138,7 +138,7 @@ public void TestFullFix() private void WaitFor( string failMessage, - Func condition, + Func condition, int maxWaitMilliseconds = 5000) { var start = DateTime.Now; @@ -169,7 +169,7 @@ public void TestRemotedMessageNdcPushPop() string testMessage = string.Format("test message [ {0} ]", (new Random()).Next()); - using(NDC.Push("value")) + using (NDC.Push("value")) { } @@ -241,7 +241,7 @@ private void RegisterRemotingServerChannel() ChannelServices.RegisterChannel(m_remotingChannel); #endif } - catch(Exception ex) + catch (Exception ex) { Assert.Fail("Failed to set up LoggingSink: {0}", ex); } @@ -251,7 +251,7 @@ private void RegisterRemotingServerChannel() } } - /// + /// /// Shuts down any loggers in the hierarchy, along /// with all appenders. /// @@ -283,21 +283,25 @@ public void TearDown() ResetRepository(); } - /// - /// Close down remoting infrastructure - /// - [OneTimeTearDown] - public void UnregisterRemotingServerChannel() { - if (m_remotingChannel != null) { - ((TcpChannel) m_remotingChannel).StopListening(null); - try { - ChannelServices.UnregisterChannel(m_remotingChannel); - } - catch (Exception) { - } - m_remotingChannel = null; - } + /// + /// Close down remoting infrastructure + /// + [OneTimeTearDown] + public void UnregisterRemotingServerChannel() + { + if (m_remotingChannel != null) + { + ((TcpChannel)m_remotingChannel).StopListening(null); + try + { + ChannelServices.UnregisterChannel(m_remotingChannel); + } + catch (Exception) + { } + m_remotingChannel = null; + } + } /// /// Configures the root appender for counting and rolling @@ -420,7 +424,7 @@ public class Feature public void Test() { - using(NDC.Push("test1")) + using (NDC.Push("test1")) { log.Info("feature"); Thread.Sleep(100); @@ -444,7 +448,7 @@ public class Dal public void Test() { - using(NDC.Push("test2")) + using (NDC.Push("test2")) { log.Info("return"); Thread.Sleep(100); diff --git a/src/log4net.Tests/Appender/RollingFileAppenderTest.cs b/src/log4net.Tests/Appender/RollingFileAppenderTest.cs index 883a9c0b..c6e59387 100644 --- a/src/log4net.Tests/Appender/RollingFileAppenderTest.cs +++ b/src/log4net.Tests/Appender/RollingFileAppenderTest.cs @@ -35,2108 +35,2108 @@ namespace log4net.Tests.Appender { - /// - /// Used for internal unit testing the class. - /// - [TestFixture] - public class RollingFileAppenderTest - { - private const string c_fileName = "test_41d3d834_4320f4da.log"; - - private const string c_testMessage98Chars = - "01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567"; - - private const string c_testMessage99Chars = - "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678"; - - private const int c_iMaximumFileSize = 450; // in bytes - private int _iMessagesLoggedThisFile = 0; - private int _iMessagesLogged = 0; - private int _iCountDirection = 0; - private int _MaxSizeRollBackups = 3; - private CountingAppender _caRoot; - private Logger _root; + /// + /// Used for internal unit testing the class. + /// + [TestFixture] + public class RollingFileAppenderTest + { + private const string c_fileName = "test_41d3d834_4320f4da.log"; + + private const string c_testMessage98Chars = + "01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567"; + + private const string c_testMessage99Chars = + "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678"; + + private const int c_iMaximumFileSize = 450; // in bytes + private int _iMessagesLoggedThisFile = 0; + private int _iMessagesLogged = 0; + private int _iCountDirection = 0; + private int _MaxSizeRollBackups = 3; + private CountingAppender _caRoot; + private Logger _root; #if !NETSTANDARD1_3 - private CultureInfo _currentCulture; - private CultureInfo _currentUICulture; + private CultureInfo _currentCulture; + private CultureInfo _currentUICulture; #endif - private class SilentErrorHandler : IErrorHandler - { - private StringBuilder m_buffer = new StringBuilder(); - - public string Message - { - get { return m_buffer.ToString(); } - } - - public void Error(string message) - { - m_buffer.Append(message + "\n"); - } - - public void Error(string message, Exception e) - { - m_buffer.Append(message + "\n" + e.Message + "\n"); - } - - public void Error(string message, Exception e, ErrorCode errorCode) - { - m_buffer.Append(message + "\n" + e.Message + "\n"); - } - } + private class SilentErrorHandler : IErrorHandler + { + private StringBuilder m_buffer = new StringBuilder(); + + public string Message + { + get { return m_buffer.ToString(); } + } + + public void Error(string message) + { + m_buffer.Append(message + "\n"); + } + + public void Error(string message, Exception e) + { + m_buffer.Append(message + "\n" + e.Message + "\n"); + } + + public void Error(string message, Exception e, ErrorCode errorCode) + { + m_buffer.Append(message + "\n" + e.Message + "\n"); + } + } - /// - /// Sets up variables used for the tests - /// - private void InitializeVariables() - { - _iMessagesLoggedThisFile = 0; - _iMessagesLogged = 0; - _iCountDirection = +1; // Up - _MaxSizeRollBackups = 3; - } + /// + /// Sets up variables used for the tests + /// + private void InitializeVariables() + { + _iMessagesLoggedThisFile = 0; + _iMessagesLogged = 0; + _iCountDirection = +1; // Up + _MaxSizeRollBackups = 3; + } - /// - /// Shuts down any loggers in the hierarchy, along - /// with all appenders, and deletes any test files used - /// for logging. - /// - private static void ResetAndDeleteTestFiles() - { - // Regular users should not use the clear method lightly! - Utils.GetRepository().ResetConfiguration(); - Utils.GetRepository().Shutdown(); - ((Repository.Hierarchy.Hierarchy)Utils.GetRepository()).Clear(); + /// + /// Shuts down any loggers in the hierarchy, along + /// with all appenders, and deletes any test files used + /// for logging. + /// + private static void ResetAndDeleteTestFiles() + { + // Regular users should not use the clear method lightly! + Utils.GetRepository().ResetConfiguration(); + Utils.GetRepository().Shutdown(); + ((Repository.Hierarchy.Hierarchy)Utils.GetRepository()).Clear(); - DeleteTestFiles(); - } + DeleteTestFiles(); + } - /// - /// Any initialization that happens before each test can - /// go here - /// - [SetUp] - public void SetUp() - { - ResetAndDeleteTestFiles(); - InitializeVariables(); + /// + /// Any initialization that happens before each test can + /// go here + /// + [SetUp] + public void SetUp() + { + ResetAndDeleteTestFiles(); + InitializeVariables(); #if !NETSTANDARD1_3 - // set correct thread culture - _currentCulture = System.Threading.Thread.CurrentThread.CurrentCulture; - _currentUICulture = System.Threading.Thread.CurrentThread.CurrentUICulture; - System.Threading.Thread.CurrentThread.CurrentCulture = - System.Threading.Thread.CurrentThread.CurrentUICulture = - System.Globalization.CultureInfo.InvariantCulture; + // set correct thread culture + _currentCulture = System.Threading.Thread.CurrentThread.CurrentCulture; + _currentUICulture = System.Threading.Thread.CurrentThread.CurrentUICulture; + System.Threading.Thread.CurrentThread.CurrentCulture = + System.Threading.Thread.CurrentThread.CurrentUICulture = + System.Globalization.CultureInfo.InvariantCulture; #endif - } + } - /// - /// Any steps that happen after each test go here - /// - [TearDown] - public void TearDown() - { - ResetAndDeleteTestFiles(); + /// + /// Any steps that happen after each test go here + /// + [TearDown] + public void TearDown() + { + ResetAndDeleteTestFiles(); #if !NETSTANDARD1_3 - // restore previous culture - System.Threading.Thread.CurrentThread.CurrentCulture = _currentCulture; - System.Threading.Thread.CurrentThread.CurrentUICulture = _currentUICulture; + // restore previous culture + System.Threading.Thread.CurrentThread.CurrentCulture = _currentCulture; + System.Threading.Thread.CurrentThread.CurrentUICulture = _currentUICulture; #endif - } - - /// - /// Finds the number of files that match the base file name, - /// and matches the result against an expected count - /// - /// - private static void VerifyFileCount(int iExpectedCount) - { - VerifyFileCount(iExpectedCount, false); - } - - /// - /// Finds the number of files that match the base file name, - /// and matches the result against an expected count - /// - /// - private static void VerifyFileCount(int iExpectedCount, bool preserveLogFileNameExtension) - { - ArrayList alFiles = GetExistingFiles(c_fileName, preserveLogFileNameExtension); - Assert.IsNotNull(alFiles); - Assert.AreEqual(iExpectedCount, alFiles.Count); - } - - /// - /// Creates a file with the given number, and the shared base file name - /// - /// - private static void CreateFile(int iFileNumber) - { - FileInfo fileInfo = new FileInfo(MakeFileName(c_fileName, iFileNumber)); - - FileStream fileStream = null; - try - { - fileStream = fileInfo.Create(); - } - finally - { - if (null != fileStream) - { - try - { - fileStream.Close(); - } - catch - { - } - } - } - } - - /// - /// Verifies that the code correctly loads all filenames - /// - [Test] - public void TestGetExistingFiles() - { - VerifyFileCount(0); - CreateFile(0); - VerifyFileCount(1); - CreateFile(1); - VerifyFileCount(2); - } - - [Test] - public void RollingCombinedWithPreserveExtension() - { - _root = ((Repository.Hierarchy.Hierarchy)Utils.GetRepository()).Root; - _root.Level = Level.All; - PatternLayout patternLayout = new PatternLayout(); - patternLayout.ActivateOptions(); - - RollingFileAppender roller = new RollingFileAppender(); - roller.StaticLogFileName = false; - roller.Layout = patternLayout; - roller.AppendToFile = true; - roller.RollingStyle = RollingFileAppender.RollingMode.Composite; - roller.DatePattern = "dd_MM_yyyy"; - roller.MaxSizeRollBackups = 1; - roller.CountDirection = 1; - roller.PreserveLogFileNameExtension = true; - roller.MaximumFileSize = "10KB"; - roller.File = c_fileName; - roller.ActivateOptions(); - _root.AddAppender(roller); - - _root.Repository.Configured = true; - - for (int i = 0; i < 1000; i++) - { - StringBuilder s = new StringBuilder(); - for (int j = 50; j < 100; j++) - { - if (j > 50) - { - s.Append(" "); - } - - s.Append(j); - } - - _root.Log(Level.Debug, s.ToString(), null); - } - - VerifyFileCount(2, true); - } - - /// - /// Removes all test files that exist - /// - private static void DeleteTestFiles() - { - ArrayList alFiles = GetExistingFiles(c_fileName); - alFiles.AddRange(GetExistingFiles(c_fileName, true)); - foreach (string sFile in alFiles) - { - try - { - Debug.WriteLine("Deleting test file " + sFile); - File.Delete(sFile); - } - catch (Exception ex) - { - Debug.WriteLine("Exception while deleting test file " + ex); - } - } - } - - ///// - ///// Generates a file name associated with the count. - ///// - ///// - ///// - //private string MakeFileName(int iFileCount) - //{ - // return MakeFileName(_fileName, iFileCount); - //} - - /// - /// Generates a file name associated with the count, using - /// the base file name. - /// - /// - /// - /// - private static string MakeFileName(string sBaseFile, int iFileCount) - { - if (0 == iFileCount) - { - return sBaseFile; - } - - return sBaseFile + "." + iFileCount; - } - - /// - /// Returns a RollingFileAppender using all the internal settings for maximum - /// file size and number of backups - /// - /// - private RollingFileAppender CreateAppender() - { - return CreateAppender(new FileAppender.ExclusiveLock()); - } + } - /// - /// Returns a RollingFileAppender using all the internal settings for maximum - /// file size and number of backups - /// - /// The locking model to test - /// - private RollingFileAppender CreateAppender(FileAppender.LockingModelBase lockModel) - { - // - // Use a basic pattern that - // includes just the message and a CR/LF. - // - PatternLayout layout = new PatternLayout("%m%n"); - - // - // Create the new appender - // - RollingFileAppender appender = new RollingFileAppender(); - appender.Layout = layout; - appender.File = c_fileName; - appender.Encoding = Encoding.ASCII; - appender.MaximumFileSize = c_iMaximumFileSize.ToString(); - appender.MaxSizeRollBackups = _MaxSizeRollBackups; - appender.CountDirection = _iCountDirection; - appender.RollingStyle = RollingFileAppender.RollingMode.Size; - appender.LockingModel = lockModel; - - appender.ActivateOptions(); - - return appender; - } + /// + /// Finds the number of files that match the base file name, + /// and matches the result against an expected count + /// + /// + private static void VerifyFileCount(int iExpectedCount) + { + VerifyFileCount(iExpectedCount, false); + } - /// - /// Used for test purposes, a table of these objects can be used to identify - /// any existing files and their expected length. - /// - public class RollFileEntry - { - /// - /// Stores the name of the file - /// - private string m_fileName; - - /// - /// The expected length of the file - /// - private long m_fileLength; - - /// - /// Default constructor - /// - public RollFileEntry() - { - } + /// + /// Finds the number of files that match the base file name, + /// and matches the result against an expected count + /// + /// + private static void VerifyFileCount(int iExpectedCount, bool preserveLogFileNameExtension) + { + ArrayList alFiles = GetExistingFiles(c_fileName, preserveLogFileNameExtension); + Assert.IsNotNull(alFiles); + Assert.AreEqual(iExpectedCount, alFiles.Count); + } - /// - /// Constructor used when the fileInfo and expected length are known - /// - /// - /// - public RollFileEntry(string fileName, long fileLength) - { - m_fileName = fileName; - m_fileLength = fileLength; - } + /// + /// Creates a file with the given number, and the shared base file name + /// + /// + private static void CreateFile(int iFileNumber) + { + FileInfo fileInfo = new FileInfo(MakeFileName(c_fileName, iFileNumber)); + + FileStream fileStream = null; + try + { + fileStream = fileInfo.Create(); + } + finally + { + if (null != fileStream) + { + try + { + fileStream.Close(); + } + catch + { + } + } + } + } - /// - /// Stores the name of the file - /// - public string FileName - { - get { return m_fileName; } - } + /// + /// Verifies that the code correctly loads all filenames + /// + [Test] + public void TestGetExistingFiles() + { + VerifyFileCount(0); + CreateFile(0); + VerifyFileCount(1); + CreateFile(1); + VerifyFileCount(2); + } - /// - /// The expected length of the file - /// - public long FileLength - { - get { return m_fileLength; } - } - } + [Test] + public void RollingCombinedWithPreserveExtension() + { + _root = ((Repository.Hierarchy.Hierarchy)Utils.GetRepository()).Root; + _root.Level = Level.All; + PatternLayout patternLayout = new PatternLayout(); + patternLayout.ActivateOptions(); + + RollingFileAppender roller = new RollingFileAppender(); + roller.StaticLogFileName = false; + roller.Layout = patternLayout; + roller.AppendToFile = true; + roller.RollingStyle = RollingFileAppender.RollingMode.Composite; + roller.DatePattern = "dd_MM_yyyy"; + roller.MaxSizeRollBackups = 1; + roller.CountDirection = 1; + roller.PreserveLogFileNameExtension = true; + roller.MaximumFileSize = "10KB"; + roller.File = c_fileName; + roller.ActivateOptions(); + _root.AddAppender(roller); + + _root.Repository.Configured = true; + + for (int i = 0; i < 1000; i++) + { + StringBuilder s = new StringBuilder(); + for (int j = 50; j < 100; j++) + { + if (j > 50) + { + s.Append(" "); + } + + s.Append(j); + } + + _root.Log(Level.Debug, s.ToString(), null); + } + + VerifyFileCount(2, true); + } - /// - /// Used for table-driven testing. This class holds information that can be used - /// for testing of file rolling. - /// - public class RollConditions + /// + /// Removes all test files that exist + /// + private static void DeleteTestFiles() + { + ArrayList alFiles = GetExistingFiles(c_fileName); + alFiles.AddRange(GetExistingFiles(c_fileName, true)); + foreach (string sFile in alFiles) + { + try { - /// - /// A table of entries showing files that should exist and their expected sizes - /// before logging is called - /// - private RollFileEntry[] m_preLogFileEntries; - - /// - /// A table of entries showing files that should exist and their expected sizes - /// after a message is logged - /// - private RollFileEntry[] m_postLogFileEntries; - - /// - /// Constructor, taking all required parameters - /// - /// - /// - public RollConditions(RollFileEntry[] preLogFileEntries, RollFileEntry[] postLogFileEntries) - { - m_preLogFileEntries = preLogFileEntries; - m_postLogFileEntries = postLogFileEntries; - } - - /// - /// A table of entries showing files that should exist and their expected sizes - /// before logging is called - /// - public RollFileEntry[] GetPreLogFileEntries() - { - return m_preLogFileEntries; - } - - /// - /// A table of entries showing files that should exist and their expected sizes - /// after a message is logged - /// - public RollFileEntry[] GetPostLogFileEntries() - { - return m_postLogFileEntries; - } + Debug.WriteLine("Deleting test file " + sFile); + File.Delete(sFile); } - - private static void VerifyExistenceAndRemoveFromList(ArrayList alExisting, - string sFileName, - FileInfo file, - RollFileEntry entry) + catch (Exception ex) { - Assert.IsTrue(alExisting.Contains(sFileName), "filename {0} not found in test directory", sFileName); - Assert.AreEqual(entry.FileLength, file.Length, "file length mismatch"); - // Remove this file from the list - alExisting.Remove(sFileName); + Debug.WriteLine("Exception while deleting test file " + ex); } + } + } - /// - /// Checks that all the expected files exist, and only the expected files. Also - /// verifies the length of all files against the expected length - /// - /// - /// - private static void VerifyFileConditions(string sBaseFileName, RollFileEntry[] fileEntries) - { - ArrayList alExisting = GetExistingFiles(sBaseFileName); - if (null != fileEntries) - { - // AssertEquals( "File count mismatch", alExisting.Count, fileEntries.Length ); - foreach (RollFileEntry rollFile in fileEntries) - { - string sFileName = rollFile.FileName; - FileInfo file = new FileInfo(sFileName); - - if (rollFile.FileLength > 0) - { - Assert.IsTrue(file.Exists, "filename {0} does not exist", sFileName); - VerifyExistenceAndRemoveFromList(alExisting, sFileName, file, rollFile); - } - else - { - // If length is 0, file may not exist yet. If file exists, make sure length - // is zero. If file doesn't exist, this is OK - - if (file.Exists) - { - VerifyExistenceAndRemoveFromList(alExisting, sFileName, file, rollFile); - } - } - } - } - else - { - Assert.AreEqual(0, alExisting.Count); - } + ///// + ///// Generates a file name associated with the count. + ///// + ///// + ///// + //private string MakeFileName(int iFileCount) + //{ + // return MakeFileName(_fileName, iFileCount); + //} - // This check ensures no extra files matching the wildcard pattern exist. - // We only want the files we expect, and no others - Assert.AreEqual(0, alExisting.Count); - } + /// + /// Generates a file name associated with the count, using + /// the base file name. + /// + /// + /// + /// + private static string MakeFileName(string sBaseFile, int iFileCount) + { + if (0 == iFileCount) + { + return sBaseFile; + } - /// - /// Called before logging a message to check that all the expected files exist, - /// and only the expected files. Also verifies the length of all files against - /// the expected length - /// - /// - /// - private static void VerifyPreConditions(string sBaseFileName, RollConditions entry) - { - VerifyFileConditions(sBaseFileName, entry.GetPreLogFileEntries()); - } + return sBaseFile + "." + iFileCount; + } - /// - /// Called after logging a message to check that all the expected files exist, - /// and only the expected files. Also verifies the length of all files against - /// the expected length - /// - /// - /// - private static void VerifyPostConditions(string sBaseFileName, RollConditions entry) - { - VerifyFileConditions(sBaseFileName, entry.GetPostLogFileEntries()); - } + /// + /// Returns a RollingFileAppender using all the internal settings for maximum + /// file size and number of backups + /// + /// + private RollingFileAppender CreateAppender() + { + return CreateAppender(new FileAppender.ExclusiveLock()); + } - /// - /// Logs a message, verifying the expected message counts against the - /// current running totals. - /// - /// - /// - private void LogMessage(RollConditions entry, string sMessageToLog) - { - Assert.AreEqual(_caRoot.Counter, _iMessagesLogged++); - _root.Log(Level.Debug, sMessageToLog, null); - Assert.AreEqual(_caRoot.Counter, _iMessagesLogged); - _iMessagesLoggedThisFile++; - } + /// + /// Returns a RollingFileAppender using all the internal settings for maximum + /// file size and number of backups + /// + /// The locking model to test + /// + private RollingFileAppender CreateAppender(FileAppender.LockingModelBase lockModel) + { + // + // Use a basic pattern that + // includes just the message and a CR/LF. + // + PatternLayout layout = new PatternLayout("%m%n"); + + // + // Create the new appender + // + RollingFileAppender appender = new RollingFileAppender(); + appender.Layout = layout; + appender.File = c_fileName; + appender.Encoding = Encoding.ASCII; + appender.MaximumFileSize = c_iMaximumFileSize.ToString(); + appender.MaxSizeRollBackups = _MaxSizeRollBackups; + appender.CountDirection = _iCountDirection; + appender.RollingStyle = RollingFileAppender.RollingMode.Size; + appender.LockingModel = lockModel; + + appender.ActivateOptions(); + + return appender; + } - //private void DumpFileEntry( RollFileEntry entry ) - //{ - // System.Diagnostics.Debug.WriteLine( "\tfile name: " + entry.FileName ); - // System.Diagnostics.Debug.WriteLine( "\tfile length: " + entry.FileLength ); - //} - - //private void DumpTableEntry( RollConditions entry ) - //{ - // System.Diagnostics.Debug.WriteLine( "Pre-Conditions" ); - // foreach( RollFileEntry file in entry.GetPreLogFileEntries() ) - // { - // DumpFileEntry( file ); - // } - // System.Diagnostics.Debug.WriteLine( "Post-Conditions" ); - // foreach( RollFileEntry file in entry.GetPostLogFileEntries() ) - // { - // DumpFileEntry( file ); - // } - // // System.Diagnostics.Debug.WriteLine(""); - //} - - /// - /// Runs through all table entries, logging messages. Before each message is logged, - /// pre-conditions are checked to ensure the expected files exist and they are the - /// expected size. After logging, verifies the same. - /// - /// - /// - /// - private void RollFromTableEntries(string sBaseFileName, RollConditions[] entries, string sMessageToLog) - { - for (int i = 0; i < entries.Length; i++) - { - RollConditions entry = entries[i]; - - // System.Diagnostics.Debug.WriteLine( i + ": Entry " + i + " pre/post conditions"); - // DumpTableEntry( entry ); - // System.Diagnostics.Debug.WriteLine( i + ": Testing entry pre-conditions"); - VerifyPreConditions(sBaseFileName, entry); - // System.Diagnostics.Debug.WriteLine( i + ": Logging message"); - LogMessage(entry, sMessageToLog); - // System.Diagnostics.Debug.WriteLine( i + ": Testing entry post-conditions"); - VerifyPostConditions(sBaseFileName, entry); - // System.Diagnostics.Debug.WriteLine( i + ": Finished validating entry\n"); - } - } + /// + /// Used for test purposes, a table of these objects can be used to identify + /// any existing files and their expected length. + /// + public class RollFileEntry + { + /// + /// Stores the name of the file + /// + private string m_fileName; + + /// + /// The expected length of the file + /// + private long m_fileLength; + + /// + /// Default constructor + /// + public RollFileEntry() + { + } + + /// + /// Constructor used when the fileInfo and expected length are known + /// + /// + /// + public RollFileEntry(string fileName, long fileLength) + { + m_fileName = fileName; + m_fileLength = fileLength; + } + + /// + /// Stores the name of the file + /// + public string FileName + { + get { return m_fileName; } + } + + /// + /// The expected length of the file + /// + public long FileLength + { + get { return m_fileLength; } + } + } - private static readonly int s_Newline_Length = Environment.NewLine.Length; + /// + /// Used for table-driven testing. This class holds information that can be used + /// for testing of file rolling. + /// + public class RollConditions + { + /// + /// A table of entries showing files that should exist and their expected sizes + /// before logging is called + /// + private RollFileEntry[] m_preLogFileEntries; + + /// + /// A table of entries showing files that should exist and their expected sizes + /// after a message is logged + /// + private RollFileEntry[] m_postLogFileEntries; + + /// + /// Constructor, taking all required parameters + /// + /// + /// + public RollConditions(RollFileEntry[] preLogFileEntries, RollFileEntry[] postLogFileEntries) + { + m_preLogFileEntries = preLogFileEntries; + m_postLogFileEntries = postLogFileEntries; + } + + /// + /// A table of entries showing files that should exist and their expected sizes + /// before logging is called + /// + public RollFileEntry[] GetPreLogFileEntries() + { + return m_preLogFileEntries; + } + + /// + /// A table of entries showing files that should exist and their expected sizes + /// after a message is logged + /// + public RollFileEntry[] GetPostLogFileEntries() + { + return m_postLogFileEntries; + } + } - /// - /// Returns the number of bytes logged per message, including - /// any newline characters in addition to the message length. - /// - /// - /// - private static int TotalMessageLength(string sMessage) - { - return sMessage.Length + s_Newline_Length; - } + private static void VerifyExistenceAndRemoveFromList(ArrayList alExisting, + string sFileName, + FileInfo file, + RollFileEntry entry) + { + Assert.IsTrue(alExisting.Contains(sFileName), "filename {0} not found in test directory", sFileName); + Assert.AreEqual(entry.FileLength, file.Length, "file length mismatch"); + // Remove this file from the list + alExisting.Remove(sFileName); + } - /// - /// Determines how many messages of a fixed length can be logged - /// to a single file before the file rolls. - /// - /// - /// - private static int MessagesPerFile(int iMessageLength) - { - int iMessagesPerFile = c_iMaximumFileSize / iMessageLength; - - // - // RollingFileAppender checks for wrap BEFORE logging, - // so we will actually get one more message per file than - // we would otherwise. - // - if (iMessagesPerFile * iMessageLength < c_iMaximumFileSize) + /// + /// Checks that all the expected files exist, and only the expected files. Also + /// verifies the length of all files against the expected length + /// + /// + /// + private static void VerifyFileConditions(string sBaseFileName, RollFileEntry[] fileEntries) + { + ArrayList alExisting = GetExistingFiles(sBaseFileName); + if (null != fileEntries) + { + // AssertEquals( "File count mismatch", alExisting.Count, fileEntries.Length ); + foreach (RollFileEntry rollFile in fileEntries) + { + string sFileName = rollFile.FileName; + FileInfo file = new FileInfo(sFileName); + + if (rollFile.FileLength > 0) + { + Assert.IsTrue(file.Exists, "filename {0} does not exist", sFileName); + VerifyExistenceAndRemoveFromList(alExisting, sFileName, file, rollFile); + } + else + { + // If length is 0, file may not exist yet. If file exists, make sure length + // is zero. If file doesn't exist, this is OK + + if (file.Exists) { - iMessagesPerFile++; + VerifyExistenceAndRemoveFromList(alExisting, sFileName, file, rollFile); } - - return iMessagesPerFile; - } - - /// - /// Determines the name of the current file - /// - /// - private static string GetCurrentFile() - { - // Current file name is always the base file name when - // counting. Dates will need a different approach - return c_fileName; + } } + } + else + { + Assert.AreEqual(0, alExisting.Count); + } - /// - /// Turns a group of file names into an array of file entries that include the name - /// and a size. This is useful for assigning the properties of backup files, when - /// the length of the files are all the same size due to a fixed message length. - /// - /// - /// - /// - private static RollFileEntry[] MakeBackupFileEntriesFromBackupGroup(string sBackupGroup, int iBackupFileLength) - { - string[] sFiles = sBackupGroup.Split(' '); - - ArrayList alEntries = new ArrayList(); + // This check ensures no extra files matching the wildcard pattern exist. + // We only want the files we expect, and no others + Assert.AreEqual(0, alExisting.Count); + } - for (int i = 0; i < sFiles.Length; i++) - { - // Weed out any whitespace entries from the array - if (sFiles[i].Trim().Length > 0) - { - alEntries.Add(new RollFileEntry(sFiles[i], iBackupFileLength)); - } - } + /// + /// Called before logging a message to check that all the expected files exist, + /// and only the expected files. Also verifies the length of all files against + /// the expected length + /// + /// + /// + private static void VerifyPreConditions(string sBaseFileName, RollConditions entry) + { + VerifyFileConditions(sBaseFileName, entry.GetPreLogFileEntries()); + } - return (RollFileEntry[])alEntries.ToArray(typeof(RollFileEntry)); - } + /// + /// Called after logging a message to check that all the expected files exist, + /// and only the expected files. Also verifies the length of all files against + /// the expected length + /// + /// + /// + private static void VerifyPostConditions(string sBaseFileName, RollConditions entry) + { + VerifyFileConditions(sBaseFileName, entry.GetPostLogFileEntries()); + } - /// - /// Finds the iGroup group in the string (comma separated groups) - /// - /// - /// - /// - private static string GetBackupGroup(string sBackupGroups, int iGroup) - { - string[] sGroups = sBackupGroups.Split(','); - return sGroups[iGroup]; - } + /// + /// Logs a message, verifying the expected message counts against the + /// current running totals. + /// + /// + /// + private void LogMessage(RollConditions entry, string sMessageToLog) + { + Assert.AreEqual(_caRoot.Counter, _iMessagesLogged++); + _root.Log(Level.Debug, sMessageToLog, null); + Assert.AreEqual(_caRoot.Counter, _iMessagesLogged); + _iMessagesLoggedThisFile++; + } - ///// - ///// Builds a collection of file entries based on the file names - ///// specified in a groups string and the max file size from the - ///// stats object - ///// - ///// - ///// - ///// - //private RollFileEntry[] MakeBackupFileEntriesForPreCondition( string sBackupGroups, RollingStats stats ) - //{ - // if (0 == stats.NumberOfFileRolls ) - // { - // return null; // first round has no previous backups - // } - // string sGroup; - // if (0 == stats.MessagesThisFile ) - // { - // // first file has special pattern...since rolling doesn't occur when message - // // is logged, rather before next message is logged. - // if (stats.NumberOfFileRolls <= 1 ) - // { - // return null; - // } - // // Use backup files from previous round. The minus 2 is because we have already - // // rolled, and the first round uses null instead of the string - // sGroup = GetBackupGroup( sBackupGroups, stats.NumberOfFileRolls-2 ); - // } - // else - // { - // sGroup = GetBackupGroup( sBackupGroups, stats.NumberOfFileRolls-1 ); - // } - // return MakeBackupFileEntriesFromBackupGroup( sGroup, stats.MaximumFileSize ); - //} - - /// - /// Builds a collection of file entries based on the file names - /// specified in a groups string and the max file size from the - /// stats object - /// - /// - /// - /// - private static RollFileEntry[] MakeBackupFileEntriesForPostCondition(string sBackupGroups, RollingStats stats) - { - if (0 == stats.NumberOfFileRolls) - { - return null; // first round has no previous backups - } + //private void DumpFileEntry( RollFileEntry entry ) + //{ + // System.Diagnostics.Debug.WriteLine( "\tfile name: " + entry.FileName ); + // System.Diagnostics.Debug.WriteLine( "\tfile length: " + entry.FileLength ); + //} + + //private void DumpTableEntry( RollConditions entry ) + //{ + // System.Diagnostics.Debug.WriteLine( "Pre-Conditions" ); + // foreach( RollFileEntry file in entry.GetPreLogFileEntries() ) + // { + // DumpFileEntry( file ); + // } + // System.Diagnostics.Debug.WriteLine( "Post-Conditions" ); + // foreach( RollFileEntry file in entry.GetPostLogFileEntries() ) + // { + // DumpFileEntry( file ); + // } + // // System.Diagnostics.Debug.WriteLine(""); + //} - string sGroup = GetBackupGroup(sBackupGroups, stats.NumberOfFileRolls - 1); - return MakeBackupFileEntriesFromBackupGroup(sGroup, stats.MaximumFileSize); - } + /// + /// Runs through all table entries, logging messages. Before each message is logged, + /// pre-conditions are checked to ensure the expected files exist and they are the + /// expected size. After logging, verifies the same. + /// + /// + /// + /// + private void RollFromTableEntries(string sBaseFileName, RollConditions[] entries, string sMessageToLog) + { + for (int i = 0; i < entries.Length; i++) + { + RollConditions entry = entries[i]; + + // System.Diagnostics.Debug.WriteLine( i + ": Entry " + i + " pre/post conditions"); + // DumpTableEntry( entry ); + // System.Diagnostics.Debug.WriteLine( i + ": Testing entry pre-conditions"); + VerifyPreConditions(sBaseFileName, entry); + // System.Diagnostics.Debug.WriteLine( i + ": Logging message"); + LogMessage(entry, sMessageToLog); + // System.Diagnostics.Debug.WriteLine( i + ": Testing entry post-conditions"); + VerifyPostConditions(sBaseFileName, entry); + // System.Diagnostics.Debug.WriteLine( i + ": Finished validating entry\n"); + } + } + private static readonly int s_Newline_Length = Environment.NewLine.Length; - /// - /// This class holds information that is used while we are generating - /// test data sets - /// - public class RollingStats - { - private int iTotalMessageLength; - private int iMessagesPerFile; - private int iMessagesThisFile; - private int iNumberOfFileRolls; - - /// - /// Number of total bytes a log file can reach. - /// - public int MaximumFileSize - { - get { return TotalMessageLength * MessagesPerFile; } - } + /// + /// Returns the number of bytes logged per message, including + /// any newline characters in addition to the message length. + /// + /// + /// + private static int TotalMessageLength(string sMessage) + { + return sMessage.Length + s_Newline_Length; + } - /// - /// The length of a message, including any CR/LF characters. - /// This length assumes all messages are a fixed length for - /// test purposes. - /// - public int TotalMessageLength - { - get { return iTotalMessageLength; } - set { iTotalMessageLength = value; } - } + /// + /// Determines how many messages of a fixed length can be logged + /// to a single file before the file rolls. + /// + /// + /// + private static int MessagesPerFile(int iMessageLength) + { + int iMessagesPerFile = c_iMaximumFileSize / iMessageLength; + + // + // RollingFileAppender checks for wrap BEFORE logging, + // so we will actually get one more message per file than + // we would otherwise. + // + if (iMessagesPerFile * iMessageLength < c_iMaximumFileSize) + { + iMessagesPerFile++; + } + + return iMessagesPerFile; + } - /// - /// A count of the number of messages that are logged to each - /// file. - /// - public int MessagesPerFile - { - get { return iMessagesPerFile; } - set { iMessagesPerFile = value; } - } + /// + /// Determines the name of the current file + /// + /// + private static string GetCurrentFile() + { + // Current file name is always the base file name when + // counting. Dates will need a different approach + return c_fileName; + } - /// - /// Counts how many messages have been logged to the current file - /// - public int MessagesThisFile - { - get { return iMessagesThisFile; } - set { iMessagesThisFile = value; } - } + /// + /// Turns a group of file names into an array of file entries that include the name + /// and a size. This is useful for assigning the properties of backup files, when + /// the length of the files are all the same size due to a fixed message length. + /// + /// + /// + /// + private static RollFileEntry[] MakeBackupFileEntriesFromBackupGroup(string sBackupGroup, int iBackupFileLength) + { + string[] sFiles = sBackupGroup.Split(' '); - /// - /// Counts how many times a file roll has occurred - /// - public int NumberOfFileRolls - { - get { return iNumberOfFileRolls; } - set { iNumberOfFileRolls = value; } - } - } + ArrayList alEntries = new ArrayList(); - /// - /// The stats are used to keep track of progress while we are algorithmically - /// generating a table of pre/post condition tests for file rolling. - /// - /// - /// - private static RollingStats InitializeStats(string sTestMessage) + for (int i = 0; i < sFiles.Length; i++) + { + // Weed out any whitespace entries from the array + if (sFiles[i].Trim().Length > 0) { - RollingStats rollingStats = new RollingStats(); - - rollingStats.TotalMessageLength = TotalMessageLength(sTestMessage); - rollingStats.MessagesPerFile = MessagesPerFile(rollingStats.TotalMessageLength); - rollingStats.MessagesThisFile = 0; - rollingStats.NumberOfFileRolls = 0; - - return rollingStats; + alEntries.Add(new RollFileEntry(sFiles[i], iBackupFileLength)); } + } - /// - /// Takes an existing array of RollFileEntry objects, creates a new array one element - /// bigger, and appends the final element to the end. If the existing entries are - /// null (no entries), then a one-element array is returned with the final element - /// as the only entry. - /// - /// - /// - /// - private static RollFileEntry[] AddFinalElement(RollFileEntry[] existing, RollFileEntry final) - { - int iLength = 1; - if (null != existing) - { - iLength += existing.Length; - } - - RollFileEntry[] combined = new RollFileEntry[iLength]; - if (null != existing) - { - Array.Copy(existing, 0, combined, 0, existing.Length); - } - - combined[iLength - 1] = final; - return combined; - } + return (RollFileEntry[])alEntries.ToArray(typeof(RollFileEntry)); + } - /// - /// Generates the pre and post condition arrays from an array of backup files and the - /// current file / next file. - /// - /// - /// - /// - /// - /// - /// - private static RollConditions BuildTableEntry(string sBackupFiles, - RollConditions preCondition, - RollFileEntry current, - RollFileEntry currentNext, - RollingStats rollingStats) - { - RollFileEntry[] backupsPost = MakeBackupFileEntriesForPostCondition(sBackupFiles, rollingStats); - RollFileEntry[] post = AddFinalElement(backupsPost, currentNext); - if (null == preCondition) - { - return new RollConditions(AddFinalElement(null, current), post); - } + /// + /// Finds the iGroup group in the string (comma separated groups) + /// + /// + /// + /// + private static string GetBackupGroup(string sBackupGroups, int iGroup) + { + string[] sGroups = sBackupGroups.Split(','); + return sGroups[iGroup]; + } - return new RollConditions(preCondition.GetPostLogFileEntries(), post); - } + ///// + ///// Builds a collection of file entries based on the file names + ///// specified in a groups string and the max file size from the + ///// stats object + ///// + ///// + ///// + ///// + //private RollFileEntry[] MakeBackupFileEntriesForPreCondition( string sBackupGroups, RollingStats stats ) + //{ + // if (0 == stats.NumberOfFileRolls ) + // { + // return null; // first round has no previous backups + // } + // string sGroup; + // if (0 == stats.MessagesThisFile ) + // { + // // first file has special pattern...since rolling doesn't occur when message + // // is logged, rather before next message is logged. + // if (stats.NumberOfFileRolls <= 1 ) + // { + // return null; + // } + // // Use backup files from previous round. The minus 2 is because we have already + // // rolled, and the first round uses null instead of the string + // sGroup = GetBackupGroup( sBackupGroups, stats.NumberOfFileRolls-2 ); + // } + // else + // { + // sGroup = GetBackupGroup( sBackupGroups, stats.NumberOfFileRolls-1 ); + // } + // return MakeBackupFileEntriesFromBackupGroup( sGroup, stats.MaximumFileSize ); + //} - /// - /// Returns a RollFileEntry that represents the next state of the current file, - /// based on the current state. When the current state would roll, the next - /// entry is the current file wrapped to 0 bytes. Otherwise, the next state - /// is the post-condition passed in as the currentNext parameter - /// - /// - /// - /// - private static RollFileEntry MoveNextEntry(RollingStats rollingStats, RollFileEntry currentNext) - { - rollingStats.MessagesThisFile = rollingStats.MessagesThisFile + 1; - if (rollingStats.MessagesThisFile >= rollingStats.MessagesPerFile) - { - rollingStats.MessagesThisFile = 0; - rollingStats.NumberOfFileRolls = rollingStats.NumberOfFileRolls + 1; + /// + /// Builds a collection of file entries based on the file names + /// specified in a groups string and the max file size from the + /// stats object + /// + /// + /// + /// + private static RollFileEntry[] MakeBackupFileEntriesForPostCondition(string sBackupGroups, RollingStats stats) + { + if (0 == stats.NumberOfFileRolls) + { + return null; // first round has no previous backups + } - return new RollFileEntry(GetCurrentFile(), 0); - } - else - { - return currentNext; - } - } + string sGroup = GetBackupGroup(sBackupGroups, stats.NumberOfFileRolls - 1); + return MakeBackupFileEntriesFromBackupGroup(sGroup, stats.MaximumFileSize); + } - /// - /// Callback point for the regular expression parser. Turns - /// the number into a file name. - /// - /// - /// - private static string NumberedNameMaker(Match match) - { - Int32 iValue = Int32.Parse(match.Value); - return MakeFileName(c_fileName, iValue); - } - /// - /// Parses a numeric list of files, turning them into file names. - /// Calls back to a method that does the actual replacement, turning - /// the numeric value into a filename. - /// - /// - /// - /// - private static string ConvertToFiles(string sBackupInfo, MatchEvaluator evaluator) - { - Regex regex = new Regex(@"\d+"); - return regex.Replace(sBackupInfo, evaluator); - } + /// + /// This class holds information that is used while we are generating + /// test data sets + /// + public class RollingStats + { + private int iTotalMessageLength; + private int iMessagesPerFile; + private int iMessagesThisFile; + private int iNumberOfFileRolls; + + /// + /// Number of total bytes a log file can reach. + /// + public int MaximumFileSize + { + get { return TotalMessageLength * MessagesPerFile; } + } + + /// + /// The length of a message, including any CR/LF characters. + /// This length assumes all messages are a fixed length for + /// test purposes. + /// + public int TotalMessageLength + { + get { return iTotalMessageLength; } + set { iTotalMessageLength = value; } + } + + /// + /// A count of the number of messages that are logged to each + /// file. + /// + public int MessagesPerFile + { + get { return iMessagesPerFile; } + set { iMessagesPerFile = value; } + } + + /// + /// Counts how many messages have been logged to the current file + /// + public int MessagesThisFile + { + get { return iMessagesThisFile; } + set { iMessagesThisFile = value; } + } + + /// + /// Counts how many times a file roll has occurred + /// + public int NumberOfFileRolls + { + get { return iNumberOfFileRolls; } + set { iNumberOfFileRolls = value; } + } + } - /// - /// Makes test entries used for verifying counted file names - /// - /// A message to log repeatedly - /// Filename groups used to indicate backup file name progression - /// that results after each message is logged - /// How many times the test message will be repeatedly logged - /// - private static RollConditions[] MakeNumericTestEntries(string sTestMessage, - string sBackupInfo, - int iMessagesToLog) - { - return MakeTestEntries( - sTestMessage, - sBackupInfo, - iMessagesToLog, - new MatchEvaluator(NumberedNameMaker)); - } + /// + /// The stats are used to keep track of progress while we are algorithmically + /// generating a table of pre/post condition tests for file rolling. + /// + /// + /// + private static RollingStats InitializeStats(string sTestMessage) + { + RollingStats rollingStats = new RollingStats(); - /// - /// This routine takes a list of backup file names and a message that will be logged - /// repeatedly, and generates a collection of objects containing pre-condition and - /// post-condition information. This pre/post information shows the names and expected - /// file sizes for all files just before and just after a message is logged. - /// - /// A message to log repeatedly - /// Filename groups used to indicate backup file name progression - /// that results after each message is logged - /// How many times the test message will be repeatedly logged - /// Function that can turn a number into a filename - /// - private static RollConditions[] MakeTestEntries(string sTestMessage, - string sBackupInfo, - int iMessagesToLog, - MatchEvaluator evaluator) - { - string sBackupFiles = ConvertToFiles(sBackupInfo, evaluator); + rollingStats.TotalMessageLength = TotalMessageLength(sTestMessage); + rollingStats.MessagesPerFile = MessagesPerFile(rollingStats.TotalMessageLength); + rollingStats.MessagesThisFile = 0; + rollingStats.NumberOfFileRolls = 0; - RollConditions[] table = new RollConditions[iMessagesToLog]; + return rollingStats; + } - RollingStats rollingStats = InitializeStats(sTestMessage); + /// + /// Takes an existing array of RollFileEntry objects, creates a new array one element + /// bigger, and appends the final element to the end. If the existing entries are + /// null (no entries), then a one-element array is returned with the final element + /// as the only entry. + /// + /// + /// + /// + private static RollFileEntry[] AddFinalElement(RollFileEntry[] existing, RollFileEntry final) + { + int iLength = 1; + if (null != existing) + { + iLength += existing.Length; + } + + RollFileEntry[] combined = new RollFileEntry[iLength]; + if (null != existing) + { + Array.Copy(existing, 0, combined, 0, existing.Length); + } + + combined[iLength - 1] = final; + return combined; + } - RollConditions preCondition = null; - rollingStats.MessagesThisFile = 0; + /// + /// Generates the pre and post condition arrays from an array of backup files and the + /// current file / next file. + /// + /// + /// + /// + /// + /// + /// + private static RollConditions BuildTableEntry(string sBackupFiles, + RollConditions preCondition, + RollFileEntry current, + RollFileEntry currentNext, + RollingStats rollingStats) + { + RollFileEntry[] backupsPost = MakeBackupFileEntriesForPostCondition(sBackupFiles, rollingStats); + RollFileEntry[] post = AddFinalElement(backupsPost, currentNext); + if (null == preCondition) + { + return new RollConditions(AddFinalElement(null, current), post); + } + + return new RollConditions(preCondition.GetPostLogFileEntries(), post); + } - RollFileEntry currentFile = new RollFileEntry(GetCurrentFile(), 0); - for (int i = 0; i < iMessagesToLog; i++) - { - RollFileEntry currentNext = new RollFileEntry( - GetCurrentFile(), - (1 + rollingStats.MessagesThisFile) * rollingStats.TotalMessageLength); + /// + /// Returns a RollFileEntry that represents the next state of the current file, + /// based on the current state. When the current state would roll, the next + /// entry is the current file wrapped to 0 bytes. Otherwise, the next state + /// is the post-condition passed in as the currentNext parameter + /// + /// + /// + /// + private static RollFileEntry MoveNextEntry(RollingStats rollingStats, RollFileEntry currentNext) + { + rollingStats.MessagesThisFile = rollingStats.MessagesThisFile + 1; + if (rollingStats.MessagesThisFile >= rollingStats.MessagesPerFile) + { + rollingStats.MessagesThisFile = 0; + rollingStats.NumberOfFileRolls = rollingStats.NumberOfFileRolls + 1; + + return new RollFileEntry(GetCurrentFile(), 0); + } + else + { + return currentNext; + } + } - table[i] = BuildTableEntry(sBackupFiles, preCondition, currentFile, currentNext, rollingStats); - preCondition = table[i]; + /// + /// Callback point for the regular expression parser. Turns + /// the number into a file name. + /// + /// + /// + private static string NumberedNameMaker(Match match) + { + Int32 iValue = Int32.Parse(match.Value); + return MakeFileName(c_fileName, iValue); + } - //System.Diagnostics.Debug.WriteLine( "Message " + i ); - //DumpTableEntry( table[i] ); + /// + /// Parses a numeric list of files, turning them into file names. + /// Calls back to a method that does the actual replacement, turning + /// the numeric value into a filename. + /// + /// + /// + /// + private static string ConvertToFiles(string sBackupInfo, MatchEvaluator evaluator) + { + Regex regex = new Regex(@"\d+"); + return regex.Replace(sBackupInfo, evaluator); + } - currentFile = MoveNextEntry(rollingStats, currentNext); - } + /// + /// Makes test entries used for verifying counted file names + /// + /// A message to log repeatedly + /// Filename groups used to indicate backup file name progression + /// that results after each message is logged + /// How many times the test message will be repeatedly logged + /// + private static RollConditions[] MakeNumericTestEntries(string sTestMessage, + string sBackupInfo, + int iMessagesToLog) + { + return MakeTestEntries( + sTestMessage, + sBackupInfo, + iMessagesToLog, + new MatchEvaluator(NumberedNameMaker)); + } - return table; - } + /// + /// This routine takes a list of backup file names and a message that will be logged + /// repeatedly, and generates a collection of objects containing pre-condition and + /// post-condition information. This pre/post information shows the names and expected + /// file sizes for all files just before and just after a message is logged. + /// + /// A message to log repeatedly + /// Filename groups used to indicate backup file name progression + /// that results after each message is logged + /// How many times the test message will be repeatedly logged + /// Function that can turn a number into a filename + /// + private static RollConditions[] MakeTestEntries(string sTestMessage, + string sBackupInfo, + int iMessagesToLog, + MatchEvaluator evaluator) + { + string sBackupFiles = ConvertToFiles(sBackupInfo, evaluator); - /// - /// Uses the externally defined rolling table to verify rolling names/sizes - /// - /// - /// Pattern is: check pre-conditions. Log messages, checking size of current file. - /// when size exceeds limit, check post conditions. Can determine from message the - /// number of messages N that will cause a roll to occur. Challenge is to verify the - /// expected files, their sizes, and the names. For a message of length L, the backups - /// will be of size (N * L), and the current file will be of size (K * L), where K is - /// the number of messages that have been logged to this file. - /// - /// File sizes can be checked algorithmically. - /// - /// File names are generated using a table driven algorithm, where a number is turned into - /// the actual filename. - /// - /// The entries are comma-separated, with spaces between the names. Each comma indicates - /// a 'roll', and the group between commas indicates the numbers for all backup files that - /// occur as a result of the roll. It is assumed that no backup files exist before a roll - /// occurs - /// - /// - private void VerifyRolling(RollConditions[] table) - { - ConfigureRootAppender(); - RollFromTableEntries(c_fileName, table, GetTestMessage()); - } + RollConditions[] table = new RollConditions[iMessagesToLog]; - /// - /// Validates rolling using a fixed number of backup files, with - /// count direction set to up, so that newer files have higher counts. - /// Newest = N, Oldest = N-K, where K is the number of backups to allow - /// and N is the number of times rolling has occurred. - /// - [Test] - public void TestRollingCountUpFixedBackups() - { - // - // Oldest to newest when reading in a group left-to-right, so 1 2 3 means 1 is the - // oldest, and 3 is the newest - // - string sBackupInfo = "1, 1 2, 1 2 3, 2 3 4, 3 4 5"; - - // - // Count Up - // - _iCountDirection = +1; - - // - // Log 30 messages. This is 5 groups, 6 checks per group ( 0, 100, 200, 300, 400, 500 - // bytes for current file as messages are logged. - // - int iMessagesToLog = 30; - - VerifyRolling(MakeNumericTestEntries(GetTestMessage(), sBackupInfo, iMessagesToLog)); - } + RollingStats rollingStats = InitializeStats(sTestMessage); - /// - /// Validates rolling using an infinite number of backup files, with - /// count direction set to up, so that newer files have higher counts. - /// Newest = N, Oldest = 1, where N is the number of times rolling has - /// occurred. - /// - [Test] - public void TestRollingCountUpInfiniteBackups() - { - // - // Oldest to newest when reading in a group left-to-right, so 1 2 3 means 1 is the - // oldest, and 3 is the newest - // - string sBackupInfo = "1, 1 2, 1 2 3, 1 2 3 4, 1 2 3 4 5"; - - // - // Count Up - // - _iCountDirection = +1; - - // - // Infinite backups - // - _MaxSizeRollBackups = -1; - - // - // Log 30 messages. This is 5 groups, 6 checks per group ( 0, 100, 200, 300, 400, 500 - // bytes for current file as messages are logged. - // - int iMessagesToLog = 30; - - VerifyRolling(MakeNumericTestEntries(GetTestMessage(), sBackupInfo, iMessagesToLog)); - } + RollConditions preCondition = null; + rollingStats.MessagesThisFile = 0; - /// - /// Validates rolling with no backup files, with count direction set to up. - /// Only the current file should be present, wrapping to 0 bytes once the - /// previous file fills up. - /// - [Test] - public void TestRollingCountUpZeroBackups() - { - // - // Oldest to newest when reading in a group left-to-right, so 1 2 3 means 1 is the - // oldest, and 3 is the newest - // - string sBackupInfo = ", , , , "; - - // - // Count Up - // - _iCountDirection = +1; - - // - // No backups - // - _MaxSizeRollBackups = 0; - - // - // Log 30 messages. This is 5 groups, 6 checks per group ( 0, 100, 200, 300, 400, 500 - // bytes for current file as messages are logged. - // - int iMessagesToLog = 30; - - VerifyRolling(MakeNumericTestEntries(GetTestMessage(), sBackupInfo, iMessagesToLog)); - } + RollFileEntry currentFile = new RollFileEntry(GetCurrentFile(), 0); + for (int i = 0; i < iMessagesToLog; i++) + { + RollFileEntry currentNext = new RollFileEntry( + GetCurrentFile(), + (1 + rollingStats.MessagesThisFile) * rollingStats.TotalMessageLength); + table[i] = BuildTableEntry(sBackupFiles, preCondition, currentFile, currentNext, rollingStats); + preCondition = table[i]; - /// - /// Validates rolling using a fixed number of backup files, with - /// count direction set to down, so that older files have higher counts. - /// Newest = 1, Oldest = N, where N is the number of backups to allow - /// - [Test] - public void TestRollingCountDownFixedBackups() - { - // - // Oldest to newest when reading in a group left-to-right, so 1 2 3 means 1 is the - // oldest, and 3 is the newest - // - string sBackupInfo = "1, 1 2, 1 2 3, 1 2 3, 1 2 3"; - - // - // Count Up - // - _iCountDirection = -1; - - // - // Log 30 messages. This is 5 groups, 6 checks per group ( 0, 100, 200, 300, 400, 500 - // bytes for current file as messages are logged. - // - int iMessagesToLog = 30; - - VerifyRolling(MakeNumericTestEntries(GetTestMessage(), sBackupInfo, iMessagesToLog)); - } + //System.Diagnostics.Debug.WriteLine( "Message " + i ); + //DumpTableEntry( table[i] ); - /// - /// Validates rolling using an infinite number of backup files, with - /// count direction set to down, so that older files have higher counts. - /// Newest = 1, Oldest = N, where N is the number of times rolling has - /// occurred - /// - [Test] - public void TestRollingCountDownInfiniteBackups() - { - // - // Oldest to newest when reading in a group left-to-right, so 1 2 3 means 1 is the - // oldest, and 3 is the newest - // - string sBackupInfo = "1, 1 2, 1 2 3, 1 2 3 4, 1 2 3 4 5"; - - // - // Count Down - // - _iCountDirection = -1; - - // - // Infinite backups - // - _MaxSizeRollBackups = -1; - - // - // Log 30 messages. This is 5 groups, 6 checks per group ( 0, 100, 200, 300, 400, 500 - // bytes for current file as messages are logged. - // - int iMessagesToLog = 30; - - VerifyRolling(MakeNumericTestEntries(GetTestMessage(), sBackupInfo, iMessagesToLog)); - } + currentFile = MoveNextEntry(rollingStats, currentNext); + } - /// - /// Validates rolling with no backup files, with count direction set to down. - /// Only the current file should be present, wrapping to 0 bytes once the - /// previous file fills up. - /// - [Test] - public void TestRollingCountDownZeroBackups() - { - // - // Oldest to newest when reading in a group left-to-right, so 1 2 3 means 1 is the - // oldest, and 3 is the newest - // - string sBackupInfo = ", , , , "; - - // - // Count Up - // - _iCountDirection = -1; - - // - // No backups - // - _MaxSizeRollBackups = 0; - - // - // Log 30 messages. This is 5 groups, 6 checks per group ( 0, 100, 200, 300, 400, 500 - // bytes for current file as messages are logged. - // - int iMessagesToLog = 30; - - VerifyRolling(MakeNumericTestEntries(GetTestMessage(), sBackupInfo, iMessagesToLog)); - } + return table; + } - /// - /// Configures the root appender for counting and rolling - /// - private void ConfigureRootAppender() - { - _root = ((Repository.Hierarchy.Hierarchy)Utils.GetRepository()).Root; - _root.Level = Level.Debug; - _caRoot = new CountingAppender(); - _root.AddAppender(_caRoot); - Assert.AreEqual(_caRoot.Counter, 0); - - // - // Set the root appender with a RollingFileAppender - // - _root.AddAppender(CreateAppender()); - - _root.Repository.Configured = true; - } + /// + /// Uses the externally defined rolling table to verify rolling names/sizes + /// + /// + /// Pattern is: check pre-conditions. Log messages, checking size of current file. + /// when size exceeds limit, check post conditions. Can determine from message the + /// number of messages N that will cause a roll to occur. Challenge is to verify the + /// expected files, their sizes, and the names. For a message of length L, the backups + /// will be of size (N * L), and the current file will be of size (K * L), where K is + /// the number of messages that have been logged to this file. + /// + /// File sizes can be checked algorithmically. + /// + /// File names are generated using a table driven algorithm, where a number is turned into + /// the actual filename. + /// + /// The entries are comma-separated, with spaces between the names. Each comma indicates + /// a 'roll', and the group between commas indicates the numbers for all backup files that + /// occur as a result of the roll. It is assumed that no backup files exist before a roll + /// occurs + /// + /// + private void VerifyRolling(RollConditions[] table) + { + ConfigureRootAppender(); + RollFromTableEntries(c_fileName, table, GetTestMessage()); + } - /// - /// Verifies that the current backup index is detected correctly when initializing - /// - /// - /// - /// - private static void VerifyInitializeRollBackupsFromBaseFile(string sBaseFile, - ArrayList alFiles, - int iExpectedCurSizeRollBackups) - { - InitializeAndVerifyExpectedValue(alFiles, sBaseFile, CreateRollingFileAppender("5,0,1"), - iExpectedCurSizeRollBackups); - } + /// + /// Validates rolling using a fixed number of backup files, with + /// count direction set to up, so that newer files have higher counts. + /// Newest = N, Oldest = N-K, where K is the number of backups to allow + /// and N is the number of times rolling has occurred. + /// + [Test] + public void TestRollingCountUpFixedBackups() + { + // + // Oldest to newest when reading in a group left-to-right, so 1 2 3 means 1 is the + // oldest, and 3 is the newest + // + string sBackupInfo = "1, 1 2, 1 2 3, 2 3 4, 3 4 5"; + + // + // Count Up + // + _iCountDirection = +1; + + // + // Log 30 messages. This is 5 groups, 6 checks per group ( 0, 100, 200, 300, 400, 500 + // bytes for current file as messages are logged. + // + int iMessagesToLog = 30; + + VerifyRolling(MakeNumericTestEntries(GetTestMessage(), sBackupInfo, iMessagesToLog)); + } - /// - /// Tests that the current backup index is 0 when no - /// existing files are seen - /// - [Test] - public void TestInitializeRollBackups1() - { - string sBaseFile = "LogFile.log"; - ArrayList arrFiles = new ArrayList(); - arrFiles.Add("junk1"); - arrFiles.Add("junk1.log"); - arrFiles.Add("junk2.log"); - arrFiles.Add("junk.log.1"); - arrFiles.Add("junk.log.2"); - - int iExpectedCurSizeRollBackups = 0; - VerifyInitializeRollBackupsFromBaseFile(sBaseFile, arrFiles, iExpectedCurSizeRollBackups); - } + /// + /// Validates rolling using an infinite number of backup files, with + /// count direction set to up, so that newer files have higher counts. + /// Newest = N, Oldest = 1, where N is the number of times rolling has + /// occurred. + /// + [Test] + public void TestRollingCountUpInfiniteBackups() + { + // + // Oldest to newest when reading in a group left-to-right, so 1 2 3 means 1 is the + // oldest, and 3 is the newest + // + string sBackupInfo = "1, 1 2, 1 2 3, 1 2 3 4, 1 2 3 4 5"; + + // + // Count Up + // + _iCountDirection = +1; + + // + // Infinite backups + // + _MaxSizeRollBackups = -1; + + // + // Log 30 messages. This is 5 groups, 6 checks per group ( 0, 100, 200, 300, 400, 500 + // bytes for current file as messages are logged. + // + int iMessagesToLog = 30; + + VerifyRolling(MakeNumericTestEntries(GetTestMessage(), sBackupInfo, iMessagesToLog)); + } - /// - /// Verifies that files are detected when the base file is specified - /// - /// - private static void VerifyInitializeRollBackupsFromBaseFile(string sBaseFile) - { - ArrayList alFiles = MakeTestDataFromString(sBaseFile, "0,1,2"); + /// + /// Validates rolling with no backup files, with count direction set to up. + /// Only the current file should be present, wrapping to 0 bytes once the + /// previous file fills up. + /// + [Test] + public void TestRollingCountUpZeroBackups() + { + // + // Oldest to newest when reading in a group left-to-right, so 1 2 3 means 1 is the + // oldest, and 3 is the newest + // + string sBackupInfo = ", , , , "; + + // + // Count Up + // + _iCountDirection = +1; + + // + // No backups + // + _MaxSizeRollBackups = 0; + + // + // Log 30 messages. This is 5 groups, 6 checks per group ( 0, 100, 200, 300, 400, 500 + // bytes for current file as messages are logged. + // + int iMessagesToLog = 30; + + VerifyRolling(MakeNumericTestEntries(GetTestMessage(), sBackupInfo, iMessagesToLog)); + } - int iExpectedCurSizeRollBackups = 2; - VerifyInitializeRollBackupsFromBaseFile(sBaseFile, alFiles, iExpectedCurSizeRollBackups); - } - /// - /// Verifies that count goes to the highest when counting up - /// - [Test] - public void TestInitializeCountUpFixed() - { - ArrayList alFiles = MakeTestDataFromString("3,4,5"); - int iExpectedValue = 5; - InitializeAndVerifyExpectedValue(alFiles, c_fileName, CreateRollingFileAppender("3,0,1"), iExpectedValue); - } + /// + /// Validates rolling using a fixed number of backup files, with + /// count direction set to down, so that older files have higher counts. + /// Newest = 1, Oldest = N, where N is the number of backups to allow + /// + [Test] + public void TestRollingCountDownFixedBackups() + { + // + // Oldest to newest when reading in a group left-to-right, so 1 2 3 means 1 is the + // oldest, and 3 is the newest + // + string sBackupInfo = "1, 1 2, 1 2 3, 1 2 3, 1 2 3"; + + // + // Count Up + // + _iCountDirection = -1; + + // + // Log 30 messages. This is 5 groups, 6 checks per group ( 0, 100, 200, 300, 400, 500 + // bytes for current file as messages are logged. + // + int iMessagesToLog = 30; + + VerifyRolling(MakeNumericTestEntries(GetTestMessage(), sBackupInfo, iMessagesToLog)); + } - /// - /// Verifies that count goes to the highest when counting up - /// - [Test] - public void TestInitializeCountUpFixed2() - { - ArrayList alFiles = MakeTestDataFromString("0,3"); - int iExpectedValue = 3; - InitializeAndVerifyExpectedValue(alFiles, c_fileName, CreateRollingFileAppender("3,0,1"), iExpectedValue); - } + /// + /// Validates rolling using an infinite number of backup files, with + /// count direction set to down, so that older files have higher counts. + /// Newest = 1, Oldest = N, where N is the number of times rolling has + /// occurred + /// + [Test] + public void TestRollingCountDownInfiniteBackups() + { + // + // Oldest to newest when reading in a group left-to-right, so 1 2 3 means 1 is the + // oldest, and 3 is the newest + // + string sBackupInfo = "1, 1 2, 1 2 3, 1 2 3 4, 1 2 3 4 5"; + + // + // Count Down + // + _iCountDirection = -1; + + // + // Infinite backups + // + _MaxSizeRollBackups = -1; + + // + // Log 30 messages. This is 5 groups, 6 checks per group ( 0, 100, 200, 300, 400, 500 + // bytes for current file as messages are logged. + // + int iMessagesToLog = 30; + + VerifyRolling(MakeNumericTestEntries(GetTestMessage(), sBackupInfo, iMessagesToLog)); + } - /// - /// Verifies that count stays at 0 for the zero backups case - /// when counting up - /// - [Test] - public void TestInitializeCountUpZeroBackups() - { - ArrayList alFiles = MakeTestDataFromString("0,3"); - int iExpectedValue = 0; - InitializeAndVerifyExpectedValue(alFiles, c_fileName, CreateRollingFileAppender("0,0,1"), iExpectedValue); - } + /// + /// Validates rolling with no backup files, with count direction set to down. + /// Only the current file should be present, wrapping to 0 bytes once the + /// previous file fills up. + /// + [Test] + public void TestRollingCountDownZeroBackups() + { + // + // Oldest to newest when reading in a group left-to-right, so 1 2 3 means 1 is the + // oldest, and 3 is the newest + // + string sBackupInfo = ", , , , "; + + // + // Count Up + // + _iCountDirection = -1; + + // + // No backups + // + _MaxSizeRollBackups = 0; + + // + // Log 30 messages. This is 5 groups, 6 checks per group ( 0, 100, 200, 300, 400, 500 + // bytes for current file as messages are logged. + // + int iMessagesToLog = 30; + + VerifyRolling(MakeNumericTestEntries(GetTestMessage(), sBackupInfo, iMessagesToLog)); + } - /// - /// Verifies that count stays at 0 for the zero backups case - /// when counting down - /// - [Test] - public void TestInitializeCountDownZeroBackups() - { - ArrayList alFiles = MakeTestDataFromString("0,3"); - int iExpectedValue = 0; - InitializeAndVerifyExpectedValue(alFiles, c_fileName, CreateRollingFileAppender("0,0,-1"), iExpectedValue); - } + /// + /// Configures the root appender for counting and rolling + /// + private void ConfigureRootAppender() + { + _root = ((Repository.Hierarchy.Hierarchy)Utils.GetRepository()).Root; + _root.Level = Level.Debug; + _caRoot = new CountingAppender(); + _root.AddAppender(_caRoot); + Assert.AreEqual(_caRoot.Counter, 0); + + // + // Set the root appender with a RollingFileAppender + // + _root.AddAppender(CreateAppender()); + + _root.Repository.Configured = true; + } + /// + /// Verifies that the current backup index is detected correctly when initializing + /// + /// + /// + /// + private static void VerifyInitializeRollBackupsFromBaseFile(string sBaseFile, + ArrayList alFiles, + int iExpectedCurSizeRollBackups) + { + InitializeAndVerifyExpectedValue(alFiles, sBaseFile, CreateRollingFileAppender("5,0,1"), + iExpectedCurSizeRollBackups); + } - /// - /// Verifies that count goes to the highest when counting up - /// - [Test] - public void TestInitializeCountDownFixed() - { - ArrayList alFiles = MakeTestDataFromString("4,5,6"); - VerifyInitializeDownFixedExpectedValue(alFiles, c_fileName, 0); - } + /// + /// Tests that the current backup index is 0 when no + /// existing files are seen + /// + [Test] + public void TestInitializeRollBackups1() + { + string sBaseFile = "LogFile.log"; + ArrayList arrFiles = new ArrayList(); + arrFiles.Add("junk1"); + arrFiles.Add("junk1.log"); + arrFiles.Add("junk2.log"); + arrFiles.Add("junk.log.1"); + arrFiles.Add("junk.log.2"); + + int iExpectedCurSizeRollBackups = 0; + VerifyInitializeRollBackupsFromBaseFile(sBaseFile, arrFiles, iExpectedCurSizeRollBackups); + } - /// - /// Verifies that count goes to the highest when counting up - /// - [Test] - public void TestInitializeCountDownFixed2() - { - ArrayList alFiles = MakeTestDataFromString("1,5,6"); - VerifyInitializeDownFixedExpectedValue(alFiles, c_fileName, 1); - } + /// + /// Verifies that files are detected when the base file is specified + /// + /// + private static void VerifyInitializeRollBackupsFromBaseFile(string sBaseFile) + { + ArrayList alFiles = MakeTestDataFromString(sBaseFile, "0,1,2"); - /// - /// Verifies that count goes to the highest when counting up - /// - [Test] - public void TestInitializeCountDownFixed3() - { - ArrayList alFiles = MakeTestDataFromString("2,5,6"); - VerifyInitializeDownFixedExpectedValue(alFiles, c_fileName, 2); - } + int iExpectedCurSizeRollBackups = 2; + VerifyInitializeRollBackupsFromBaseFile(sBaseFile, alFiles, iExpectedCurSizeRollBackups); + } - /// - /// Verifies that count goes to the highest when counting up - /// - [Test] - public void TestInitializeCountDownFixed4() - { - ArrayList alFiles = MakeTestDataFromString("3,5,6"); - VerifyInitializeDownFixedExpectedValue(alFiles, c_fileName, 3); - } + /// + /// Verifies that count goes to the highest when counting up + /// + [Test] + public void TestInitializeCountUpFixed() + { + ArrayList alFiles = MakeTestDataFromString("3,4,5"); + int iExpectedValue = 5; + InitializeAndVerifyExpectedValue(alFiles, c_fileName, CreateRollingFileAppender("3,0,1"), iExpectedValue); + } - /// - /// Verifies that count goes to the highest when counting up - /// - [Test] - public void TestInitializeCountDownFixed5() - { - ArrayList alFiles = MakeTestDataFromString("1,2,3"); - VerifyInitializeDownFixedExpectedValue(alFiles, c_fileName, 3); - } + /// + /// Verifies that count goes to the highest when counting up + /// + [Test] + public void TestInitializeCountUpFixed2() + { + ArrayList alFiles = MakeTestDataFromString("0,3"); + int iExpectedValue = 3; + InitializeAndVerifyExpectedValue(alFiles, c_fileName, CreateRollingFileAppender("3,0,1"), iExpectedValue); + } - /// - /// Verifies that count goes to the highest when counting up - /// - [Test] - public void TestInitializeCountDownFixed6() - { - ArrayList alFiles = MakeTestDataFromString("1,2"); - VerifyInitializeDownFixedExpectedValue(alFiles, c_fileName, 2); - } + /// + /// Verifies that count stays at 0 for the zero backups case + /// when counting up + /// + [Test] + public void TestInitializeCountUpZeroBackups() + { + ArrayList alFiles = MakeTestDataFromString("0,3"); + int iExpectedValue = 0; + InitializeAndVerifyExpectedValue(alFiles, c_fileName, CreateRollingFileAppender("0,0,1"), iExpectedValue); + } - /// - /// Verifies that count goes to the highest when counting up - /// - [Test] - public void TestInitializeCountDownFixed7() - { - ArrayList alFiles = MakeTestDataFromString("2,3"); - VerifyInitializeDownFixedExpectedValue(alFiles, c_fileName, 3); - } + /// + /// Verifies that count stays at 0 for the zero backups case + /// when counting down + /// + [Test] + public void TestInitializeCountDownZeroBackups() + { + ArrayList alFiles = MakeTestDataFromString("0,3"); + int iExpectedValue = 0; + InitializeAndVerifyExpectedValue(alFiles, c_fileName, CreateRollingFileAppender("0,0,-1"), iExpectedValue); + } - private static void InitializeAndVerifyExpectedValue(ArrayList alFiles, - string sBaseFile, - RollingFileAppender rfa, - int iExpectedValue) - { - InitializeRollBackups(rfa, sBaseFile, alFiles); - Assert.AreEqual(iExpectedValue, GetFieldCurSizeRollBackups(rfa)); - } - /// - /// Tests the count down case, with infinite max backups, to see that - /// initialization of the rolling file appender results in the expected value - /// - /// - /// - /// - private static void VerifyInitializeDownInfiniteExpectedValue(ArrayList alFiles, - string sBaseFile, - int iExpectedValue) - { - InitializeAndVerifyExpectedValue(alFiles, sBaseFile, CreateRollingFileAppender("-1,0,-1"), iExpectedValue); - } + /// + /// Verifies that count goes to the highest when counting up + /// + [Test] + public void TestInitializeCountDownFixed() + { + ArrayList alFiles = MakeTestDataFromString("4,5,6"); + VerifyInitializeDownFixedExpectedValue(alFiles, c_fileName, 0); + } - /// - /// Creates a RollingFileAppender with the desired values, where the - /// values are passed as a comma separated string, with 3 parameters, - /// m_maxSizeRollBackups, m_curSizeRollBackups, CountDirection - /// - /// - /// - private static RollingFileAppender CreateRollingFileAppender(string sParams) - { - string[] asParams = sParams.Split(','); - if (null == asParams || asParams.Length != 3) - { - throw new ArgumentOutOfRangeException(sParams, sParams, - "Must have 3 comma separated params: MaxSizeRollBackups, CurSizeRollBackups, CountDirection"); - } + /// + /// Verifies that count goes to the highest when counting up + /// + [Test] + public void TestInitializeCountDownFixed2() + { + ArrayList alFiles = MakeTestDataFromString("1,5,6"); + VerifyInitializeDownFixedExpectedValue(alFiles, c_fileName, 1); + } - RollingFileAppender rfa = new RollingFileAppender(); - rfa.RollingStyle = RollingFileAppender.RollingMode.Size; - SetFieldMaxSizeRollBackups(rfa, Int32.Parse(asParams[0].Trim())); - SetFieldCurSizeRollBackups(rfa, Int32.Parse(asParams[1].Trim())); - rfa.CountDirection = Int32.Parse(asParams[2].Trim()); + /// + /// Verifies that count goes to the highest when counting up + /// + [Test] + public void TestInitializeCountDownFixed3() + { + ArrayList alFiles = MakeTestDataFromString("2,5,6"); + VerifyInitializeDownFixedExpectedValue(alFiles, c_fileName, 2); + } - return rfa; - } + /// + /// Verifies that count goes to the highest when counting up + /// + [Test] + public void TestInitializeCountDownFixed4() + { + ArrayList alFiles = MakeTestDataFromString("3,5,6"); + VerifyInitializeDownFixedExpectedValue(alFiles, c_fileName, 3); + } - /// - /// Verifies that count goes to the highest when counting down - /// and infinite backups are selected - /// - [Test] - public void TestInitializeCountDownInfinite() - { - ArrayList alFiles = MakeTestDataFromString("2,3"); - VerifyInitializeDownInfiniteExpectedValue(alFiles, c_fileName, 3); - } + /// + /// Verifies that count goes to the highest when counting up + /// + [Test] + public void TestInitializeCountDownFixed5() + { + ArrayList alFiles = MakeTestDataFromString("1,2,3"); + VerifyInitializeDownFixedExpectedValue(alFiles, c_fileName, 3); + } - /// - /// Verifies that count goes to the highest when counting down - /// and infinite backups are selected - /// - [Test] - public void TestInitializeCountDownInfinite2() - { - ArrayList alFiles = MakeTestDataFromString("2,3,4,5,6,7,8,9,10"); - VerifyInitializeDownInfiniteExpectedValue(alFiles, c_fileName, 10); - } + /// + /// Verifies that count goes to the highest when counting up + /// + [Test] + public void TestInitializeCountDownFixed6() + { + ArrayList alFiles = MakeTestDataFromString("1,2"); + VerifyInitializeDownFixedExpectedValue(alFiles, c_fileName, 2); + } - /// - /// Verifies that count goes to the highest when counting down - /// and infinite backups are selected - /// - [Test] - public void TestInitializeCountDownInfinite3() - { - ArrayList alFiles = MakeTestDataFromString("9,10,3,4,5,7,9,6,1,2,8"); - VerifyInitializeDownInfiniteExpectedValue(alFiles, c_fileName, 10); - } + /// + /// Verifies that count goes to the highest when counting up + /// + [Test] + public void TestInitializeCountDownFixed7() + { + ArrayList alFiles = MakeTestDataFromString("2,3"); + VerifyInitializeDownFixedExpectedValue(alFiles, c_fileName, 3); + } - /// - /// Verifies that count goes to the highest when counting up - /// and infinite backups are selected - /// - [Test] - public void TestInitializeCountUpInfinite() - { - ArrayList alFiles = MakeTestDataFromString("2,3"); - VerifyInitializeUpInfiniteExpectedValue(alFiles, c_fileName, 3); - } + private static void InitializeAndVerifyExpectedValue(ArrayList alFiles, + string sBaseFile, + RollingFileAppender rfa, + int iExpectedValue) + { + InitializeRollBackups(rfa, sBaseFile, alFiles); + Assert.AreEqual(iExpectedValue, GetFieldCurSizeRollBackups(rfa)); + } - /// - /// Verifies that count goes to the highest when counting up - /// and infinite backups are selected - /// - [Test] - public void TestInitializeCountUpInfinite2() - { - ArrayList alFiles = MakeTestDataFromString("2,3,4,5,6,7,8,9,10"); - VerifyInitializeUpInfiniteExpectedValue(alFiles, c_fileName, 10); - } + /// + /// Tests the count down case, with infinite max backups, to see that + /// initialization of the rolling file appender results in the expected value + /// + /// + /// + /// + private static void VerifyInitializeDownInfiniteExpectedValue(ArrayList alFiles, + string sBaseFile, + int iExpectedValue) + { + InitializeAndVerifyExpectedValue(alFiles, sBaseFile, CreateRollingFileAppender("-1,0,-1"), iExpectedValue); + } - /// - /// Verifies that count goes to the highest when counting up - /// and infinite backups are selected - /// - [Test] - public void TestInitializeCountUpInfinite3() - { - ArrayList alFiles = MakeTestDataFromString("9,10,3,4,5,7,9,6,1,2,8"); - VerifyInitializeUpInfiniteExpectedValue(alFiles, c_fileName, 10); - } + /// + /// Creates a RollingFileAppender with the desired values, where the + /// values are passed as a comma separated string, with 3 parameters, + /// m_maxSizeRollBackups, m_curSizeRollBackups, CountDirection + /// + /// + /// + private static RollingFileAppender CreateRollingFileAppender(string sParams) + { + string[] asParams = sParams.Split(','); + if (null == asParams || asParams.Length != 3) + { + throw new ArgumentOutOfRangeException(sParams, sParams, + "Must have 3 comma separated params: MaxSizeRollBackups, CurSizeRollBackups, CountDirection"); + } + + RollingFileAppender rfa = new RollingFileAppender(); + rfa.RollingStyle = RollingFileAppender.RollingMode.Size; + SetFieldMaxSizeRollBackups(rfa, Int32.Parse(asParams[0].Trim())); + SetFieldCurSizeRollBackups(rfa, Int32.Parse(asParams[1].Trim())); + rfa.CountDirection = Int32.Parse(asParams[2].Trim()); + + return rfa; + } - /// - /// Creates a logger hierarchy, configures a rolling file appender and returns an ILogger - /// - /// The filename to log to - /// The locking model to use. - /// The error handler to use. - /// A configured ILogger - private static ILogger CreateLogger(string filename, - FileAppender.LockingModelBase lockModel, - IErrorHandler handler) - { - return CreateLogger(filename, lockModel, handler, 100000, 0); - } + /// + /// Verifies that count goes to the highest when counting down + /// and infinite backups are selected + /// + [Test] + public void TestInitializeCountDownInfinite() + { + ArrayList alFiles = MakeTestDataFromString("2,3"); + VerifyInitializeDownInfiniteExpectedValue(alFiles, c_fileName, 3); + } - /// - /// Creates a logger hierarchy, configures a rolling file appender and returns an ILogger - /// - /// The filename to log to - /// The locking model to use. - /// The error handler to use. - /// Maximum file size for roll - /// Maximum number of roll backups - /// A configured ILogger - private static ILogger CreateLogger(string filename, - FileAppender.LockingModelBase lockModel, - IErrorHandler handler, - int maxFileSize, - int maxSizeRollBackups) - { - Repository.Hierarchy.Hierarchy h = - (Repository.Hierarchy.Hierarchy)LogManager.CreateRepository("TestRepository"); - - RollingFileAppender appender = new RollingFileAppender(); - appender.File = filename; - appender.AppendToFile = false; - appender.CountDirection = 0; - appender.RollingStyle = RollingFileAppender.RollingMode.Size; - appender.MaxFileSize = maxFileSize; - appender.Encoding = Encoding.ASCII; - appender.ErrorHandler = handler; - appender.MaxSizeRollBackups = maxSizeRollBackups; - if (lockModel != null) - { - appender.LockingModel = lockModel; - } + /// + /// Verifies that count goes to the highest when counting down + /// and infinite backups are selected + /// + [Test] + public void TestInitializeCountDownInfinite2() + { + ArrayList alFiles = MakeTestDataFromString("2,3,4,5,6,7,8,9,10"); + VerifyInitializeDownInfiniteExpectedValue(alFiles, c_fileName, 10); + } - PatternLayout layout = new PatternLayout(); - layout.ConversionPattern = "%m%n"; - layout.ActivateOptions(); + /// + /// Verifies that count goes to the highest when counting down + /// and infinite backups are selected + /// + [Test] + public void TestInitializeCountDownInfinite3() + { + ArrayList alFiles = MakeTestDataFromString("9,10,3,4,5,7,9,6,1,2,8"); + VerifyInitializeDownInfiniteExpectedValue(alFiles, c_fileName, 10); + } - appender.Layout = layout; - appender.ActivateOptions(); + /// + /// Verifies that count goes to the highest when counting up + /// and infinite backups are selected + /// + [Test] + public void TestInitializeCountUpInfinite() + { + ArrayList alFiles = MakeTestDataFromString("2,3"); + VerifyInitializeUpInfiniteExpectedValue(alFiles, c_fileName, 3); + } - h.Root.AddAppender(appender); - h.Configured = true; + /// + /// Verifies that count goes to the highest when counting up + /// and infinite backups are selected + /// + [Test] + public void TestInitializeCountUpInfinite2() + { + ArrayList alFiles = MakeTestDataFromString("2,3,4,5,6,7,8,9,10"); + VerifyInitializeUpInfiniteExpectedValue(alFiles, c_fileName, 10); + } - ILogger log = h.GetLogger("Logger"); - return log; - } + /// + /// Verifies that count goes to the highest when counting up + /// and infinite backups are selected + /// + [Test] + public void TestInitializeCountUpInfinite3() + { + ArrayList alFiles = MakeTestDataFromString("9,10,3,4,5,7,9,6,1,2,8"); + VerifyInitializeUpInfiniteExpectedValue(alFiles, c_fileName, 10); + } - /// - /// Destroys the logger hierarchy created by - /// - private static void DestroyLogger() - { - Repository.Hierarchy.Hierarchy h = - (Repository.Hierarchy.Hierarchy)LogManager.GetRepository("TestRepository"); - h.ResetConfiguration(); - //Replace the repository selector so that we can recreate the hierarchy with the same name if necessary - LoggerManager.RepositorySelector = - new DefaultRepositorySelector(typeof(log4net.Repository.Hierarchy.Hierarchy)); - } + /// + /// Creates a logger hierarchy, configures a rolling file appender and returns an ILogger + /// + /// The filename to log to + /// The locking model to use. + /// The error handler to use. + /// A configured ILogger + private static ILogger CreateLogger(string filename, + FileAppender.LockingModelBase lockModel, + IErrorHandler handler) + { + return CreateLogger(filename, lockModel, handler, 100000, 0); + } - private static void AssertFileEquals(string filename, string contents) - { - FileInfo fileinfo = new FileInfo(filename); - StreamReader sr = new StreamReader(fileinfo.OpenRead()); - string logcont = sr.ReadToEnd(); - sr.Close(); + /// + /// Creates a logger hierarchy, configures a rolling file appender and returns an ILogger + /// + /// The filename to log to + /// The locking model to use. + /// The error handler to use. + /// Maximum file size for roll + /// Maximum number of roll backups + /// A configured ILogger + private static ILogger CreateLogger(string filename, + FileAppender.LockingModelBase lockModel, + IErrorHandler handler, + int maxFileSize, + int maxSizeRollBackups) + { + Repository.Hierarchy.Hierarchy h = + (Repository.Hierarchy.Hierarchy)LogManager.CreateRepository("TestRepository"); + + RollingFileAppender appender = new RollingFileAppender(); + appender.File = filename; + appender.AppendToFile = false; + appender.CountDirection = 0; + appender.RollingStyle = RollingFileAppender.RollingMode.Size; + appender.MaxFileSize = maxFileSize; + appender.Encoding = Encoding.ASCII; + appender.ErrorHandler = handler; + appender.MaxSizeRollBackups = maxSizeRollBackups; + if (lockModel != null) + { + appender.LockingModel = lockModel; + } + + PatternLayout layout = new PatternLayout(); + layout.ConversionPattern = "%m%n"; + layout.ActivateOptions(); + + appender.Layout = layout; + appender.ActivateOptions(); + + h.Root.AddAppender(appender); + h.Configured = true; + + ILogger log = h.GetLogger("Logger"); + return log; + } - Assert.AreEqual(contents, logcont, "Log contents is not what is expected"); + /// + /// Destroys the logger hierarchy created by + /// + private static void DestroyLogger() + { + Repository.Hierarchy.Hierarchy h = + (Repository.Hierarchy.Hierarchy)LogManager.GetRepository("TestRepository"); + h.ResetConfiguration(); + //Replace the repository selector so that we can recreate the hierarchy with the same name if necessary + LoggerManager.RepositorySelector = + new DefaultRepositorySelector(typeof(log4net.Repository.Hierarchy.Hierarchy)); + } - File.Delete(filename); - } + private static void AssertFileEquals(string filename, string contents) + { + FileInfo fileinfo = new FileInfo(filename); + StreamReader sr = new StreamReader(fileinfo.OpenRead()); + string logcont = sr.ReadToEnd(); + sr.Close(); - /// - /// Verifies that logging a message actually produces output - /// - [Test] - public void TestLogOutput() - { - string filename = "test_simple.log"; - SilentErrorHandler sh = new SilentErrorHandler(); - ILogger log = CreateLogger(filename, new FileAppender.ExclusiveLock(), sh); - log.Log(GetType(), Level.Info, "This is a message", null); - log.Log(GetType(), Level.Info, "This is a message 2", null); - DestroyLogger(); - - AssertFileEquals(filename, - "This is a message" + Environment.NewLine + "This is a message 2" + Environment.NewLine); - Assert.AreEqual("", sh.Message, "Unexpected error message"); - } + Assert.AreEqual(contents, logcont, "Log contents is not what is expected"); - /// - /// Verifies that attempting to log to a locked file fails gracefully - /// - [Test] - public void TestExclusiveLockFails() - { - string filename = "test_exclusive_lock_fails.log"; + File.Delete(filename); + } - FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.None); - fs.Write(Encoding.ASCII.GetBytes("Test"), 0, 4); + /// + /// Verifies that logging a message actually produces output + /// + [Test] + public void TestLogOutput() + { + string filename = "test_simple.log"; + SilentErrorHandler sh = new SilentErrorHandler(); + ILogger log = CreateLogger(filename, new FileAppender.ExclusiveLock(), sh); + log.Log(GetType(), Level.Info, "This is a message", null); + log.Log(GetType(), Level.Info, "This is a message 2", null); + DestroyLogger(); + + AssertFileEquals(filename, + "This is a message" + Environment.NewLine + "This is a message 2" + Environment.NewLine); + Assert.AreEqual("", sh.Message, "Unexpected error message"); + } - SilentErrorHandler sh = new SilentErrorHandler(); - ILogger log = CreateLogger(filename, new FileAppender.ExclusiveLock(), sh); - log.Log(GetType(), Level.Info, "This is a message", null); - log.Log(GetType(), Level.Info, "This is a message 2", null); - DestroyLogger(); - fs.Close(); + /// + /// Verifies that attempting to log to a locked file fails gracefully + /// + [Test] + public void TestExclusiveLockFails() + { + string filename = "test_exclusive_lock_fails.log"; - AssertFileEquals(filename, "Test"); - Assert.AreEqual(sh.Message.Substring(0, 30), "Unable to acquire lock on file", - "Expecting an error message"); - } + FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.None); + fs.Write(Encoding.ASCII.GetBytes("Test"), 0, 4); - /// - /// Verifies that attempting to log to a locked file recovers if the lock is released - /// - [Test] - public void TestExclusiveLockRecovers() - { - string filename = "test_exclusive_lock_recovers.log"; + SilentErrorHandler sh = new SilentErrorHandler(); + ILogger log = CreateLogger(filename, new FileAppender.ExclusiveLock(), sh); + log.Log(GetType(), Level.Info, "This is a message", null); + log.Log(GetType(), Level.Info, "This is a message 2", null); + DestroyLogger(); + fs.Close(); - FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.None); - fs.Write(Encoding.ASCII.GetBytes("Test"), 0, 4); + AssertFileEquals(filename, "Test"); + Assert.AreEqual(sh.Message.Substring(0, 30), "Unable to acquire lock on file", + "Expecting an error message"); + } - SilentErrorHandler sh = new SilentErrorHandler(); - ILogger log = CreateLogger(filename, new FileAppender.ExclusiveLock(), sh); - log.Log(GetType(), Level.Info, "This is a message", null); - fs.Close(); - log.Log(GetType(), Level.Info, "This is a message 2", null); - DestroyLogger(); + /// + /// Verifies that attempting to log to a locked file recovers if the lock is released + /// + [Test] + public void TestExclusiveLockRecovers() + { + string filename = "test_exclusive_lock_recovers.log"; - AssertFileEquals(filename, "This is a message 2" + Environment.NewLine); - Assert.AreEqual("Unable to acquire lock on file", sh.Message.Substring(0, 30), - "Expecting an error message"); - } + FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.None); + fs.Write(Encoding.ASCII.GetBytes("Test"), 0, 4); - /// - /// Verifies that attempting to log to a file with ExclusiveLock really locks the file - /// - [Test] - public void TestExclusiveLockLocks() - { - string filename = "test_exclusive_lock_locks.log"; - bool locked = false; + SilentErrorHandler sh = new SilentErrorHandler(); + ILogger log = CreateLogger(filename, new FileAppender.ExclusiveLock(), sh); + log.Log(GetType(), Level.Info, "This is a message", null); + fs.Close(); + log.Log(GetType(), Level.Info, "This is a message 2", null); + DestroyLogger(); - SilentErrorHandler sh = new SilentErrorHandler(); - ILogger log = CreateLogger(filename, new FileAppender.ExclusiveLock(), sh); - log.Log(GetType(), Level.Info, "This is a message", null); + AssertFileEquals(filename, "This is a message 2" + Environment.NewLine); + Assert.AreEqual("Unable to acquire lock on file", sh.Message.Substring(0, 30), + "Expecting an error message"); + } - try - { - FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.None); - fs.Write(Encoding.ASCII.GetBytes("Test"), 0, 4); - fs.Close(); - } - catch (IOException e1) - { + /// + /// Verifies that attempting to log to a file with ExclusiveLock really locks the file + /// + [Test] + public void TestExclusiveLockLocks() + { + string filename = "test_exclusive_lock_locks.log"; + bool locked = false; + + SilentErrorHandler sh = new SilentErrorHandler(); + ILogger log = CreateLogger(filename, new FileAppender.ExclusiveLock(), sh); + log.Log(GetType(), Level.Info, "This is a message", null); + + try + { + FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.None); + fs.Write(Encoding.ASCII.GetBytes("Test"), 0, 4); + fs.Close(); + } + catch (IOException e1) + { #if MONO Assert.AreEqual("Sharing violation on path ", e1.Message.Substring(0, 26), "Unexpected exception"); #else - Assert.AreEqual("The process cannot access the file ", e1.Message.Substring(0, 35), - "Unexpected exception"); + Assert.AreEqual("The process cannot access the file ", e1.Message.Substring(0, 35), + "Unexpected exception"); #endif - locked = true; - } + locked = true; + } - log.Log(GetType(), Level.Info, "This is a message 2", null); - DestroyLogger(); + log.Log(GetType(), Level.Info, "This is a message 2", null); + DestroyLogger(); - Assert.IsTrue(locked, "File was not locked"); + Assert.IsTrue(locked, "File was not locked"); #if !MONO || MONO_3_5 || MONO_4_0 // at least on Linux with Mono 2.4 exclusive locking doesn't work as one would expect - AssertFileEquals(filename, - "This is a message" + Environment.NewLine + "This is a message 2" + Environment.NewLine); + AssertFileEquals(filename, + "This is a message" + Environment.NewLine + "This is a message 2" + Environment.NewLine); #endif - Assert.AreEqual("", sh.Message, "Unexpected error message"); - } + Assert.AreEqual("", sh.Message, "Unexpected error message"); + } - /// - /// Verifies that attempting to log to a locked file fails gracefully - /// - [Test] - public void TestMinimalLockFails() - { - string filename = "test_minimal_lock_fails.log"; + /// + /// Verifies that attempting to log to a locked file fails gracefully + /// + [Test] + public void TestMinimalLockFails() + { + string filename = "test_minimal_lock_fails.log"; - FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.None); - fs.Write(Encoding.ASCII.GetBytes("Test"), 0, 4); + FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.None); + fs.Write(Encoding.ASCII.GetBytes("Test"), 0, 4); - SilentErrorHandler sh = new SilentErrorHandler(); - ILogger log = CreateLogger(filename, new FileAppender.MinimalLock(), sh); - log.Log(GetType(), Level.Info, "This is a message", null); - log.Log(GetType(), Level.Info, "This is a message 2", null); - DestroyLogger(); - fs.Close(); + SilentErrorHandler sh = new SilentErrorHandler(); + ILogger log = CreateLogger(filename, new FileAppender.MinimalLock(), sh); + log.Log(GetType(), Level.Info, "This is a message", null); + log.Log(GetType(), Level.Info, "This is a message 2", null); + DestroyLogger(); + fs.Close(); - AssertFileEquals(filename, "Test"); - Assert.AreEqual("Unable to acquire lock on file", sh.Message.Substring(0, 30), - "Expecting an error message"); - } + AssertFileEquals(filename, "Test"); + Assert.AreEqual("Unable to acquire lock on file", sh.Message.Substring(0, 30), + "Expecting an error message"); + } - /// - /// Verifies that attempting to log to a locked file recovers if the lock is released - /// - [Test] - public void TestMinimalLockRecovers() - { - string filename = "test_minimal_lock_recovers.log"; + /// + /// Verifies that attempting to log to a locked file recovers if the lock is released + /// + [Test] + public void TestMinimalLockRecovers() + { + string filename = "test_minimal_lock_recovers.log"; - FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.None); - fs.Write(Encoding.ASCII.GetBytes("Test"), 0, 4); + FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.None); + fs.Write(Encoding.ASCII.GetBytes("Test"), 0, 4); - SilentErrorHandler sh = new SilentErrorHandler(); - ILogger log = CreateLogger(filename, new FileAppender.MinimalLock(), sh); - log.Log(GetType(), Level.Info, "This is a message", null); - fs.Close(); - log.Log(GetType(), Level.Info, "This is a message 2", null); - DestroyLogger(); + SilentErrorHandler sh = new SilentErrorHandler(); + ILogger log = CreateLogger(filename, new FileAppender.MinimalLock(), sh); + log.Log(GetType(), Level.Info, "This is a message", null); + fs.Close(); + log.Log(GetType(), Level.Info, "This is a message 2", null); + DestroyLogger(); - AssertFileEquals(filename, "This is a message 2" + Environment.NewLine); - Assert.AreEqual("Unable to acquire lock on file", sh.Message.Substring(0, 30), - "Expecting an error message"); - } + AssertFileEquals(filename, "This is a message 2" + Environment.NewLine); + Assert.AreEqual("Unable to acquire lock on file", sh.Message.Substring(0, 30), + "Expecting an error message"); + } - /// - /// Verifies that attempting to log to a file with MinimalLock doesn't lock the file - /// - [Test] - public void TestMinimalLockUnlocks() - { - string filename = "test_minimal_lock_unlocks.log"; - bool locked; - - SilentErrorHandler sh = new SilentErrorHandler(); - ILogger log = CreateLogger(filename, new FileAppender.MinimalLock(), sh); - log.Log(GetType(), Level.Info, "This is a message", null); - - locked = true; - FileStream fs = new FileStream(filename, FileMode.Append, FileAccess.Write, FileShare.None); - fs.Write(Encoding.ASCII.GetBytes("Test" + Environment.NewLine), 0, 4 + Environment.NewLine.Length); - fs.Close(); - - log.Log(GetType(), Level.Info, "This is a message 2", null); - DestroyLogger(); - - Assert.IsTrue(locked, "File was not locked"); - AssertFileEquals(filename, - "This is a message" + Environment.NewLine + "Test" + Environment.NewLine + "This is a message 2" + - Environment.NewLine); - Assert.AreEqual("", sh.Message, "Unexpected error message"); - } + /// + /// Verifies that attempting to log to a file with MinimalLock doesn't lock the file + /// + [Test] + public void TestMinimalLockUnlocks() + { + string filename = "test_minimal_lock_unlocks.log"; + bool locked; + + SilentErrorHandler sh = new SilentErrorHandler(); + ILogger log = CreateLogger(filename, new FileAppender.MinimalLock(), sh); + log.Log(GetType(), Level.Info, "This is a message", null); + + locked = true; + FileStream fs = new FileStream(filename, FileMode.Append, FileAccess.Write, FileShare.None); + fs.Write(Encoding.ASCII.GetBytes("Test" + Environment.NewLine), 0, 4 + Environment.NewLine.Length); + fs.Close(); + + log.Log(GetType(), Level.Info, "This is a message 2", null); + DestroyLogger(); + + Assert.IsTrue(locked, "File was not locked"); + AssertFileEquals(filename, + "This is a message" + Environment.NewLine + "Test" + Environment.NewLine + "This is a message 2" + + Environment.NewLine); + Assert.AreEqual("", sh.Message, "Unexpected error message"); + } #if !NETCF - /// - /// Verifies that attempting to log to a locked file fails gracefully - /// - [Test] - public void TestInterProcessLockFails() - { - string filename = "test_interprocess_lock_fails.log"; + /// + /// Verifies that attempting to log to a locked file fails gracefully + /// + [Test] + public void TestInterProcessLockFails() + { + string filename = "test_interprocess_lock_fails.log"; - FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.None); - fs.Write(Encoding.ASCII.GetBytes("Test"), 0, 4); + FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.None); + fs.Write(Encoding.ASCII.GetBytes("Test"), 0, 4); - SilentErrorHandler sh = new SilentErrorHandler(); - ILogger log = CreateLogger(filename, new FileAppender.InterProcessLock(), sh); - log.Log(GetType(), Level.Info, "This is a message", null); - log.Log(GetType(), Level.Info, "This is a message 2", null); - DestroyLogger(); - fs.Close(); + SilentErrorHandler sh = new SilentErrorHandler(); + ILogger log = CreateLogger(filename, new FileAppender.InterProcessLock(), sh); + log.Log(GetType(), Level.Info, "This is a message", null); + log.Log(GetType(), Level.Info, "This is a message 2", null); + DestroyLogger(); + fs.Close(); - AssertFileEquals(filename, "Test"); - Assert.AreEqual("Unable to acquire lock on file", sh.Message.Substring(0, 30), - "Expecting an error message"); - } + AssertFileEquals(filename, "Test"); + Assert.AreEqual("Unable to acquire lock on file", sh.Message.Substring(0, 30), + "Expecting an error message"); + } - /// - /// Verifies that attempting to log to a locked file recovers if the lock is released - /// - [Test] - public void TestInterProcessLockRecovers() - { - string filename = "test_interprocess_lock_recovers.log"; + /// + /// Verifies that attempting to log to a locked file recovers if the lock is released + /// + [Test] + public void TestInterProcessLockRecovers() + { + string filename = "test_interprocess_lock_recovers.log"; - FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.None); - fs.Write(Encoding.ASCII.GetBytes("Test"), 0, 4); + FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.None); + fs.Write(Encoding.ASCII.GetBytes("Test"), 0, 4); - SilentErrorHandler sh = new SilentErrorHandler(); - ILogger log = CreateLogger(filename, new FileAppender.InterProcessLock(), sh); - log.Log(GetType(), Level.Info, "This is a message", null); - fs.Close(); - log.Log(GetType(), Level.Info, "This is a message 2", null); - DestroyLogger(); + SilentErrorHandler sh = new SilentErrorHandler(); + ILogger log = CreateLogger(filename, new FileAppender.InterProcessLock(), sh); + log.Log(GetType(), Level.Info, "This is a message", null); + fs.Close(); + log.Log(GetType(), Level.Info, "This is a message 2", null); + DestroyLogger(); - AssertFileEquals(filename, "This is a message 2" + Environment.NewLine); - Assert.AreEqual("Unable to acquire lock on file", sh.Message.Substring(0, 30), - "Expecting an error message"); - } + AssertFileEquals(filename, "This is a message 2" + Environment.NewLine); + Assert.AreEqual("Unable to acquire lock on file", sh.Message.Substring(0, 30), + "Expecting an error message"); + } - /// - /// Verifies that attempting to log to a file with InterProcessLock really locks the file - /// - [Test] - public void TestInterProcessLockUnlocks() - { - string filename = "test_interprocess_lock_unlocks.log"; - bool locked; - - SilentErrorHandler sh = new SilentErrorHandler(); - ILogger log = CreateLogger(filename, new FileAppender.InterProcessLock(), sh); - log.Log(GetType(), Level.Info, "This is a message", null); - - locked = true; - FileStream fs = new FileStream(filename, FileMode.Append, FileAccess.Write, FileShare.ReadWrite); - fs.Write(Encoding.ASCII.GetBytes("Test" + Environment.NewLine), 0, 4 + Environment.NewLine.Length); - fs.Close(); - - log.Log(GetType(), Level.Info, "This is a message 2", null); - DestroyLogger(); - - Assert.IsTrue(locked, "File was not locked"); - AssertFileEquals(filename, - "This is a message" + Environment.NewLine + "Test" + Environment.NewLine + "This is a message 2" + - Environment.NewLine); - Assert.AreEqual("", sh.Message, "Unexpected error message"); - } + /// + /// Verifies that attempting to log to a file with InterProcessLock really locks the file + /// + [Test] + public void TestInterProcessLockUnlocks() + { + string filename = "test_interprocess_lock_unlocks.log"; + bool locked; + + SilentErrorHandler sh = new SilentErrorHandler(); + ILogger log = CreateLogger(filename, new FileAppender.InterProcessLock(), sh); + log.Log(GetType(), Level.Info, "This is a message", null); + + locked = true; + FileStream fs = new FileStream(filename, FileMode.Append, FileAccess.Write, FileShare.ReadWrite); + fs.Write(Encoding.ASCII.GetBytes("Test" + Environment.NewLine), 0, 4 + Environment.NewLine.Length); + fs.Close(); + + log.Log(GetType(), Level.Info, "This is a message 2", null); + DestroyLogger(); + + Assert.IsTrue(locked, "File was not locked"); + AssertFileEquals(filename, + "This is a message" + Environment.NewLine + "Test" + Environment.NewLine + "This is a message 2" + + Environment.NewLine); + Assert.AreEqual("", sh.Message, "Unexpected error message"); + } - /// - /// Verifies that rolling file works - /// - [Test] - public void TestInterProcessLockRoll() - { - string filename = "test_interprocess_lock_roll.log"; + /// + /// Verifies that rolling file works + /// + [Test] + public void TestInterProcessLockRoll() + { + string filename = "test_interprocess_lock_roll.log"; - SilentErrorHandler sh = new SilentErrorHandler(); - ILogger log = CreateLogger(filename, new FileAppender.InterProcessLock(), sh, 1, 2); + SilentErrorHandler sh = new SilentErrorHandler(); + ILogger log = CreateLogger(filename, new FileAppender.InterProcessLock(), sh, 1, 2); - Assert.DoesNotThrow(delegate - { - log.Log(GetType(), Level.Info, "A", null); - }); - Assert.DoesNotThrow(delegate - { - log.Log(GetType(), Level.Info, "A", null); - }); + Assert.DoesNotThrow(delegate + { + log.Log(GetType(), Level.Info, "A", null); + }); + Assert.DoesNotThrow(delegate + { + log.Log(GetType(), Level.Info, "A", null); + }); - DestroyLogger(); + DestroyLogger(); - AssertFileEquals(filename, "A" + Environment.NewLine); - AssertFileEquals(filename + ".1", "A" + Environment.NewLine); - Assert.IsEmpty(sh.Message); - } + AssertFileEquals(filename, "A" + Environment.NewLine); + AssertFileEquals(filename + ".1", "A" + Environment.NewLine); + Assert.IsEmpty(sh.Message); + } #endif - /// - /// Verify that the default LockModel is ExclusiveLock, to maintain backwards compatibility with previous behaviour - /// - [Test] - public void TestDefaultLockingModel() - { - string filename = "test_default.log"; - - SilentErrorHandler sh = new SilentErrorHandler(); - ILogger log = CreateLogger(filename, null, sh); + /// + /// Verify that the default LockModel is ExclusiveLock, to maintain backwards compatibility with previous behaviour + /// + [Test] + public void TestDefaultLockingModel() + { + string filename = "test_default.log"; - IAppender[] appenders = log.Repository.GetAppenders(); - Assert.AreEqual(1, appenders.Length, "The wrong number of appenders are configured"); + SilentErrorHandler sh = new SilentErrorHandler(); + ILogger log = CreateLogger(filename, null, sh); - RollingFileAppender rfa = (RollingFileAppender)(appenders[0]); - Assert.AreEqual(typeof(log4net.Appender.FileAppender.ExclusiveLock), rfa.LockingModel.GetType(), - "The LockingModel is of an unexpected type"); + IAppender[] appenders = log.Repository.GetAppenders(); + Assert.AreEqual(1, appenders.Length, "The wrong number of appenders are configured"); - DestroyLogger(); - } + RollingFileAppender rfa = (RollingFileAppender)(appenders[0]); + Assert.AreEqual(typeof(log4net.Appender.FileAppender.ExclusiveLock), rfa.LockingModel.GetType(), + "The LockingModel is of an unexpected type"); - /// - /// Tests the count up case, with infinite max backups , to see that - /// initialization of the rolling file appender results in the expected value - /// - /// - /// - /// - private static void VerifyInitializeUpInfiniteExpectedValue(ArrayList alFiles, - string sBaseFile, - int iExpectedValue) - { - InitializeAndVerifyExpectedValue(alFiles, sBaseFile, CreateRollingFileAppender("-1,0,1"), iExpectedValue); - } + DestroyLogger(); + } + /// + /// Tests the count up case, with infinite max backups , to see that + /// initialization of the rolling file appender results in the expected value + /// + /// + /// + /// + private static void VerifyInitializeUpInfiniteExpectedValue(ArrayList alFiles, + string sBaseFile, + int iExpectedValue) + { + InitializeAndVerifyExpectedValue(alFiles, sBaseFile, CreateRollingFileAppender("-1,0,1"), iExpectedValue); + } - /// - /// Tests the count down case, with max backups limited to 3, to see that - /// initialization of the rolling file appender results in the expected value - /// - /// - /// - /// - private static void VerifyInitializeDownFixedExpectedValue(ArrayList alFiles, - string sBaseFile, - int iExpectedValue) - { - InitializeAndVerifyExpectedValue(alFiles, sBaseFile, CreateRollingFileAppender("3,0,-1"), iExpectedValue); - } - /// - /// Turns a string of comma separated numbers into a collection of filenames - /// generated from the numbers. - /// - /// Defaults to filename in _fileName variable. - /// - /// - /// Comma separated list of numbers for counted file names - /// - private static ArrayList MakeTestDataFromString(string sFileNumbers) - { - return MakeTestDataFromString(c_fileName, sFileNumbers); - } + /// + /// Tests the count down case, with max backups limited to 3, to see that + /// initialization of the rolling file appender results in the expected value + /// + /// + /// + /// + private static void VerifyInitializeDownFixedExpectedValue(ArrayList alFiles, + string sBaseFile, + int iExpectedValue) + { + InitializeAndVerifyExpectedValue(alFiles, sBaseFile, CreateRollingFileAppender("3,0,-1"), iExpectedValue); + } - /// - /// Turns a string of comma separated numbers into a collection of filenames - /// generated from the numbers - /// - /// Uses the input filename. - /// - /// Name of file to combine with numbers when generating counted file names - /// Comma separated list of numbers for counted file names - /// - private static ArrayList MakeTestDataFromString(string sFileName, string sFileNumbers) - { - ArrayList alFiles = new ArrayList(); + /// + /// Turns a string of comma separated numbers into a collection of filenames + /// generated from the numbers. + /// + /// Defaults to filename in _fileName variable. + /// + /// + /// Comma separated list of numbers for counted file names + /// + private static ArrayList MakeTestDataFromString(string sFileNumbers) + { + return MakeTestDataFromString(c_fileName, sFileNumbers); + } - string[] sNumbers = sFileNumbers.Split(','); - foreach (string sNumber in sNumbers) - { - Int32 iValue = Int32.Parse(sNumber.Trim()); - alFiles.Add(MakeFileName(sFileName, iValue)); - } + /// + /// Turns a string of comma separated numbers into a collection of filenames + /// generated from the numbers + /// + /// Uses the input filename. + /// + /// Name of file to combine with numbers when generating counted file names + /// Comma separated list of numbers for counted file names + /// + private static ArrayList MakeTestDataFromString(string sFileName, string sFileNumbers) + { + ArrayList alFiles = new ArrayList(); - return alFiles; - } + string[] sNumbers = sFileNumbers.Split(','); + foreach (string sNumber in sNumbers) + { + Int32 iValue = Int32.Parse(sNumber.Trim()); + alFiles.Add(MakeFileName(sFileName, iValue)); + } - /// - /// Tests that the current backup index is correctly detected - /// for a file with no extension - /// - [Test] - public void TestInitializeRollBackups2() - { - VerifyInitializeRollBackupsFromBaseFile("LogFile"); - } + return alFiles; + } - /// - /// Tests that the current backup index is correctly detected - /// for a file with a .log extension - /// - [Test] - public void TestInitializeRollBackups3() - { - VerifyInitializeRollBackupsFromBaseFile("LogFile.log"); - } + /// + /// Tests that the current backup index is correctly detected + /// for a file with no extension + /// + [Test] + public void TestInitializeRollBackups2() + { + VerifyInitializeRollBackupsFromBaseFile("LogFile"); + } - /// - /// Makes sure that the initialization can detect the backup - /// number correctly. - /// - /// - /// - public void VerifyInitializeRollBackups(int iBackups, int iMaxSizeRollBackups) - { - string sBaseFile = "LogFile.log"; - ArrayList arrFiles = new ArrayList(); - arrFiles.Add("junk1"); - for (int i = 0; i < iBackups; i++) - { - arrFiles.Add(MakeFileName(sBaseFile, i)); - } + /// + /// Tests that the current backup index is correctly detected + /// for a file with a .log extension + /// + [Test] + public void TestInitializeRollBackups3() + { + VerifyInitializeRollBackupsFromBaseFile("LogFile.log"); + } - RollingFileAppender rfa = new RollingFileAppender(); - rfa.RollingStyle = RollingFileAppender.RollingMode.Size; - SetFieldMaxSizeRollBackups(rfa, iMaxSizeRollBackups); - SetFieldCurSizeRollBackups(rfa, 0); - InitializeRollBackups(rfa, sBaseFile, arrFiles); - - // iBackups / Meaning - // 0 = none - // 1 = file.log - // 2 = file.log.1 - // 3 = file.log.2 - if (0 == iBackups || - 1 == iBackups) - { - Assert.AreEqual(0, GetFieldCurSizeRollBackups(rfa)); - } - else - { - Assert.AreEqual(Math.Min(iBackups - 1, iMaxSizeRollBackups), GetFieldCurSizeRollBackups(rfa)); - } - } + /// + /// Makes sure that the initialization can detect the backup + /// number correctly. + /// + /// + /// + public void VerifyInitializeRollBackups(int iBackups, int iMaxSizeRollBackups) + { + string sBaseFile = "LogFile.log"; + ArrayList arrFiles = new ArrayList(); + arrFiles.Add("junk1"); + for (int i = 0; i < iBackups; i++) + { + arrFiles.Add(MakeFileName(sBaseFile, i)); + } + + RollingFileAppender rfa = new RollingFileAppender(); + rfa.RollingStyle = RollingFileAppender.RollingMode.Size; + SetFieldMaxSizeRollBackups(rfa, iMaxSizeRollBackups); + SetFieldCurSizeRollBackups(rfa, 0); + InitializeRollBackups(rfa, sBaseFile, arrFiles); + + // iBackups / Meaning + // 0 = none + // 1 = file.log + // 2 = file.log.1 + // 3 = file.log.2 + if (0 == iBackups || + 1 == iBackups) + { + Assert.AreEqual(0, GetFieldCurSizeRollBackups(rfa)); + } + else + { + Assert.AreEqual(Math.Min(iBackups - 1, iMaxSizeRollBackups), GetFieldCurSizeRollBackups(rfa)); + } + } - /// - /// Tests that the current backup index is correctly detected, - /// and gets no bigger than the max backups setting - /// - [Test] - public void TestInitializeRollBackups4() - { - const int iMaxRollBackups = 5; - VerifyInitializeRollBackups(0, iMaxRollBackups); - VerifyInitializeRollBackups(1, iMaxRollBackups); - VerifyInitializeRollBackups(2, iMaxRollBackups); - VerifyInitializeRollBackups(3, iMaxRollBackups); - VerifyInitializeRollBackups(4, iMaxRollBackups); - VerifyInitializeRollBackups(5, iMaxRollBackups); - VerifyInitializeRollBackups(6, iMaxRollBackups); - // Final we cap out at the max value - VerifyInitializeRollBackups(7, iMaxRollBackups); - VerifyInitializeRollBackups(8, iMaxRollBackups); - } + /// + /// Tests that the current backup index is correctly detected, + /// and gets no bigger than the max backups setting + /// + [Test] + public void TestInitializeRollBackups4() + { + const int iMaxRollBackups = 5; + VerifyInitializeRollBackups(0, iMaxRollBackups); + VerifyInitializeRollBackups(1, iMaxRollBackups); + VerifyInitializeRollBackups(2, iMaxRollBackups); + VerifyInitializeRollBackups(3, iMaxRollBackups); + VerifyInitializeRollBackups(4, iMaxRollBackups); + VerifyInitializeRollBackups(5, iMaxRollBackups); + VerifyInitializeRollBackups(6, iMaxRollBackups); + // Final we cap out at the max value + VerifyInitializeRollBackups(7, iMaxRollBackups); + VerifyInitializeRollBackups(8, iMaxRollBackups); + } - /// - /// - /// - [Test, - Ignore("Not Implemented: Want to test counted files limited up, to see that others are ?? ignored? deleted?")] - public void TestInitialization3() - { - } + /// + /// + /// + [Test, + Ignore("Not Implemented: Want to test counted files limited up, to see that others are ?? ignored? deleted?")] + public void TestInitialization3() + { + } - /// - /// - /// - [Test, - Ignore( - "Not Implemented: Want to test counted files limited down, to see that others are ?? ignored? deleted?")] - public void TestInitialization4() - { - } + /// + /// + /// + [Test, + Ignore( + "Not Implemented: Want to test counted files limited down, to see that others are ?? ignored? deleted?")] + public void TestInitialization4() + { + } - /// - /// - /// - [Test, - Ignore("Not Implemented: Want to test dated files with a limit, to see that others are ?? ignored? deleted?")] - public void TestInitialization5() - { - } + /// + /// + /// + [Test, + Ignore("Not Implemented: Want to test dated files with a limit, to see that others are ?? ignored? deleted?")] + public void TestInitialization5() + { + } - /// - /// - /// - [Test, - Ignore("Not Implemented: Want to test dated files with no limit, to see that others are ?? ignored? deleted?")] - public void TestInitialization6() - { - } + /// + /// + /// + [Test, + Ignore("Not Implemented: Want to test dated files with no limit, to see that others are ?? ignored? deleted?")] + public void TestInitialization6() + { + } - /// - /// - /// - [Test, - Ignore( - "Not Implemented: Want to test dated files with mixed dates existing, to see that other dates do not matter")] - public void TestInitialization7() - { - } + /// + /// + /// + [Test, + Ignore( + "Not Implemented: Want to test dated files with mixed dates existing, to see that other dates do not matter")] + public void TestInitialization7() + { + } - // - // Helper functions to dig into the appender - // + // + // Helper functions to dig into the appender + // - private static ArrayList GetExistingFiles(string baseFilePath) - { - return GetExistingFiles(baseFilePath, false); - } + private static ArrayList GetExistingFiles(string baseFilePath) + { + return GetExistingFiles(baseFilePath, false); + } - private static ArrayList GetExistingFiles(string baseFilePath, bool preserveLogFileNameExtension) - { - RollingFileAppender appender = new RollingFileAppender(); - appender.PreserveLogFileNameExtension = preserveLogFileNameExtension; - appender.SecurityContext = NullSecurityContext.Instance; + private static ArrayList GetExistingFiles(string baseFilePath, bool preserveLogFileNameExtension) + { + RollingFileAppender appender = new RollingFileAppender(); + appender.PreserveLogFileNameExtension = preserveLogFileNameExtension; + appender.SecurityContext = NullSecurityContext.Instance; - return (ArrayList)Utils.InvokeMethod(appender, "GetExistingFiles", baseFilePath); - } + return (ArrayList)Utils.InvokeMethod(appender, "GetExistingFiles", baseFilePath); + } - private static void InitializeRollBackups(RollingFileAppender appender, string baseFile, ArrayList arrayFiles) - { - Utils.InvokeMethod(appender, "InitializeRollBackups", baseFile, arrayFiles); - } + private static void InitializeRollBackups(RollingFileAppender appender, string baseFile, ArrayList arrayFiles) + { + Utils.InvokeMethod(appender, "InitializeRollBackups", baseFile, arrayFiles); + } - private static int GetFieldCurSizeRollBackups(RollingFileAppender appender) - { - return (int)Utils.GetField(appender, "m_curSizeRollBackups"); - } + private static int GetFieldCurSizeRollBackups(RollingFileAppender appender) + { + return (int)Utils.GetField(appender, "m_curSizeRollBackups"); + } - private static void SetFieldCurSizeRollBackups(RollingFileAppender appender, int val) - { - Utils.SetField(appender, "m_curSizeRollBackups", val); - } + private static void SetFieldCurSizeRollBackups(RollingFileAppender appender, int val) + { + Utils.SetField(appender, "m_curSizeRollBackups", val); + } - private static void SetFieldMaxSizeRollBackups(RollingFileAppender appender, int val) - { - Utils.SetField(appender, "m_maxSizeRollBackups", val); - } + private static void SetFieldMaxSizeRollBackups(RollingFileAppender appender, int val) + { + Utils.SetField(appender, "m_maxSizeRollBackups", val); + } - private static string GetTestMessage() - { - switch (Environment.NewLine.Length) - { - case 2: - return c_testMessage98Chars; + private static string GetTestMessage() + { + switch (Environment.NewLine.Length) + { + case 2: + return c_testMessage98Chars; - case 1: - return c_testMessage99Chars; + case 1: + return c_testMessage99Chars; - default: - throw new Exception("Unexpected Environment.NewLine.Length"); - } - } + default: + throw new Exception("Unexpected Environment.NewLine.Length"); + } } + } - [TestFixture] - public class RollingFileAppenderSubClassTest : RollingFileAppender + [TestFixture] + public class RollingFileAppenderSubClassTest : RollingFileAppender + { + [Test] + public void TestComputeCheckPeriod() { - [Test] - public void TestComputeCheckPeriod() - { - RollingFileAppender rfa = new RollingFileAppender(); + RollingFileAppender rfa = new RollingFileAppender(); - Assert.AreEqual(RollPoint.TopOfMinute, InvokeComputeCheckPeriod(rfa, ".yyyy-MM-dd HH:mm"), - "TopOfMinute pattern"); - Assert.AreEqual(RollPoint.TopOfHour, InvokeComputeCheckPeriod(rfa, ".yyyy-MM-dd HH"), "TopOfHour pattern"); - Assert.AreEqual(RollPoint.HalfDay, InvokeComputeCheckPeriod(rfa, ".yyyy-MM-dd tt"), "HalfDay pattern"); - Assert.AreEqual(RollPoint.TopOfDay, InvokeComputeCheckPeriod(rfa, ".yyyy-MM-dd"), "TopOfDay pattern"); - Assert.AreEqual(RollPoint.TopOfMonth, InvokeComputeCheckPeriod(rfa, ".yyyy-MM"), "TopOfMonth pattern"); + Assert.AreEqual(RollPoint.TopOfMinute, InvokeComputeCheckPeriod(rfa, ".yyyy-MM-dd HH:mm"), + "TopOfMinute pattern"); + Assert.AreEqual(RollPoint.TopOfHour, InvokeComputeCheckPeriod(rfa, ".yyyy-MM-dd HH"), "TopOfHour pattern"); + Assert.AreEqual(RollPoint.HalfDay, InvokeComputeCheckPeriod(rfa, ".yyyy-MM-dd tt"), "HalfDay pattern"); + Assert.AreEqual(RollPoint.TopOfDay, InvokeComputeCheckPeriod(rfa, ".yyyy-MM-dd"), "TopOfDay pattern"); + Assert.AreEqual(RollPoint.TopOfMonth, InvokeComputeCheckPeriod(rfa, ".yyyy-MM"), "TopOfMonth pattern"); - // Test invalid roll point - Assert.AreEqual(RollPoint.InvalidRollPoint, InvokeComputeCheckPeriod(rfa, "..."), "TopOfMonth pattern"); - } + // Test invalid roll point + Assert.AreEqual(RollPoint.InvalidRollPoint, InvokeComputeCheckPeriod(rfa, "..."), "TopOfMonth pattern"); + } - private static RollPoint InvokeComputeCheckPeriod(RollingFileAppender rollingFileAppender, string datePattern) - { - return (RollPoint)Utils.InvokeMethod(rollingFileAppender, "ComputeCheckPeriod", datePattern); - } + private static RollPoint InvokeComputeCheckPeriod(RollingFileAppender rollingFileAppender, string datePattern) + { + return (RollPoint)Utils.InvokeMethod(rollingFileAppender, "ComputeCheckPeriod", datePattern); } + } } \ No newline at end of file diff --git a/src/log4net.Tests/Appender/SmtpPickupDirAppenderTest.cs b/src/log4net.Tests/Appender/SmtpPickupDirAppenderTest.cs index 6cd5a9ed..6ebc75a8 100644 --- a/src/log4net.Tests/Appender/SmtpPickupDirAppenderTest.cs +++ b/src/log4net.Tests/Appender/SmtpPickupDirAppenderTest.cs @@ -188,11 +188,11 @@ public void TestOutputContainsSentDate() const string dateHeaderStart = "Date: "; foreach (string line in fileContent) { - if(line.StartsWith(dateHeaderStart)) + if (line.StartsWith(dateHeaderStart)) { string datePart = line.Substring(dateHeaderStart.Length); DateTime date = DateTime.ParseExact(datePart, "r", System.Globalization.CultureInfo.InvariantCulture); - double diff = Math.Abs( (DateTime.UtcNow - date).TotalMilliseconds); + double diff = Math.Abs((DateTime.UtcNow - date).TotalMilliseconds); Assert.LessOrEqual(diff, 1000, "Times should be equal, allowing a diff of one second to make test robust"); hasDateHeader = true; } diff --git a/src/log4net.Tests/Appender/TraceAppenderTest.cs b/src/log4net.Tests/Appender/TraceAppenderTest.cs index 21e8fbdb..a164f740 100644 --- a/src/log4net.Tests/Appender/TraceAppenderTest.cs +++ b/src/log4net.Tests/Appender/TraceAppenderTest.cs @@ -29,84 +29,84 @@ namespace log4net.Tests.Appender { - [TestFixture] - public class TraceAppenderTest + [TestFixture] + public class TraceAppenderTest + { + [Test] + public void DefaultCategoryTest() { - [Test] - public void DefaultCategoryTest() - { - CategoryTraceListener categoryTraceListener = new CategoryTraceListener(); - Trace.Listeners.Clear(); - Trace.Listeners.Add(categoryTraceListener); + CategoryTraceListener categoryTraceListener = new CategoryTraceListener(); + Trace.Listeners.Clear(); + Trace.Listeners.Add(categoryTraceListener); - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - TraceAppender traceAppender = new TraceAppender(); - traceAppender.Layout = new SimpleLayout(); - traceAppender.ActivateOptions(); + TraceAppender traceAppender = new TraceAppender(); + traceAppender.Layout = new SimpleLayout(); + traceAppender.ActivateOptions(); - BasicConfigurator.Configure(rep, traceAppender); + BasicConfigurator.Configure(rep, traceAppender); - ILog log = LogManager.GetLogger(rep.Name, GetType()); - log.Debug("Message"); + ILog log = LogManager.GetLogger(rep.Name, GetType()); + log.Debug("Message"); - Assert.AreEqual( - GetType().ToString(), - categoryTraceListener.Category); - } + Assert.AreEqual( + GetType().ToString(), + categoryTraceListener.Category); + } #if !NETSTANDARD1_3 // "LocationInfo can't get method names on NETSTANDARD1_3 due to unavailable stack frame APIs" - [Test] - public void MethodNameCategoryTest() - { - CategoryTraceListener categoryTraceListener = new CategoryTraceListener(); - Trace.Listeners.Clear(); - Trace.Listeners.Add(categoryTraceListener); - - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - - TraceAppender traceAppender = new TraceAppender(); - PatternLayout methodLayout = new PatternLayout("%method"); - methodLayout.ActivateOptions(); - traceAppender.Category = methodLayout; - traceAppender.Layout = new SimpleLayout(); - traceAppender.ActivateOptions(); - - BasicConfigurator.Configure(rep, traceAppender); - - ILog log = LogManager.GetLogger(rep.Name, GetType()); - log.Debug("Message"); - - Assert.AreEqual( - System.Reflection.MethodInfo.GetCurrentMethod().Name, - categoryTraceListener.Category); - } + [Test] + public void MethodNameCategoryTest() + { + CategoryTraceListener categoryTraceListener = new CategoryTraceListener(); + Trace.Listeners.Clear(); + Trace.Listeners.Add(categoryTraceListener); + + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + + TraceAppender traceAppender = new TraceAppender(); + PatternLayout methodLayout = new PatternLayout("%method"); + methodLayout.ActivateOptions(); + traceAppender.Category = methodLayout; + traceAppender.Layout = new SimpleLayout(); + traceAppender.ActivateOptions(); + + BasicConfigurator.Configure(rep, traceAppender); + + ILog log = LogManager.GetLogger(rep.Name, GetType()); + log.Debug("Message"); + + Assert.AreEqual( + System.Reflection.MethodInfo.GetCurrentMethod().Name, + categoryTraceListener.Category); + } #endif + } + + public class CategoryTraceListener : TraceListener + { + private string lastCategory; + + public override void Write(string message) + { + // empty + } + + public override void WriteLine(string message) + { + Write(message); + } + + public override void Write(string message, string category) + { + lastCategory = category; + base.Write(message, category); } - public class CategoryTraceListener : TraceListener + public string Category { - private string lastCategory; - - public override void Write(string message) - { - // empty - } - - public override void WriteLine(string message) - { - Write(message); - } - - public override void Write(string message, string category) - { - lastCategory = category; - base.Write(message, category); - } - - public string Category - { - get { return lastCategory; } - } + get { return lastCategory; } } + } } diff --git a/src/log4net.Tests/Context/ThreadContextTest.cs b/src/log4net.Tests/Context/ThreadContextTest.cs index 951d32d2..b34af135 100644 --- a/src/log4net.Tests/Context/ThreadContextTest.cs +++ b/src/log4net.Tests/Context/ThreadContextTest.cs @@ -33,249 +33,249 @@ namespace log4net.Tests.Context { - /// - /// Used for internal unit testing the class. - /// - /// - /// Used for internal unit testing the class. - /// - [TestFixture] - public class ThreadContextTest + /// + /// Used for internal unit testing the class. + /// + /// + /// Used for internal unit testing the class. + /// + [TestFixture] + public class ThreadContextTest + { + [TearDown] + public void TearDown() { - [TearDown] - public void TearDown() - { - Utils.RemovePropertyFromAllContexts(); - } + Utils.RemovePropertyFromAllContexts(); + } - [Test] - public void TestThreadPropertiesPattern() - { - StringAppender stringAppender = new StringAppender(); - stringAppender.Layout = new PatternLayout("%property{" + Utils.PROPERTY_KEY + "}"); + [Test] + public void TestThreadPropertiesPattern() + { + StringAppender stringAppender = new StringAppender(); + stringAppender.Layout = new PatternLayout("%property{" + Utils.PROPERTY_KEY + "}"); - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - BasicConfigurator.Configure(rep, stringAppender); + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + BasicConfigurator.Configure(rep, stringAppender); - ILog log1 = LogManager.GetLogger(rep.Name, "TestThreadProperiesPattern"); + ILog log1 = LogManager.GetLogger(rep.Name, "TestThreadProperiesPattern"); - log1.Info("TestMessage"); - Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test no thread properties value set"); - stringAppender.Reset(); + log1.Info("TestMessage"); + Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test no thread properties value set"); + stringAppender.Reset(); - ThreadContext.Properties[Utils.PROPERTY_KEY] = "val1"; + ThreadContext.Properties[Utils.PROPERTY_KEY] = "val1"; - log1.Info("TestMessage"); - Assert.AreEqual("val1", stringAppender.GetString(), "Test thread properties value set"); - stringAppender.Reset(); + log1.Info("TestMessage"); + Assert.AreEqual("val1", stringAppender.GetString(), "Test thread properties value set"); + stringAppender.Reset(); - ThreadContext.Properties.Remove(Utils.PROPERTY_KEY); + ThreadContext.Properties.Remove(Utils.PROPERTY_KEY); - log1.Info("TestMessage"); - Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test thread properties value removed"); - stringAppender.Reset(); - } + log1.Info("TestMessage"); + Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test thread properties value removed"); + stringAppender.Reset(); + } - [Test] - public void TestThreadStackPattern() - { - StringAppender stringAppender = new StringAppender(); - stringAppender.Layout = new PatternLayout("%property{" + Utils.PROPERTY_KEY + "}"); + [Test] + public void TestThreadStackPattern() + { + StringAppender stringAppender = new StringAppender(); + stringAppender.Layout = new PatternLayout("%property{" + Utils.PROPERTY_KEY + "}"); - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - BasicConfigurator.Configure(rep, stringAppender); + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + BasicConfigurator.Configure(rep, stringAppender); - ILog log1 = LogManager.GetLogger(rep.Name, "TestThreadStackPattern"); + ILog log1 = LogManager.GetLogger(rep.Name, "TestThreadStackPattern"); - log1.Info("TestMessage"); - Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test no thread stack value set"); - stringAppender.Reset(); + log1.Info("TestMessage"); + Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test no thread stack value set"); + stringAppender.Reset(); - using (ThreadContext.Stacks[Utils.PROPERTY_KEY].Push("val1")) - { - log1.Info("TestMessage"); - Assert.AreEqual("val1", stringAppender.GetString(), "Test thread stack value set"); - stringAppender.Reset(); - } + using (ThreadContext.Stacks[Utils.PROPERTY_KEY].Push("val1")) + { + log1.Info("TestMessage"); + Assert.AreEqual("val1", stringAppender.GetString(), "Test thread stack value set"); + stringAppender.Reset(); + } - log1.Info("TestMessage"); - Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test thread stack value removed"); - stringAppender.Reset(); - } + log1.Info("TestMessage"); + Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test thread stack value removed"); + stringAppender.Reset(); + } + + [Test] + public void TestThreadStackPattern2() + { + StringAppender stringAppender = new StringAppender(); + stringAppender.Layout = new PatternLayout("%property{" + Utils.PROPERTY_KEY + "}"); + + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + BasicConfigurator.Configure(rep, stringAppender); + + ILog log1 = LogManager.GetLogger(rep.Name, "TestThreadStackPattern"); - [Test] - public void TestThreadStackPattern2() + log1.Info("TestMessage"); + Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test no thread stack value set"); + stringAppender.Reset(); + + using (ThreadContext.Stacks[Utils.PROPERTY_KEY].Push("val1")) + { + log1.Info("TestMessage"); + Assert.AreEqual("val1", stringAppender.GetString(), "Test thread stack value set"); + stringAppender.Reset(); + + using (ThreadContext.Stacks[Utils.PROPERTY_KEY].Push("val2")) { - StringAppender stringAppender = new StringAppender(); - stringAppender.Layout = new PatternLayout("%property{" + Utils.PROPERTY_KEY + "}"); - - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - BasicConfigurator.Configure(rep, stringAppender); - - ILog log1 = LogManager.GetLogger(rep.Name, "TestThreadStackPattern"); - - log1.Info("TestMessage"); - Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test no thread stack value set"); - stringAppender.Reset(); - - using (ThreadContext.Stacks[Utils.PROPERTY_KEY].Push("val1")) - { - log1.Info("TestMessage"); - Assert.AreEqual("val1", stringAppender.GetString(), "Test thread stack value set"); - stringAppender.Reset(); - - using (ThreadContext.Stacks[Utils.PROPERTY_KEY].Push("val2")) - { - log1.Info("TestMessage"); - Assert.AreEqual("val1 val2", stringAppender.GetString(), "Test thread stack value pushed 2nd val"); - stringAppender.Reset(); - } - } - - log1.Info("TestMessage"); - Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test thread stack value removed"); - stringAppender.Reset(); + log1.Info("TestMessage"); + Assert.AreEqual("val1 val2", stringAppender.GetString(), "Test thread stack value pushed 2nd val"); + stringAppender.Reset(); } + } - [Test] - public void TestThreadStackPatternNullVal() - { - StringAppender stringAppender = new StringAppender(); - stringAppender.Layout = new PatternLayout("%property{" + Utils.PROPERTY_KEY + "}"); + log1.Info("TestMessage"); + Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test thread stack value removed"); + stringAppender.Reset(); + } - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - BasicConfigurator.Configure(rep, stringAppender); + [Test] + public void TestThreadStackPatternNullVal() + { + StringAppender stringAppender = new StringAppender(); + stringAppender.Layout = new PatternLayout("%property{" + Utils.PROPERTY_KEY + "}"); - ILog log1 = LogManager.GetLogger(rep.Name, "TestThreadStackPattern"); + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + BasicConfigurator.Configure(rep, stringAppender); - log1.Info("TestMessage"); - Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test no thread stack value set"); - stringAppender.Reset(); + ILog log1 = LogManager.GetLogger(rep.Name, "TestThreadStackPattern"); - using (ThreadContext.Stacks[Utils.PROPERTY_KEY].Push(null)) - { - log1.Info("TestMessage"); - Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test thread stack value set"); - stringAppender.Reset(); - } + log1.Info("TestMessage"); + Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test no thread stack value set"); + stringAppender.Reset(); - log1.Info("TestMessage"); - Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test thread stack value removed"); - stringAppender.Reset(); - } + using (ThreadContext.Stacks[Utils.PROPERTY_KEY].Push(null)) + { + log1.Info("TestMessage"); + Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test thread stack value set"); + stringAppender.Reset(); + } + + log1.Info("TestMessage"); + Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test thread stack value removed"); + stringAppender.Reset(); + } + + [Test] + public void TestThreadStackPatternNullVal2() + { + StringAppender stringAppender = new StringAppender(); + stringAppender.Layout = new PatternLayout("%property{" + Utils.PROPERTY_KEY + "}"); + + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + BasicConfigurator.Configure(rep, stringAppender); + + ILog log1 = LogManager.GetLogger(rep.Name, "TestThreadStackPattern"); - [Test] - public void TestThreadStackPatternNullVal2() + log1.Info("TestMessage"); + Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test no thread stack value set"); + stringAppender.Reset(); + + using (ThreadContext.Stacks[Utils.PROPERTY_KEY].Push("val1")) + { + log1.Info("TestMessage"); + Assert.AreEqual("val1", stringAppender.GetString(), "Test thread stack value set"); + stringAppender.Reset(); + + using (ThreadContext.Stacks[Utils.PROPERTY_KEY].Push(null)) { - StringAppender stringAppender = new StringAppender(); - stringAppender.Layout = new PatternLayout("%property{" + Utils.PROPERTY_KEY + "}"); - - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - BasicConfigurator.Configure(rep, stringAppender); - - ILog log1 = LogManager.GetLogger(rep.Name, "TestThreadStackPattern"); - - log1.Info("TestMessage"); - Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test no thread stack value set"); - stringAppender.Reset(); - - using (ThreadContext.Stacks[Utils.PROPERTY_KEY].Push("val1")) - { - log1.Info("TestMessage"); - Assert.AreEqual("val1", stringAppender.GetString(), "Test thread stack value set"); - stringAppender.Reset(); - - using (ThreadContext.Stacks[Utils.PROPERTY_KEY].Push(null)) - { - log1.Info("TestMessage"); - Assert.AreEqual("val1 ", stringAppender.GetString(), "Test thread stack value pushed null"); - stringAppender.Reset(); - } - } - - log1.Info("TestMessage"); - Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test thread stack value removed"); - stringAppender.Reset(); + log1.Info("TestMessage"); + Assert.AreEqual("val1 ", stringAppender.GetString(), "Test thread stack value pushed null"); + stringAppender.Reset(); } + } + + log1.Info("TestMessage"); + Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test thread stack value removed"); + stringAppender.Reset(); + } - private static string TestBackgroundThreadContextPropertyRepository; + private static string TestBackgroundThreadContextPropertyRepository; - [Test] - public void TestBackgroundThreadContextProperty() - { - StringAppender stringAppender = new StringAppender(); - stringAppender.Layout = new PatternLayout("%property{DateTimeTodayToString}"); + [Test] + public void TestBackgroundThreadContextProperty() + { + StringAppender stringAppender = new StringAppender(); + stringAppender.Layout = new PatternLayout("%property{DateTimeTodayToString}"); - ILoggerRepository rep = LogManager.CreateRepository(TestBackgroundThreadContextPropertyRepository = - "TestBackgroundThreadContextPropertyRepository" + Guid.NewGuid().ToString()); - BasicConfigurator.Configure(rep, stringAppender); + ILoggerRepository rep = LogManager.CreateRepository(TestBackgroundThreadContextPropertyRepository = + "TestBackgroundThreadContextPropertyRepository" + Guid.NewGuid().ToString()); + BasicConfigurator.Configure(rep, stringAppender); - Thread thread = new Thread(new ThreadStart(ExecuteBackgroundThread)); - thread.Start(); + Thread thread = new Thread(new ThreadStart(ExecuteBackgroundThread)); + thread.Start(); - Thread.CurrentThread.Join(2000); - } + Thread.CurrentThread.Join(2000); + } - private static void ExecuteBackgroundThread() - { - ILog log = LogManager.GetLogger(TestBackgroundThreadContextPropertyRepository, "ExecuteBackGroundThread"); - ThreadContext.Properties["DateTimeTodayToString"] = DateTime.Today.ToString(); + private static void ExecuteBackgroundThread() + { + ILog log = LogManager.GetLogger(TestBackgroundThreadContextPropertyRepository, "ExecuteBackGroundThread"); + ThreadContext.Properties["DateTimeTodayToString"] = DateTime.Today.ToString(); - log.Info("TestMessage"); + log.Info("TestMessage"); - Repository.Hierarchy.Hierarchy hierarchyLoggingRepository = - (Repository.Hierarchy.Hierarchy) log.Logger.Repository; - StringAppender stringAppender = (StringAppender) hierarchyLoggingRepository.Root.Appenders[0]; + Repository.Hierarchy.Hierarchy hierarchyLoggingRepository = + (Repository.Hierarchy.Hierarchy)log.Logger.Repository; + StringAppender stringAppender = (StringAppender)hierarchyLoggingRepository.Root.Appenders[0]; - Assert.AreEqual(DateTime.Today.ToString(), stringAppender.GetString()); - } + Assert.AreEqual(DateTime.Today.ToString(), stringAppender.GetString()); + } - [Test] - public void PropertiesShouldBeThreadSafe() - { - // Arrange - var threads = new List(); - var flags = new List(); - - // Act - for (var i = 0; i < 256; i++) - { - var t = new Thread(SpinAndCheck); - var flag = new FlagContainer(); - t.Start(flag); - flags.Add(flag); - threads.Add(t); - } - - foreach (var t in threads) - { - t.Join(); - } - - // Assert - Expect(flags) - .To.Contain.All.Matched.By(o => o.Flag == false); - } + [Test] + public void PropertiesShouldBeThreadSafe() + { + // Arrange + var threads = new List(); + var flags = new List(); + + // Act + for (var i = 0; i < 256; i++) + { + var t = new Thread(SpinAndCheck); + var flag = new FlagContainer(); + t.Start(flag); + flags.Add(flag); + threads.Add(t); + } + + foreach (var t in threads) + { + t.Join(); + } + + // Assert + Expect(flags) + .To.Contain.All.Matched.By(o => o.Flag == false); + } - public class FlagContainer - { - public bool Flag { get; set; } - } + public class FlagContainer + { + public bool Flag { get; set; } + } - private void SpinAndCheck(object obj) + private void SpinAndCheck(object obj) + { + var container = obj as FlagContainer; + var threadid = Thread.CurrentThread.ManagedThreadId; + for (var i = 0; i < 100000; i++) + { + ThreadContext.Properties["threadid"] = threadid; + Thread.Sleep(0); + if ((int)ThreadContext.Properties["threadid"] != threadid) { - var container = obj as FlagContainer; - var threadid = Thread.CurrentThread.ManagedThreadId; - for (var i = 0; i < 100000; i++) - { - ThreadContext.Properties["threadid"] = threadid; - Thread.Sleep(0); - if ((int) ThreadContext.Properties["threadid"] != threadid) - { - container.Flag = true; - break; - } - } + container.Flag = true; + break; } + } } + } } \ No newline at end of file diff --git a/src/log4net.Tests/Core/FixingTest.cs b/src/log4net.Tests/Core/FixingTest.cs index 6c5dbb8b..1431ce0e 100644 --- a/src/log4net.Tests/Core/FixingTest.cs +++ b/src/log4net.Tests/Core/FixingTest.cs @@ -34,24 +34,28 @@ namespace log4net.Tests.Core [TestFixture] public class FixingTest { - const string TEST_REPOSITORY = "Test Repository"; + const string TEST_REPOSITORY = "Test Repository"; - [OneTimeSetUp] + [OneTimeSetUp] public void CreateRepository() { - bool exists = false; - Repository.ILoggerRepository[] repositories = LogManager.GetAllRepositories(); - if (repositories != null) { - foreach (Repository.ILoggerRepository r in repositories) { - if (r.Name == TEST_REPOSITORY) { - exists = true; - break; - } - } - } - if (!exists) { - LogManager.CreateRepository(TEST_REPOSITORY); - } + bool exists = false; + Repository.ILoggerRepository[] repositories = LogManager.GetAllRepositories(); + if (repositories != null) + { + foreach (Repository.ILoggerRepository r in repositories) + { + if (r.Name == TEST_REPOSITORY) + { + exists = true; + break; + } + } + } + if (!exists) + { + LogManager.CreateRepository(TEST_REPOSITORY); + } // write-once if (Thread.CurrentThread.Name == null) @@ -164,8 +168,8 @@ private static void AssertExpectedLoggingEvent(LoggingEvent loggingEvent, Loggin Assert.AreEqual("log4net.Tests.Core.FixingTest", loggingEventData.LoggerName, "LoggerName is incorrect"); Assert.AreEqual(LogManager.GetRepository(TEST_REPOSITORY), loggingEvent.Repository, "Repository is incorrect"); Assert.AreEqual(Thread.CurrentThread.Name, loggingEventData.ThreadName, "ThreadName is incorrect"); - // This test is redundant as loggingEventData.TimeStamp is a value type and cannot be null - // Assert.IsNotNull(loggingEventData.TimeStampUtc, "TimeStamp is incorrect"); + // This test is redundant as loggingEventData.TimeStamp is a value type and cannot be null + // Assert.IsNotNull(loggingEventData.TimeStampUtc, "TimeStamp is incorrect"); Assert.AreEqual("TestUser", loggingEventData.UserName, "UserName is incorrect"); Assert.AreEqual("Logging event works", loggingEvent.RenderedMessage, "Message is incorrect"); } diff --git a/src/log4net.Tests/Filter/FilterTest.cs b/src/log4net.Tests/Filter/FilterTest.cs index 7c9539e9..7e9d2cf3 100644 --- a/src/log4net.Tests/Filter/FilterTest.cs +++ b/src/log4net.Tests/Filter/FilterTest.cs @@ -31,15 +31,15 @@ namespace log4net.Tests.Filter { - [TestFixture] - public class FilterTest + [TestFixture] + public class FilterTest + { + [Test] + public void FilterConfigurationTest() { - [Test] - public void FilterConfigurationTest() - { - XmlDocument log4netConfig = new XmlDocument(); - #region Load log4netConfig - log4netConfig.LoadXml(@" + XmlDocument log4netConfig = new XmlDocument(); + #region Load log4netConfig + log4netConfig.LoadXml(@" @@ -58,61 +58,64 @@ public void FilterConfigurationTest() "); - #endregion + #endregion - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - XmlConfigurator.Configure(rep, log4netConfig["log4net"]); + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + XmlConfigurator.Configure(rep, log4netConfig["log4net"]); - IAppender[] appenders = LogManager.GetRepository(rep.Name).GetAppenders(); - Assert.IsTrue(appenders.Length == 1); + IAppender[] appenders = LogManager.GetRepository(rep.Name).GetAppenders(); + Assert.IsTrue(appenders.Length == 1); - IAppender appender = Array.Find(appenders, delegate(IAppender a) { - return a.Name == "MemoryAppender"; - }); - Assert.IsNotNull(appender); + IAppender appender = Array.Find(appenders, delegate (IAppender a) + { + return a.Name == "MemoryAppender"; + }); + Assert.IsNotNull(appender); - MultiplePropertyFilter multiplePropertyFilter = - ((AppenderSkeleton)appender).FilterHead as MultiplePropertyFilter; + MultiplePropertyFilter multiplePropertyFilter = + ((AppenderSkeleton)appender).FilterHead as MultiplePropertyFilter; - MultiplePropertyFilter.Condition[] conditions = multiplePropertyFilter.GetConditions(); - Assert.AreEqual(2, conditions.Length); - Assert.AreEqual("ABC", conditions[0].Key); - Assert.AreEqual("123", conditions[0].StringToMatch); - Assert.AreEqual("DEF", conditions[1].Key); - Assert.AreEqual("456", conditions[1].StringToMatch); - } + MultiplePropertyFilter.Condition[] conditions = multiplePropertyFilter.GetConditions(); + Assert.AreEqual(2, conditions.Length); + Assert.AreEqual("ABC", conditions[0].Key); + Assert.AreEqual("123", conditions[0].StringToMatch); + Assert.AreEqual("DEF", conditions[1].Key); + Assert.AreEqual("456", conditions[1].StringToMatch); } + } - public class MultiplePropertyFilter : FilterSkeleton + public class MultiplePropertyFilter : FilterSkeleton + { + private readonly List _conditions = new List(); + + public override FilterDecision Decide(LoggingEvent loggingEvent) { - private readonly List _conditions = new List(); + return FilterDecision.Accept; + } - public override FilterDecision Decide(LoggingEvent loggingEvent) - { - return FilterDecision.Accept; - } + public Condition[] GetConditions() + { + return _conditions.ToArray(); + } - public Condition[] GetConditions() - { - return _conditions.ToArray(); - } + public void AddCondition(Condition condition) + { + _conditions.Add(condition); + } - public void AddCondition(Condition condition) - { - _conditions.Add(condition); - } - - public class Condition - { - private string key, stringToMatch; - public string Key { - get { return key; } - set { key = value; } - } - public string StringToMatch { - get { return stringToMatch; } - set { stringToMatch = value; } - } - } + public class Condition + { + private string key, stringToMatch; + public string Key + { + get { return key; } + set { key = value; } + } + public string StringToMatch + { + get { return stringToMatch; } + set { stringToMatch = value; } + } } + } } diff --git a/src/log4net.Tests/Hierarchy/Hierarchy.cs b/src/log4net.Tests/Hierarchy/Hierarchy.cs index 7daa95ec..94dd0178 100644 --- a/src/log4net.Tests/Hierarchy/Hierarchy.cs +++ b/src/log4net.Tests/Hierarchy/Hierarchy.cs @@ -30,15 +30,15 @@ namespace log4net.Tests.Hierarchy { - [TestFixture] - public class Hierarchy + [TestFixture] + public class Hierarchy + { + [Test] + public void SetRepositoryPropertiesInConfigFile() { - [Test] - public void SetRepositoryPropertiesInConfigFile() - { - // LOG4NET-53: Allow repository properties to be set in the config file - XmlDocument log4netConfig = new XmlDocument(); - log4netConfig.LoadXml(@" + // LOG4NET-53: Allow repository properties to be set in the config file + XmlDocument log4netConfig = new XmlDocument(); + log4netConfig.LoadXml(@" @@ -53,58 +53,58 @@ public void SetRepositoryPropertiesInConfigFile() "); - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - XmlConfigurator.Configure(rep, log4netConfig["log4net"]); + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + XmlConfigurator.Configure(rep, log4netConfig["log4net"]); - Assert.AreEqual("4", rep.Properties["two-plus-two"]); - Assert.IsNull(rep.Properties["one-plus-one"]); - } + Assert.AreEqual("4", rep.Properties["two-plus-two"]); + Assert.IsNull(rep.Properties["one-plus-one"]); + } - [Test] - public void AddingMultipleAppenders() - { - CountingAppender alpha = new CountingAppender(); - CountingAppender beta = new CountingAppender(); + [Test] + public void AddingMultipleAppenders() + { + CountingAppender alpha = new CountingAppender(); + CountingAppender beta = new CountingAppender(); - Repository.Hierarchy.Hierarchy hierarchy = - (Repository.Hierarchy.Hierarchy)Utils.GetRepository(); + Repository.Hierarchy.Hierarchy hierarchy = + (Repository.Hierarchy.Hierarchy)Utils.GetRepository(); - hierarchy.Root.AddAppender(alpha); - hierarchy.Root.AddAppender(beta); - hierarchy.Configured = true; + hierarchy.Root.AddAppender(alpha); + hierarchy.Root.AddAppender(beta); + hierarchy.Configured = true; - ILog log = LogManager.GetLogger(GetType()); - log.Debug("Hello World"); + ILog log = LogManager.GetLogger(GetType()); + log.Debug("Hello World"); - Assert.AreEqual(1, alpha.Counter); - Assert.AreEqual(1, beta.Counter); - } + Assert.AreEqual(1, alpha.Counter); + Assert.AreEqual(1, beta.Counter); + } - [Test] - public void AddingMultipleAppenders2() - { - CountingAppender alpha = new CountingAppender(); - CountingAppender beta = new CountingAppender(); + [Test] + public void AddingMultipleAppenders2() + { + CountingAppender alpha = new CountingAppender(); + CountingAppender beta = new CountingAppender(); #if NETSTANDARD1_3 BasicConfigurator.Configure(Utils.GetRepository(), alpha, beta); #else - BasicConfigurator.Configure(alpha, beta); + BasicConfigurator.Configure(alpha, beta); #endif - ILog log = LogManager.GetLogger(GetType()); - log.Debug("Hello World"); + ILog log = LogManager.GetLogger(GetType()); + log.Debug("Hello World"); - Assert.AreEqual(1, alpha.Counter); - Assert.AreEqual(1, beta.Counter); - } + Assert.AreEqual(1, alpha.Counter); + Assert.AreEqual(1, beta.Counter); + } - [Test] - // LOG4NET-343 - public void LoggerNameCanConsistOfASingleDot() - { - XmlDocument log4netConfig = new XmlDocument(); - log4netConfig.LoadXml(@" + [Test] + // LOG4NET-343 + public void LoggerNameCanConsistOfASingleDot() + { + XmlDocument log4netConfig = new XmlDocument(); + log4netConfig.LoadXml(@" @@ -118,15 +118,15 @@ public void LoggerNameCanConsistOfASingleDot() "); - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - XmlConfigurator.Configure(rep, log4netConfig["log4net"]); - } + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + XmlConfigurator.Configure(rep, log4netConfig["log4net"]); + } - [Test] - public void LoggerNameCanConsistOfASingleNonDot() - { - XmlDocument log4netConfig = new XmlDocument(); - log4netConfig.LoadXml(@" + [Test] + public void LoggerNameCanConsistOfASingleNonDot() + { + XmlDocument log4netConfig = new XmlDocument(); + log4netConfig.LoadXml(@" @@ -140,15 +140,15 @@ public void LoggerNameCanConsistOfASingleNonDot() "); - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - XmlConfigurator.Configure(rep, log4netConfig["log4net"]); - } + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + XmlConfigurator.Configure(rep, log4netConfig["log4net"]); + } - [Test] - public void LoggerNameCanContainSequenceOfDots() - { - XmlDocument log4netConfig = new XmlDocument(); - log4netConfig.LoadXml(@" + [Test] + public void LoggerNameCanContainSequenceOfDots() + { + XmlDocument log4netConfig = new XmlDocument(); + log4netConfig.LoadXml(@" @@ -162,8 +162,8 @@ public void LoggerNameCanContainSequenceOfDots() "); - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - XmlConfigurator.Configure(rep, log4netConfig["log4net"]); - } + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + XmlConfigurator.Configure(rep, log4netConfig["log4net"]); } + } } diff --git a/src/log4net.Tests/Layout/DynamicPatternLayoutTest.cs b/src/log4net.Tests/Layout/DynamicPatternLayoutTest.cs index ee79a0aa..782935e8 100644 --- a/src/log4net.Tests/Layout/DynamicPatternLayoutTest.cs +++ b/src/log4net.Tests/Layout/DynamicPatternLayoutTest.cs @@ -21,17 +21,21 @@ using NUnit.Framework; -namespace log4net.Tests.Layout { - /// - /// Used for internal unit testing the class. - /// - public class DynamicPatternLayoutTest : PatternLayoutTest { - protected override PatternLayout NewPatternLayout() { - return new DynamicPatternLayout(); - } +namespace log4net.Tests.Layout +{ + /// + /// Used for internal unit testing the class. + /// + public class DynamicPatternLayoutTest : PatternLayoutTest + { + protected override PatternLayout NewPatternLayout() + { + return new DynamicPatternLayout(); + } - protected override PatternLayout NewPatternLayout(string pattern) { - return new DynamicPatternLayout(pattern); - } + protected override PatternLayout NewPatternLayout(string pattern) + { + return new DynamicPatternLayout(pattern); } + } } diff --git a/src/log4net.Tests/Layout/PatternLayoutTest.cs b/src/log4net.Tests/Layout/PatternLayoutTest.cs index d2937d5b..ebfbfd7b 100644 --- a/src/log4net.Tests/Layout/PatternLayoutTest.cs +++ b/src/log4net.Tests/Layout/PatternLayoutTest.cs @@ -58,28 +58,31 @@ public void SetUp() } - [TearDown] - public void TearDown() { + [TearDown] + public void TearDown() + { Utils.RemovePropertyFromAllContexts(); // restore previous culture System.Threading.Thread.CurrentThread.CurrentCulture = _currentCulture; System.Threading.Thread.CurrentThread.CurrentUICulture = _currentUICulture; - } + } #endif - protected virtual PatternLayout NewPatternLayout() { - return new PatternLayout(); - } + protected virtual PatternLayout NewPatternLayout() + { + return new PatternLayout(); + } - protected virtual PatternLayout NewPatternLayout(string pattern) { - return new PatternLayout(pattern); - } + protected virtual PatternLayout NewPatternLayout(string pattern) + { + return new PatternLayout(pattern); + } - [Test] + [Test] public void TestThreadPropertiesPattern() { StringAppender stringAppender = new StringAppender(); - stringAppender.Layout = NewPatternLayout("%property{" + Utils.PROPERTY_KEY + "}"); + stringAppender.Layout = NewPatternLayout("%property{" + Utils.PROPERTY_KEY + "}"); ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); BasicConfigurator.Configure(rep, stringAppender); @@ -104,28 +107,28 @@ public void TestThreadPropertiesPattern() } #if !NETSTANDARD1_3 - [Test] - public void TestStackTracePattern() - { - StringAppender stringAppender = new StringAppender(); - stringAppender.Layout = NewPatternLayout("%stacktrace{2}"); + [Test] + public void TestStackTracePattern() + { + StringAppender stringAppender = new StringAppender(); + stringAppender.Layout = NewPatternLayout("%stacktrace{2}"); - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - BasicConfigurator.Configure(rep, stringAppender); + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + BasicConfigurator.Configure(rep, stringAppender); - ILog log1 = LogManager.GetLogger(rep.Name, "TestStackTracePattern"); + ILog log1 = LogManager.GetLogger(rep.Name, "TestStackTracePattern"); - log1.Info("TestMessage"); - StringAssert.EndsWith("PatternLayoutTest.TestStackTracePattern", stringAppender.GetString(), "stack trace value set"); - stringAppender.Reset(); - } + log1.Info("TestMessage"); + StringAssert.EndsWith("PatternLayoutTest.TestStackTracePattern", stringAppender.GetString(), "stack trace value set"); + stringAppender.Reset(); + } #endif [Test] public void TestGlobalPropertiesPattern() { StringAppender stringAppender = new StringAppender(); - stringAppender.Layout = NewPatternLayout("%property{" + Utils.PROPERTY_KEY + "}"); + stringAppender.Layout = NewPatternLayout("%property{" + Utils.PROPERTY_KEY + "}"); ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); BasicConfigurator.Configure(rep, stringAppender); @@ -171,147 +174,148 @@ public void TestAddingCustomPattern() stringAppender.Reset(); } - [Test] - public void NamedPatternConverterWithoutPrecisionShouldReturnFullName() - { - StringAppender stringAppender = new StringAppender(); - PatternLayout layout = NewPatternLayout(); - layout.AddConverter("message-as-name", typeof(MessageAsNamePatternConverter)); - layout.ConversionPattern = "%message-as-name"; - layout.ActivateOptions(); - stringAppender.Layout = layout; - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - BasicConfigurator.Configure(rep, stringAppender); - ILog log1 = LogManager.GetLogger(rep.Name, "TestAddingCustomPattern"); - - log1.Info("NoDots"); - Assert.AreEqual("NoDots", stringAppender.GetString(), "%message-as-name not registered"); - stringAppender.Reset(); - - log1.Info("One.Dot"); - Assert.AreEqual("One.Dot", stringAppender.GetString(), "%message-as-name not registered"); - stringAppender.Reset(); - - log1.Info("Tw.o.Dots"); - Assert.AreEqual("Tw.o.Dots", stringAppender.GetString(), "%message-as-name not registered"); - stringAppender.Reset(); - - log1.Info("TrailingDot."); - Assert.AreEqual("TrailingDot.", stringAppender.GetString(), "%message-as-name not registered"); - stringAppender.Reset(); - - log1.Info(".LeadingDot"); - Assert.AreEqual(".LeadingDot", stringAppender.GetString(), "%message-as-name not registered"); - stringAppender.Reset(); - - // empty string and other evil combinations as tests for of-by-one mistakes in index calculations - log1.Info(string.Empty); - Assert.AreEqual(string.Empty, stringAppender.GetString(), "%message-as-name not registered"); - stringAppender.Reset(); - - log1.Info("."); - Assert.AreEqual(".", stringAppender.GetString(), "%message-as-name not registered"); - stringAppender.Reset(); - - log1.Info("x"); - Assert.AreEqual("x", stringAppender.GetString(), "%message-as-name not registered"); - stringAppender.Reset(); - } - - [Test] - public void NamedPatternConverterWithPrecision1ShouldStripLeadingStuffIfPresent() - { - StringAppender stringAppender = new StringAppender(); - PatternLayout layout = NewPatternLayout(); - layout.AddConverter("message-as-name", typeof(MessageAsNamePatternConverter)); - layout.ConversionPattern = "%message-as-name{1}"; - layout.ActivateOptions(); - stringAppender.Layout = layout; - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - BasicConfigurator.Configure(rep, stringAppender); - ILog log1 = LogManager.GetLogger(rep.Name, "TestAddingCustomPattern"); - - log1.Info("NoDots"); - Assert.AreEqual("NoDots", stringAppender.GetString(), "%message-as-name not registered"); - stringAppender.Reset(); - - log1.Info("One.Dot"); - Assert.AreEqual("Dot", stringAppender.GetString(), "%message-as-name not registered"); - stringAppender.Reset(); - - log1.Info("Tw.o.Dots"); - Assert.AreEqual("Dots", stringAppender.GetString(), "%message-as-name not registered"); - stringAppender.Reset(); - - log1.Info("TrailingDot."); - Assert.AreEqual("TrailingDot.", stringAppender.GetString(), "%message-as-name not registered"); - stringAppender.Reset(); - - log1.Info(".LeadingDot"); - Assert.AreEqual("LeadingDot", stringAppender.GetString(), "%message-as-name not registered"); - stringAppender.Reset(); - - // empty string and other evil combinations as tests for of-by-one mistakes in index calculations - log1.Info(string.Empty); - Assert.AreEqual(string.Empty, stringAppender.GetString(), "%message-as-name not registered"); - stringAppender.Reset(); - - log1.Info("x"); - Assert.AreEqual("x", stringAppender.GetString(), "%message-as-name not registered"); - stringAppender.Reset(); - - log1.Info("."); - Assert.AreEqual(".", stringAppender.GetString(), "%message-as-name not registered"); - stringAppender.Reset(); - } - - [Test] - public void NamedPatternConverterWithPrecision2ShouldStripLessLeadingStuffIfPresent() { - StringAppender stringAppender = new StringAppender(); - PatternLayout layout = NewPatternLayout(); - layout.AddConverter("message-as-name", typeof(MessageAsNamePatternConverter)); - layout.ConversionPattern = "%message-as-name{2}"; - layout.ActivateOptions(); - stringAppender.Layout = layout; - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - BasicConfigurator.Configure(rep, stringAppender); - ILog log1 = LogManager.GetLogger(rep.Name, "TestAddingCustomPattern"); - - log1.Info("NoDots"); - Assert.AreEqual("NoDots", stringAppender.GetString(), "%message-as-name not registered"); - stringAppender.Reset(); - - log1.Info("One.Dot"); - Assert.AreEqual("One.Dot", stringAppender.GetString(), "%message-as-name not registered"); - stringAppender.Reset(); - - log1.Info("Tw.o.Dots"); - Assert.AreEqual("o.Dots", stringAppender.GetString(), "%message-as-name not registered"); - stringAppender.Reset(); - - log1.Info("TrailingDot."); - Assert.AreEqual("TrailingDot.", stringAppender.GetString(), "%message-as-name not registered"); - stringAppender.Reset(); - - log1.Info(".LeadingDot"); - Assert.AreEqual("LeadingDot", stringAppender.GetString(), "%message-as-name not registered"); - stringAppender.Reset(); - - // empty string and other evil combinations as tests for of-by-one mistakes in index calculations - log1.Info(string.Empty); - Assert.AreEqual(string.Empty, stringAppender.GetString(), "%message-as-name not registered"); - stringAppender.Reset(); - - log1.Info("x"); - Assert.AreEqual("x", stringAppender.GetString(), "%message-as-name not registered"); - stringAppender.Reset(); - - log1.Info("."); - Assert.AreEqual(".", stringAppender.GetString(), "%message-as-name not registered"); - stringAppender.Reset(); - } - - /// + [Test] + public void NamedPatternConverterWithoutPrecisionShouldReturnFullName() + { + StringAppender stringAppender = new StringAppender(); + PatternLayout layout = NewPatternLayout(); + layout.AddConverter("message-as-name", typeof(MessageAsNamePatternConverter)); + layout.ConversionPattern = "%message-as-name"; + layout.ActivateOptions(); + stringAppender.Layout = layout; + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + BasicConfigurator.Configure(rep, stringAppender); + ILog log1 = LogManager.GetLogger(rep.Name, "TestAddingCustomPattern"); + + log1.Info("NoDots"); + Assert.AreEqual("NoDots", stringAppender.GetString(), "%message-as-name not registered"); + stringAppender.Reset(); + + log1.Info("One.Dot"); + Assert.AreEqual("One.Dot", stringAppender.GetString(), "%message-as-name not registered"); + stringAppender.Reset(); + + log1.Info("Tw.o.Dots"); + Assert.AreEqual("Tw.o.Dots", stringAppender.GetString(), "%message-as-name not registered"); + stringAppender.Reset(); + + log1.Info("TrailingDot."); + Assert.AreEqual("TrailingDot.", stringAppender.GetString(), "%message-as-name not registered"); + stringAppender.Reset(); + + log1.Info(".LeadingDot"); + Assert.AreEqual(".LeadingDot", stringAppender.GetString(), "%message-as-name not registered"); + stringAppender.Reset(); + + // empty string and other evil combinations as tests for of-by-one mistakes in index calculations + log1.Info(string.Empty); + Assert.AreEqual(string.Empty, stringAppender.GetString(), "%message-as-name not registered"); + stringAppender.Reset(); + + log1.Info("."); + Assert.AreEqual(".", stringAppender.GetString(), "%message-as-name not registered"); + stringAppender.Reset(); + + log1.Info("x"); + Assert.AreEqual("x", stringAppender.GetString(), "%message-as-name not registered"); + stringAppender.Reset(); + } + + [Test] + public void NamedPatternConverterWithPrecision1ShouldStripLeadingStuffIfPresent() + { + StringAppender stringAppender = new StringAppender(); + PatternLayout layout = NewPatternLayout(); + layout.AddConverter("message-as-name", typeof(MessageAsNamePatternConverter)); + layout.ConversionPattern = "%message-as-name{1}"; + layout.ActivateOptions(); + stringAppender.Layout = layout; + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + BasicConfigurator.Configure(rep, stringAppender); + ILog log1 = LogManager.GetLogger(rep.Name, "TestAddingCustomPattern"); + + log1.Info("NoDots"); + Assert.AreEqual("NoDots", stringAppender.GetString(), "%message-as-name not registered"); + stringAppender.Reset(); + + log1.Info("One.Dot"); + Assert.AreEqual("Dot", stringAppender.GetString(), "%message-as-name not registered"); + stringAppender.Reset(); + + log1.Info("Tw.o.Dots"); + Assert.AreEqual("Dots", stringAppender.GetString(), "%message-as-name not registered"); + stringAppender.Reset(); + + log1.Info("TrailingDot."); + Assert.AreEqual("TrailingDot.", stringAppender.GetString(), "%message-as-name not registered"); + stringAppender.Reset(); + + log1.Info(".LeadingDot"); + Assert.AreEqual("LeadingDot", stringAppender.GetString(), "%message-as-name not registered"); + stringAppender.Reset(); + + // empty string and other evil combinations as tests for of-by-one mistakes in index calculations + log1.Info(string.Empty); + Assert.AreEqual(string.Empty, stringAppender.GetString(), "%message-as-name not registered"); + stringAppender.Reset(); + + log1.Info("x"); + Assert.AreEqual("x", stringAppender.GetString(), "%message-as-name not registered"); + stringAppender.Reset(); + + log1.Info("."); + Assert.AreEqual(".", stringAppender.GetString(), "%message-as-name not registered"); + stringAppender.Reset(); + } + + [Test] + public void NamedPatternConverterWithPrecision2ShouldStripLessLeadingStuffIfPresent() + { + StringAppender stringAppender = new StringAppender(); + PatternLayout layout = NewPatternLayout(); + layout.AddConverter("message-as-name", typeof(MessageAsNamePatternConverter)); + layout.ConversionPattern = "%message-as-name{2}"; + layout.ActivateOptions(); + stringAppender.Layout = layout; + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + BasicConfigurator.Configure(rep, stringAppender); + ILog log1 = LogManager.GetLogger(rep.Name, "TestAddingCustomPattern"); + + log1.Info("NoDots"); + Assert.AreEqual("NoDots", stringAppender.GetString(), "%message-as-name not registered"); + stringAppender.Reset(); + + log1.Info("One.Dot"); + Assert.AreEqual("One.Dot", stringAppender.GetString(), "%message-as-name not registered"); + stringAppender.Reset(); + + log1.Info("Tw.o.Dots"); + Assert.AreEqual("o.Dots", stringAppender.GetString(), "%message-as-name not registered"); + stringAppender.Reset(); + + log1.Info("TrailingDot."); + Assert.AreEqual("TrailingDot.", stringAppender.GetString(), "%message-as-name not registered"); + stringAppender.Reset(); + + log1.Info(".LeadingDot"); + Assert.AreEqual("LeadingDot", stringAppender.GetString(), "%message-as-name not registered"); + stringAppender.Reset(); + + // empty string and other evil combinations as tests for of-by-one mistakes in index calculations + log1.Info(string.Empty); + Assert.AreEqual(string.Empty, stringAppender.GetString(), "%message-as-name not registered"); + stringAppender.Reset(); + + log1.Info("x"); + Assert.AreEqual("x", stringAppender.GetString(), "%message-as-name not registered"); + stringAppender.Reset(); + + log1.Info("."); + Assert.AreEqual(".", stringAppender.GetString(), "%message-as-name not registered"); + stringAppender.Reset(); + } + + /// /// Converter to include event message /// private class TestMessagePatternConverter : PatternLayoutConverter @@ -348,12 +352,12 @@ public void TestExceptionPattern() stringAppender.Reset(); } - private class MessageAsNamePatternConverter : NamedPatternConverter - { - protected override string GetFullyQualifiedName(LoggingEvent loggingEvent) - { - return loggingEvent.MessageObject.ToString(); - } - } + private class MessageAsNamePatternConverter : NamedPatternConverter + { + protected override string GetFullyQualifiedName(LoggingEvent loggingEvent) + { + return loggingEvent.MessageObject.ToString(); + } } + } } \ No newline at end of file diff --git a/src/log4net.Tests/Layout/XmlLayoutTest.cs b/src/log4net.Tests/Layout/XmlLayoutTest.cs index 17cd67eb..6160dc56 100644 --- a/src/log4net.Tests/Layout/XmlLayoutTest.cs +++ b/src/log4net.Tests/Layout/XmlLayoutTest.cs @@ -306,67 +306,76 @@ public void TestPropertyIllegalCharacterMaskingInName() } #if NET_4_0 || MONO_4_0 || NETSTANDARD - [Test] - public void BracketsInStackTracesKeepLogWellFormed() { - XmlLayout layout = new XmlLayout(); - StringAppender stringAppender = new StringAppender(); - stringAppender.Layout = layout; - - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - BasicConfigurator.Configure(rep, stringAppender); - ILog log1 = LogManager.GetLogger(rep.Name, "TestLogger"); - Action bar = foo => { - try { - throw new NullReferenceException(); - } catch (Exception ex) { - log1.Error(string.Format("Error {0}", foo), ex); - } - }; - bar(42); - - // really only asserts there is no exception - var loggedDoc = new XmlDocument(); - loggedDoc.LoadXml(stringAppender.GetString()); + [Test] + public void BracketsInStackTracesKeepLogWellFormed() + { + XmlLayout layout = new XmlLayout(); + StringAppender stringAppender = new StringAppender(); + stringAppender.Layout = layout; + + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + BasicConfigurator.Configure(rep, stringAppender); + ILog log1 = LogManager.GetLogger(rep.Name, "TestLogger"); + Action bar = foo => + { + try + { + throw new NullReferenceException(); + } + catch (Exception ex) + { + log1.Error(string.Format("Error {0}", foo), ex); + } + }; + bar(42); + + // really only asserts there is no exception + var loggedDoc = new XmlDocument(); + loggedDoc.LoadXml(stringAppender.GetString()); + } + + [Test] + public void BracketsInStackTracesAreEscapedProperly() + { + XmlLayout layout = new XmlLayout(); + StringAppender stringAppender = new StringAppender(); + stringAppender.Layout = layout; + + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + BasicConfigurator.Configure(rep, stringAppender); + ILog log1 = LogManager.GetLogger(rep.Name, "TestLogger"); + Action bar = foo => + { + try + { + throw new NullReferenceException(); } + catch (Exception ex) + { + log1.Error(string.Format("Error {0}", foo), ex); + } + }; + bar(42); - [Test] - public void BracketsInStackTracesAreEscapedProperly() { - XmlLayout layout = new XmlLayout(); - StringAppender stringAppender = new StringAppender(); - stringAppender.Layout = layout; - - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - BasicConfigurator.Configure(rep, stringAppender); - ILog log1 = LogManager.GetLogger(rep.Name, "TestLogger"); - Action bar = foo => { - try { - throw new NullReferenceException(); - } - catch (Exception ex) { - log1.Error(string.Format("Error {0}", foo), ex); - } - }; - bar(42); - - var log = stringAppender.GetString(); + var log = stringAppender.GetString(); #if NETSTANDARD1_3 var startOfExceptionText = log.IndexOf("", StringComparison.Ordinal) + 11; var endOfExceptionText = log.IndexOf("", StringComparison.Ordinal); #else - var startOfExceptionText = log.IndexOf("", StringComparison.InvariantCulture) + 11; - var endOfExceptionText = log.IndexOf("", StringComparison.InvariantCulture); + var startOfExceptionText = log.IndexOf("", StringComparison.InvariantCulture) + 11; + var endOfExceptionText = log.IndexOf("", StringComparison.InvariantCulture); #endif - var sub = log.Substring(startOfExceptionText, endOfExceptionText - startOfExceptionText); - if (sub.StartsWith("", sub); - } - else - { - StringAssert.DoesNotContain("<", sub); - StringAssert.DoesNotContain(">", sub); - } - } + var sub = log.Substring(startOfExceptionText, endOfExceptionText - startOfExceptionText); + if (sub.StartsWith("", sub); + } + else + { + StringAssert.DoesNotContain("<", sub); + StringAssert.DoesNotContain(">", sub); + } + } #endif } } \ No newline at end of file diff --git a/src/log4net.Tests/LoggerRepository/ConfigurationMessages.cs b/src/log4net.Tests/LoggerRepository/ConfigurationMessages.cs index daa26724..c06f9f94 100644 --- a/src/log4net.Tests/LoggerRepository/ConfigurationMessages.cs +++ b/src/log4net.Tests/LoggerRepository/ConfigurationMessages.cs @@ -31,18 +31,19 @@ namespace log4net.Tests.LoggerRepository { - [TestFixture] - public class ConfigurationMessages + [TestFixture] + public class ConfigurationMessages + { + [Test] + public void ConfigurationMessagesTest() { - [Test] - public void ConfigurationMessagesTest() - { - try { - LogLog.EmitInternalMessages = false; - LogLog.InternalDebugging = true; + try + { + LogLog.EmitInternalMessages = false; + LogLog.InternalDebugging = true; - XmlDocument log4netConfig = new XmlDocument(); - log4netConfig.LoadXml(@" + XmlDocument log4netConfig = new XmlDocument(); + log4netConfig.LoadXml(@" @@ -57,45 +58,46 @@ public void ConfigurationMessagesTest() "); - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - rep.ConfigurationChanged += new LoggerRepositoryConfigurationChangedEventHandler(rep_ConfigurationChanged); + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + rep.ConfigurationChanged += new LoggerRepositoryConfigurationChangedEventHandler(rep_ConfigurationChanged); - ICollection configurationMessages = XmlConfigurator.Configure(rep, log4netConfig["log4net"]); + ICollection configurationMessages = XmlConfigurator.Configure(rep, log4netConfig["log4net"]); - Assert.IsTrue(configurationMessages.Count > 0); - } - finally { - LogLog.EmitInternalMessages = true; - LogLog.InternalDebugging = false; - } - } + Assert.IsTrue(configurationMessages.Count > 0); + } + finally + { + LogLog.EmitInternalMessages = true; + LogLog.InternalDebugging = false; + } + } - static void rep_ConfigurationChanged(object sender, EventArgs e) - { - ConfigurationChangedEventArgs configChanged = (ConfigurationChangedEventArgs)e; + static void rep_ConfigurationChanged(object sender, EventArgs e) + { + ConfigurationChangedEventArgs configChanged = (ConfigurationChangedEventArgs)e; - Assert.IsTrue(configChanged.ConfigurationMessages.Count > 0); - } + Assert.IsTrue(configChanged.ConfigurationMessages.Count > 0); } + } - public class LogLogAppender : AppenderSkeleton - { - private static readonly Type declaringType = typeof(LogLogAppender); + public class LogLogAppender : AppenderSkeleton + { + private static readonly Type declaringType = typeof(LogLogAppender); - public override void ActivateOptions() - { - LogLog.Debug(declaringType, "Debug - Activating options..."); - LogLog.Warn(declaringType, "Warn - Activating options..."); - LogLog.Error(declaringType, "Error - Activating options..."); + public override void ActivateOptions() + { + LogLog.Debug(declaringType, "Debug - Activating options..."); + LogLog.Warn(declaringType, "Warn - Activating options..."); + LogLog.Error(declaringType, "Error - Activating options..."); - base.ActivateOptions(); - } + base.ActivateOptions(); + } - protected override void Append(LoggingEvent loggingEvent) - { - LogLog.Debug(declaringType, "Debug - Appending..."); - LogLog.Warn(declaringType, "Warn - Appending..."); - LogLog.Error(declaringType, "Error - Appending..."); - } + protected override void Append(LoggingEvent loggingEvent) + { + LogLog.Debug(declaringType, "Debug - Appending..."); + LogLog.Warn(declaringType, "Warn - Appending..."); + LogLog.Error(declaringType, "Error - Appending..."); } + } } diff --git a/src/log4net.Tests/NUnitTestRunnerInitializer.cs b/src/log4net.Tests/NUnitTestRunnerInitializer.cs index 90748c06..08b42154 100644 --- a/src/log4net.Tests/NUnitTestRunnerInitializer.cs +++ b/src/log4net.Tests/NUnitTestRunnerInitializer.cs @@ -1,16 +1,16 @@ namespace log4net.Tests { - using System.IO; + using System.IO; - using NUnit.Framework; + using NUnit.Framework; - [SetUpFixture] - public class NUnitTestRunnerInitializer + [SetUpFixture] + public class NUnitTestRunnerInitializer + { + [OneTimeSetUp] + public void RunBeforeAnyTests() { - [OneTimeSetUp] - public void RunBeforeAnyTests() - { - Directory.SetCurrentDirectory(TestContext.CurrentContext.TestDirectory); - } + Directory.SetCurrentDirectory(TestContext.CurrentContext.TestDirectory); } + } } diff --git a/src/log4net.Tests/Signing.cs b/src/log4net.Tests/Signing.cs index 86516740..93d45563 100644 --- a/src/log4net.Tests/Signing.cs +++ b/src/log4net.Tests/Signing.cs @@ -5,19 +5,19 @@ namespace log4net.Tests { - [TestFixture] - public class Signing + [TestFixture] + public class Signing + { + [Test] + public void AssemblyShouldBeSigned() { - [Test] - public void AssemblyShouldBeSigned() - { - // Arrange - var asm = typeof(LoggerRepositorySkeleton).Assembly; - // Act - var result = asm.GetName().GetPublicKey(); - // Assert - Expect(result) - .Not.To.Be.Empty(); - } + // Arrange + var asm = typeof(LoggerRepositorySkeleton).Assembly; + // Act + var result = asm.GetName().GetPublicKey(); + // Assert + Expect(result) + .Not.To.Be.Empty(); } + } } \ No newline at end of file diff --git a/src/log4net.Tests/Util/EnvironmentPatternConverterTest.cs b/src/log4net.Tests/Util/EnvironmentPatternConverterTest.cs index e475ae5a..da115941 100644 --- a/src/log4net.Tests/Util/EnvironmentPatternConverterTest.cs +++ b/src/log4net.Tests/Util/EnvironmentPatternConverterTest.cs @@ -29,88 +29,90 @@ namespace log4net.Tests.Util { - [TestFixture] - public class EnvironmentPatternConverterTest + [TestFixture] + public class EnvironmentPatternConverterTest + { + private const string ENVIRONMENT_VARIABLE_NAME = "LOG4NET_TEST_TEMP"; + const string SYSTEM_LEVEL_VALUE = "SystemLevelEnvironmentValue"; + const string USER_LEVEL_VALUE = "UserLevelEnvironmentValue"; + const string PROCESS_LEVEL_VALUE = "ProcessLevelEnvironmentValue"; + + [Test] + public void SystemLevelEnvironmentVariable() { - private const string ENVIRONMENT_VARIABLE_NAME = "LOG4NET_TEST_TEMP"; - const string SYSTEM_LEVEL_VALUE = "SystemLevelEnvironmentValue"; - const string USER_LEVEL_VALUE = "UserLevelEnvironmentValue"; - const string PROCESS_LEVEL_VALUE = "ProcessLevelEnvironmentValue"; - - [Test] - public void SystemLevelEnvironmentVariable() - { - EnvironmentPatternConverter converter = new EnvironmentPatternConverter(); - try { - Environment.SetEnvironmentVariable(ENVIRONMENT_VARIABLE_NAME, SYSTEM_LEVEL_VALUE, EnvironmentVariableTarget.Machine); - } - catch (System.Security.SecurityException) { - Assert.Ignore("Test skipped as current user must not set system level environment variables"); - } - - converter.Option = ENVIRONMENT_VARIABLE_NAME; + EnvironmentPatternConverter converter = new EnvironmentPatternConverter(); + try + { + Environment.SetEnvironmentVariable(ENVIRONMENT_VARIABLE_NAME, SYSTEM_LEVEL_VALUE, EnvironmentVariableTarget.Machine); + } + catch (System.Security.SecurityException) + { + Assert.Ignore("Test skipped as current user must not set system level environment variables"); + } + + converter.Option = ENVIRONMENT_VARIABLE_NAME; StringWriter sw = new StringWriter(); converter.Convert(sw, null); - Assert.AreEqual(SYSTEM_LEVEL_VALUE, sw.ToString(), "System level environment variable not expended correctly."); + Assert.AreEqual(SYSTEM_LEVEL_VALUE, sw.ToString(), "System level environment variable not expended correctly."); - Environment.SetEnvironmentVariable(ENVIRONMENT_VARIABLE_NAME, null, EnvironmentVariableTarget.Machine); - } - - [Test] - public void UserLevelEnvironmentVariable() - { - EnvironmentPatternConverter converter = new EnvironmentPatternConverter(); - Environment.SetEnvironmentVariable(ENVIRONMENT_VARIABLE_NAME, USER_LEVEL_VALUE, EnvironmentVariableTarget.User); - - converter.Option = ENVIRONMENT_VARIABLE_NAME; - - StringWriter sw = new StringWriter(); - converter.Convert(sw, null); + Environment.SetEnvironmentVariable(ENVIRONMENT_VARIABLE_NAME, null, EnvironmentVariableTarget.Machine); + } - Assert.AreEqual(USER_LEVEL_VALUE, sw.ToString(), "User level environment variable not expended correctly."); + [Test] + public void UserLevelEnvironmentVariable() + { + EnvironmentPatternConverter converter = new EnvironmentPatternConverter(); + Environment.SetEnvironmentVariable(ENVIRONMENT_VARIABLE_NAME, USER_LEVEL_VALUE, EnvironmentVariableTarget.User); - Environment.SetEnvironmentVariable(ENVIRONMENT_VARIABLE_NAME, null, EnvironmentVariableTarget.User); - } + converter.Option = ENVIRONMENT_VARIABLE_NAME; - [Test] - public void ProcessLevelEnvironmentVariable() - { - EnvironmentPatternConverter converter = new EnvironmentPatternConverter(); - Environment.SetEnvironmentVariable(ENVIRONMENT_VARIABLE_NAME, PROCESS_LEVEL_VALUE); + StringWriter sw = new StringWriter(); + converter.Convert(sw, null); - converter.Option = ENVIRONMENT_VARIABLE_NAME; + Assert.AreEqual(USER_LEVEL_VALUE, sw.ToString(), "User level environment variable not expended correctly."); - StringWriter sw = new StringWriter(); - converter.Convert(sw, null); + Environment.SetEnvironmentVariable(ENVIRONMENT_VARIABLE_NAME, null, EnvironmentVariableTarget.User); + } - Assert.AreEqual(PROCESS_LEVEL_VALUE, sw.ToString(), "Process level environment variable not expended correctly."); + [Test] + public void ProcessLevelEnvironmentVariable() + { + EnvironmentPatternConverter converter = new EnvironmentPatternConverter(); + Environment.SetEnvironmentVariable(ENVIRONMENT_VARIABLE_NAME, PROCESS_LEVEL_VALUE); - Environment.SetEnvironmentVariable(ENVIRONMENT_VARIABLE_NAME, null); - } + converter.Option = ENVIRONMENT_VARIABLE_NAME; - private class EnvironmentPatternConverter - { - private object target = null; + StringWriter sw = new StringWriter(); + converter.Convert(sw, null); - public EnvironmentPatternConverter() - { - target = Utils.CreateInstance("log4net.Util.PatternStringConverters.EnvironmentPatternConverter,log4net"); - } + Assert.AreEqual(PROCESS_LEVEL_VALUE, sw.ToString(), "Process level environment variable not expended correctly."); - public string Option - { - get { return Utils.GetProperty(target, "Option") as string; } - set { Utils.SetProperty(target, "Option", value); } - } + Environment.SetEnvironmentVariable(ENVIRONMENT_VARIABLE_NAME, null); + } - public void Convert(TextWriter writer, object state) - { - Utils.InvokeMethod(target, "Convert", writer, state); - } - } + private class EnvironmentPatternConverter + { + private object target = null; + + public EnvironmentPatternConverter() + { + target = Utils.CreateInstance("log4net.Util.PatternStringConverters.EnvironmentPatternConverter,log4net"); + } + + public string Option + { + get { return Utils.GetProperty(target, "Option") as string; } + set { Utils.SetProperty(target, "Option", value); } + } + + public void Convert(TextWriter writer, object state) + { + Utils.InvokeMethod(target, "Convert", writer, state); + } } + } } #endif diff --git a/src/log4net.Tests/Util/LogLogTest.cs b/src/log4net.Tests/Util/LogLogTest.cs index 7d9030b6..d9fcf4fe 100644 --- a/src/log4net.Tests/Util/LogLogTest.cs +++ b/src/log4net.Tests/Util/LogLogTest.cs @@ -26,84 +26,86 @@ namespace log4net.Tests.Util { - [TestFixture] - public class LogLogTest + [TestFixture] + public class LogLogTest + { + [Test] + public void TraceListenerCounterTest() { - [Test] - public void TraceListenerCounterTest() - { - TraceListenerCounter listTraceListener = new TraceListenerCounter(); - - Trace.Listeners.Clear(); - Trace.Listeners.Add(listTraceListener); - - Trace.Write("Hello"); - Trace.Write("World"); - - Assert.AreEqual(2, listTraceListener.Count); - } - - [Test] - public void EmitInternalMessages() - { - TraceListenerCounter listTraceListener = new TraceListenerCounter(); - Trace.Listeners.Clear(); - Trace.Listeners.Add(listTraceListener); - LogLog.Error(GetType(), "Hello"); - LogLog.Error(GetType(), "World"); - Trace.Flush(); - Assert.AreEqual(2, listTraceListener.Count); - - try { - LogLog.EmitInternalMessages = false; - - LogLog.Error(GetType(), "Hello"); - LogLog.Error(GetType(), "World"); - Assert.AreEqual(2, listTraceListener.Count); - } - finally { - LogLog.EmitInternalMessages = true; - } - } - - [Test] - public void LogReceivedAdapter() - { - ArrayList messages = new ArrayList(); - - using (new LogLog.LogReceivedAdapter(messages)) - { - LogLog.Debug(GetType(), "Won't be recorded"); - LogLog.Error(GetType(), "This will be recorded."); - LogLog.Error(GetType(), "This will be recorded."); - } - - Assert.AreEqual(2, messages.Count); - } + TraceListenerCounter listTraceListener = new TraceListenerCounter(); + + Trace.Listeners.Clear(); + Trace.Listeners.Add(listTraceListener); + + Trace.Write("Hello"); + Trace.Write("World"); + + Assert.AreEqual(2, listTraceListener.Count); + } + + [Test] + public void EmitInternalMessages() + { + TraceListenerCounter listTraceListener = new TraceListenerCounter(); + Trace.Listeners.Clear(); + Trace.Listeners.Add(listTraceListener); + LogLog.Error(GetType(), "Hello"); + LogLog.Error(GetType(), "World"); + Trace.Flush(); + Assert.AreEqual(2, listTraceListener.Count); + + try + { + LogLog.EmitInternalMessages = false; + + LogLog.Error(GetType(), "Hello"); + LogLog.Error(GetType(), "World"); + Assert.AreEqual(2, listTraceListener.Count); + } + finally + { + LogLog.EmitInternalMessages = true; + } + } + + [Test] + public void LogReceivedAdapter() + { + ArrayList messages = new ArrayList(); + + using (new LogLog.LogReceivedAdapter(messages)) + { + LogLog.Debug(GetType(), "Won't be recorded"); + LogLog.Error(GetType(), "This will be recorded."); + LogLog.Error(GetType(), "This will be recorded."); + } + + Assert.AreEqual(2, messages.Count); + } + } + + public class TraceListenerCounter : TraceListener + { + private int count = 0; + + public override void Write(string message) + { + count++; + } + + public override void WriteLine(string message) + { + Write(message); + } + + public void Reset() + { + count = 0; } - public class TraceListenerCounter : TraceListener + public int Count { - private int count = 0; - - public override void Write(string message) - { - count++; - } - - public override void WriteLine(string message) - { - Write(message); - } - - public void Reset() - { - count = 0; - } - - public int Count - { - get { return count; } - } + get { return count; } } + } } diff --git a/src/log4net.Tests/Util/PatternConverterTest.cs b/src/log4net.Tests/Util/PatternConverterTest.cs index 06f352eb..e8830f31 100644 --- a/src/log4net.Tests/Util/PatternConverterTest.cs +++ b/src/log4net.Tests/Util/PatternConverterTest.cs @@ -32,14 +32,14 @@ namespace log4net.Tests.Util { - [TestFixture] - public class PatternConverterTest + [TestFixture] + public class PatternConverterTest + { + [Test] + public void PatternLayoutConverterProperties() { - [Test] - public void PatternLayoutConverterProperties() - { - XmlDocument log4netConfig = new XmlDocument(); - log4netConfig.LoadXml(@" + XmlDocument log4netConfig = new XmlDocument(); + log4netConfig.LoadXml(@" @@ -64,27 +64,27 @@ public void PatternLayoutConverterProperties() "); - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - XmlConfigurator.Configure(rep, log4netConfig["log4net"]); + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + XmlConfigurator.Configure(rep, log4netConfig["log4net"]); - ILog log = LogManager.GetLogger(rep.Name, "PatternLayoutConverterProperties"); - log.Debug("Message"); + ILog log = LogManager.GetLogger(rep.Name, "PatternLayoutConverterProperties"); + log.Debug("Message"); - PropertyKeyCountPatternLayoutConverter converter = - PropertyKeyCountPatternLayoutConverter.MostRecentInstance; - Assert.AreEqual(2, converter.Properties.Count); - Assert.AreEqual("4", converter.Properties["two-plus-two"]); + PropertyKeyCountPatternLayoutConverter converter = + PropertyKeyCountPatternLayoutConverter.MostRecentInstance; + Assert.AreEqual(2, converter.Properties.Count); + Assert.AreEqual("4", converter.Properties["two-plus-two"]); - StringAppender appender = - (StringAppender)LogManager.GetRepository(rep.Name).GetAppenders()[0]; - Assert.AreEqual("2", appender.GetString()); - } + StringAppender appender = + (StringAppender)LogManager.GetRepository(rep.Name).GetAppenders()[0]; + Assert.AreEqual("2", appender.GetString()); + } - [Test] - public void PatternConverterProperties() - { - XmlDocument log4netConfig = new XmlDocument(); - log4netConfig.LoadXml(@" + [Test] + public void PatternConverterProperties() + { + XmlDocument log4netConfig = new XmlDocument(); + log4netConfig.LoadXml(@" @@ -110,83 +110,83 @@ public void PatternConverterProperties() "); - ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); - XmlConfigurator.Configure(rep, log4netConfig["log4net"]); + ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); + XmlConfigurator.Configure(rep, log4netConfig["log4net"]); + + ILog log = LogManager.GetLogger(rep.Name, "PatternConverterProperties"); + log.Debug("Message"); + + PropertyKeyCountPatternConverter converter = + PropertyKeyCountPatternConverter.MostRecentInstance; + Assert.AreEqual(2, converter.Properties.Count); + Assert.AreEqual("4", converter.Properties["two-plus-two"]); + + PatternStringAppender appender = + (PatternStringAppender)LogManager.GetRepository(rep.Name).GetAppenders()[0]; + Assert.AreEqual("2", appender.Setting.Format()); + } + } - ILog log = LogManager.GetLogger(rep.Name, "PatternConverterProperties"); - log.Debug("Message"); + public class PropertyKeyCountPatternLayoutConverter : PatternLayoutConverter + { + private static PropertyKeyCountPatternLayoutConverter mostRecentInstance; - PropertyKeyCountPatternConverter converter = - PropertyKeyCountPatternConverter.MostRecentInstance; - Assert.AreEqual(2, converter.Properties.Count); - Assert.AreEqual("4", converter.Properties["two-plus-two"]); + public PropertyKeyCountPatternLayoutConverter() + { + mostRecentInstance = this; + } + + protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) + { + writer.Write(Properties.GetKeys().Length); + } - PatternStringAppender appender = - (PatternStringAppender)LogManager.GetRepository(rep.Name).GetAppenders()[0]; - Assert.AreEqual("2", appender.Setting.Format()); - } + public static PropertyKeyCountPatternLayoutConverter MostRecentInstance + { + get { return mostRecentInstance; } } + } + + public class PropertyKeyCountPatternConverter : PatternConverter + { + private static PropertyKeyCountPatternConverter mostRecentInstance; - public class PropertyKeyCountPatternLayoutConverter : PatternLayoutConverter + public PropertyKeyCountPatternConverter() { - private static PropertyKeyCountPatternLayoutConverter mostRecentInstance; - - public PropertyKeyCountPatternLayoutConverter() - { - mostRecentInstance = this; - } - - protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) - { - writer.Write(Properties.GetKeys().Length); - } - - public static PropertyKeyCountPatternLayoutConverter MostRecentInstance - { - get { return mostRecentInstance; } - } + mostRecentInstance = this; } - public class PropertyKeyCountPatternConverter : PatternConverter + protected override void Convert(TextWriter writer, object state) { - private static PropertyKeyCountPatternConverter mostRecentInstance; - - public PropertyKeyCountPatternConverter() - { - mostRecentInstance = this; - } - - protected override void Convert(TextWriter writer, object state) - { - writer.Write(Properties.GetKeys().Length); - } - - public static PropertyKeyCountPatternConverter MostRecentInstance - { - get { return mostRecentInstance; } - } + writer.Write(Properties.GetKeys().Length); } - public class PatternStringAppender : StringAppender + public static PropertyKeyCountPatternConverter MostRecentInstance { - private static PatternStringAppender mostRecentInstace; + get { return mostRecentInstance; } + } + } + + public class PatternStringAppender : StringAppender + { + private static PatternStringAppender mostRecentInstace; - private PatternString setting; + private PatternString setting; - public PatternStringAppender() - { - mostRecentInstace = this; - } + public PatternStringAppender() + { + mostRecentInstace = this; + } - public PatternString Setting - { - get { return setting; } - set { setting = value; } - } + public PatternString Setting + { + get { return setting; } + set { setting = value; } + } - public static PatternStringAppender MostRecentInstace - { - get { return mostRecentInstace; } - } + public static PatternStringAppender MostRecentInstace + { + get { return mostRecentInstace; } } + } } diff --git a/src/log4net.Tests/Util/PatternStringTest.cs b/src/log4net.Tests/Util/PatternStringTest.cs index e15bebeb..3f5d52e9 100644 --- a/src/log4net.Tests/Util/PatternStringTest.cs +++ b/src/log4net.Tests/Util/PatternStringTest.cs @@ -30,86 +30,86 @@ namespace log4net.Tests.Util { - [TestFixture] - public class PatternStringTest : MarshalByRefObject + [TestFixture] + public class PatternStringTest : MarshalByRefObject + { + [Test] + public void TestEnvironmentFolderPathPatternConverter() { - [Test] - public void TestEnvironmentFolderPathPatternConverter() - { - string[] specialFolderNames = Enum.GetNames(typeof(Environment.SpecialFolder)); + string[] specialFolderNames = Enum.GetNames(typeof(Environment.SpecialFolder)); - foreach (string specialFolderName in specialFolderNames) - { - string pattern = "%envFolderPath{" + specialFolderName + "}"; + foreach (string specialFolderName in specialFolderNames) + { + string pattern = "%envFolderPath{" + specialFolderName + "}"; - PatternString patternString = new PatternString(pattern); + PatternString patternString = new PatternString(pattern); - string evaluatedPattern = patternString.Format(); + string evaluatedPattern = patternString.Format(); - Environment.SpecialFolder specialFolder = - (Environment.SpecialFolder)Enum.Parse(typeof(Environment.SpecialFolder), specialFolderName); + Environment.SpecialFolder specialFolder = + (Environment.SpecialFolder)Enum.Parse(typeof(Environment.SpecialFolder), specialFolderName); - Assert.AreEqual(Environment.GetFolderPath(specialFolder), evaluatedPattern); - } - } + Assert.AreEqual(Environment.GetFolderPath(specialFolder), evaluatedPattern); + } + } - [Test] - public void TestAppSettingPathConverter() - { - string configurationFileContent = @" + [Test] + public void TestAppSettingPathConverter() + { + string configurationFileContent = @" "; - string configurationFileName = null; - AppDomain appDomain = null; - try - { - configurationFileName = CreateTempConfigFile(configurationFileContent); - appDomain = CreateConfiguredDomain("AppSettingsTestDomain", configurationFileName); + string configurationFileName = null; + AppDomain appDomain = null; + try + { + configurationFileName = CreateTempConfigFile(configurationFileContent); + appDomain = CreateConfiguredDomain("AppSettingsTestDomain", configurationFileName); - PatternStringTest pst = (PatternStringTest)appDomain.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().FullName, this.GetType().FullName); - pst.TestAppSettingPathConverterInConfiguredDomain(); - } - finally - { - if (appDomain != null) AppDomain.Unload(appDomain); - if (configurationFileName != null) File.Delete(configurationFileName); - } - } + PatternStringTest pst = (PatternStringTest)appDomain.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().FullName, this.GetType().FullName); + pst.TestAppSettingPathConverterInConfiguredDomain(); + } + finally + { + if (appDomain != null) AppDomain.Unload(appDomain); + if (configurationFileName != null) File.Delete(configurationFileName); + } + } - public void TestAppSettingPathConverterInConfiguredDomain() - { - string pattern = "%appSetting{TestKey}"; - PatternString patternString = new PatternString(pattern); - string evaluatedPattern = patternString.Format(); - string appSettingValue = ConfigurationManager.AppSettings["TestKey"]; - Assert.AreEqual("TestValue", appSettingValue, "Expected configuration file to contain a key TestKey with the value TestValue"); - Assert.AreEqual(appSettingValue, evaluatedPattern, "Evaluated pattern expected to be identical to appSetting value"); + public void TestAppSettingPathConverterInConfiguredDomain() + { + string pattern = "%appSetting{TestKey}"; + PatternString patternString = new PatternString(pattern); + string evaluatedPattern = patternString.Format(); + string appSettingValue = ConfigurationManager.AppSettings["TestKey"]; + Assert.AreEqual("TestValue", appSettingValue, "Expected configuration file to contain a key TestKey with the value TestValue"); + Assert.AreEqual(appSettingValue, evaluatedPattern, "Evaluated pattern expected to be identical to appSetting value"); - string badPattern = "%appSetting{UnknownKey}"; - patternString = new PatternString(badPattern); - evaluatedPattern = patternString.Format(); - Assert.AreEqual("(null)", evaluatedPattern, "Evaluated pattern expected to be \"(null)\" for non-existent appSettings key"); - } + string badPattern = "%appSetting{UnknownKey}"; + patternString = new PatternString(badPattern); + evaluatedPattern = patternString.Format(); + Assert.AreEqual("(null)", evaluatedPattern, "Evaluated pattern expected to be \"(null)\" for non-existent appSettings key"); + } - private static string CreateTempConfigFile(string configurationFileContent) - { - string fileName = Path.GetTempFileName(); - File.WriteAllText(fileName, configurationFileContent); - return fileName; - } + private static string CreateTempConfigFile(string configurationFileContent) + { + string fileName = Path.GetTempFileName(); + File.WriteAllText(fileName, configurationFileContent); + return fileName; + } - private static AppDomain CreateConfiguredDomain(string domainName, string configurationFileName) - { - AppDomainSetup ads = new AppDomainSetup(); - ads.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory; - ads.ConfigurationFile = configurationFileName; - AppDomain ad = AppDomain.CreateDomain(domainName, null, ads); - return ad; - } + private static AppDomain CreateConfiguredDomain(string domainName, string configurationFileName) + { + AppDomainSetup ads = new AppDomainSetup(); + ads.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory; + ads.ConfigurationFile = configurationFileName; + AppDomain ad = AppDomain.CreateDomain(domainName, null, ads); + return ad; } + } } #endif diff --git a/src/log4net.Tests/Util/PropertiesDictionaryTest.cs b/src/log4net.Tests/Util/PropertiesDictionaryTest.cs index 04d66c8c..8f12f60a 100644 --- a/src/log4net.Tests/Util/PropertiesDictionaryTest.cs +++ b/src/log4net.Tests/Util/PropertiesDictionaryTest.cs @@ -42,7 +42,7 @@ public void TestSerialization() { PropertiesDictionary pd = new PropertiesDictionary(); - for(int i = 0; i < 10; i++) + for (int i = 0; i < 10; i++) { pd[i.ToString()] = i; } @@ -60,7 +60,7 @@ public void TestSerialization() Assert.AreEqual(10, pd2.Count, "Deserialized Dictionary should have 10 items"); - foreach(string key in pd.GetKeys()) + foreach (string key in pd.GetKeys()) { Assert.AreEqual(pd[key], pd2[key], "Check Value Persisted for key [{0}]", key); } diff --git a/src/log4net.Tests/Util/SystemInfoTest.cs b/src/log4net.Tests/Util/SystemInfoTest.cs index b943e09b..34d57e44 100644 --- a/src/log4net.Tests/Util/SystemInfoTest.cs +++ b/src/log4net.Tests/Util/SystemInfoTest.cs @@ -89,7 +89,8 @@ public void TestGetTypeFromStringFullyQualified() } #if !NETSTANDARD1_3 - [Test][Platform(Include="Win")] + [Test] + [Platform(Include = "Win")] public void TestGetTypeFromStringCaseInsensitiveOnAssemblyName() { Type t; @@ -155,7 +156,7 @@ public void TestGetTypeFromStringFails2() t = GetTypeFromString("LOG4NET.TESTS.UTIL.SYSTEMINFOTEST", false, false); Assert.AreSame(null, t, "Test explicit case sensitive fails type load"); - Assert.Throws(() => GetTypeFromString("LOG4NET.TESTS.UTIL.SYSTEMINFOTEST", true, false)); + Assert.Throws(() => GetTypeFromString("LOG4NET.TESTS.UTIL.SYSTEMINFOTEST", true, false)); } // Wraps SystemInfo.GetTypeFromString because the method relies on GetCallingAssembly, which is @@ -170,40 +171,40 @@ private Type GetTypeFromString(string typeName, bool throwOnError, bool ignoreCa #endif } - [Test] - public void EqualsIgnoringCase_BothNull_true() - { - Assert.True(SystemInfo.EqualsIgnoringCase(null, null)); - } - - [Test] - public void EqualsIgnoringCase_LeftNull_false() - { - Assert.False(SystemInfo.EqualsIgnoringCase(null, "foo")); - } - - [Test] - public void EqualsIgnoringCase_RightNull_false() - { - Assert.False(SystemInfo.EqualsIgnoringCase("foo", null)); - } - - [Test] - public void EqualsIgnoringCase_SameStringsSameCase_true() - { - Assert.True(SystemInfo.EqualsIgnoringCase("foo", "foo")); - } - - [Test] - public void EqualsIgnoringCase_SameStringsDifferentCase_true() - { - Assert.True(SystemInfo.EqualsIgnoringCase("foo", "FOO")); - } - - [Test] - public void EqualsIgnoringCase_DifferentStrings_false() - { - Assert.False(SystemInfo.EqualsIgnoringCase("foo", "foobar")); - } + [Test] + public void EqualsIgnoringCase_BothNull_true() + { + Assert.True(SystemInfo.EqualsIgnoringCase(null, null)); + } + + [Test] + public void EqualsIgnoringCase_LeftNull_false() + { + Assert.False(SystemInfo.EqualsIgnoringCase(null, "foo")); + } + + [Test] + public void EqualsIgnoringCase_RightNull_false() + { + Assert.False(SystemInfo.EqualsIgnoringCase("foo", null)); + } + + [Test] + public void EqualsIgnoringCase_SameStringsSameCase_true() + { + Assert.True(SystemInfo.EqualsIgnoringCase("foo", "foo")); + } + + [Test] + public void EqualsIgnoringCase_SameStringsDifferentCase_true() + { + Assert.True(SystemInfo.EqualsIgnoringCase("foo", "FOO")); + } + + [Test] + public void EqualsIgnoringCase_DifferentStrings_false() + { + Assert.False(SystemInfo.EqualsIgnoringCase("foo", "foobar")); + } } } diff --git a/src/log4net.Tests/Util/TransformTest.cs b/src/log4net.Tests/Util/TransformTest.cs index 7d4026a8..216eb13b 100644 --- a/src/log4net.Tests/Util/TransformTest.cs +++ b/src/log4net.Tests/Util/TransformTest.cs @@ -23,23 +23,24 @@ using NUnit.Framework; -namespace log4net.Tests.Util { +namespace log4net.Tests.Util +{ - [TestFixture] - public class TransformTest + [TestFixture] + public class TransformTest + { + [Test] + public void MaskXmlInvalidCharactersAllowsJapaneseCharacters() { - [Test] - public void MaskXmlInvalidCharactersAllowsJapaneseCharacters() - { - string kome = "\u203B"; - Assert.AreEqual(kome, Transform.MaskXmlInvalidCharacters(kome, "?")); - } + string kome = "\u203B"; + Assert.AreEqual(kome, Transform.MaskXmlInvalidCharacters(kome, "?")); + } - [Test] - public void MaskXmlInvalidCharactersMasks0Char() - { - string c = "\u0000"; - Assert.AreEqual("?", Transform.MaskXmlInvalidCharacters(c, "?")); - } + [Test] + public void MaskXmlInvalidCharactersMasks0Char() + { + string c = "\u0000"; + Assert.AreEqual("?", Transform.MaskXmlInvalidCharacters(c, "?")); } + } } diff --git a/src/log4net.Tests/Utils.cs b/src/log4net.Tests/Utils.cs index d4ad6316..5264ad50 100644 --- a/src/log4net.Tests/Utils.cs +++ b/src/log4net.Tests/Utils.cs @@ -99,7 +99,7 @@ private static Type[] GetTypesArray(object[] args) { Type[] types = new Type[args.Length]; - for(int i = 0; i < args.Length; i++) + for (int i = 0; i < args.Length; i++) { if (args[i] == null) { @@ -114,33 +114,34 @@ private static Type[] GetTypesArray(object[] args) return types; } - internal const string PROPERTY_KEY = "prop1"; + internal const string PROPERTY_KEY = "prop1"; - internal static void RemovePropertyFromAllContexts() { - GlobalContext.Properties.Remove(PROPERTY_KEY); - ThreadContext.Properties.Remove(PROPERTY_KEY); + internal static void RemovePropertyFromAllContexts() + { + GlobalContext.Properties.Remove(PROPERTY_KEY); + ThreadContext.Properties.Remove(PROPERTY_KEY); #if !NETCF - LogicalThreadContext.Properties.Remove(PROPERTY_KEY); + LogicalThreadContext.Properties.Remove(PROPERTY_KEY); #endif - } + } - // Wrappers because repository/logger retrieval APIs require an Assembly argument on NETSTANDARD1_3 - internal static ILog GetLogger(string name) - { + // Wrappers because repository/logger retrieval APIs require an Assembly argument on NETSTANDARD1_3 + internal static ILog GetLogger(string name) + { #if NETSTANDARD1_3 return LogManager.GetLogger(typeof(Utils).GetTypeInfo().Assembly, name); #else - return LogManager.GetLogger(name); + return LogManager.GetLogger(name); #endif - } + } - internal static ILoggerRepository GetRepository() - { + internal static ILoggerRepository GetRepository() + { #if NETSTANDARD1_3 return LogManager.GetRepository(typeof(Utils).GetTypeInfo().Assembly); #else - return LogManager.GetRepository(); + return LogManager.GetRepository(); #endif - } } + } } \ No newline at end of file