1 // Copyright 2004-2008 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
.ActiveRecord
.Framework
.Config
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
;
26 /// Enum for database types support for configuration construction.
27 /// Not to be confused by databases supported by ActiveRecord
29 public enum DatabaseType
32 /// Microsoft SQL Server 2005
36 /// Microsoft SQL Server 2000
42 /// Usefull for test cases.
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
;
51 private bool isLazyByDefault
;
52 private bool pluralizeTableNames
;
53 private bool verifyModelsAgainstDBSchema
;
56 /// Initializes a new instance of the <see cref="InPlaceConfigurationSource"/> class.
58 public InPlaceConfigurationSource()
62 #region IConfigurationSource Members
65 /// Return a type that implements
66 /// the interface <see cref="IThreadScopeInfo"/>
69 public Type ThreadScopeInfoImplementation
71 get { return threadScopeInfoImplementation; }
72 set { threadScopeInfoImplementation = value; }
76 /// Return a type that implements
77 /// the interface <see cref="ISessionFactoryHolder"/>
80 public Type SessionFactoryHolderImplementation
82 get { return sessionFactoryHolderImplementation; }
83 set { sessionFactoryHolderImplementation = value; }
87 /// Return a type that implements
88 /// the interface NHibernate.Cfg.INamingStrategy
91 public Type NamingStrategyImplementation
93 get { return namingStrategyImplementation; }
94 set { namingStrategyImplementation = value; }
98 /// Return an <see cref="IConfiguration"/> for the specified type.
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
;
110 /// Gets a value indicating whether this <see cref="IConfigurationSource"/> produce debug information
112 /// <value><c>true</c> if debug; otherwise, <c>false</c>.</value>
115 get { return debug; }
119 /// Gets a value indicating whether the entities should be lazy by default.
122 /// <c>true</c> if entities should be lazy by default; otherwise, <c>false</c>.
124 public bool IsLazyByDefault
126 get { return isLazyByDefault; }
130 /// Gets a value indicating whether table names are assumed plural by default.
133 /// <c>true</c> if table names should be pluralized by default; otherwise, <c>false</c>.
135 public bool PluralizeTableNames
137 get { return pluralizeTableNames; }
138 set { pluralizeTableNames = value; }
142 /// Gets or Sets a value indicating whether the models should be verified against the db schema on Initialisation.
145 /// <c>true</c> if models should be verified; otherwise, <c>false</c>.
147 public bool VerifyModelsAgainstDBSchema
149 get { return verifyModelsAgainstDBSchema; }
150 set { verifyModelsAgainstDBSchema = value; }
156 /// Builds a InPlaceConfigurationSource set up to access a MS SQL server database using integrated security.
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");
170 /// Builds a InPlaceConfigurationSource set up to access a MS SQL server database using the specified username and password.
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
);
188 /// Builds an InPlaceConfiguratioSource for the specified database.
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
);
222 /// Sets a value indicating whether this instance is running in web app.
225 /// <c>true</c> if this instance is running in web app; otherwise, <c>false</c>.
227 public bool IsRunningInWebApp
229 set { SetUpThreadInfoType(value, null); }
233 /// Adds the specified type with the properties
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
));
243 /// Adds the specified type with configuration
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
;
255 /// Sets the type of the thread info.
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;
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
;
286 /// Sets the type of the session factory holder.
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
;
311 /// Sets the type of the naming strategy.
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
;
334 /// Sets the debug flag.
336 /// <param name="isDebug">if set to <c>true</c> Active Record will produce debug information.</param>
337 protected void SetDebugFlag(bool isDebug
)
343 /// Set whatever entities are lazy by default or not.
345 protected void SetIsLazyByDefault(bool lazyByDefault
)
347 isLazyByDefault
= lazyByDefault
;
351 /// Sets the debug flag.
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
;
360 /// Sets the pluralizeTableNames flag.
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()));
381 /// Processes the configuration applying any substitutions.
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);