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
.Collections
.Specialized
;
20 using System
.ComponentModel
;
21 using System
.Configuration
;
24 using Castle
.Components
.Validator
;
26 using Castle
.MonoRail
.Framework
.Configuration
;
27 using Castle
.MonoRail
.Framework
.Internal
;
28 using Castle
.MonoRail
.Framework
.Services
;
29 using Castle
.MonoRail
.Framework
.Services
.AjaxProxyGenerator
;
32 /// Parent Service container for the MonoRail framework
34 public class MonoRailServiceContainer
: AbstractServiceContainer
36 /// <summary></summary>
37 private static string mrExtension
= ".castle";
39 /// <summary>The only one Extension Manager</summary>
40 protected internal ExtensionManager extensionManager
;
42 /// <summary>Prevents GC from collecting the extensions</summary>
43 private IList extensions
= new ArrayList();
45 /// <summary>Keeps only one copy of the config</summary>
46 private MonoRailConfiguration config
;
50 /// Initializes a new instance of the <see cref="MonoRailServiceContainer"/> class.
52 public MonoRailServiceContainer()
57 /// Initializes a new instance of the <see cref="MonoRailServiceContainer"/> class.
59 /// <param name="config">The config.</param>
60 public MonoRailServiceContainer(MonoRailConfiguration config
) : this()
66 /// Allows registration without the configuration
68 public void RegisterBaseService(Type service
, object instance
)
70 InvokeServiceEnabled(instance
);
71 InvokeInitialize(instance
);
73 AddService(service
, instance
);
77 /// Initializes the container state and its services
81 DiscoverHttpHandlerExtensions();
85 MonoRailConfiguration config
= ObtainConfiguration();
87 InitExtensions(config
);
92 /// Checks whether the specified URL is to be handled by MonoRail
94 /// <param name="url">The URL.</param>
96 /// <see langword="true"/> if it is a MonoRail request; otherwise, <see langword="false"/>.
98 public bool IsMonoRailRequest(String url
)
100 String extension
= Path
.GetExtension(url
);
102 return string.Compare(mrExtension
, extension
, StringComparison
.InvariantCultureIgnoreCase
) == 0;
105 /// <summary></summary>
106 public static string MonoRailExtension
108 get { return mrExtension; }
111 private static void DiscoverHttpHandlerExtensions()
113 XmlDocument webConfig
= new XmlDocument();
114 webConfig
.Load(Path
.Combine(AppDomain
.CurrentDomain
.BaseDirectory
, "web.config"));
116 XmlNodeList addNodes
= webConfig
.DocumentElement
.SelectNodes(
117 "/configuration/system.web/httpHandlers/add");
119 if (addNodes
.Count
== 0)
121 // Possibly the web.config configuration node is using a namespace declaration
123 XmlElement systemWebElem
= webConfig
.DocumentElement
["system.web"];
124 XmlElement handlers
= systemWebElem
["httpHandlers"];
125 addNodes
= handlers
.ChildNodes
;
130 foreach(XmlNode addNode
in addNodes
)
132 if (addNode
.NodeType
!= XmlNodeType
.Element
)
137 XmlElement addElem
= (XmlElement
) addNode
;
139 String type
= addElem
.GetAttribute("type");
141 if (type
.StartsWith("Castle.MonoRail.Framework.MonoRailHttpHandlerFactory"))
143 mrExtension
= addElem
.GetAttribute("path").Substring(1);
150 throw new RailsException("We inspected the web.config httpHandlers section and " +
151 "couldn't find an extension that mapped to MonoRailHttpHandlerFactory. " +
152 "Is your configuration right to use MonoRail?");
157 /// Reads the configuration and initializes
158 /// registered extensions.
160 /// <param name="config">The configuration object</param>
161 private void InitExtensions(MonoRailConfiguration config
)
163 extensionManager
= new ExtensionManager(this);
165 foreach(ExtensionEntry entry
in config
.ExtensionEntries
)
167 AssertImplementsService(typeof(IMonoRailExtension
), entry
.ExtensionType
);
169 IMonoRailExtension extension
= (IMonoRailExtension
) ActivateService(entry
.ExtensionType
);
171 extension
.SetExtensionConfigNode(entry
.ExtensionNode
);
173 extensions
.Add(extension
);
178 /// Coordinates the instantiation, registering and initialization (lifecycle-wise)
179 /// of the services used by MonoRail.
181 /// <param name="config">The configuration object</param>
182 private void InitServices(MonoRailConfiguration config
)
184 AddService(typeof(ExtensionManager
), extensionManager
);
185 AddService(typeof(MonoRailConfiguration
), config
);
187 IList services
= InstantiateAndRegisterServices(config
.ServiceEntries
);
189 LifecycleService(services
);
190 LifecycleService(extensions
);
192 LifecycleInitialize(services
);
193 LifecycleInitialize(extensions
);
197 /// Checks for services that implements <see cref="IInitializable"/>
198 /// or <see cref="ISupportInitialize"/> and initialize them through the interface
200 /// <param name="services">List of MonoRail's services</param>
201 private void LifecycleInitialize(IList services
)
203 foreach(object instance
in services
)
205 InvokeInitialize(instance
);
210 /// Checks for services that implements <see cref="IServiceEnabledComponent"/>
211 /// and invoke <see cref="IServiceEnabledComponent.Service"/> on them
213 /// <param name="services">List of MonoRail's services</param>
214 private void LifecycleService(IList services
)
216 foreach(object instance
in services
)
218 InvokeServiceEnabled(instance
);
223 /// Instantiates and registers the services used by MonoRail.
225 /// <param name="services">The service's registry</param>
226 /// <returns>List of service's instances</returns>
227 private IList
InstantiateAndRegisterServices(ServiceEntryCollection services
)
229 IList instances
= new ArrayList();
233 foreach(DictionaryEntry entry
in services
.ServiceImplMap
)
235 Type service
= (Type
) entry
.Key
;
236 Type impl
= (Type
) entry
.Value
;
238 AssertImplementsService(service
, impl
);
240 object instance
= ActivateService(impl
);
242 AddService(service
, instance
);
244 instances
.Add(instance
);
249 foreach(Type type
in services
.CustomServices
)
251 object instance
= ActivateService(type
);
253 AddService(type
, instance
);
255 instances
.Add(instance
);
262 /// Registers the default implementation of services, if
263 /// they are not registered
265 private void InitConfiguration()
267 config
= ObtainConfiguration();
269 RegisterMissingServices(config
);
273 /// Checks whether non-optional services were supplied
274 /// through the configuration, and if not, register the
275 /// default implementation.
277 /// <param name="config">The configuration object</param>
278 private void RegisterMissingServices(MonoRailConfiguration config
)
280 ServiceEntryCollection services
= config
.ServiceEntries
;
282 services
.RegisterService(ServiceIdentification
.ViewEngineManager
,
283 typeof(DefaultViewEngineManager
));
286 if (!services
.HasService(ServiceIdentification
.ViewSourceLoader
))
288 services
.RegisterService(ServiceIdentification
.ViewSourceLoader
,
289 typeof(FileAssemblyViewSourceLoader
));
291 if (!services
.HasService(ServiceIdentification
.ScaffoldingSupport
))
293 Type defaultScaffoldingType
=
294 TypeLoadUtil
.GetType(
295 TypeLoadUtil
.GetEffectiveTypeName(
296 "Castle.MonoRail.ActiveRecordScaffold.ScaffoldingSupport, Castle.MonoRail.ActiveRecordScaffold"), true);
298 if (defaultScaffoldingType
!= null)
300 services
.RegisterService(ServiceIdentification
.ScaffoldingSupport
, defaultScaffoldingType
);
303 if (!services
.HasService(ServiceIdentification
.ControllerFactory
))
305 if (config
.ControllersConfig
.CustomControllerFactory
!= null)
307 services
.RegisterService(ServiceIdentification
.ControllerFactory
,
308 config
.ControllersConfig
.CustomControllerFactory
);
312 services
.RegisterService(ServiceIdentification
.ControllerFactory
,
313 typeof(DefaultControllerFactory
));
316 if (!services
.HasService(ServiceIdentification
.ViewComponentFactory
))
318 if (config
.ViewComponentsConfig
.CustomViewComponentFactory
!= null)
320 services
.RegisterService(ServiceIdentification
.ViewComponentFactory
,
321 config
.ViewComponentsConfig
.CustomViewComponentFactory
);
325 services
.RegisterService(ServiceIdentification
.ViewComponentFactory
,
326 typeof(DefaultViewComponentFactory
));
329 if (!services
.HasService(ServiceIdentification
.FilterFactory
))
331 if (config
.CustomFilterFactory
!= null)
333 services
.RegisterService(ServiceIdentification
.FilterFactory
,
334 config
.CustomFilterFactory
);
338 services
.RegisterService(ServiceIdentification
.FilterFactory
,
339 typeof(DefaultFilterFactory
));
342 if (!services
.HasService(ServiceIdentification
.ResourceFactory
))
344 services
.RegisterService(ServiceIdentification
.ResourceFactory
, typeof(DefaultResourceFactory
));
346 if (!services
.HasService(ServiceIdentification
.EmailSender
))
348 services
.RegisterService(ServiceIdentification
.EmailSender
, typeof(MonoRailSmtpSender
));
350 if (!services
.HasService(ServiceIdentification
.ControllerDescriptorProvider
))
352 services
.RegisterService(ServiceIdentification
.ControllerDescriptorProvider
,
353 typeof(DefaultControllerDescriptorProvider
));
355 if (!services
.HasService(ServiceIdentification
.ResourceDescriptorProvider
))
357 services
.RegisterService(ServiceIdentification
.ResourceDescriptorProvider
, typeof(DefaultResourceDescriptorProvider
));
359 if (!services
.HasService(ServiceIdentification
.RescueDescriptorProvider
))
361 services
.RegisterService(ServiceIdentification
.RescueDescriptorProvider
, typeof(DefaultRescueDescriptorProvider
));
363 if (!services
.HasService(ServiceIdentification
.LayoutDescriptorProvider
))
365 services
.RegisterService(ServiceIdentification
.LayoutDescriptorProvider
, typeof(DefaultLayoutDescriptorProvider
));
367 if (!services
.HasService(ServiceIdentification
.HelperDescriptorProvider
))
369 services
.RegisterService(ServiceIdentification
.HelperDescriptorProvider
, typeof(DefaultHelperDescriptorProvider
));
371 if (!services
.HasService(ServiceIdentification
.FilterDescriptorProvider
))
373 services
.RegisterService(ServiceIdentification
.FilterDescriptorProvider
, typeof(DefaultFilterDescriptorProvider
));
375 if (!services
.HasService(ServiceIdentification
.EmailTemplateService
))
377 services
.RegisterService(ServiceIdentification
.EmailTemplateService
, typeof(EmailTemplateService
));
379 if (!services
.HasService(ServiceIdentification
.ControllerTree
))
381 services
.RegisterService(ServiceIdentification
.ControllerTree
, typeof(DefaultControllerTree
));
383 if (!services
.HasService(ServiceIdentification
.CacheProvider
))
385 services
.RegisterService(ServiceIdentification
.CacheProvider
, typeof(DefaultCacheProvider
));
387 if (!services
.HasService(ServiceIdentification
.ExecutorFactory
))
389 services
.RegisterService(ServiceIdentification
.ExecutorFactory
, typeof(DefaultControllerLifecycleExecutorFactory
));
391 if (!services
.HasService(ServiceIdentification
.TransformationFilterFactory
))
393 services
.RegisterService(ServiceIdentification
.TransformationFilterFactory
, typeof(DefaultTransformFilterFactory
));
395 if (!services
.HasService(ServiceIdentification
.TransformFilterDescriptorProvider
))
397 services
.RegisterService(ServiceIdentification
.TransformFilterDescriptorProvider
,
398 typeof(DefaultTransformFilterDescriptorProvider
));
401 if (!services
.HasService(ServiceIdentification
.UrlBuilder
))
403 services
.RegisterService(ServiceIdentification
.UrlBuilder
, typeof(DefaultUrlBuilder
));
405 if (!services
.HasService(ServiceIdentification
.UrlTokenizer
))
407 services
.RegisterService(ServiceIdentification
.UrlTokenizer
, typeof(DefaultUrlTokenizer
));
409 if (!services
.HasService(ServiceIdentification
.ValidatorRegistry
))
411 services
.RegisterService(ServiceIdentification
.ValidatorRegistry
, typeof(CachedValidationRegistry
));
414 if (!services
.HasService(ServiceIdentification
.AjaxProxyGenerator
))
416 services
.RegisterService(ServiceIdentification
.AjaxProxyGenerator
, typeof(PrototypeAjaxProxyGenerator
));
420 private object ActivateService(Type type
)
424 return Activator
.CreateInstance(type
);
428 String message
= String
.Format("Initialization Exception: " +
429 "Could not instantiate {0}", type
.FullName
);
430 throw new ConfigurationErrorsException(message
, ex
);
434 private void InvokeInitialize(object instance
)
436 IInitializable initializable
= instance
as IInitializable
;
438 if (initializable
!= null)
440 initializable
.Initialize();
443 ISupportInitialize suppInitialize
= instance
as ISupportInitialize
;
445 if (suppInitialize
!= null)
447 suppInitialize
.BeginInit();
448 suppInitialize
.EndInit();
452 private void InvokeServiceEnabled(object instance
)
454 IServiceEnabledComponent serviceEnabled
= instance
as IServiceEnabledComponent
;
456 if (serviceEnabled
!= null)
458 serviceEnabled
.Service(this);
462 private MonoRailConfiguration
ObtainConfiguration()
466 config
= MonoRailConfiguration
.GetConfig();
472 private void AssertImplementsService(Type service
, Type impl
)
474 if (!service
.IsAssignableFrom(impl
))
476 String message
= String
.Format("Initialization Exception: " +
477 "Service {0} does not implement or extend {1}", impl
.FullName
, service
.FullName
);
478 throw new ConfigurationErrorsException(message
);