Fixing Windsor's issue of not resolving components by the order they were registered.
[castle.git] / Facilities / ActiveRecordIntegration / Castle.Facilities.ActiveRecordIntegration / ActiveRecordFacility.cs
blob9fbe3df3dad09bdc289452a536a602e5fe0d9010
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.Facilities.ActiveRecordIntegration
17 using System;
18 using System.Reflection;
19 using System.Collections;
20 using System.Configuration;
22 using Castle.ActiveRecord;
23 using Castle.ActiveRecord.Framework;
24 using Castle.ActiveRecord.Framework.Config;
25 using Castle.MicroKernel.Facilities;
26 using Castle.Core;
27 using Castle.Core.Configuration;
28 using Castle.Core.Logging;
29 using Castle.Services.Transaction;
31 using TransactionMode = Castle.Services.Transaction.TransactionMode;
33 /// <summary>
34 /// Provides integration with ActiveRecord framework.
35 /// </summary>
36 public class ActiveRecordFacility : AbstractFacility
38 private ILogger log = NullLogger.Instance;
39 private int sessionFactoryCount, sessionFactoryHolderCount;
41 public ActiveRecordFacility()
45 protected override void Init()
47 if (Kernel.HasComponent(typeof(ILoggerFactory)))
49 log = ((ILoggerFactory) Kernel[typeof(ILoggerFactory)]).Create(GetType());
52 log.Debug("Initializing AR Facility");
54 if (FacilityConfig == null)
56 log.FatalError("Configuration for AR Facility not found.");
57 throw new FacilityException("Sorry, but the ActiveRecord Facility depends on a proper configuration node.");
60 IConfiguration assemblyConfig = FacilityConfig.Children["assemblies"];
62 if (assemblyConfig == null || assemblyConfig.Children.Count == 0)
64 log.FatalError("No assembly specified on AR Facility config.");
66 throw new FacilityException("You need to specify at least one assembly that contains " +
67 "the ActiveRecord classes. For example, <assemblies><item>MyAssembly</item></assemblies>");
70 ConfigurationCollection assembliyConfigNodes = assemblyConfig.Children;
72 ArrayList assemblies = new ArrayList(assembliyConfigNodes.Count);
74 foreach(IConfiguration assemblyNode in assembliyConfigNodes)
76 assemblies.Add(ObtainAssembly(assemblyNode.Value));
79 Kernel.ComponentCreated += new Castle.MicroKernel.ComponentInstanceDelegate(Kernel_ComponentCreated);
81 SetUpTransactionManager();
83 InitializeFramework(assemblies);
86 public override void Dispose()
88 log.Info("AR Facility is being disposed.");
89 base.Dispose();
92 private void InitializeFramework(ArrayList assemblies)
94 log.Info("Initializing ActiveRecord Framework");
96 ActiveRecordStarter.ResetInitializationFlag();
97 ActiveRecordStarter.SessionFactoryHolderCreated += new SessionFactoryHolderDelegate(OnSessionFactoryHolderCreated);
99 try
101 ConfigurationSourceAdapter adapter = new ConfigurationSourceAdapter(FacilityConfig);
103 if (log.IsDebugEnabled)
105 log.Debug("Is Debug enabled {0}", adapter.Debug);
106 log.Debug("ThreadScopeInfo {0}", adapter.ThreadScopeInfoImplementation);
107 log.Debug("NamingStrategy {0}", adapter.NamingStrategyImplementation);
108 log.Debug("SessionFactoryHolder {0}", adapter.SessionFactoryHolderImplementation);
111 ActiveRecordStarter.Initialize(
112 (Assembly[]) assemblies.ToArray(typeof(Assembly)), adapter);
114 finally
116 ActiveRecordStarter.SessionFactoryHolderCreated -= new SessionFactoryHolderDelegate(OnSessionFactoryHolderCreated);
120 private void SetUpTransactionManager()
122 if (!Kernel.HasComponent(typeof(ITransactionManager)))
124 log.Info("No Transaction Manager registered on Kernel, registering AR Transaction Manager");
126 Kernel.AddComponent("ar.transaction.manager",
127 typeof(ITransactionManager), typeof(DefaultTransactionManager));
131 private void OnNewTransaction(ITransaction transaction, TransactionMode transactionMode, IsolationMode isolationMode, bool distributedTransaction)
133 if (!transaction.DistributedTransaction)
135 transaction.Enlist(new TransactionScopeResourceAdapter(transactionMode));
139 private Assembly ObtainAssembly(String assemblyName)
141 log.Debug("Loading model assembly '{0}' for AR", assemblyName);
142 return Assembly.Load(assemblyName);
145 private void Kernel_ComponentCreated(ComponentModel model, object instance)
147 if (model.Service != null && model.Service == typeof(ITransactionManager))
149 (instance as ITransactionManager).TransactionCreated += new TransactionCreationInfoDelegate(OnNewTransaction);
153 private void OnSessionFactoryHolderCreated(Castle.ActiveRecord.Framework.ISessionFactoryHolder holder)
155 holder.OnRootTypeRegistered += new RootTypeHandler(OnRootTypeRegistered);
157 string componentName = "activerecord.sessionfactoryholder";
159 if (Kernel.HasComponent(componentName))
161 componentName += "." + (++sessionFactoryHolderCount);
164 while(Kernel.HasComponent(componentName))
166 componentName =
167 componentName.Substring(0, componentName.LastIndexOf('.'))
168 + (++sessionFactoryHolderCount);
171 log.Info("Registering SessionFactoryHolder named '{0}': {1}", componentName, holder);
172 Kernel.AddComponentInstance(
173 componentName, typeof(ISessionFactoryHolder), holder);
176 private void OnRootTypeRegistered(object sender, Type rootType)
178 string componentName = "activerecord.sessionfactory";
180 if (Kernel.HasComponent(componentName))
182 componentName += "." + (++sessionFactoryCount);
185 while(Kernel.HasComponent(componentName))
187 componentName =
188 componentName.Substring(0, componentName.LastIndexOf('.'))
189 + (++sessionFactoryCount);
192 log.Info("Registering SessionFactory named '{0}' for the root type {1}: {2}", componentName, rootType, sender);
193 Kernel.AddComponentInstance(
194 componentName,
195 typeof(NHibernate.ISessionFactory),
196 new SessionFactoryDelegate((ISessionFactoryHolder) sender, rootType));
200 internal class ConfigurationSourceAdapter : InPlaceConfigurationSource
202 public ConfigurationSourceAdapter(IConfiguration facilityConfig)
204 String isWeb = facilityConfig.Attributes["isWeb"];
205 String threadinfotype = facilityConfig.Attributes["threadinfotype"];
206 string isDebug = facilityConfig.Attributes["isDebug"];
207 string sessionfactoryholdertype = facilityConfig.Attributes["sessionfactoryholdertype"];
208 string isLazyByDefault = facilityConfig.Attributes["default-lazy"];
209 string pluralize = facilityConfig.Attributes["pluralizeTableNames"];
210 string verifyModelsAgainstDBSchema = facilityConfig.Attributes["verifyModelsAgainstDBSchema"];
212 SetUpThreadInfoType(ConvertBool(isWeb), threadinfotype);
213 SetDebugFlag(ConvertBool(isDebug));
214 SetUpSessionFactoryHolderType(sessionfactoryholdertype);
215 SetIsLazyByDefault(ConvertBool(isLazyByDefault));
216 PluralizeTableNames = ConvertBool(pluralize);
217 VerifyModelsAgainstDBSchema = ConvertBool(verifyModelsAgainstDBSchema);
219 foreach(IConfiguration config in facilityConfig.Children)
221 if (!"config".Equals(config.Name)) continue;
223 Type type = typeof(ActiveRecordBase);
225 String typeAtt = config.Attributes["type"];
227 if (typeAtt != null)
229 type = ObtainType(typeAtt);
232 Add(type, AdjustConfiguration(config));
236 private IConfiguration AdjustConfiguration(IConfiguration config)
238 MutableConfiguration newConfig = new MutableConfiguration("entry");
240 foreach(IConfiguration configNode in config.Children)
242 String key = configNode.Attributes["key"];
243 String value = configNode.Attributes["value"];
245 newConfig.Children.Add(new MutableConfiguration(key, value));
248 return newConfig;
251 private static Type ObtainType(String typeAtt)
253 Type type = Type.GetType(typeAtt, false, false);
255 if (type == null)
257 String message = String.Format("Could not obtain type from name {0}", typeAtt);
259 throw new ConfigurationErrorsException(message);
262 return type;
265 private static bool ConvertBool(string boolString)
267 return "true".Equals(boolString, StringComparison.OrdinalIgnoreCase);