#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 { /// /// 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 readonly static 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)); } } } }