1 // Copyright 2004-2007 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
38 /// Usefull for test cases.
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
;
47 private bool isLazyByDefault
;
48 private bool pluralizeTableNames
;
49 private bool verifyModelsAgainstDBSchema
;
52 /// Initializes a new instance of the <see cref="InPlaceConfigurationSource"/> class.
54 public InPlaceConfigurationSource()
58 #region IConfigurationSource Members
61 /// Return a type that implements
62 /// the interface <see cref="IThreadScopeInfo"/>
65 public Type ThreadScopeInfoImplementation
67 get { return threadScopeInfoImplementation; }
68 set { threadScopeInfoImplementation = value; }
72 /// Return a type that implements
73 /// the interface <see cref="ISessionFactoryHolder"/>
76 public Type SessionFactoryHolderImplementation
78 get { return sessionFactoryHolderImplementation; }
79 set { sessionFactoryHolderImplementation = value; }
83 /// Return a type that implements
84 /// the interface NHibernate.Cfg.INamingStrategy
87 public Type NamingStrategyImplementation
89 get { return namingStrategyImplementation; }
90 set { namingStrategyImplementation = value; }
94 /// Return an <see cref="IConfiguration"/> for the specified type.
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
;
106 /// Gets a value indicating whether this <see cref="IConfigurationSource"/> produce debug information
108 /// <value><c>true</c> if debug; otherwise, <c>false</c>.</value>
111 get { return debug; }
115 /// Gets a value indicating whether the entities should be lazy by default.
118 /// <c>true</c> if entities should be lazy by default; otherwise, <c>false</c>.
120 public bool IsLazyByDefault
122 get { return isLazyByDefault; }
126 /// Gets a value indicating whether table names are assumed plural by default.
129 /// <c>true</c> if table names should be pluralized by default; otherwise, <c>false</c>.
131 public bool PluralizeTableNames
133 get { return pluralizeTableNames; }
134 set { pluralizeTableNames = value; }
138 /// Gets or Sets a value indicating whether the models should be verified against the db schema on Initialisation.
141 /// <c>true</c> if models should be verified; otherwise, <c>false</c>.
143 public bool VerifyModelsAgainstDBSchema
145 get { return verifyModelsAgainstDBSchema; }
146 set { verifyModelsAgainstDBSchema = value; }
152 /// Builds a InPlaceConfigurationSource set up to access a MS SQL server database using integrated security.
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");
166 /// Builds a InPlaceConfigurationSource set up to access a MS SQL server database using the specified username and password.
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
);
184 /// Builds an InPlaceConfiguratioSource for the specified database.
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
);
211 /// Sets a value indicating whether this instance is running in web app.
214 /// <c>true</c> if this instance is running in web app; otherwise, <c>false</c>.
216 public bool IsRunningInWebApp
218 set { SetUpThreadInfoType(value, null); }
222 /// Adds the specified type with the properties
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
));
232 /// Adds the specified type with configuration
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
;
244 /// Sets the type of the thread info.
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;
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
;
275 /// Sets the type of the session factory holder.
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
;
300 /// Sets the type of the naming strategy.
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
;
323 /// Sets the debug flag.
325 /// <param name="isDebug">if set to <c>true</c> Active Record will produce debug information.</param>
326 protected void SetDebugFlag(bool isDebug
)
332 /// Set whatever entities are lazy by default or not.
334 protected void SetIsLazyByDefault(bool lazyByDefault
)
336 isLazyByDefault
= lazyByDefault
;
340 /// Sets the debug flag.
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
;
349 /// Sets the pluralizeTableNames flag.
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()));
370 /// Processes the configuration applying any substitutions.
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);