#region Apache License
|
//
|
// Licensed to the Apache Software Foundation (ASF) under one or more
|
// contributor license agreements. See the NOTICE file distributed with
|
// this work for additional information regarding copyright ownership.
|
// The ASF licenses this file to you under the Apache License, Version 2.0
|
// (the "License"); you may not use this file except in compliance with
|
// the License. You may obtain a copy of the License at
|
//
|
// http://www.apache.org/licenses/LICENSE-2.0
|
//
|
// Unless required by applicable law or agreed to in writing, software
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
// See the License for the specific language governing permissions and
|
// limitations under the License.
|
//
|
#endregion
|
|
using System;
|
using System.Collections;
|
using System.Reflection;
|
|
using log4net.Appender;
|
using log4net.Util;
|
using log4net.Repository;
|
|
|
namespace log4net.Core
|
{
|
/// <summary>
|
/// The implementation of the <see cref="IRepositorySelector"/> interface suitable
|
/// for use with the compact framework
|
/// </summary>
|
/// <remarks>
|
/// <para>
|
/// This <see cref="IRepositorySelector"/> implementation is a simple
|
/// mapping between repository name and <see cref="ILoggerRepository"/>
|
/// object.
|
/// </para>
|
/// <para>
|
/// The .NET Compact Framework 1.0 does not support retrieving assembly
|
/// level attributes therefore unlike the <c>DefaultRepositorySelector</c>
|
/// this selector does not examine the calling assembly for attributes.
|
/// </para>
|
/// </remarks>
|
/// <author>Nicko Cadell</author>
|
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
|
|
/// <summary>
|
/// Create a new repository selector
|
/// </summary>
|
/// <param name="defaultRepositoryType">the type of the repositories to create, must implement <see cref="ILoggerRepository"/></param>
|
/// <remarks>
|
/// <para>
|
/// Create an new compact repository selector.
|
/// The default type for repositories must be specified,
|
/// an appropriate value would be <see cref="log4net.Repository.Hierarchy.Hierarchy"/>.
|
/// </para>
|
/// </remarks>
|
/// <exception cref="ArgumentNullException">throw if <paramref name="defaultRepositoryType"/> is null</exception>
|
/// <exception cref="ArgumentOutOfRangeException">throw if <paramref name="defaultRepositoryType"/> does not implement <see cref="ILoggerRepository"/></exception>
|
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
|
|
/// <summary>
|
/// Get the <see cref="ILoggerRepository"/> for the specified assembly
|
/// </summary>
|
/// <param name="assembly">not used</param>
|
/// <returns>The default <see cref="ILoggerRepository"/></returns>
|
/// <remarks>
|
/// <para>
|
/// The <paramref name="assembly"/> argument is not used. This selector does not create a
|
/// separate repository for each assembly.
|
/// </para>
|
/// <para>
|
/// As a named repository is not specified the default repository is
|
/// returned. The default repository is named <c>log4net-default-repository</c>.
|
/// </para>
|
/// </remarks>
|
public ILoggerRepository GetRepository(Assembly assembly)
|
{
|
return CreateRepository(assembly, m_defaultRepositoryType);
|
}
|
|
/// <summary>
|
/// Get the named <see cref="ILoggerRepository"/>
|
/// </summary>
|
/// <param name="repositoryName">the name of the repository to lookup</param>
|
/// <returns>The named <see cref="ILoggerRepository"/></returns>
|
/// <remarks>
|
/// <para>
|
/// Get the named <see cref="ILoggerRepository"/>. The default
|
/// repository is <c>log4net-default-repository</c>. Other repositories
|
/// must be created using the <see cref="CreateRepository(string, Type)"/>.
|
/// If the named repository does not exist an exception is thrown.
|
/// </para>
|
/// </remarks>
|
/// <exception cref="ArgumentNullException">throw if <paramref name="repositoryName"/> is null</exception>
|
/// <exception cref="LogException">throw if the <paramref name="repositoryName"/> does not exist</exception>
|
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;
|
}
|
}
|
|
/// <summary>
|
/// Create a new repository for the assembly specified
|
/// </summary>
|
/// <param name="assembly">not used</param>
|
/// <param name="repositoryType">the type of repository to create, must implement <see cref="ILoggerRepository"/></param>
|
/// <returns>the repository created</returns>
|
/// <remarks>
|
/// <para>
|
/// The <paramref name="assembly"/> argument is not used. This selector does not create a
|
/// separate repository for each assembly.
|
/// </para>
|
/// <para>
|
/// If the <paramref name="repositoryType"/> is <c>null</c> then the
|
/// default repository type specified to the constructor is used.
|
/// </para>
|
/// <para>
|
/// As a named repository is not specified the default repository is
|
/// returned. The default repository is named <c>log4net-default-repository</c>.
|
/// </para>
|
/// </remarks>
|
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;
|
}
|
}
|
|
/// <summary>
|
/// Create a new repository for the repository specified
|
/// </summary>
|
/// <param name="repositoryName">the repository to associate with the <see cref="ILoggerRepository"/></param>
|
/// <param name="repositoryType">the type of repository to create, must implement <see cref="ILoggerRepository"/>.
|
/// If this param is null then the default repository type is used.</param>
|
/// <returns>the repository created</returns>
|
/// <remarks>
|
/// <para>
|
/// The <see cref="ILoggerRepository"/> created will be associated with the repository
|
/// specified such that a call to <see cref="GetRepository(string)"/> with the
|
/// same repository specified will return the same repository instance.
|
/// </para>
|
/// <para>
|
/// If the named repository already exists an exception will be thrown.
|
/// </para>
|
/// <para>
|
/// If <paramref name="repositoryType"/> is <c>null</c> then the default
|
/// repository type specified to the constructor is used.
|
/// </para>
|
/// </remarks>
|
/// <exception cref="ArgumentNullException">throw if <paramref name="repositoryName"/> is null</exception>
|
/// <exception cref="LogException">throw if the <paramref name="repositoryName"/> already exists</exception>
|
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;
|
}
|
}
|
|
/// <summary>
|
/// Test if a named repository exists
|
/// </summary>
|
/// <param name="repositoryName">the named repository to check</param>
|
/// <returns><c>true</c> if the repository exists</returns>
|
/// <remarks>
|
/// <para>
|
/// Test if a named repository exists. Use <see cref="CreateRepository(string, Type)"/>
|
/// to create a new repository and <see cref="GetRepository(string)"/> to retrieve
|
/// a repository.
|
/// </para>
|
/// </remarks>
|
public bool ExistsRepository(string repositoryName)
|
{
|
lock(this)
|
{
|
return m_name2repositoryMap.ContainsKey(repositoryName);
|
}
|
}
|
|
/// <summary>
|
/// Gets a list of <see cref="ILoggerRepository"/> objects
|
/// </summary>
|
/// <returns>an array of all known <see cref="ILoggerRepository"/> objects</returns>
|
/// <remarks>
|
/// <para>
|
/// Gets an array of all of the repositories created by this selector.
|
/// </para>
|
/// </remarks>
|
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
|
|
/// <summary>
|
/// The fully qualified type of the CompactRepositorySelector class.
|
/// </summary>
|
/// <remarks>
|
/// Used by the internal logger to record the Type of the
|
/// log message.
|
/// </remarks>
|
private readonly static Type declaringType = typeof(CompactRepositorySelector);
|
|
#endregion Private Static Fields
|
|
/// <summary>
|
/// Event to notify that a logger repository has been created.
|
/// </summary>
|
/// <value>
|
/// Event to notify that a logger repository has been created.
|
/// </value>
|
/// <remarks>
|
/// <para>
|
/// Event raised when a new repository is created.
|
/// The event source will be this selector. The event args will
|
/// be a <see cref="LoggerRepositoryCreationEventArgs"/> which
|
/// holds the newly created <see cref="ILoggerRepository"/>.
|
/// </para>
|
/// </remarks>
|
public event LoggerRepositoryCreationEventHandler LoggerRepositoryCreatedEvent
|
{
|
add { m_loggerRepositoryCreatedEvent += value; }
|
remove { m_loggerRepositoryCreatedEvent -= value; }
|
}
|
|
/// <summary>
|
/// Notify the registered listeners that the repository has been created
|
/// </summary>
|
/// <param name="repository">The repository that has been created</param>
|
/// <remarks>
|
/// <para>
|
/// Raises the <event cref="LoggerRepositoryCreatedEvent">LoggerRepositoryCreatedEvent</event>
|
/// event.
|
/// </para>
|
/// </remarks>
|
protected virtual void OnLoggerRepositoryCreatedEvent(ILoggerRepository repository)
|
{
|
LoggerRepositoryCreationEventHandler handler = m_loggerRepositoryCreatedEvent;
|
if (handler != null)
|
{
|
handler(this, new LoggerRepositoryCreationEventArgs(repository));
|
}
|
}
|
}
|
}
|