/Dependencies/log4net/Core/WrapperMap.cs
C# | 259 lines | 84 code | 35 blank | 140 comment | 10 complexity | 53e36183ce8d9515f7eb0b072dfc9dec MD5 | raw file
1#region Apache License 2// 3// Licensed to the Apache Software Foundation (ASF) under one or more 4// contributor license agreements. See the NOTICE file distributed with 5// this work for additional information regarding copyright ownership. 6// The ASF licenses this file to you under the Apache License, Version 2.0 7// (the "License"); you may not use this file except in compliance with 8// the License. You may obtain a copy of the License at 9// 10// http://www.apache.org/licenses/LICENSE-2.0 11// 12// Unless required by applicable law or agreed to in writing, software 13// distributed under the License is distributed on an "AS IS" BASIS, 14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15// See the License for the specific language governing permissions and 16// limitations under the License. 17// 18#endregion 19 20using System; 21using System.Collections; 22 23using log4net.Repository; 24 25namespace log4net.Core 26{ 27 #region WrapperCreationHandler 28 29 /// <summary> 30 /// Delegate used to handle creation of new wrappers. 31 /// </summary> 32 /// <param name="logger">The logger to wrap in a wrapper.</param> 33 /// <remarks> 34 /// <para> 35 /// Delegate used to handle creation of new wrappers. This delegate 36 /// is called from the <see cref="WrapperMap.CreateNewWrapperObject"/> 37 /// method to construct the wrapper for the specified logger. 38 /// </para> 39 /// <para> 40 /// The delegate to use is supplied to the <see cref="WrapperMap"/> 41 /// constructor. 42 /// </para> 43 /// </remarks> 44 public delegate ILoggerWrapper WrapperCreationHandler(ILogger logger); 45 46 #endregion WrapperCreationHandler 47 48 /// <summary> 49 /// Maps between logger objects and wrapper objects. 50 /// </summary> 51 /// <remarks> 52 /// <para> 53 /// This class maintains a mapping between <see cref="ILogger"/> objects and 54 /// <see cref="ILoggerWrapper"/> objects. Use the <see cref="GetWrapper"/> method to 55 /// lookup the <see cref="ILoggerWrapper"/> for the specified <see cref="ILogger"/>. 56 /// </para> 57 /// <para> 58 /// New wrapper instances are created by the <see cref="CreateNewWrapperObject"/> 59 /// method. The default behavior is for this method to delegate construction 60 /// of the wrapper to the <see cref="WrapperCreationHandler"/> delegate supplied 61 /// to the constructor. This allows specialization of the behavior without 62 /// requiring subclassing of this type. 63 /// </para> 64 /// </remarks> 65 /// <author>Nicko Cadell</author> 66 /// <author>Gert Driesen</author> 67 public class WrapperMap 68 { 69 #region Public Instance Constructors 70 71 /// <summary> 72 /// Initializes a new instance of the <see cref="WrapperMap" /> 73 /// </summary> 74 /// <param name="createWrapperHandler">The handler to use to create the wrapper objects.</param> 75 /// <remarks> 76 /// <para> 77 /// Initializes a new instance of the <see cref="WrapperMap" /> class with 78 /// the specified handler to create the wrapper objects. 79 /// </para> 80 /// </remarks> 81 public WrapperMap(WrapperCreationHandler createWrapperHandler) 82 { 83 m_createWrapperHandler = createWrapperHandler; 84 85 // Create the delegates for the event callbacks 86 m_shutdownHandler = new LoggerRepositoryShutdownEventHandler(ILoggerRepository_Shutdown); 87 } 88 89 #endregion Public Instance Constructors 90 91 #region Public Instance Properties 92 93 /// <summary> 94 /// Gets the wrapper object for the specified logger. 95 /// </summary> 96 /// <returns>The wrapper object for the specified logger</returns> 97 /// <remarks> 98 /// <para> 99 /// If the logger is null then the corresponding wrapper is null. 100 /// </para> 101 /// <para> 102 /// Looks up the wrapper it it has previously been requested and 103 /// returns it. If the wrapper has never been requested before then 104 /// the <see cref="CreateNewWrapperObject"/> virtual method is 105 /// called. 106 /// </para> 107 /// </remarks> 108 virtual public ILoggerWrapper GetWrapper(ILogger logger) 109 { 110 // If the logger is null then the corresponding wrapper is null 111 if (logger == null) 112 { 113 return null; 114 } 115 116 lock(this) 117 { 118 // Lookup hierarchy in map. 119 Hashtable wrappersMap = (Hashtable)m_repositories[logger.Repository]; 120 121 if (wrappersMap == null) 122 { 123 // Hierarchy does not exist in map. 124 // Must register with hierarchy 125 126 wrappersMap = new Hashtable(); 127 m_repositories[logger.Repository] = wrappersMap; 128 129 // Register for config reset & shutdown on repository 130 logger.Repository.ShutdownEvent += m_shutdownHandler; 131 } 132 133 // Look for the wrapper object in the map 134 ILoggerWrapper wrapperObject = wrappersMap[logger] as ILoggerWrapper; 135 136 if (wrapperObject == null) 137 { 138 // No wrapper object exists for the specified logger 139 140 // Create a new wrapper wrapping the logger 141 wrapperObject = CreateNewWrapperObject(logger); 142 143 // Store wrapper logger in map 144 wrappersMap[logger] = wrapperObject; 145 } 146 147 return wrapperObject; 148 } 149 } 150 151 #endregion Public Instance Properties 152 153 #region Protected Instance Properties 154 155 /// <summary> 156 /// Gets the map of logger repositories. 157 /// </summary> 158 /// <value> 159 /// Map of logger repositories. 160 /// </value> 161 /// <remarks> 162 /// <para> 163 /// Gets the hashtable that is keyed on <see cref="ILoggerRepository"/>. The 164 /// values are hashtables keyed on <see cref="ILogger"/> with the 165 /// value being the corresponding <see cref="ILoggerWrapper"/>. 166 /// </para> 167 /// </remarks> 168 protected Hashtable Repositories 169 { 170 get { return this.m_repositories; } 171 } 172 173 #endregion Protected Instance Properties 174 175 #region Protected Instance Methods 176 177 /// <summary> 178 /// Creates the wrapper object for the specified logger. 179 /// </summary> 180 /// <param name="logger">The logger to wrap in a wrapper.</param> 181 /// <returns>The wrapper object for the logger.</returns> 182 /// <remarks> 183 /// <para> 184 /// This implementation uses the <see cref="WrapperCreationHandler"/> 185 /// passed to the constructor to create the wrapper. This method 186 /// can be overridden in a subclass. 187 /// </para> 188 /// </remarks> 189 virtual protected ILoggerWrapper CreateNewWrapperObject(ILogger logger) 190 { 191 if (m_createWrapperHandler != null) 192 { 193 return m_createWrapperHandler(logger); 194 } 195 return null; 196 } 197 198 /// <summary> 199 /// Called when a monitored repository shutdown event is received. 200 /// </summary> 201 /// <param name="repository">The <see cref="ILoggerRepository"/> that is shutting down</param> 202 /// <remarks> 203 /// <para> 204 /// This method is called when a <see cref="ILoggerRepository"/> that this 205 /// <see cref="WrapperMap"/> is holding loggers for has signaled its shutdown 206 /// event <see cref="ILoggerRepository.ShutdownEvent"/>. The default 207 /// behavior of this method is to release the references to the loggers 208 /// and their wrappers generated for this repository. 209 /// </para> 210 /// </remarks> 211 virtual protected void RepositoryShutdown(ILoggerRepository repository) 212 { 213 lock(this) 214 { 215 // Remove the repository from map 216 m_repositories.Remove(repository); 217 218 // Unhook events from the repository 219 repository.ShutdownEvent -= m_shutdownHandler; 220 } 221 } 222 223 /// <summary> 224 /// Event handler for repository shutdown event. 225 /// </summary> 226 /// <param name="sender">The sender of the event.</param> 227 /// <param name="e">The event args.</param> 228 private void ILoggerRepository_Shutdown(object sender, EventArgs e) 229 { 230 ILoggerRepository repository = sender as ILoggerRepository; 231 if (repository != null) 232 { 233 // Remove all repository from map 234 RepositoryShutdown(repository); 235 } 236 } 237 238 #endregion Protected Instance Methods 239 240 #region Private Instance Variables 241 242 /// <summary> 243 /// Map of logger repositories to hashtables of ILogger to ILoggerWrapper mappings 244 /// </summary> 245 private readonly Hashtable m_repositories = new Hashtable(); 246 247 /// <summary> 248 /// The handler to use to create the extension wrapper objects. 249 /// </summary> 250 private readonly WrapperCreationHandler m_createWrapperHandler; 251 252 /// <summary> 253 /// Internal reference to the delegate used to register for repository shutdown events. 254 /// </summary> 255 private readonly LoggerRepositoryShutdownEventHandler m_shutdownHandler; 256 257 #endregion Private Instance Variables 258 } 259}