#region Copyright & License
//
// Copyright 2001-2005 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#endregion
using System;
using System.Configuration;
using System.Reflection;
using log4net.Util;
using log4net.Repository;
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("LoggerManager: 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(GetVersionInfo());
// Set the default repository selector
#if NETCF
s_repositorySelector = new CompactRepositorySelector(typeof(log4net.Repository.Hierarchy.Hierarchy));
#else
// 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("LoggerManager: 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("LoggerManager: Exception while creating RepositorySelector ["+appRepositorySelectorType.FullName+"]", ex);
}
if (appRepositorySelectorObj != null && appRepositorySelectorObj is IRepositorySelector)
{
s_repositorySelector = (IRepositorySelector)appRepositorySelectorObj;
}
else
{
LogLog.Error("LoggerManager: RepositorySelector Type ["+appRepositorySelectorType.FullName+"] is not an IRepositorySelector");
}
}
}
// Create the DefaultRepositorySelector if not configured above
if (s_repositorySelector == null)
{
s_repositorySelector = new DefaultRepositorySelector(typeof(log4net.Repository.Hierarchy.Hierarchy));
}
#endif
}
///
/// 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
// 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);
#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();
// Grab the currently executing assembly
Assembly myAssembly = Assembly.GetExecutingAssembly();
// Build Up message
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
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();
}
#endif
#endregion Private Static Methods
#region Private Static Fields
///
/// Initialize the default repository selector
///
private static IRepositorySelector s_repositorySelector;
#endregion Private Static Fields
}
}