#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 log4net.Repository; 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. /// /// virtual public 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. /// /// virtual protected 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. /// /// virtual protected 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 } }