Removed untyped contructor from ComponentRegistration and add a protected setter.
[castle.git] / ActiveRecord / Castle.ActiveRecord / Framework / Config / InPlaceConfigurationSource.cs
blobc2b3a287e20d9e000f57cc0c17efe9ded8e930d1
1 // Copyright 2004-2008 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.ActiveRecord.Framework.Config
17 using System;
18 using System.Collections;
19 using System.Collections.Generic;
20 using System.Configuration;
21 using System.Text.RegularExpressions;
22 using Castle.ActiveRecord.Framework.Scopes;
23 using Castle.Core.Configuration;
25 /// <summary>
26 /// Enum for database types support for configuration construction.
27 /// Not to be confused by databases supported by ActiveRecord
28 /// </summary>
29 public enum DatabaseType
31 /// <summary>
32 /// Microsoft SQL Server 2005
33 /// </summary>
34 MSSQLServer2005,
35 /// <summary>
36 /// Microsoft SQL Server 2000
37 /// </summary>
38 MSSQLServer2000
41 /// <summary>
42 /// Usefull for test cases.
43 /// </summary>
44 public class InPlaceConfigurationSource : IConfigurationSource
46 private readonly IDictionary<Type, IConfiguration> _type2Config = new Dictionary<Type, IConfiguration>();
47 private Type threadScopeInfoImplementation;
48 private Type sessionFactoryHolderImplementation;
49 private Type namingStrategyImplementation;
50 private bool debug;
51 private bool isLazyByDefault;
52 private bool pluralizeTableNames;
53 private bool verifyModelsAgainstDBSchema;
55 /// <summary>
56 /// Initializes a new instance of the <see cref="InPlaceConfigurationSource"/> class.
57 /// </summary>
58 public InPlaceConfigurationSource()
62 #region IConfigurationSource Members
64 /// <summary>
65 /// Return a type that implements
66 /// the interface <see cref="IThreadScopeInfo"/>
67 /// </summary>
68 /// <value></value>
69 public Type ThreadScopeInfoImplementation
71 get { return threadScopeInfoImplementation; }
72 set { threadScopeInfoImplementation = value; }
75 /// <summary>
76 /// Return a type that implements
77 /// the interface <see cref="ISessionFactoryHolder"/>
78 /// </summary>
79 /// <value></value>
80 public Type SessionFactoryHolderImplementation
82 get { return sessionFactoryHolderImplementation; }
83 set { sessionFactoryHolderImplementation = value; }
86 /// <summary>
87 /// Return a type that implements
88 /// the interface NHibernate.Cfg.INamingStrategy
89 /// </summary>
90 /// <value></value>
91 public Type NamingStrategyImplementation
93 get { return namingStrategyImplementation; }
94 set { namingStrategyImplementation = value; }
97 /// <summary>
98 /// Return an <see cref="IConfiguration"/> for the specified type.
99 /// </summary>
100 /// <param name="type"></param>
101 /// <returns></returns>
102 public IConfiguration GetConfiguration(Type type)
104 IConfiguration configuration;
105 _type2Config.TryGetValue(type, out configuration);
106 return configuration;
109 /// <summary>
110 /// Gets a value indicating whether this <see cref="IConfigurationSource"/> produce debug information
111 /// </summary>
112 /// <value><c>true</c> if debug; otherwise, <c>false</c>.</value>
113 public bool Debug
115 get { return debug; }
118 /// <summary>
119 /// Gets a value indicating whether the entities should be lazy by default.
120 /// </summary>
121 /// <value>
122 /// <c>true</c> if entities should be lazy by default; otherwise, <c>false</c>.
123 /// </value>
124 public bool IsLazyByDefault
126 get { return isLazyByDefault; }
129 /// <summary>
130 /// Gets a value indicating whether table names are assumed plural by default.
131 /// </summary>
132 /// <value>
133 /// <c>true</c> if table names should be pluralized by default; otherwise, <c>false</c>.
134 /// </value>
135 public bool PluralizeTableNames
137 get { return pluralizeTableNames; }
138 set { pluralizeTableNames = value; }
141 /// <summary>
142 /// Gets or Sets a value indicating whether the models should be verified against the db schema on Initialisation.
143 /// </summary>
144 /// <value>
145 /// <c>true</c> if models should be verified; otherwise, <c>false</c>.
146 /// </value>
147 public bool VerifyModelsAgainstDBSchema
149 get { return verifyModelsAgainstDBSchema; }
150 set { verifyModelsAgainstDBSchema = value; }
153 #endregion
155 /// <summary>
156 /// Builds a InPlaceConfigurationSource set up to access a MS SQL server database using integrated security.
157 /// </summary>
158 /// <param name="server">The server.</param>
159 /// <param name="initialCatalog">The initial catalog.</param>
160 /// <returns></returns>
161 public static InPlaceConfigurationSource BuildForMSSqlServer(string server, string initialCatalog)
163 if (string.IsNullOrEmpty(server)) throw new ArgumentNullException("server");
164 if (string.IsNullOrEmpty(initialCatalog)) throw new ArgumentNullException("initialCatalog");
166 return Build(DatabaseType.MSSQLServer2005, "Server=" + server + ";initial catalog=" + initialCatalog + ";Integrated Security=SSPI");
169 /// <summary>
170 /// Builds a InPlaceConfigurationSource set up to access a MS SQL server database using the specified username and password.
171 /// </summary>
172 /// <param name="server">The server.</param>
173 /// <param name="initialCatalog">The initial catalog.</param>
174 /// <param name="username">The username.</param>
175 /// <param name="password">The password.</param>
176 /// <returns></returns>
177 public static InPlaceConfigurationSource BuildForMSSqlServer(string server, string initialCatalog, string username, string password)
179 if (string.IsNullOrEmpty(server)) throw new ArgumentNullException("server");
180 if (string.IsNullOrEmpty(initialCatalog)) throw new ArgumentNullException("initialCatalog");
181 if (string.IsNullOrEmpty(username)) throw new ArgumentNullException("username");
182 if (string.IsNullOrEmpty(password)) throw new ArgumentNullException("password");
184 return Build(DatabaseType.MSSQLServer2005, "Server=" + server + ";initial catalog=" + initialCatalog + ";User id=" + username + ";password=" + password);
187 /// <summary>
188 /// Builds an InPlaceConfiguratioSource for the specified database.
189 /// </summary>
190 /// <param name="database">The database.</param>
191 /// <param name="connectionString">The connection string.</param>
192 /// <returns></returns>
193 public static InPlaceConfigurationSource Build(DatabaseType database, string connectionString)
195 if (string.IsNullOrEmpty(connectionString)) throw new ArgumentNullException("connectionString");
197 InPlaceConfigurationSource config = new InPlaceConfigurationSource();
199 Hashtable parameters = new Hashtable();
200 parameters["connection.provider"] = "NHibernate.Connection.DriverConnectionProvider";
201 parameters["cache.use_second_level_cache"] = "false";
203 if (database == DatabaseType.MSSQLServer2000)
205 parameters["connection.driver_class"] = "NHibernate.Driver.SqlClientDriver";
206 parameters["dialect"] = "NHibernate.Dialect.MsSql2000Dialect";
207 parameters["connection.connection_string"] = connectionString;
209 else if (database == DatabaseType.MSSQLServer2005)
211 parameters["connection.driver_class"] = "NHibernate.Driver.SqlClientDriver";
212 parameters["dialect"] = "NHibernate.Dialect.MsSql2005Dialect";
213 parameters["connection.connection_string"] = connectionString;
216 config.Add(typeof(ActiveRecordBase), parameters);
218 return config;
221 /// <summary>
222 /// Sets a value indicating whether this instance is running in web app.
223 /// </summary>
224 /// <value>
225 /// <c>true</c> if this instance is running in web app; otherwise, <c>false</c>.
226 /// </value>
227 public bool IsRunningInWebApp
229 set { SetUpThreadInfoType(value, null); }
232 /// <summary>
233 /// Adds the specified type with the properties
234 /// </summary>
235 /// <param name="type">The type.</param>
236 /// <param name="properties">The properties.</param>
237 public void Add(Type type, IDictionary properties)
239 Add(type, ConvertToConfiguration(properties));
242 /// <summary>
243 /// Adds the specified type with configuration
244 /// </summary>
245 /// <param name="type">The type.</param>
246 /// <param name="config">The config.</param>
247 public void Add(Type type, IConfiguration config)
249 ProcessConfiguration(config);
251 _type2Config[type] = config;
254 /// <summary>
255 /// Sets the type of the thread info.
256 /// </summary>
257 /// <param name="isWeb">if we run in a web context or not</param>
258 /// <param name="customType">Type of the custom implementation</param>
259 protected void SetUpThreadInfoType(bool isWeb, String customType)
261 Type threadInfoType = null;
263 if (isWeb)
265 threadInfoType = typeof(WebThreadScopeInfo);
268 if (customType != null && customType != String.Empty)
270 String typeName = customType;
272 threadInfoType = Type.GetType(typeName, false, false);
274 if (threadInfoType == null)
276 String message = String.Format("The type name {0} could not be found", typeName);
278 throw new ActiveRecordException(message);
282 ThreadScopeInfoImplementation = threadInfoType;
285 /// <summary>
286 /// Sets the type of the session factory holder.
287 /// </summary>
288 /// <param name="customType">Custom implementation</param>
289 protected void SetUpSessionFactoryHolderType(String customType)
291 Type sessionFactoryHolderType = typeof(SessionFactoryHolder);
293 if (customType != null && customType != String.Empty)
295 String typeName = customType;
297 sessionFactoryHolderType = Type.GetType(typeName, false, false);
299 if (sessionFactoryHolderType == null)
301 String message = String.Format("The type name {0} could not be found", typeName);
303 throw new ActiveRecordException(message);
307 SessionFactoryHolderImplementation = sessionFactoryHolderType;
310 /// <summary>
311 /// Sets the type of the naming strategy.
312 /// </summary>
313 /// <param name="customType">Custom implementation type name</param>
314 protected void SetUpNamingStrategyType(String customType)
316 if (customType != null && customType != String.Empty)
318 String typeName = customType;
320 Type namingStrategyType = Type.GetType(typeName, false, false);
322 if (namingStrategyType == null)
324 String message = String.Format("The type name {0} could not be found", typeName);
326 throw new ActiveRecordException(message);
329 NamingStrategyImplementation = namingStrategyType;
333 /// <summary>
334 /// Sets the debug flag.
335 /// </summary>
336 /// <param name="isDebug">if set to <c>true</c> Active Record will produce debug information.</param>
337 protected void SetDebugFlag(bool isDebug)
339 debug = isDebug;
342 /// <summary>
343 /// Set whatever entities are lazy by default or not.
344 /// </summary>
345 protected void SetIsLazyByDefault(bool lazyByDefault)
347 isLazyByDefault = lazyByDefault;
350 /// <summary>
351 /// Sets the debug flag.
352 /// </summary>
353 /// <param name="verifyModelsAgainstDBSchema">if set to <c>true</c> Active Record will verify the models against the db schema on startup.</param>
354 protected void SetVerifyModelsAgainstDBSchema(bool verifyModelsAgainstDBSchema)
356 this.verifyModelsAgainstDBSchema = verifyModelsAgainstDBSchema;
359 /// <summary>
360 /// Sets the pluralizeTableNames flag.
361 /// </summary>
362 /// <param name="pluralize">if set to <c>true</c> Active Record will pluralize inferred table names.</param>
363 protected void SetPluralizeTableNames(bool pluralize)
365 pluralizeTableNames = pluralize;
368 private static IConfiguration ConvertToConfiguration(IDictionary properties)
370 MutableConfiguration conf = new MutableConfiguration("Config");
372 foreach(DictionaryEntry entry in properties)
374 conf.Children.Add(new MutableConfiguration(entry.Key.ToString(), entry.Value.ToString()));
377 return conf;
380 /// <summary>
381 /// Processes the configuration applying any substitutions.
382 /// </summary>
383 /// <param name="config">The configuration</param>
384 private static void ProcessConfiguration(IConfiguration config)
386 const string ConnectionStringKey = "connection.connection_string";
388 for(int i = 0; i < config.Children.Count; ++i)
390 IConfiguration property = config.Children[i];
392 if (property.Name.IndexOf(ConnectionStringKey) >= 0)
394 String value = property.Value;
395 Regex connectionStringRegex = new Regex(@"ConnectionString\s*=\s*\$\{(?<ConnectionStringName>[^}]+)\}");
397 if (connectionStringRegex.IsMatch(value))
399 string connectionStringName = connectionStringRegex.Match(value).
400 Groups["ConnectionStringName"].Value;
401 value = ConfigurationManager.ConnectionStrings[connectionStringName].ConnectionString;
402 config.Children[i] = new MutableConfiguration(property.Name, value);