WrapperMap.cs 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  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. using System;
  20. using System.Collections;
  21. using log4net.Repository;
  22. namespace log4net.Core
  23. {
  24. #region WrapperCreationHandler
  25. /// <summary>
  26. /// Delegate used to handle creation of new wrappers.
  27. /// </summary>
  28. /// <param name="logger">The logger to wrap in a wrapper.</param>
  29. /// <remarks>
  30. /// <para>
  31. /// Delegate used to handle creation of new wrappers. This delegate
  32. /// is called from the <see cref="WrapperMap.CreateNewWrapperObject"/>
  33. /// method to construct the wrapper for the specified logger.
  34. /// </para>
  35. /// <para>
  36. /// The delegate to use is supplied to the <see cref="WrapperMap"/>
  37. /// constructor.
  38. /// </para>
  39. /// </remarks>
  40. public delegate ILoggerWrapper WrapperCreationHandler(ILogger logger);
  41. #endregion WrapperCreationHandler
  42. /// <summary>
  43. /// Maps between logger objects and wrapper objects.
  44. /// </summary>
  45. /// <remarks>
  46. /// <para>
  47. /// This class maintains a mapping between <see cref="ILogger"/> objects and
  48. /// <see cref="ILoggerWrapper"/> objects. Use the <see cref="GetWrapper"/> method to
  49. /// lookup the <see cref="ILoggerWrapper"/> for the specified <see cref="ILogger"/>.
  50. /// </para>
  51. /// <para>
  52. /// New wrapper instances are created by the <see cref="CreateNewWrapperObject"/>
  53. /// method. The default behavior is for this method to delegate construction
  54. /// of the wrapper to the <see cref="WrapperCreationHandler"/> delegate supplied
  55. /// to the constructor. This allows specialization of the behavior without
  56. /// requiring subclassing of this type.
  57. /// </para>
  58. /// </remarks>
  59. /// <author>Nicko Cadell</author>
  60. /// <author>Gert Driesen</author>
  61. public class WrapperMap
  62. {
  63. #region Public Instance Constructors
  64. /// <summary>
  65. /// Initializes a new instance of the <see cref="WrapperMap" />
  66. /// </summary>
  67. /// <param name="createWrapperHandler">The handler to use to create the wrapper objects.</param>
  68. /// <remarks>
  69. /// <para>
  70. /// Initializes a new instance of the <see cref="WrapperMap" /> class with
  71. /// the specified handler to create the wrapper objects.
  72. /// </para>
  73. /// </remarks>
  74. public WrapperMap(WrapperCreationHandler createWrapperHandler)
  75. {
  76. m_createWrapperHandler = createWrapperHandler;
  77. // Create the delegates for the event callbacks
  78. m_shutdownHandler = new LoggerRepositoryShutdownEventHandler(ILoggerRepository_Shutdown);
  79. }
  80. #endregion Public Instance Constructors
  81. #region Public Instance Properties
  82. /// <summary>
  83. /// Gets the wrapper object for the specified logger.
  84. /// </summary>
  85. /// <returns>The wrapper object for the specified logger</returns>
  86. /// <remarks>
  87. /// <para>
  88. /// If the logger is null then the corresponding wrapper is null.
  89. /// </para>
  90. /// <para>
  91. /// Looks up the wrapper it it has previously been requested and
  92. /// returns it. If the wrapper has never been requested before then
  93. /// the <see cref="CreateNewWrapperObject"/> virtual method is
  94. /// called.
  95. /// </para>
  96. /// </remarks>
  97. virtual public ILoggerWrapper GetWrapper(ILogger logger)
  98. {
  99. // If the logger is null then the corresponding wrapper is null
  100. if (logger == null)
  101. {
  102. return null;
  103. }
  104. lock(this)
  105. {
  106. // Lookup hierarchy in map.
  107. Hashtable wrappersMap = (Hashtable)m_repositories[logger.Repository];
  108. if (wrappersMap == null)
  109. {
  110. // Hierarchy does not exist in map.
  111. // Must register with hierarchy
  112. wrappersMap = new Hashtable();
  113. m_repositories[logger.Repository] = wrappersMap;
  114. // Register for config reset & shutdown on repository
  115. logger.Repository.ShutdownEvent += m_shutdownHandler;
  116. }
  117. // Look for the wrapper object in the map
  118. ILoggerWrapper wrapperObject = wrappersMap[logger] as ILoggerWrapper;
  119. if (wrapperObject == null)
  120. {
  121. // No wrapper object exists for the specified logger
  122. // Create a new wrapper wrapping the logger
  123. wrapperObject = CreateNewWrapperObject(logger);
  124. // Store wrapper logger in map
  125. wrappersMap[logger] = wrapperObject;
  126. }
  127. return wrapperObject;
  128. }
  129. }
  130. #endregion Public Instance Properties
  131. #region Protected Instance Properties
  132. /// <summary>
  133. /// Gets the map of logger repositories.
  134. /// </summary>
  135. /// <value>
  136. /// Map of logger repositories.
  137. /// </value>
  138. /// <remarks>
  139. /// <para>
  140. /// Gets the hashtable that is keyed on <see cref="ILoggerRepository"/>. The
  141. /// values are hashtables keyed on <see cref="ILogger"/> with the
  142. /// value being the corresponding <see cref="ILoggerWrapper"/>.
  143. /// </para>
  144. /// </remarks>
  145. protected Hashtable Repositories
  146. {
  147. get { return this.m_repositories; }
  148. }
  149. #endregion Protected Instance Properties
  150. #region Protected Instance Methods
  151. /// <summary>
  152. /// Creates the wrapper object for the specified logger.
  153. /// </summary>
  154. /// <param name="logger">The logger to wrap in a wrapper.</param>
  155. /// <returns>The wrapper object for the logger.</returns>
  156. /// <remarks>
  157. /// <para>
  158. /// This implementation uses the <see cref="WrapperCreationHandler"/>
  159. /// passed to the constructor to create the wrapper. This method
  160. /// can be overridden in a subclass.
  161. /// </para>
  162. /// </remarks>
  163. virtual protected ILoggerWrapper CreateNewWrapperObject(ILogger logger)
  164. {
  165. if (m_createWrapperHandler != null)
  166. {
  167. return m_createWrapperHandler(logger);
  168. }
  169. return null;
  170. }
  171. /// <summary>
  172. /// Called when a monitored repository shutdown event is received.
  173. /// </summary>
  174. /// <param name="repository">The <see cref="ILoggerRepository"/> that is shutting down</param>
  175. /// <remarks>
  176. /// <para>
  177. /// This method is called when a <see cref="ILoggerRepository"/> that this
  178. /// <see cref="WrapperMap"/> is holding loggers for has signaled its shutdown
  179. /// event <see cref="ILoggerRepository.ShutdownEvent"/>. The default
  180. /// behavior of this method is to release the references to the loggers
  181. /// and their wrappers generated for this repository.
  182. /// </para>
  183. /// </remarks>
  184. virtual protected void RepositoryShutdown(ILoggerRepository repository)
  185. {
  186. lock(this)
  187. {
  188. // Remove the repository from map
  189. m_repositories.Remove(repository);
  190. // Unhook events from the repository
  191. repository.ShutdownEvent -= m_shutdownHandler;
  192. }
  193. }
  194. /// <summary>
  195. /// Event handler for repository shutdown event.
  196. /// </summary>
  197. /// <param name="sender">The sender of the event.</param>
  198. /// <param name="e">The event args.</param>
  199. private void ILoggerRepository_Shutdown(object sender, EventArgs e)
  200. {
  201. ILoggerRepository repository = sender as ILoggerRepository;
  202. if (repository != null)
  203. {
  204. // Remove all repository from map
  205. RepositoryShutdown(repository);
  206. }
  207. }
  208. #endregion Protected Instance Methods
  209. #region Private Instance Variables
  210. /// <summary>
  211. /// Map of logger repositories to hashtables of ILogger to ILoggerWrapper mappings
  212. /// </summary>
  213. private readonly Hashtable m_repositories = new Hashtable();
  214. /// <summary>
  215. /// The handler to use to create the extension wrapper objects.
  216. /// </summary>
  217. private readonly WrapperCreationHandler m_createWrapperHandler;
  218. /// <summary>
  219. /// Internal reference to the delegate used to register for repository shutdown events.
  220. /// </summary>
  221. private readonly LoggerRepositoryShutdownEventHandler m_shutdownHandler;
  222. #endregion Private Instance Variables
  223. }
  224. }