1 // Copyright 2004-2007 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
.MonoRail
.Framework
18 using System
.Collections
;
19 using System
.ComponentModel
;
20 using System
.Configuration
;
23 using Castle
.Components
.Validator
;
25 using Castle
.MonoRail
.Framework
.Configuration
;
26 using Castle
.MonoRail
.Framework
.Internal
;
27 using Castle
.MonoRail
.Framework
.Services
;
28 using Castle
.MonoRail
.Framework
.Services
.AjaxProxyGenerator
;
31 /// Parent Service container for the MonoRail framework
33 public class MonoRailServiceContainer
: AbstractServiceContainer
35 /// <summary></summary>
36 private static string mrExtension
= ".castle";
38 /// <summary>The only one Extension Manager</summary>
39 protected internal ExtensionManager extensionManager
;
41 /// <summary>Prevents GC from collecting the extensions</summary>
42 private IList extensions
= new ArrayList();
44 /// <summary>Keeps only one copy of the config</summary>
45 private MonoRailConfiguration config
;
49 /// Initializes a new instance of the <see cref="MonoRailServiceContainer"/> class.
51 public MonoRailServiceContainer()
56 /// Initializes a new instance of the <see cref="MonoRailServiceContainer"/> class.
58 /// <param name="config">The config.</param>
59 public MonoRailServiceContainer(MonoRailConfiguration config
) : this()
65 /// Allows registration without the configuration
67 public void RegisterBaseService(Type service
, object instance
)
69 InvokeServiceEnabled(instance
);
70 InvokeInitialize(instance
);
72 AddService(service
, instance
);
76 /// Initializes the container state and its services
80 DiscoverHttpHandlerExtensions();
84 MonoRailConfiguration config
= ObtainConfiguration();
86 InitExtensions(config
);
91 /// Checks whether the specified URL is to be handled by MonoRail
93 /// <param name="url">The URL.</param>
95 /// <see langword="true"/> if it is a MonoRail request; otherwise, <see langword="false"/>.
97 public bool IsMonoRailRequest(String url
)
99 String extension
= Path
.GetExtension(url
);
101 return string.Compare(mrExtension
, extension
, StringComparison
.InvariantCultureIgnoreCase
) == 0;
104 /// <summary></summary>
105 public static string MonoRailExtension
107 get { return mrExtension; }
110 private static void DiscoverHttpHandlerExtensions()
112 XmlDocument webConfig
= new XmlDocument();
113 webConfig
.Load(Path
.Combine(AppDomain
.CurrentDomain
.BaseDirectory
, "web.config"));
115 XmlNodeList addNodes
= webConfig
.DocumentElement
.SelectNodes(
116 "/configuration/system.web/httpHandlers/add");
118 if (addNodes
.Count
== 0)
120 // Possibly the web.config configuration node is using a namespace declaration
122 XmlElement systemWebElem
= webConfig
.DocumentElement
["system.web"];
123 XmlElement handlers
= systemWebElem
["httpHandlers"];
124 addNodes
= handlers
.ChildNodes
;
129 foreach(XmlNode addNode
in addNodes
)
131 if (addNode
.NodeType
!= XmlNodeType
.Element
)
136 XmlElement addElem
= (XmlElement
) addNode
;
138 String type
= addElem
.GetAttribute("type");
140 if (type
.StartsWith("Castle.MonoRail.Framework.MonoRailHttpHandlerFactory"))
142 mrExtension
= addElem
.GetAttribute("path").Substring(1);
149 throw new MonoRailException("We inspected the web.config httpHandlers section and " +
150 "couldn't find an extension that mapped to MonoRailHttpHandlerFactory. " +
151 "Is your configuration right to use MonoRail?");
156 /// Reads the configuration and initializes
157 /// registered extensions.
159 /// <param name="config">The configuration object</param>
160 private void InitExtensions(MonoRailConfiguration config
)
162 extensionManager
= new ExtensionManager(this);
164 foreach(ExtensionEntry entry
in config
.ExtensionEntries
)
166 AssertImplementsService(typeof(IMonoRailExtension
), entry
.ExtensionType
);
168 IMonoRailExtension extension
= (IMonoRailExtension
) ActivateService(entry
.ExtensionType
);
170 extension
.SetExtensionConfigNode(entry
.ExtensionNode
);
172 extensions
.Add(extension
);
177 /// Coordinates the instantiation, registering and initialization (lifecycle-wise)
178 /// of the services used by MonoRail.
180 /// <param name="config">The configuration object</param>
181 private void InitServices(MonoRailConfiguration config
)
183 AddService(typeof(ExtensionManager
), extensionManager
);
184 AddService(typeof(MonoRailConfiguration
), config
);
186 IList services
= InstantiateAndRegisterServices(config
.ServiceEntries
);
188 LifecycleService(services
);
189 LifecycleService(extensions
);
191 LifecycleInitialize(services
);
192 LifecycleInitialize(extensions
);
196 /// Checks for services that implements <see cref="IInitializable"/>
197 /// or <see cref="ISupportInitialize"/> and initialize them through the interface
199 /// <param name="services">List of MonoRail's services</param>
200 private void LifecycleInitialize(IList services
)
202 foreach(object instance
in services
)
204 InvokeInitialize(instance
);
209 /// Checks for services that implements <see cref="IServiceEnabledComponent"/>
210 /// and invoke <see cref="IServiceEnabledComponent.Service"/> on them
212 /// <param name="services">List of MonoRail's services</param>
213 private void LifecycleService(IList services
)
215 foreach(object instance
in services
)
217 InvokeServiceEnabled(instance
);
222 /// Instantiates and registers the services used by MonoRail.
224 /// <param name="services">The service's registry</param>
225 /// <returns>List of service's instances</returns>
226 private IList
InstantiateAndRegisterServices(ServiceEntryCollection services
)
228 IList instances
= new ArrayList();
232 foreach(DictionaryEntry entry
in services
.ServiceImplMap
)
234 Type service
= (Type
) entry
.Key
;
235 Type impl
= (Type
) entry
.Value
;
237 AssertImplementsService(service
, impl
);
239 object instance
= ActivateService(impl
);
241 AddService(service
, instance
);
243 instances
.Add(instance
);
248 foreach(Type type
in services
.CustomServices
)
250 object instance
= ActivateService(type
);
252 AddService(type
, instance
);
254 instances
.Add(instance
);
261 /// Registers the default implementation of services, if
262 /// they are not registered
264 private void InitConfiguration()
266 config
= ObtainConfiguration();
268 RegisterMissingServices(config
);
272 /// Checks whether non-optional services were supplied
273 /// through the configuration, and if not, register the
274 /// default implementation.
276 /// <param name="config">The configuration object</param>
277 private static void RegisterMissingServices(MonoRailConfiguration config
)
279 ServiceEntryCollection services
= config
.ServiceEntries
;
281 services
.RegisterService(ServiceIdentification
.ViewEngineManager
,
282 typeof(DefaultViewEngineManager
));
285 if (!services
.HasService(ServiceIdentification
.ViewSourceLoader
))
287 services
.RegisterService(ServiceIdentification
.ViewSourceLoader
,
288 typeof(FileAssemblyViewSourceLoader
));
290 if (!services
.HasService(ServiceIdentification
.ViewComponentDescriptorProvider
))
292 services
.RegisterService(ServiceIdentification
.ViewComponentDescriptorProvider
,
293 typeof(DefaultViewComponentDescriptorProvider
));
295 if (!services
.HasService(ServiceIdentification
.ScaffoldingSupport
))
297 Type defaultScaffoldingType
=
298 TypeLoadUtil
.GetType(
299 TypeLoadUtil
.GetEffectiveTypeName(
300 "Castle.MonoRail.ActiveRecordScaffold.ScaffoldingSupport, Castle.MonoRail.ActiveRecordScaffold"), true);
302 if (defaultScaffoldingType
!= null)
304 services
.RegisterService(ServiceIdentification
.ScaffoldingSupport
, defaultScaffoldingType
);
307 if (!services
.HasService(ServiceIdentification
.ControllerFactory
))
309 if (config
.ControllersConfig
.CustomControllerFactory
!= null)
311 services
.RegisterService(ServiceIdentification
.ControllerFactory
,
312 config
.ControllersConfig
.CustomControllerFactory
);
316 services
.RegisterService(ServiceIdentification
.ControllerFactory
,
317 typeof(DefaultControllerFactory
));
320 if (!services
.HasService(ServiceIdentification
.ViewComponentFactory
))
322 if (config
.ViewComponentsConfig
.CustomViewComponentFactory
!= null)
324 services
.RegisterService(ServiceIdentification
.ViewComponentFactory
,
325 config
.ViewComponentsConfig
.CustomViewComponentFactory
);
329 services
.RegisterService(ServiceIdentification
.ViewComponentFactory
,
330 typeof(DefaultViewComponentFactory
));
333 if (!services
.HasService(ServiceIdentification
.FilterFactory
))
335 if (config
.CustomFilterFactory
!= null)
337 services
.RegisterService(ServiceIdentification
.FilterFactory
,
338 config
.CustomFilterFactory
);
342 services
.RegisterService(ServiceIdentification
.FilterFactory
,
343 typeof(DefaultFilterFactory
));
346 if (!services
.HasService(ServiceIdentification
.ResourceFactory
))
348 services
.RegisterService(ServiceIdentification
.ResourceFactory
, typeof(DefaultResourceFactory
));
350 if (!services
.HasService(ServiceIdentification
.EmailSender
))
352 services
.RegisterService(ServiceIdentification
.EmailSender
, typeof(MonoRailSmtpSender
));
354 if (!services
.HasService(ServiceIdentification
.ControllerDescriptorProvider
))
356 services
.RegisterService(ServiceIdentification
.ControllerDescriptorProvider
,
357 typeof(DefaultControllerDescriptorProvider
));
359 if (!services
.HasService(ServiceIdentification
.ResourceDescriptorProvider
))
361 services
.RegisterService(ServiceIdentification
.ResourceDescriptorProvider
, typeof(DefaultResourceDescriptorProvider
));
363 if (!services
.HasService(ServiceIdentification
.RescueDescriptorProvider
))
365 services
.RegisterService(ServiceIdentification
.RescueDescriptorProvider
, typeof(DefaultRescueDescriptorProvider
));
367 if (!services
.HasService(ServiceIdentification
.LayoutDescriptorProvider
))
369 services
.RegisterService(ServiceIdentification
.LayoutDescriptorProvider
, typeof(DefaultLayoutDescriptorProvider
));
371 if (!services
.HasService(ServiceIdentification
.HelperDescriptorProvider
))
373 services
.RegisterService(ServiceIdentification
.HelperDescriptorProvider
, typeof(DefaultHelperDescriptorProvider
));
375 if (!services
.HasService(ServiceIdentification
.FilterDescriptorProvider
))
377 services
.RegisterService(ServiceIdentification
.FilterDescriptorProvider
, typeof(DefaultFilterDescriptorProvider
));
379 if (!services
.HasService(ServiceIdentification
.EmailTemplateService
))
381 services
.RegisterService(ServiceIdentification
.EmailTemplateService
, typeof(EmailTemplateService
));
383 if (!services
.HasService(ServiceIdentification
.ControllerTree
))
385 services
.RegisterService(ServiceIdentification
.ControllerTree
, typeof(DefaultControllerTree
));
387 if (!services
.HasService(ServiceIdentification
.CacheProvider
))
389 services
.RegisterService(ServiceIdentification
.CacheProvider
, typeof(DefaultCacheProvider
));
391 if (!services
.HasService(ServiceIdentification
.ExecutorFactory
))
393 services
.RegisterService(ServiceIdentification
.ExecutorFactory
, typeof(DefaultControllerLifecycleExecutorFactory
));
395 if (!services
.HasService(ServiceIdentification
.TransformationFilterFactory
))
397 services
.RegisterService(ServiceIdentification
.TransformationFilterFactory
, typeof(DefaultTransformFilterFactory
));
399 if (!services
.HasService(ServiceIdentification
.TransformFilterDescriptorProvider
))
401 services
.RegisterService(ServiceIdentification
.TransformFilterDescriptorProvider
,
402 typeof(DefaultTransformFilterDescriptorProvider
));
405 if (!services
.HasService(ServiceIdentification
.UrlBuilder
))
407 services
.RegisterService(ServiceIdentification
.UrlBuilder
, typeof(DefaultUrlBuilder
));
409 if (!services
.HasService(ServiceIdentification
.UrlTokenizer
))
411 services
.RegisterService(ServiceIdentification
.UrlTokenizer
, typeof(DefaultUrlTokenizer
));
413 if (!services
.HasService(ServiceIdentification
.ValidatorRegistry
))
415 services
.RegisterService(ServiceIdentification
.ValidatorRegistry
, typeof(CachedValidationRegistry
));
418 if (!services
.HasService(ServiceIdentification
.AjaxProxyGenerator
))
420 services
.RegisterService(ServiceIdentification
.AjaxProxyGenerator
, typeof(PrototypeAjaxProxyGenerator
));
424 private static object ActivateService(Type type
)
428 return Activator
.CreateInstance(type
);
432 String message
= String
.Format("Initialization Exception: " +
433 "Could not instantiate {0}", type
.FullName
);
434 throw new ConfigurationErrorsException(message
, ex
);
438 private static void InvokeInitialize(object instance
)
440 IInitializable initializable
= instance
as IInitializable
;
442 if (initializable
!= null)
444 initializable
.Initialize();
447 ISupportInitialize suppInitialize
= instance
as ISupportInitialize
;
449 if (suppInitialize
!= null)
451 suppInitialize
.BeginInit();
452 suppInitialize
.EndInit();
456 private void InvokeServiceEnabled(object instance
)
458 IServiceEnabledComponent serviceEnabled
= instance
as IServiceEnabledComponent
;
460 if (serviceEnabled
!= null)
462 serviceEnabled
.Service(this);
466 private MonoRailConfiguration
ObtainConfiguration()
470 config
= MonoRailConfiguration
.GetConfig();
476 private static void AssertImplementsService(Type service
, Type impl
)
478 if (!service
.IsAssignableFrom(impl
))
480 String message
= String
.Format("Initialization Exception: " +
481 "Service {0} does not implement or extend {1}", impl
.FullName
, service
.FullName
);
482 throw new ConfigurationErrorsException(message
);