Added property-ref support to many-to-one (BelongsTo) relationships.
[castle.git] / ActiveRecord / Castle.ActiveRecord / Framework / Config / InPlaceConfigurationSource.cs
blobed310774e55e0f0d85374333820b85e9c9029ba5
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.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
33 /// </summary>
34 MSSQLServer
37 /// <summary>
38 /// Usefull for test cases.
39 /// </summary>
40 public class InPlaceConfigurationSource : IConfigurationSource
42 private readonly IDictionary<Type, IConfiguration> _type2Config = new Dictionary<Type, IConfiguration>();
43 private Type threadScopeInfoImplementation;
44 private Type sessionFactoryHolderImplementation;
45 private Type namingStrategyImplementation;
46 private bool debug;
47 private bool isLazyByDefault;
48 private bool pluralizeTableNames;
49 private bool verifyModelsAgainstDBSchema;
51 /// <summary>
52 /// Initializes a new instance of the <see cref="InPlaceConfigurationSource"/> class.
53 /// </summary>
54 public InPlaceConfigurationSource()
58 #region IConfigurationSource Members
60 /// <summary>
61 /// Return a type that implements
62 /// the interface <see cref="IThreadScopeInfo"/>
63 /// </summary>
64 /// <value></value>
65 public Type ThreadScopeInfoImplementation
67 get { return threadScopeInfoImplementation; }
68 set { threadScopeInfoImplementation = value; }
71 /// <summary>
72 /// Return a type that implements
73 /// the interface <see cref="ISessionFactoryHolder"/>
74 /// </summary>
75 /// <value></value>
76 public Type SessionFactoryHolderImplementation
78 get { return sessionFactoryHolderImplementation; }
79 set { sessionFactoryHolderImplementation = value; }
82 /// <summary>
83 /// Return a type that implements
84 /// the interface NHibernate.Cfg.INamingStrategy
85 /// </summary>
86 /// <value></value>
87 public Type NamingStrategyImplementation
89 get { return namingStrategyImplementation; }
90 set { namingStrategyImplementation = value; }
93 /// <summary>
94 /// Return an <see cref="IConfiguration"/> for the specified type.
95 /// </summary>
96 /// <param name="type"></param>
97 /// <returns></returns>
98 public IConfiguration GetConfiguration(Type type)
100 IConfiguration configuration;
101 _type2Config.TryGetValue(type, out configuration);
102 return configuration;
105 /// <summary>
106 /// Gets a value indicating whether this <see cref="IConfigurationSource"/> produce debug information
107 /// </summary>
108 /// <value><c>true</c> if debug; otherwise, <c>false</c>.</value>
109 public bool Debug
111 get { return debug; }
114 /// <summary>
115 /// Gets a value indicating whether the entities should be lazy by default.
116 /// </summary>
117 /// <value>
118 /// <c>true</c> if entities should be lazy by default; otherwise, <c>false</c>.
119 /// </value>
120 public bool IsLazyByDefault
122 get { return isLazyByDefault; }
125 /// <summary>
126 /// Gets a value indicating whether table names are assumed plural by default.
127 /// </summary>
128 /// <value>
129 /// <c>true</c> if table names should be pluralized by default; otherwise, <c>false</c>.
130 /// </value>
131 public bool PluralizeTableNames
133 get { return pluralizeTableNames; }
134 set { pluralizeTableNames = value; }
137 /// <summary>
138 /// Gets or Sets a value indicating whether the models should be verified against the db schema on Initialisation.
139 /// </summary>
140 /// <value>
141 /// <c>true</c> if models should be verified; otherwise, <c>false</c>.
142 /// </value>
143 public bool VerifyModelsAgainstDBSchema
145 get { return verifyModelsAgainstDBSchema; }
146 set { verifyModelsAgainstDBSchema = value; }
149 #endregion
151 /// <summary>
152 /// Builds a InPlaceConfigurationSource set up to access a MS SQL server database using integrated security.
153 /// </summary>
154 /// <param name="server">The server.</param>
155 /// <param name="initialCatalog">The initial catalog.</param>
156 /// <returns></returns>
157 public static InPlaceConfigurationSource BuildForMSSqlServer(string server, string initialCatalog)
159 if (string.IsNullOrEmpty(server)) throw new ArgumentNullException("server");
160 if (string.IsNullOrEmpty(initialCatalog)) throw new ArgumentNullException("initialCatalog");
162 return Build(DatabaseType.MSSQLServer, "Server=" + server + ";initial catalog=" + initialCatalog + ";Integrated Security=SSPI");
165 /// <summary>
166 /// Builds a InPlaceConfigurationSource set up to access a MS SQL server database using the specified username and password.
167 /// </summary>
168 /// <param name="server">The server.</param>
169 /// <param name="initialCatalog">The initial catalog.</param>
170 /// <param name="username">The username.</param>
171 /// <param name="password">The password.</param>
172 /// <returns></returns>
173 public static InPlaceConfigurationSource BuildForMSSqlServer(string server, string initialCatalog, string username, string password)
175 if (string.IsNullOrEmpty(server)) throw new ArgumentNullException("server");
176 if (string.IsNullOrEmpty(initialCatalog)) throw new ArgumentNullException("initialCatalog");
177 if (string.IsNullOrEmpty(username)) throw new ArgumentNullException("username");
178 if (string.IsNullOrEmpty(password)) throw new ArgumentNullException("password");
180 return Build(DatabaseType.MSSQLServer, "Server=" + server + ";initial catalog=" + initialCatalog + ";User id=" + username + ";password=" + password);
183 /// <summary>
184 /// Builds an InPlaceConfiguratioSource for the specified database.
185 /// </summary>
186 /// <param name="database">The database.</param>
187 /// <param name="connectionString">The connection string.</param>
188 /// <returns></returns>
189 public static InPlaceConfigurationSource Build(DatabaseType database, string connectionString)
191 if (string.IsNullOrEmpty(connectionString)) throw new ArgumentNullException("connectionString");
193 InPlaceConfigurationSource config = new InPlaceConfigurationSource();
195 Hashtable parameters = new Hashtable();
196 parameters["hibernate.connection.provider"] = "NHibernate.Connection.DriverConnectionProvider";
198 if (database == DatabaseType.MSSQLServer)
200 parameters["hibernate.connection.driver_class"] = "NHibernate.Driver.SqlClientDriver";
201 parameters["hibernate.dialect"] = "NHibernate.Dialect.MsSql2000Dialect";
202 parameters["hibernate.connection.connection_string"] = connectionString;
205 config.Add(typeof(ActiveRecordBase), parameters);
207 return config;
210 /// <summary>
211 /// Sets a value indicating whether this instance is running in web app.
212 /// </summary>
213 /// <value>
214 /// <c>true</c> if this instance is running in web app; otherwise, <c>false</c>.
215 /// </value>
216 public bool IsRunningInWebApp
218 set { SetUpThreadInfoType(value, null); }
221 /// <summary>
222 /// Adds the specified type with the properties
223 /// </summary>
224 /// <param name="type">The type.</param>
225 /// <param name="properties">The properties.</param>
226 public void Add(Type type, IDictionary properties)
228 Add(type, ConvertToConfiguration(properties));
231 /// <summary>
232 /// Adds the specified type with configuration
233 /// </summary>
234 /// <param name="type">The type.</param>
235 /// <param name="config">The config.</param>
236 public void Add(Type type, IConfiguration config)
238 ProcessConfiguration(config);
240 _type2Config[type] = config;
243 /// <summary>
244 /// Sets the type of the thread info.
245 /// </summary>
246 /// <param name="isWeb">if we run in a web context or not</param>
247 /// <param name="customType">Type of the custom implementation</param>
248 protected void SetUpThreadInfoType(bool isWeb, String customType)
250 Type threadInfoType = null;
252 if (isWeb)
254 threadInfoType = typeof(WebThreadScopeInfo);
257 if (customType != null && customType != String.Empty)
259 String typeName = customType;
261 threadInfoType = Type.GetType(typeName, false, false);
263 if (threadInfoType == null)
265 String message = String.Format("The type name {0} could not be found", typeName);
267 throw new ActiveRecordException(message);
271 ThreadScopeInfoImplementation = threadInfoType;
274 /// <summary>
275 /// Sets the type of the session factory holder.
276 /// </summary>
277 /// <param name="customType">Custom implementation</param>
278 protected void SetUpSessionFactoryHolderType(String customType)
280 Type sessionFactoryHolderType = typeof(SessionFactoryHolder);
282 if (customType != null && customType != String.Empty)
284 String typeName = customType;
286 sessionFactoryHolderType = Type.GetType(typeName, false, false);
288 if (sessionFactoryHolderType == null)
290 String message = String.Format("The type name {0} could not be found", typeName);
292 throw new ActiveRecordException(message);
296 SessionFactoryHolderImplementation = sessionFactoryHolderType;
299 /// <summary>
300 /// Sets the type of the naming strategy.
301 /// </summary>
302 /// <param name="customType">Custom implementation type name</param>
303 protected void SetUpNamingStrategyType(String customType)
305 if (customType != null && customType != String.Empty)
307 String typeName = customType;
309 Type namingStrategyType = Type.GetType(typeName, false, false);
311 if (namingStrategyType == null)
313 String message = String.Format("The type name {0} could not be found", typeName);
315 throw new ActiveRecordException(message);
318 NamingStrategyImplementation = namingStrategyType;
322 /// <summary>
323 /// Sets the debug flag.
324 /// </summary>
325 /// <param name="isDebug">if set to <c>true</c> Active Record will produce debug information.</param>
326 protected void SetDebugFlag(bool isDebug)
328 debug = isDebug;
331 /// <summary>
332 /// Set whatever entities are lazy by default or not.
333 /// </summary>
334 protected void SetIsLazyByDefault(bool lazyByDefault)
336 isLazyByDefault = lazyByDefault;
339 /// <summary>
340 /// Sets the debug flag.
341 /// </summary>
342 /// <param name="verifyModelsAgainstDBSchema">if set to <c>true</c> Active Record will verify the models against the db schema on startup.</param>
343 protected void SetVerifyModelsAgainstDBSchema(bool verifyModelsAgainstDBSchema)
345 this.verifyModelsAgainstDBSchema = verifyModelsAgainstDBSchema;
348 /// <summary>
349 /// Sets the pluralizeTableNames flag.
350 /// </summary>
351 /// <param name="pluralize">if set to <c>true</c> Active Record will pluralize inferred table names.</param>
352 protected void SetPluralizeTableNames(bool pluralize)
354 pluralizeTableNames = pluralize;
357 private static IConfiguration ConvertToConfiguration(IDictionary properties)
359 MutableConfiguration conf = new MutableConfiguration("Config");
361 foreach(DictionaryEntry entry in properties)
363 conf.Children.Add(new MutableConfiguration(entry.Key.ToString(), entry.Value.ToString()));
366 return conf;
369 /// <summary>
370 /// Processes the configuration applying any substitutions.
371 /// </summary>
372 /// <param name="config">The configuration</param>
373 private static void ProcessConfiguration(IConfiguration config)
375 const string ConnectionStringKey = "connection.connection_string";
377 for(int i = 0; i < config.Children.Count; ++i)
379 IConfiguration property = config.Children[i];
381 if (property.Name.IndexOf(ConnectionStringKey) >= 0)
383 String value = property.Value;
384 Regex connectionStringRegex = new Regex(@"ConnectionString\s*=\s*\$\{(?<ConnectionStringName>[^}]+)\}");
386 if (connectionStringRegex.IsMatch(value))
388 string connectionStringName = connectionStringRegex.Match(value).
389 Groups["ConnectionStringName"].Value;
390 value = ConfigurationManager.ConnectionStrings[connectionStringName].ConnectionString;
391 config.Children[i] = new MutableConfiguration(property.Name, value);