Fix the build.
[castle.git] / MonoRail / Castle.MonoRail.Framework / MonoRailServiceContainer.cs
blob0ea04cc4a2ac55c8ee97e7f875492badfcaf5595
1 // Copyright 2004-2007 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.MonoRail.Framework
17 using System;
18 using System.Collections;
19 using System.Collections.Specialized;
20 using System.ComponentModel;
21 using System.Configuration;
22 using System.IO;
23 using System.Xml;
24 using Castle.Components.Validator;
25 using Castle.Core;
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;
31 /// <summary>
32 /// Parent Service container for the MonoRail framework
33 /// </summary>
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;
49 /// <summary>
50 /// Initializes a new instance of the <see cref="MonoRailServiceContainer"/> class.
51 /// </summary>
52 public MonoRailServiceContainer()
56 /// <summary>
57 /// Initializes a new instance of the <see cref="MonoRailServiceContainer"/> class.
58 /// </summary>
59 /// <param name="config">The config.</param>
60 public MonoRailServiceContainer(MonoRailConfiguration config) : this()
62 this.config = config;
65 /// <summary>
66 /// Allows registration without the configuration
67 /// </summary>
68 public void RegisterBaseService(Type service, object instance)
70 InvokeServiceEnabled(instance);
71 InvokeInitialize(instance);
73 AddService(service, instance);
76 /// <summary>
77 /// Initializes the container state and its services
78 /// </summary>
79 public void Start()
81 DiscoverHttpHandlerExtensions();
83 InitConfiguration();
85 MonoRailConfiguration config = ObtainConfiguration();
87 InitExtensions(config);
88 InitServices(config);
91 /// <summary>
92 /// Checks whether the specified URL is to be handled by MonoRail
93 /// </summary>
94 /// <param name="url">The URL.</param>
95 /// <returns>
96 /// <see langword="true"/> if it is a MonoRail request; otherwise, <see langword="false"/>.
97 /// </returns>
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;
128 bool found = false;
130 foreach(XmlNode addNode in addNodes)
132 if (addNode.NodeType != XmlNodeType.Element)
134 continue;
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);
144 found = true;
148 if (!found)
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?");
156 /// <summary>
157 /// Reads the configuration and initializes
158 /// registered extensions.
159 /// </summary>
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);
177 /// <summary>
178 /// Coordinates the instantiation, registering and initialization (lifecycle-wise)
179 /// of the services used by MonoRail.
180 /// </summary>
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);
196 /// <summary>
197 /// Checks for services that implements <see cref="IInitializable"/>
198 /// or <see cref="ISupportInitialize"/> and initialize them through the interface
199 /// </summary>
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);
209 /// <summary>
210 /// Checks for services that implements <see cref="IServiceEnabledComponent"/>
211 /// and invoke <see cref="IServiceEnabledComponent.Service"/> on them
212 /// </summary>
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);
222 /// <summary>
223 /// Instantiates and registers the services used by MonoRail.
224 /// </summary>
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();
231 // Builtin services
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);
247 // Custom services
249 foreach(Type type in services.CustomServices)
251 object instance = ActivateService(type);
253 AddService(type, instance);
255 instances.Add(instance);
258 return instances;
261 /// <summary>
262 /// Registers the default implementation of services, if
263 /// they are not registered
264 /// </summary>
265 private void InitConfiguration()
267 config = ObtainConfiguration();
269 RegisterMissingServices(config);
272 /// <summary>
273 /// Checks whether non-optional services were supplied
274 /// through the configuration, and if not, register the
275 /// default implementation.
276 /// </summary>
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);
310 else
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);
323 else
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);
336 else
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);
426 catch(Exception ex)
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()
464 if (config == null)
466 config = MonoRailConfiguration.GetConfig();
469 return config;
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);