1 // Copyright 2004-2008 Castle Project - http://www.castleproject.org/
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
7 // http://www.apache.org/licenses/LICENSE-2.0
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
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
;
26 /// The supported <see cref="ILogger"/> implementations
28 public enum LoggerImplementation
43 /// A facility for logging support.
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
;
73 private LoggerImplementation
? loggingApiConfig
= null;
74 private string customLoggerFactoryConfig
= null;
75 private string configFileConfig
= null;
78 /// Initializes a new instance of the <see cref="LoggingFacility"/> class.
80 public LoggingFacility()
85 /// Initializes a new instance of the <see cref="LoggingFacility"/> class.
87 /// <param name="loggingApi">
88 /// The LoggerImplementation that should be used
90 public LoggingFacility(LoggerImplementation loggingApi
) : this(loggingApi
, null)
96 /// Initializes a new instance of the <see cref="LoggingFacility"/> class.
98 /// <param name="loggingApi">
99 /// The LoggerImplementation that should be used
101 /// <param name="configFile">
102 /// The configuration file that should be used by the chosen LoggerImplementation
104 public LoggingFacility(LoggerImplementation loggingApi
, string configFile
) : this(loggingApi
, null, configFile
)
110 /// Initializes a new instance of the <see cref="LoggingFacility"/> class using a custom LoggerImplementation
112 /// <param name="configFile">
113 /// The configuration file that should be used by the chosen LoggerImplementation
115 /// <param name="customLoggerFactory">
116 /// The type name of the type of the custom logger factory.
118 public LoggingFacility(string customLoggerFactory
, string configFile
) : this(LoggerImplementation
.Custom
, customLoggerFactory
, configFile
)
124 /// Initializes a new instance of the <see cref="LoggingFacility"/> class.
126 /// <param name="loggingApi">
127 /// The LoggerImplementation that should be used
129 /// <param name="configFile">
130 /// The configuration file that should be used by the chosen LoggerImplementation
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)
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
);
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
);
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;
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
);
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);
254 args
= new object[] { configFile }
;
258 ctor
= loggerFactoryType
.GetConstructor(flags
, null, Type
.EmptyTypes
, null);
262 throw new FacilityException("No support constructor found for logging type " + logApi
);
268 private Type
GetLoggingFactoryType(string customType
)
270 Type loggerFactoryType
;
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.");
293 case LoggerImplementation
.Null
:
294 loggerFactoryType
= typeof(NullLogFactory
);
296 case LoggerImplementation
.Console
:
297 loggerFactoryType
= typeof(ConsoleFactory
);
299 case LoggerImplementation
.Diagnostics
:
300 loggerFactoryType
= typeof(DiagnosticsLoggerFactory
);
302 case LoggerImplementation
.Trace
:
303 loggerFactoryType
= typeof (TraceLoggerFactory
);
305 case LoggerImplementation
.Web
:
306 loggerFactoryType
= typeof(WebLoggerFactory
);
308 case LoggerImplementation
.Log4net
:
309 loggerFactoryType
= (Type
)converter
.PerformConversion(Log4NetLoggerFactoryTypeName
, typeof(Type
));
311 case LoggerImplementation
.NLog
:
312 loggerFactoryType
= (Type
)converter
.PerformConversion(NLogLoggerFactoryTypeName
, typeof(Type
));
314 case LoggerImplementation
.ExtendedLog4net
:
315 loggerFactoryType
= (Type
)converter
.PerformConversion(ExtendedLog4NetLoggerFactoryTypeName
, typeof(Type
));
317 case LoggerImplementation
.ExtendedNLog
:
318 loggerFactoryType
= (Type
)converter
.PerformConversion(ExtendedNLogLoggerFactoryTypeName
, typeof(Type
));
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
;