Added the ability to change the invocation target in the DefaultProxyFactory.
[castle.git] / Facilities / Logging / Castle.Facilities.Logging / LoggingFacility.cs
blobc225e241271dcacd8fc6c569c6dc7d8eae2687bb
1 // Copyright 2004-2008 Castle Project - http://www.castleproject.org/
2 //
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 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 namespace Castle.Facilities.Logging
17 using System;
18 using System.Configuration;
19 using System.Reflection;
20 using Castle.Core.Logging;
21 using Castle.MicroKernel;
22 using Castle.MicroKernel.Facilities;
23 using Castle.MicroKernel.SubSystems.Conversion;
25 /// <summary>
26 /// The supported <see cref="ILogger"/> implementations
27 /// </summary>
28 public enum LoggerImplementation
30 Custom,
31 Null,
32 Console,
33 Diagnostics,
34 Web,
35 NLog,
36 Log4net,
37 ExtendedNLog,
38 ExtendedLog4net,
39 Trace
42 /// <summary>
43 /// A facility for logging support.
44 /// </summary>
45 /// <remarks>TODO: Document its inner working and configuration scheme</remarks>
46 public class LoggingFacility : AbstractFacility
48 private static readonly String Log4NetLoggerFactoryTypeName =
49 "Castle.Services.Logging.Log4netIntegration.Log4netFactory," +
50 "Castle.Services.Logging.Log4netIntegration,Version=1.0.3.0, Culture=neutral," +
51 "PublicKeyToken=407dd0808d44fbdc";
53 private static readonly String NLogLoggerFactoryTypeName =
54 "Castle.Services.Logging.NLogIntegration.NLogFactory," +
55 "Castle.Services.Logging.NLogIntegration,Version=1.0.3.0, Culture=neutral," +
56 "PublicKeyToken=407dd0808d44fbdc";
58 private static readonly String ExtendedLog4NetLoggerFactoryTypeName =
59 "Castle.Services.Logging.Log4netIntegration.ExtendedLog4netFactory," +
60 "Castle.Services.Logging.Log4netIntegration,Version=1.0.3.0, Culture=neutral," +
61 "PublicKeyToken=407dd0808d44fbdc";
63 private static readonly String ExtendedNLogLoggerFactoryTypeName =
64 "Castle.Services.Logging.NLogIntegration.ExtendedNLogFactory," +
65 "Castle.Services.Logging.NLogIntegration,Version=1.0.3.0, Culture=neutral," +
66 "PublicKeyToken=407dd0808d44fbdc";
68 private ITypeConverter converter;
69 private ILoggerFactory factory;
70 private LoggerImplementation logApi;
72 //Configuration
73 private LoggerImplementation? loggingApiConfig = null;
74 private string customLoggerFactoryConfig = null;
75 private string configFileConfig = null;
77 /// <summary>
78 /// Initializes a new instance of the <see cref="LoggingFacility"/> class.
79 /// </summary>
80 public LoggingFacility()
84 /// <summary>
85 /// Initializes a new instance of the <see cref="LoggingFacility"/> class.
86 /// </summary>
87 /// <param name="loggingApi">
88 /// The LoggerImplementation that should be used
89 /// </param>
90 public LoggingFacility(LoggerImplementation loggingApi) : this(loggingApi, null)
95 /// <summary>
96 /// Initializes a new instance of the <see cref="LoggingFacility"/> class.
97 /// </summary>
98 /// <param name="loggingApi">
99 /// The LoggerImplementation that should be used
100 /// </param>
101 /// <param name="configFile">
102 /// The configuration file that should be used by the chosen LoggerImplementation
103 /// </param>
104 public LoggingFacility(LoggerImplementation loggingApi, string configFile) : this(loggingApi, null, configFile)
109 /// <summary>
110 /// Initializes a new instance of the <see cref="LoggingFacility"/> class using a custom LoggerImplementation
111 /// </summary>
112 /// <param name="configFile">
113 /// The configuration file that should be used by the chosen LoggerImplementation
114 /// </param>
115 /// <param name="customLoggerFactory">
116 /// The type name of the type of the custom logger factory.
117 /// </param>
118 public LoggingFacility(string customLoggerFactory, string configFile) : this(LoggerImplementation.Custom, customLoggerFactory, configFile)
123 /// <summary>
124 /// Initializes a new instance of the <see cref="LoggingFacility"/> class.
125 /// </summary>
126 /// <param name="loggingApi">
127 /// The LoggerImplementation that should be used
128 /// </param>
129 /// <param name="configFile">
130 /// The configuration file that should be used by the chosen LoggerImplementation
131 /// </param>
132 /// <param name="customLoggerFactory">
133 /// The type name of the type of the custom logger factory. (only used when loggingApi is set to LoggerImplementation.Custom)
134 /// </param>
135 public LoggingFacility(LoggerImplementation loggingApi, string customLoggerFactory, string configFile)
137 this.loggingApiConfig = loggingApi;
138 this.customLoggerFactoryConfig = customLoggerFactory;
139 this.configFileConfig = configFile;
142 protected override void Init()
144 SetUpTypeConverter();
146 ReadConfigurationAndCreateLoggerFactory();
148 RegisterDefaultILogger();
150 RegisterSubResolver();
153 private void RegisterDefaultILogger()
155 if (logApi == LoggerImplementation.ExtendedNLog || logApi == LoggerImplementation.ExtendedLog4net)
157 ILogger defaultLogger = factory.Create("Default");
158 Kernel.AddComponentInstance("ilogger.default", typeof(IExtendedLogger), defaultLogger);
159 Kernel.AddComponentInstance("ilogger.default.base", typeof(ILogger), defaultLogger);
161 else
163 Kernel.AddComponentInstance("ilogger.default", typeof(ILogger), factory.Create("Default"));
167 private void RegisterLoggerFactory()
169 if (logApi == LoggerImplementation.ExtendedNLog || logApi == LoggerImplementation.ExtendedLog4net)
171 Kernel.AddComponentInstance("iloggerfactory", typeof(IExtendedLoggerFactory), factory);
172 Kernel.AddComponentInstance("iloggerfactory.base", typeof(ILoggerFactory), factory);
174 else
176 Kernel.AddComponentInstance("iloggerfactory", typeof(ILoggerFactory), factory);
180 private void RegisterSubResolver()
182 Kernel.Resolver.AddSubResolver(new LoggerResolver(factory));
185 private void ReadConfigurationAndCreateLoggerFactory()
187 logApi = LoggerImplementation.Console;
190 String typeAtt = (FacilityConfig != null) ? FacilityConfig.Attributes["loggingApi"] : null;
191 String customAtt = (FacilityConfig != null) ? FacilityConfig.Attributes["customLoggerFactory"] : null;
192 String configFileAtt = (FacilityConfig != null) ? FacilityConfig.Attributes["configFile"] : null;
194 if (typeAtt != null)
196 logApi = (LoggerImplementation)
197 converter.PerformConversion(typeAtt, typeof(LoggerImplementation));
199 else if (loggingApiConfig.HasValue)
201 logApi = loggingApiConfig.Value;
204 if (customAtt == null)
206 customAtt = customLoggerFactoryConfig;
209 if (configFileAtt == null)
211 configFileAtt = configFileConfig;
214 CreateProperLoggerFactory(customAtt, configFileAtt);
216 RegisterLoggerFactory();
219 private void CreateProperLoggerFactory(string customType, string configFile)
221 Type loggerFactoryType = GetLoggingFactoryType(customType);
223 if (loggerFactoryType == null)
225 throw new FacilityException("LoggingFacility was unable to find an implementation of ILoggerFactory or IExtendedLoggerFactory.");
228 object[] args = GetLoggingFactoryArguments(configFile, loggerFactoryType);
230 if (logApi == LoggerImplementation.ExtendedNLog || logApi == LoggerImplementation.ExtendedLog4net)
232 factory = (IExtendedLoggerFactory) Activator.CreateInstance(loggerFactoryType, args);
234 else
236 factory = (ILoggerFactory) Activator.CreateInstance(loggerFactoryType, args);
240 private object[] GetLoggingFactoryArguments(string configFile, Type loggerFactoryType)
242 const BindingFlags flags = BindingFlags.Instance | BindingFlags.Public;
244 object[] args = null;
245 ConstructorInfo ctor = null;
247 if (configFile != null && configFile.Length > 0)
249 ctor = loggerFactoryType.GetConstructor(flags, null, new Type[] { typeof(string) }, null);
252 if (ctor != null)
254 args = new object[] { configFile };
256 else
258 ctor = loggerFactoryType.GetConstructor(flags, null, Type.EmptyTypes, null);
260 if (ctor == null)
262 throw new FacilityException("No support constructor found for logging type " + logApi);
265 return args;
268 private Type GetLoggingFactoryType(string customType)
270 Type loggerFactoryType;
272 switch(logApi)
274 case LoggerImplementation.Custom:
275 if (customType == null)
277 String message = "If you specify loggingApi='custom' " +
278 "then you must use the attribute customLoggerFactory to inform the " +
279 "type name of the custom logger factory";
281 throw new ConfigurationErrorsException(message);
284 loggerFactoryType = (Type)
285 converter.PerformConversion(customType, typeof(Type));
287 if (!typeof(ILoggerFactory).IsAssignableFrom(loggerFactoryType) && !typeof(IExtendedLoggerFactory).IsAssignableFrom(loggerFactoryType))
289 throw new FacilityException("The specified type '" + customType +
290 "' does not implement either ILoggerFactory or IExtendedLoggerFactory.");
292 break;
293 case LoggerImplementation.Null:
294 loggerFactoryType = typeof(NullLogFactory);
295 break;
296 case LoggerImplementation.Console:
297 loggerFactoryType = typeof(ConsoleFactory);
298 break;
299 case LoggerImplementation.Diagnostics:
300 loggerFactoryType = typeof(DiagnosticsLoggerFactory);
301 break;
302 case LoggerImplementation.Trace:
303 loggerFactoryType = typeof (TraceLoggerFactory);
304 break;
305 case LoggerImplementation.Web:
306 loggerFactoryType = typeof(WebLoggerFactory);
307 break;
308 case LoggerImplementation.Log4net:
309 loggerFactoryType = (Type)converter.PerformConversion(Log4NetLoggerFactoryTypeName, typeof(Type));
310 break;
311 case LoggerImplementation.NLog:
312 loggerFactoryType = (Type)converter.PerformConversion(NLogLoggerFactoryTypeName, typeof(Type));
313 break;
314 case LoggerImplementation.ExtendedLog4net:
315 loggerFactoryType = (Type)converter.PerformConversion(ExtendedLog4NetLoggerFactoryTypeName, typeof(Type));
316 break;
317 case LoggerImplementation.ExtendedNLog:
318 loggerFactoryType = (Type)converter.PerformConversion(ExtendedNLogLoggerFactoryTypeName, typeof(Type));
319 break;
320 default:
322 String message = "An invalid loggingApi was specified: " + logApi;
324 throw new ConfigurationErrorsException(message);
327 return loggerFactoryType;
330 private void SetUpTypeConverter()
332 converter = Kernel.GetSubSystem(
333 SubSystemConstants.ConversionManagerKey) as IConversionManager;