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
.Generic
;
19 using System
.Configuration
;
20 using System
.Text
.RegularExpressions
;
21 using Castle
.ActiveRecord
.Framework
.Scopes
;
22 using Castle
.Core
.Configuration
;
25 /// Enum for database types support for configuration construction.
26 /// Not to be confused by databases supported by ActiveRecord
28 public enum DatabaseType
31 /// Microsoft SQL Server 2005
35 /// Microsoft SQL Server 2000
41 /// Usefull for test cases.
43 public class InPlaceConfigurationSource
: IConfigurationSource
45 private readonly IDictionary
<Type
, IConfiguration
> _type2Config
= new Dictionary
<Type
, IConfiguration
>();
46 private Type threadScopeInfoImplementation
;
47 private Type sessionFactoryHolderImplementation
;
48 private Type namingStrategyImplementation
;
50 private bool isLazyByDefault
;
51 private bool pluralizeTableNames
;
52 private bool verifyModelsAgainstDBSchema
;
55 /// Initializes a new instance of the <see cref="InPlaceConfigurationSource"/> class.
57 public InPlaceConfigurationSource()
61 #region IConfigurationSource Members
64 /// Return a type that implements
65 /// the interface <see cref="IThreadScopeInfo"/>
68 public Type ThreadScopeInfoImplementation
70 get { return threadScopeInfoImplementation; }
71 set { threadScopeInfoImplementation = value; }
75 /// Return a type that implements
76 /// the interface <see cref="ISessionFactoryHolder"/>
79 public Type SessionFactoryHolderImplementation
81 get { return sessionFactoryHolderImplementation; }
82 set { sessionFactoryHolderImplementation = value; }
86 /// Return a type that implements
87 /// the interface NHibernate.Cfg.INamingStrategy
90 public Type NamingStrategyImplementation
92 get { return namingStrategyImplementation; }
93 set { namingStrategyImplementation = value; }
97 /// Return an <see cref="IConfiguration"/> for the specified type.
99 /// <param name="type"></param>
100 /// <returns></returns>
101 public IConfiguration
GetConfiguration(Type type
)
103 IConfiguration configuration
;
104 _type2Config
.TryGetValue(type
, out configuration
);
105 return configuration
;
109 /// Gets a value indicating whether this <see cref="IConfigurationSource"/> produce debug information
111 /// <value><c>true</c> if debug; otherwise, <c>false</c>.</value>
114 get { return debug; }
118 /// Gets a value indicating whether the entities should be lazy by default.
121 /// <c>true</c> if entities should be lazy by default; otherwise, <c>false</c>.
123 public bool IsLazyByDefault
125 get { return isLazyByDefault; }
129 /// Gets a value indicating whether table names are assumed plural by default.
132 /// <c>true</c> if table names should be pluralized by default; otherwise, <c>false</c>.
134 public bool PluralizeTableNames
136 get { return pluralizeTableNames; }
137 set { pluralizeTableNames = value; }
141 /// Gets or Sets a value indicating whether the models should be verified against the db schema on Initialisation.
144 /// <c>true</c> if models should be verified; otherwise, <c>false</c>.
146 public bool VerifyModelsAgainstDBSchema
148 get { return verifyModelsAgainstDBSchema; }
149 set { verifyModelsAgainstDBSchema = value; }
155 /// Builds a InPlaceConfigurationSource set up to access a MS SQL server database using integrated security.
157 /// <param name="server">The server.</param>
158 /// <param name="initialCatalog">The initial catalog.</param>
159 /// <returns></returns>
160 public static InPlaceConfigurationSource
BuildForMSSqlServer(string server
, string initialCatalog
)
162 if (string.IsNullOrEmpty(server
)) throw new ArgumentNullException("server");
163 if (string.IsNullOrEmpty(initialCatalog
)) throw new ArgumentNullException("initialCatalog");
165 return Build(DatabaseType
.MSSQLServer2005
, "Server=" + server
+ ";initial catalog=" + initialCatalog
+ ";Integrated Security=SSPI");
169 /// Builds a InPlaceConfigurationSource set up to access a MS SQL server database using the specified username and password.
171 /// <param name="server">The server.</param>
172 /// <param name="initialCatalog">The initial catalog.</param>
173 /// <param name="username">The username.</param>
174 /// <param name="password">The password.</param>
175 /// <returns></returns>
176 public static InPlaceConfigurationSource
BuildForMSSqlServer(string server
, string initialCatalog
, string username
, string password
)
178 if (string.IsNullOrEmpty(server
)) throw new ArgumentNullException("server");
179 if (string.IsNullOrEmpty(initialCatalog
)) throw new ArgumentNullException("initialCatalog");
180 if (string.IsNullOrEmpty(username
)) throw new ArgumentNullException("username");
181 if (string.IsNullOrEmpty(password
)) throw new ArgumentNullException("password");
183 return Build(DatabaseType
.MSSQLServer2005
, "Server=" + server
+ ";initial catalog=" + initialCatalog
+ ";User id=" + username
+ ";password=" + password
);
187 /// Builds an InPlaceConfiguratioSource for the specified database.
189 /// <param name="database">The database.</param>
190 /// <param name="connectionString">The connection string.</param>
191 /// <returns></returns>
192 public static InPlaceConfigurationSource
Build(DatabaseType database
, string connectionString
)
194 if (string.IsNullOrEmpty(connectionString
)) throw new ArgumentNullException("connectionString");
196 InPlaceConfigurationSource config
= new InPlaceConfigurationSource();
198 Dictionary
<string,string> parameters
= new Dictionary
<string,string>();
199 parameters
["connection.provider"] = "NHibernate.Connection.DriverConnectionProvider";
200 parameters
["cache.use_second_level_cache"] = "false";
202 if (database
== DatabaseType
.MSSQLServer2000
)
204 parameters
["connection.driver_class"] = "NHibernate.Driver.SqlClientDriver";
205 parameters
["dialect"] = "NHibernate.Dialect.MsSql2000Dialect";
206 parameters
["connection.connection_string"] = connectionString
;
208 else if (database
== DatabaseType
.MSSQLServer2005
)
210 parameters
["connection.driver_class"] = "NHibernate.Driver.SqlClientDriver";
211 parameters
["dialect"] = "NHibernate.Dialect.MsSql2005Dialect";
212 parameters
["connection.connection_string"] = connectionString
;
215 config
.Add(typeof(ActiveRecordBase
), parameters
);
221 /// Sets a value indicating whether this instance is running in web app.
224 /// <c>true</c> if this instance is running in web app; otherwise, <c>false</c>.
226 public bool IsRunningInWebApp
228 set { SetUpThreadInfoType(value, null); }
232 /// Adds the specified type with the properties
234 /// <param name="type">The type.</param>
235 /// <param name="properties">The properties.</param>
236 public void Add(Type type
, IDictionary
<string,string> properties
)
238 Add(type
, ConvertToConfiguration(properties
));
242 /// Adds the specified type with configuration
244 /// <param name="type">The type.</param>
245 /// <param name="config">The config.</param>
246 public void Add(Type type
, IConfiguration config
)
248 ProcessConfiguration(config
);
250 _type2Config
[type
] = config
;
254 /// Sets the type of the thread info.
256 /// <param name="isWeb">if we run in a web context or not</param>
257 /// <param name="customType">Type of the custom implementation</param>
258 protected void SetUpThreadInfoType(bool isWeb
, String customType
)
260 Type threadInfoType
= null;
264 threadInfoType
= typeof(WebThreadScopeInfo
);
267 if (customType
!= null && customType
!= String
.Empty
)
269 String typeName
= customType
;
271 threadInfoType
= Type
.GetType(typeName
, false, false);
273 if (threadInfoType
== null)
275 String message
= String
.Format("The type name {0} could not be found", typeName
);
277 throw new ActiveRecordException(message
);
281 ThreadScopeInfoImplementation
= threadInfoType
;
285 /// Sets the type of the session factory holder.
287 /// <param name="customType">Custom implementation</param>
288 protected void SetUpSessionFactoryHolderType(String customType
)
290 Type sessionFactoryHolderType
= typeof(SessionFactoryHolder
);
292 if (customType
!= null && customType
!= String
.Empty
)
294 String typeName
= customType
;
296 sessionFactoryHolderType
= Type
.GetType(typeName
, false, false);
298 if (sessionFactoryHolderType
== null)
300 String message
= String
.Format("The type name {0} could not be found", typeName
);
302 throw new ActiveRecordException(message
);
306 SessionFactoryHolderImplementation
= sessionFactoryHolderType
;
310 /// Sets the type of the naming strategy.
312 /// <param name="customType">Custom implementation type name</param>
313 protected void SetUpNamingStrategyType(String customType
)
315 if (customType
!= null && customType
!= String
.Empty
)
317 String typeName
= customType
;
319 Type namingStrategyType
= Type
.GetType(typeName
, false, false);
321 if (namingStrategyType
== null)
323 String message
= String
.Format("The type name {0} could not be found", typeName
);
325 throw new ActiveRecordException(message
);
328 NamingStrategyImplementation
= namingStrategyType
;
333 /// Sets the debug flag.
335 /// <param name="isDebug">if set to <c>true</c> Active Record will produce debug information.</param>
336 protected void SetDebugFlag(bool isDebug
)
342 /// Set whatever entities are lazy by default or not.
344 protected void SetIsLazyByDefault(bool lazyByDefault
)
346 isLazyByDefault
= lazyByDefault
;
350 /// Sets the debug flag.
352 /// <param name="verifyModelsAgainstDBSchema">if set to <c>true</c> Active Record will verify the models against the db schema on startup.</param>
353 protected void SetVerifyModelsAgainstDBSchema(bool verifyModelsAgainstDBSchema
)
355 this.verifyModelsAgainstDBSchema
= verifyModelsAgainstDBSchema
;
359 /// Sets the pluralizeTableNames flag.
361 /// <param name="pluralize">if set to <c>true</c> Active Record will pluralize inferred table names.</param>
362 protected void SetPluralizeTableNames(bool pluralize
)
364 pluralizeTableNames
= pluralize
;
367 private static IConfiguration
ConvertToConfiguration(IDictionary
<string,string> properties
)
369 MutableConfiguration conf
= new MutableConfiguration("Config");
371 foreach(KeyValuePair
<string,string> entry
in properties
)
373 conf
.Children
.Add(new MutableConfiguration(entry
.Key
, entry
.Value
));
380 /// Processes the configuration applying any substitutions.
382 /// <param name="config">The configuration</param>
383 private static void ProcessConfiguration(IConfiguration config
)
385 const string ConnectionStringKey
= "connection.connection_string";
387 for(int i
= 0; i
< config
.Children
.Count
; ++i
)
389 IConfiguration property
= config
.Children
[i
];
391 if (property
.Name
.IndexOf(ConnectionStringKey
) >= 0)
393 String
value = property
.Value
;
394 Regex connectionStringRegex
= new Regex(@"ConnectionString\s*=\s*\$\{(?<ConnectionStringName>[^}]+)\}");
396 if (connectionStringRegex
.IsMatch(value))
398 string connectionStringName
= connectionStringRegex
.Match(value).
399 Groups
["ConnectionStringName"].Value
;
400 value = ConfigurationManager
.ConnectionStrings
[connectionStringName
].ConnectionString
;
401 config
.Children
[i
] = new MutableConfiguration(property
.Name
, value);