2 // System.Web.Configuration.WebConfigurationManager.cs
5 // Lluis Sanchez Gual (lluis@novell.com)
6 // Chris Toshok (toshok@ximian.com)
8 // Permission is hereby granted, free of charge, to any person obtaining
9 // a copy of this software and associated documentation files (the
10 // "Software"), to deal in the Software without restriction, including
11 // without limitation the rights to use, copy, modify, merge, publish,
12 // distribute, sublicense, and/or sell copies of the Software, and to
13 // permit persons to whom the Software is furnished to do so, subject to
14 // the following conditions:
16 // The above copyright notice and this permission notice shall be
17 // included in all copies or substantial portions of the Software.
19 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
23 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 // Copyright (C) 2005 Novell, Inc (http://www.novell.com)
34 using System
.Collections
;
35 using System
.Collections
.Specialized
;
36 using System
.Reflection
;
37 using System
.Web
.Util
;
39 using System
.Configuration
;
40 using System
.Configuration
.Internal
;
41 using _Configuration
= System
.Configuration
.Configuration
;
43 namespace System
.Web
.Configuration
{
45 public static class WebConfigurationManager
48 static IInternalConfigConfigurationFactory configFactory
;
49 static Hashtable configurations
= Hashtable
.Synchronized (new Hashtable ());
50 static Hashtable sectionCache
= new Hashtable (StringComparer
.OrdinalIgnoreCase
);
52 const string AppSettingsKey
= "WebConfigurationManager.AppSettings";
53 static internal IInternalConfigConfigurationFactory configFactory
56 IInternalConfigConfigurationFactory factory
= (IInternalConfigConfigurationFactory
)AppDomain
.CurrentDomain
.GetData("WebConfigurationManager.configFactory");
58 lock (AppDomain
.CurrentDomain
){
59 object initialized
= AppDomain
.CurrentDomain
.GetData("WebConfigurationManager.configFactory.initialized");
60 if (initialized
== null){
61 PropertyInfo prop
= typeof(ConfigurationManager
).GetProperty("ConfigurationFactory", BindingFlags
.Static
| BindingFlags
.NonPublic
);
63 factory
= prop
.GetValue(null, null) as IInternalConfigConfigurationFactory
;
64 configFactory
= factory
;
69 return factory
!= null ? factory
: configFactory
;
72 AppDomain
.CurrentDomain
.SetData("WebConfigurationManager.configFactory", value);
73 AppDomain
.CurrentDomain
.SetData("WebConfigurationManager.configFactory.initialized", true);
77 static internal Hashtable configurations
80 Hashtable table
= (Hashtable
)AppDomain
.CurrentDomain
.GetData("WebConfigurationManager.configurations");
82 lock (AppDomain
.CurrentDomain
){
83 object initialized
= AppDomain
.CurrentDomain
.GetData("WebConfigurationManager.configurations.initialized");
84 if (initialized
== null){
85 table
= Hashtable
.Synchronized (new Hashtable (StringComparer
.OrdinalIgnoreCase
));
86 configurations
= table
;
90 return table
!= null ? table
: configurations
;
94 AppDomain
.CurrentDomain
.SetData("WebConfigurationManager.configurations", value);
95 AppDomain
.CurrentDomain
.SetData("WebConfigurationManager.configurations.initialized", true);
99 static Hashtable sectionCache
103 Hashtable sectionCache
= (Hashtable
) AppDomain
.CurrentDomain
.GetData ("sectionCache");
104 if (sectionCache
== null) {
105 sectionCache
= new Hashtable (StringComparer
.OrdinalIgnoreCase
);
106 AppDomain
.CurrentDomain
.SetData ("sectionCache", sectionCache
);
112 AppDomain
.CurrentDomain
.SetData ("sectionCache", value);
117 static ArrayList extra_assemblies
= null;
118 static internal ArrayList ExtraAssemblies
{
120 if (extra_assemblies
== null)
121 extra_assemblies
= new ArrayList();
122 return extra_assemblies
;
126 static bool hasConfigErrors
= false;
127 static object hasConfigErrorsLock
= new object ();
128 static internal bool HasConfigErrors
{
130 lock (hasConfigErrorsLock
) {
131 return hasConfigErrors
;
136 static WebConfigurationManager ()
138 PropertyInfo prop
= typeof(ConfigurationManager
).GetProperty ("ConfigurationFactory", BindingFlags
.Static
| BindingFlags
.NonPublic
);
140 configFactory
= prop
.GetValue (null, null) as IInternalConfigConfigurationFactory
;
143 public static _Configuration
OpenMachineConfiguration ()
145 return ConfigurationManager
.OpenMachineConfiguration ();
148 [MonoLimitation ("locationSubPath is not handled")]
149 public static _Configuration
OpenMachineConfiguration (string locationSubPath
)
151 return OpenMachineConfiguration ();
154 [MonoLimitation("Mono does not support remote configuration")]
155 public static _Configuration
OpenMachineConfiguration (string locationSubPath
,
159 return OpenMachineConfiguration (locationSubPath
);
161 throw new NotSupportedException ("Mono doesn't support remote configuration");
164 [MonoLimitation("Mono does not support remote configuration")]
165 public static _Configuration
OpenMachineConfiguration (string locationSubPath
,
170 return OpenMachineConfiguration (locationSubPath
);
171 throw new NotSupportedException ("Mono doesn't support remote configuration");
174 [MonoLimitation("Mono does not support remote configuration")]
175 public static _Configuration
OpenMachineConfiguration (string locationSubPath
,
181 return OpenMachineConfiguration (locationSubPath
);
182 throw new NotSupportedException ("Mono doesn't support remote configuration");
185 public static _Configuration
OpenWebConfiguration (string path
)
187 return OpenWebConfiguration (path
, null, null, null, null, null);
190 public static _Configuration
OpenWebConfiguration (string path
, string site
)
192 return OpenWebConfiguration (path
, site
, null, null, null, null);
195 public static _Configuration
OpenWebConfiguration (string path
, string site
, string locationSubPath
)
197 return OpenWebConfiguration (path
, site
, locationSubPath
, null, null, null);
200 public static _Configuration
OpenWebConfiguration (string path
, string site
, string locationSubPath
, string server
)
202 return OpenWebConfiguration (path
, site
, locationSubPath
, server
, null, null);
205 public static _Configuration
OpenWebConfiguration (string path
, string site
, string locationSubPath
, string server
, IntPtr userToken
)
207 return OpenWebConfiguration (path
, site
, locationSubPath
, server
, null, null);
210 public static _Configuration
OpenWebConfiguration (string path
, string site
, string locationSubPath
, string server
, string userName
, string password
)
212 if (path
== null || path
.Length
== 0)
217 conf
= (_Configuration
) configurations
[path
];
220 conf
= ConfigurationFactory
.Create (typeof (WebConfigurationHost
), null, path
, site
, locationSubPath
, server
, userName
, password
);
221 configurations
[path
] = conf
;
222 } catch (Exception ex
) {
223 lock (hasConfigErrorsLock
) {
224 hasConfigErrors
= true;
232 public static _Configuration
OpenMappedWebConfiguration (WebConfigurationFileMap fileMap
, string path
)
234 return ConfigurationFactory
.Create (typeof(WebConfigurationHost
), fileMap
, path
);
237 public static _Configuration
OpenMappedWebConfiguration (WebConfigurationFileMap fileMap
, string path
, string site
)
239 return ConfigurationFactory
.Create (typeof(WebConfigurationHost
), fileMap
, path
, site
);
242 public static _Configuration
OpenMappedWebConfiguration (WebConfigurationFileMap fileMap
, string path
, string site
, string locationSubPath
)
244 return ConfigurationFactory
.Create (typeof(WebConfigurationHost
), fileMap
, path
, site
, locationSubPath
);
247 public static _Configuration
OpenMappedMachineConfiguration (ConfigurationFileMap fileMap
)
249 return ConfigurationFactory
.Create (typeof(WebConfigurationHost
), fileMap
);
252 public static _Configuration
OpenMappedMachineConfiguration (ConfigurationFileMap fileMap
,
253 string locationSubPath
)
255 return OpenMappedMachineConfiguration (fileMap
);
258 internal static object SafeGetSection (string sectionName
, Type configSectionType
)
261 return GetSection (sectionName
);
262 } catch (Exception
) {
263 if (configSectionType
!= null)
264 return Activator
.CreateInstance (configSectionType
);
269 internal static object SafeGetSection (string sectionName
, string path
, Type configSectionType
)
272 return GetSection (sectionName
, path
);
273 } catch (Exception
) {
274 if (configSectionType
!= null)
275 return Activator
.CreateInstance (configSectionType
);
280 public static object GetSection (string sectionName
)
282 return GetSection (sectionName
, GetCurrentPath (HttpContext
.Current
));
285 public static object GetSection (string sectionName
, string path
)
287 object cachedSection
= sectionCache
[GetSectionCacheKey (sectionName
, path
)];
288 if (cachedSection
!= null)
289 return cachedSection
;
291 _Configuration c
= OpenWebConfiguration (path
);
292 ConfigurationSection section
= c
.GetSection (sectionName
);
298 object value = get_runtime_object
.Invoke (section
, new object [0]);
299 if (String
.CompareOrdinal ("appSettings", sectionName
) == 0) {
300 NameValueCollection collection
;
301 collection
= new KeyValueMergedCollection (HttpContext
.Current
, (NameValueCollection
) value);
305 AddSectionToCache (GetSectionCacheKey (sectionName
, path
), value);
308 object value = SettingsMappingManager
.MapSection (get_runtime_object
.Invoke (section
, new object [0]));
309 AddSectionToCache (GetSectionCacheKey (sectionName
, path
), value);
314 static string GetCurrentPath (HttpContext ctx
)
316 return (ctx
!= null && ctx
.Request
!= null) ? ctx
.Request
.Path
: HttpRuntime
.AppDomainAppVirtualPath
;
319 internal static void RemoveConfigurationFromCache (HttpContext ctx
)
321 configurations
.Remove (GetCurrentPath (ctx
));
324 readonly static MethodInfo get_runtime_object
= typeof (ConfigurationSection
).GetMethod ("GetRuntimeObject", BindingFlags
.NonPublic
| BindingFlags
.Instance
);
326 public static object GetWebApplicationSection (string sectionName
)
328 string path
= (HttpContext
.Current
== null
329 || HttpContext
.Current
.Request
== null
330 || HttpContext
.Current
.Request
.ApplicationPath
== null
331 || HttpContext
.Current
.Request
.ApplicationPath
== "") ?
332 String
.Empty
: HttpContext
.Current
.Request
.ApplicationPath
;
334 return GetSection (sectionName
, path
);
337 public static NameValueCollection AppSettings
{
338 get { return ConfigurationManager.AppSettings; }
341 public static ConnectionStringSettingsCollection ConnectionStrings
{
342 get { return ConfigurationManager.ConnectionStrings; }
345 internal static IInternalConfigConfigurationFactory ConfigurationFactory
{
346 get { return configFactory; }
349 static void AddSectionToCache (string key
, object section
)
351 if (sectionCache
[key
] != null)
354 Hashtable tmpTable
= (Hashtable
) sectionCache
.Clone ();
355 if (tmpTable
.Contains (key
))
358 tmpTable
.Add (key
, section
);
359 sectionCache
= tmpTable
;
362 static string GetSectionCacheKey (string sectionName
, string path
)
364 return string.Concat (path
, "/", sectionName
);
368 #region stuff copied from WebConfigurationSettings
370 static internal IConfigurationSystem oldConfig
{
372 return (IConfigurationSystem
)AppDomain
.CurrentDomain
.GetData("WebConfigurationManager.oldConfig");
375 AppDomain
.CurrentDomain
.SetData("WebConfigurationManager.oldConfig", value);
379 static private Web20DefaultConfig config
{
381 return (Web20DefaultConfig
) AppDomain
.CurrentDomain
.GetData ("Web20DefaultConfig.config");
384 AppDomain
.CurrentDomain
.SetData ("Web20DefaultConfig.config", value);
388 static private IInternalConfigSystem configSystem
{
390 return (IInternalConfigSystem
) AppDomain
.CurrentDomain
.GetData ("IInternalConfigSystem.configSystem");
393 AppDomain
.CurrentDomain
.SetData ("IInternalConfigSystem.configSystem", value);
397 static internal IConfigurationSystem oldConfig
;
398 static Web20DefaultConfig config
;
399 //static IInternalConfigSystem configSystem;
401 const BindingFlags privStatic
= BindingFlags
.NonPublic
| BindingFlags
.Static
;
402 static readonly object lockobj
= new object ();
404 internal static void Init ()
410 /* deal with the ConfigurationSettings stuff */
412 Web20DefaultConfig settings
= Web20DefaultConfig
.GetInstance ();
413 Type t
= typeof (ConfigurationSettings
);
414 MethodInfo changeConfig
= t
.GetMethod ("ChangeConfigurationSystem",
417 if (changeConfig
== null)
418 throw new ConfigurationException ("Cannot find method CCS");
420 object [] args
= new object [] {settings}
;
421 oldConfig
= (IConfigurationSystem
)changeConfig
.Invoke (null, args
);
427 /* deal with the ConfigurationManager stuff */
429 HttpConfigurationSystem system
= new HttpConfigurationSystem ();
430 Type t
= typeof (ConfigurationManager
);
431 MethodInfo changeConfig
= t
.GetMethod ("ChangeConfigurationSystem",
434 if (changeConfig
== null)
435 throw new ConfigurationException ("Cannot find method CCS");
437 object [] args
= new object [] {system}
;
438 changeConfig
.Invoke (null, args
);
439 //configSystem = system;
445 class Web20DefaultConfig
: IConfigurationSystem
448 static private Web20DefaultConfig instance
{
450 Web20DefaultConfig val
= (Web20DefaultConfig
)AppDomain
.CurrentDomain
.GetData("Web20DefaultConfig.instance");
452 val
= new Web20DefaultConfig();
453 AppDomain
.CurrentDomain
.SetData("Web20DefaultConfig.instance", val
);
458 AppDomain
.CurrentDomain
.SetData("Web20DefaultConfig.instance", value);
462 static Web20DefaultConfig instance
;
465 static Web20DefaultConfig ()
467 instance
= new Web20DefaultConfig ();
470 public static Web20DefaultConfig
GetInstance ()
475 public object GetConfig (string sectionName
)
477 object o
= WebConfigurationManager
.GetWebApplicationSection (sectionName
);
479 if (o
== null || o
is IgnoreSection
) {
480 /* this can happen when the section
481 * handler doesn't subclass from
482 * ConfigurationSection. let's be
483 * nice and try to load it using the
484 * 1.x style routines in case there's
485 * a 1.x section handler registered
488 object o1
= WebConfigurationManager
.oldConfig
.GetConfig (sectionName
);
498 // nothing. We need a context.