TAppenderUnit.pas 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. {
  2. Copyright 2005-2006 Log4Delphi Project
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. }
  13. {*----------------------------------------------------------------------------
  14. Contains the TAppender class.
  15. @version 0.5
  16. @author <a href="mailto:tcmiller@users.sourceforge.net">Trevor Miller</a>
  17. ----------------------------------------------------------------------------}
  18. unit TAppenderUnit;
  19. {$ifdef fpc}
  20. {$mode objfpc}
  21. {$h+}
  22. {$endif}
  23. interface
  24. uses
  25. Classes, TLevelUnit, TLayoutUnit, TLoggingEventUnit, TErrorHandlerUnit;
  26. type
  27. IAppender = interface
  28. procedure DoAppend(AEvent : TLoggingEvent);
  29. function GetName() : String;
  30. function GetLayout() : TLayout;
  31. procedure SetName(AName : String);
  32. procedure SetLayout(ALayout : TLayout);
  33. function RequiresLayout() : Boolean;
  34. end;
  35. {*----------------------------------------------------------------------------
  36. Implement this abstract class with specific strategies for outputting
  37. log statements.
  38. ----------------------------------------------------------------------------}
  39. TAppender = class (TInterfacedObject, IAppender)
  40. private
  41. protected
  42. FLayout : TLayout;
  43. FThreshold : TLevel;
  44. FErrorHandler : TErrorHandler;
  45. FName : String;
  46. FClosed : boolean;
  47. public
  48. constructor Create;
  49. destructor Destroy; Override;
  50. procedure Append(AEvent : TLoggingEvent); Virtual; Abstract;
  51. procedure DoAppend(AEvent : TLoggingEvent);
  52. procedure SetLayout(ALayout : TLayout); Virtual;
  53. procedure SetName(AName : String);
  54. procedure SetThreshold(AThreshold : TLevel);
  55. procedure SetErrorHandler(AHandler : TErrorHandler);
  56. function GetLayout() : TLayout;
  57. function GetName() : String;
  58. function GetThreshold() : TLevel;
  59. function GetErrorHandler() : TErrorHandler;
  60. function IsAsSevereAsThreshold(ALevel : Tlevel) : Boolean;
  61. function RequiresLayout() : Boolean; Virtual;
  62. end;
  63. TAppendersCollection = class
  64. private
  65. FItems: TInterfaceList;
  66. function GetCount: Integer;
  67. function Get(Index: Integer): IAppender;
  68. procedure Put(Index: Integer; const Value: IAppender);
  69. function IndexOf(const AName : String): Integer;
  70. public
  71. constructor Create;
  72. destructor Destroy; override;
  73. property Count: Integer read GetCount;
  74. procedure Add(AAppender : IAppender);
  75. procedure Delete(const AName: String);
  76. procedure Clear;
  77. function FindByName(const AName : String): IAppender;
  78. property Items[Index: Integer]: IAppender read Get write Put; default;
  79. end;
  80. implementation
  81. uses
  82. SysUtils,
  83. TLogLogUnit;
  84. {*----------------------------------------------------------------------------
  85. Create an instance.
  86. ----------------------------------------------------------------------------}
  87. constructor TAppender.Create;
  88. begin
  89. inherited Create;
  90. Self.FName := Self.ClassName;
  91. TLogLog.debug('TAppender#Create');
  92. end;
  93. {*----------------------------------------------------------------------------
  94. Destruct this instance by freeing the layout and error handler.
  95. ----------------------------------------------------------------------------}
  96. destructor TAppender.Destroy;
  97. begin
  98. Self.FLayout.Free;
  99. Self.FErrorHandler.Free;
  100. TLogLog.debug('TAppender#Destroy: Appender destroyed - name=' + Self.FName);
  101. inherited Destroy;
  102. end;
  103. {*----------------------------------------------------------------------------
  104. Log in Appender specific way. When appropriate, Loggers will call the
  105. append method of appender implementations in order to log.
  106. @param AEvent The logging event to log
  107. ----------------------------------------------------------------------------}
  108. procedure TAppender.DoAppend(AEvent : TLoggingEvent);
  109. begin
  110. if ((NOT Self.FClosed)
  111. AND (Self.IsAsSevereAsThreshold(AEvent.GetLevel))) then
  112. Self.Append(AEvent);
  113. end;
  114. {*----------------------------------------------------------------------------
  115. Set the Layout for this appender to use.
  116. @param ALayout The layout this appender uses
  117. ----------------------------------------------------------------------------}
  118. procedure TAppender.SetLayout(ALayout : TLayout);
  119. begin
  120. Self.FLayout := ALayout;
  121. TLogLog.debug('TAppender#SetLayout: ' + ALayout.ClassName);
  122. end;
  123. {*----------------------------------------------------------------------------
  124. Set the name of this appender. The name is used by other components to
  125. identify this appender.
  126. @param AName The name of this appender
  127. ----------------------------------------------------------------------------}
  128. procedure TAppender.SetName(AName : String);
  129. begin
  130. Self.FName := AName;
  131. TLogLog.debug('TAppender#SetName: ' + AName);
  132. end;
  133. {*----------------------------------------------------------------------------
  134. Set the threshold level for this appender to use.
  135. @param AThreshold The threshold level this appender uses
  136. ----------------------------------------------------------------------------}
  137. procedure TAppender.SetThreshold(AThreshold : TLevel);
  138. begin
  139. Self.FThreshold := AThreshold;
  140. TLogLog.debug('TAppender#SetThreshold: ' + AThreshold.ToString);
  141. end;
  142. {*----------------------------------------------------------------------------
  143. Set the ErrorHandler for this appender to use.
  144. @param AHandler The error handler for this appender
  145. ----------------------------------------------------------------------------}
  146. procedure TAppender.SetErrorHandler(AHandler : TErrorHandler);
  147. begin
  148. Self.FErrorHandler := AHandler;
  149. TLogLog.debug('TAppender#SetErrorHandler: ' + AHandler.ClassName);
  150. end;
  151. {*----------------------------------------------------------------------------
  152. Returns this appenders layout.
  153. @return The layout of this appender
  154. ----------------------------------------------------------------------------}
  155. function TAppender.GetLayout() : TLayout;
  156. begin
  157. Result := Self.FLayout;
  158. end;
  159. {*----------------------------------------------------------------------------
  160. Get the name of this appender. The name uniquely identifies the appender.
  161. @return The name of this appender
  162. ----------------------------------------------------------------------------}
  163. function TAppender.GetName() : String;
  164. begin
  165. Result := Self.FName;
  166. end;
  167. {*----------------------------------------------------------------------------
  168. Returns this appender's threshold level.
  169. @return The threshold level of this appender
  170. ----------------------------------------------------------------------------}
  171. function TAppender.getThreshold() : TLevel;
  172. begin
  173. Result := Self.FThreshold;
  174. end;
  175. {*----------------------------------------------------------------------------
  176. Return the currently set ErrorHandler for this appender.
  177. @return The error handler of this appender
  178. ----------------------------------------------------------------------------}
  179. function TAppender.getErrorHandler() : TErrorHandler;
  180. begin
  181. Result := Self.FErrorHandler;
  182. end;
  183. {*----------------------------------------------------------------------------
  184. Check whether the message level is below the appender's threshold. If
  185. there is no threshold set, then the return value is always true.
  186. @param ALevel The level to check against
  187. @return True if this appenders level is greater than or equal to the
  188. given level, false otherwise
  189. ----------------------------------------------------------------------------}
  190. function TAppender.IsAsSevereAsThreshold(ALevel : Tlevel) : Boolean;
  191. begin
  192. Result := ((Self.FThreshold = Nil)
  193. OR (ALevel.IsGreaterOrEqual(Self.FThreshold)));
  194. end;
  195. {*----------------------------------------------------------------------------
  196. Determine if the appender requires a layout or not. The default value is
  197. false, appenders that require a layout will override this method.
  198. @return True if this appender requires a layout, flase otherwise
  199. ----------------------------------------------------------------------------}
  200. function TAppender.RequiresLayout() : Boolean;
  201. begin
  202. Result := false;
  203. end;
  204. { TAppendersCollection }
  205. procedure TAppendersCollection.Add(AAppender: IAppender);
  206. begin
  207. if FItems.IndexOf(AAppender) >= 0 then
  208. Exit;
  209. FItems.Add(AAppender);
  210. end;
  211. procedure TAppendersCollection.Clear;
  212. begin
  213. FItems.Clear;
  214. end;
  215. constructor TAppendersCollection.Create;
  216. begin
  217. FItems := TInterfaceList.Create;
  218. end;
  219. procedure TAppendersCollection.Delete(const AName: String);
  220. var
  221. index : Integer;
  222. begin
  223. index := IndexOf(AName);
  224. if (index >= 0) then begin
  225. FItems.Delete(index);
  226. end;
  227. end;
  228. destructor TAppendersCollection.Destroy;
  229. begin
  230. FItems.Free;
  231. inherited;
  232. end;
  233. function TAppendersCollection.FindByName(const AName: String): IAppender;
  234. var
  235. index : Integer;
  236. begin
  237. index := IndexOf(AName);
  238. if index = -1 then
  239. begin
  240. Result := nil;
  241. Exit;
  242. end;
  243. Result := IAppender(FItems[index]);
  244. end;
  245. function TAppendersCollection.Get(Index: Integer): IAppender;
  246. begin
  247. Result := IAppender(FItems[Index]);
  248. end;
  249. function TAppendersCollection.GetCount: Integer;
  250. begin
  251. Result := FItems.Count;
  252. end;
  253. function TAppendersCollection.IndexOf(const AName : String): Integer;
  254. var
  255. i: Integer;
  256. begin
  257. for i := 0 to FItems.Count - 1 do
  258. begin
  259. if not SameText(IAppender(FItems[i]).GetName, AName) then
  260. continue;
  261. Result := i;
  262. Exit;
  263. end;
  264. Result := -1;
  265. end;
  266. procedure TAppendersCollection.Put(Index: Integer;
  267. const Value: IAppender);
  268. begin
  269. FItems[Index] := Value;
  270. end;
  271. end.