merge -r 96531:96532
[mono.git] / mcs / class / System.Web / System.Web.Configuration_2.0 / WebConfigurationManager.cs
1 //
2 // System.Web.Configuration.WebConfigurationManager.cs
3 //
4 // Authors:
5 //      Lluis Sanchez Gual (lluis@novell.com)
6 //      Chris Toshok (toshok@ximian.com)
7 //
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:
15 // 
16 // The above copyright notice and this permission notice shall be
17 // included in all copies or substantial portions of the Software.
18 // 
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.
26 //
27 // Copyright (C) 2005 Novell, Inc (http://www.novell.com)
28 //
29
30 #if NET_2_0
31
32 using System;
33 using System.IO;
34 using System.Collections;
35 using System.Collections.Specialized;
36 using System.Reflection;
37 using System.Web.Util;
38 using System.Xml;
39 using System.Configuration;
40 using System.Configuration.Internal;
41 using _Configuration = System.Configuration.Configuration;
42
43 namespace System.Web.Configuration {
44
45         public static class WebConfigurationManager
46         {
47 #if !TARGET_J2EE
48                 static IInternalConfigConfigurationFactory configFactory;
49                 static Hashtable configurations = Hashtable.Synchronized (new Hashtable ());
50                 static Hashtable sectionCache = new Hashtable (StringComparer.OrdinalIgnoreCase);
51 #else
52                 const string AppSettingsKey = "WebConfigurationManager.AppSettings";
53                 static internal IInternalConfigConfigurationFactory configFactory
54                 {
55                         get{
56                                 IInternalConfigConfigurationFactory factory = (IInternalConfigConfigurationFactory)AppDomain.CurrentDomain.GetData("WebConfigurationManager.configFactory");
57                                 if (factory == null){
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);
62                                                         if (prop != null){
63                                                                 factory = prop.GetValue(null, null) as IInternalConfigConfigurationFactory;
64                                                                 configFactory = factory;
65                                                         }
66                                                 }
67                                         }
68                                 }
69                                 return factory != null ? factory : configFactory;
70                         }
71                         set{
72                                 AppDomain.CurrentDomain.SetData("WebConfigurationManager.configFactory", value);
73                                 AppDomain.CurrentDomain.SetData("WebConfigurationManager.configFactory.initialized", true);
74                         }
75                 }
76
77                 static internal Hashtable configurations
78                 {
79                         get{
80                                 Hashtable table = (Hashtable)AppDomain.CurrentDomain.GetData("WebConfigurationManager.configurations");
81                                 if (table == null){
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;
87                                                 }
88                                         }
89                                 }
90                                 return table != null ? table : configurations;
91
92                         }
93                         set{
94                                 AppDomain.CurrentDomain.SetData("WebConfigurationManager.configurations", value);
95                                 AppDomain.CurrentDomain.SetData("WebConfigurationManager.configurations.initialized", true);
96                         }
97                 }
98
99                 static Hashtable sectionCache
100                 {
101                         get
102                         {
103                                 Hashtable sectionCache = (Hashtable) AppDomain.CurrentDomain.GetData ("sectionCache");
104                                 if (sectionCache == null) {
105                                         sectionCache = new Hashtable (StringComparer.OrdinalIgnoreCase);
106                                         AppDomain.CurrentDomain.SetData ("sectionCache", sectionCache);
107                                 }
108                                 return sectionCache;
109                         }
110                         set
111                         {
112                                 AppDomain.CurrentDomain.SetData ("sectionCache", value);
113                         }
114                 }
115 #endif
116
117                 static ArrayList extra_assemblies = null;
118                 static internal ArrayList ExtraAssemblies {
119                         get {
120                                 if (extra_assemblies == null)
121                                         extra_assemblies = new ArrayList();
122                                 return extra_assemblies;
123                         }
124                 }
125
126                 static bool hasConfigErrors = false;
127                 static object hasConfigErrorsLock = new object ();
128                 static internal bool HasConfigErrors {
129                         get {
130                                 lock (hasConfigErrorsLock) {
131                                         return hasConfigErrors;
132                                 }
133                         }
134                 }
135                 
136                 static WebConfigurationManager ()
137                 {
138                         PropertyInfo prop = typeof(ConfigurationManager).GetProperty ("ConfigurationFactory", BindingFlags.Static | BindingFlags.NonPublic);
139                         if (prop != null)
140                                 configFactory = prop.GetValue (null, null) as IInternalConfigConfigurationFactory;
141                 }
142
143                 public static _Configuration OpenMachineConfiguration ()
144                 {
145                         return ConfigurationManager.OpenMachineConfiguration ();
146                 }
147                 
148                 [MonoLimitation ("locationSubPath is not handled")]
149                 public static _Configuration OpenMachineConfiguration (string locationSubPath)
150                 {
151                         return OpenMachineConfiguration ();
152                 }
153
154                 [MonoLimitation("Mono does not support remote configuration")]
155                 public static _Configuration OpenMachineConfiguration (string locationSubPath,
156                                                                        string server)
157                 {
158                         if (server == null)
159                                 return OpenMachineConfiguration (locationSubPath);
160
161                         throw new NotSupportedException ("Mono doesn't support remote configuration");
162                 }
163
164                 [MonoLimitation("Mono does not support remote configuration")]
165                 public static _Configuration OpenMachineConfiguration (string locationSubPath,
166                                                                        string server,
167                                                                        IntPtr userToken)
168                 {
169                         if (server == null)
170                                 return OpenMachineConfiguration (locationSubPath);
171                         throw new NotSupportedException ("Mono doesn't support remote configuration");
172                 }
173
174                 [MonoLimitation("Mono does not support remote configuration")]
175                 public static _Configuration OpenMachineConfiguration (string locationSubPath,
176                                                                        string server,
177                                                                        string userName,
178                                                                        string password)
179                 {
180                         if (server == null)
181                                 return OpenMachineConfiguration (locationSubPath);
182                         throw new NotSupportedException ("Mono doesn't support remote configuration");
183                 }
184
185                 public static _Configuration OpenWebConfiguration (string path)
186                 {
187                         return OpenWebConfiguration (path, null, null, null, null, null);
188                 }
189                 
190                 public static _Configuration OpenWebConfiguration (string path, string site)
191                 {
192                         return OpenWebConfiguration (path, site, null, null, null, null);
193                 }
194                 
195                 public static _Configuration OpenWebConfiguration (string path, string site, string locationSubPath)
196                 {
197                         return OpenWebConfiguration (path, site, locationSubPath, null, null, null);
198                 }
199
200                 public static _Configuration OpenWebConfiguration (string path, string site, string locationSubPath, string server)
201                 {
202                         return OpenWebConfiguration (path, site, locationSubPath, server, null, null);
203                 }
204
205                 public static _Configuration OpenWebConfiguration (string path, string site, string locationSubPath, string server, IntPtr userToken)
206                 {
207                         return OpenWebConfiguration (path, site, locationSubPath, server, null, null);
208                 }
209                 
210                 public static _Configuration OpenWebConfiguration (string path, string site, string locationSubPath, string server, string userName, string password)
211                 {
212                         if (path == null || path.Length == 0)
213                                 path = "/";
214
215                         _Configuration conf;
216
217                         conf = (_Configuration) configurations [path];
218                         if (conf == null) {
219                                 try {
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;
225                                         }
226                                         throw ex;
227                                 }
228                         }
229                         return conf;
230                 }
231
232                 public static _Configuration OpenMappedWebConfiguration (WebConfigurationFileMap fileMap, string path)
233                 {
234                         return ConfigurationFactory.Create (typeof(WebConfigurationHost), fileMap, path);
235                 }
236                 
237                 public static _Configuration OpenMappedWebConfiguration (WebConfigurationFileMap fileMap, string path, string site)
238                 {
239                         return ConfigurationFactory.Create (typeof(WebConfigurationHost), fileMap, path, site);
240                 }
241                 
242                 public static _Configuration OpenMappedWebConfiguration (WebConfigurationFileMap fileMap, string path, string site, string locationSubPath)
243                 {
244                         return ConfigurationFactory.Create (typeof(WebConfigurationHost), fileMap, path, site, locationSubPath);
245                 }
246                 
247                 public static _Configuration OpenMappedMachineConfiguration (ConfigurationFileMap fileMap)
248                 {
249                         return ConfigurationFactory.Create (typeof(WebConfigurationHost), fileMap);
250                 }
251
252                 public static _Configuration OpenMappedMachineConfiguration (ConfigurationFileMap fileMap,
253                                                                              string locationSubPath)
254                 {
255                         return OpenMappedMachineConfiguration (fileMap);
256                 }
257
258                 internal static object SafeGetSection (string sectionName, Type configSectionType)
259                 {
260                         try {
261                                 return GetSection (sectionName);
262                         } catch (Exception) {
263                                 if (configSectionType != null)
264                                         return Activator.CreateInstance (configSectionType);
265                                 return null;
266                         }
267                 }
268                 
269                 internal static object SafeGetSection (string sectionName, string path, Type configSectionType)
270                 {
271                         try {
272                                 return GetSection (sectionName, path);
273                         } catch (Exception) {
274                                 if (configSectionType != null)
275                                         return Activator.CreateInstance (configSectionType);
276                                 return null;
277                         }
278                 }
279
280                 public static object GetSection (string sectionName)
281                 {
282                         return GetSection (sectionName, GetCurrentPath (HttpContext.Current));
283                 }
284
285                 public static object GetSection (string sectionName, string path)
286                 {
287                         object cachedSection = sectionCache [GetSectionCacheKey (sectionName, path)];
288                         if (cachedSection != null)
289                                 return cachedSection;
290
291                         _Configuration c = OpenWebConfiguration (path);
292                         ConfigurationSection section = c.GetSection (sectionName);
293
294                         if (section == null)
295                                 return null;
296
297 #if TARGET_J2EE
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);
302                                 value = collection;
303                         }
304
305                         AddSectionToCache (GetSectionCacheKey (sectionName, path), value);
306                         return value;
307 #else
308                         object value = SettingsMappingManager.MapSection (get_runtime_object.Invoke (section, new object [0]));
309                         AddSectionToCache (GetSectionCacheKey (sectionName, path), value);
310                         return value;
311 #endif
312                 }
313
314                 static string GetCurrentPath (HttpContext ctx)
315                 {
316                         return (ctx != null && ctx.Request != null) ? ctx.Request.Path : HttpRuntime.AppDomainAppVirtualPath;
317                 }
318
319                 internal static void RemoveConfigurationFromCache (HttpContext ctx)
320                 {
321                         configurations.Remove (GetCurrentPath (ctx));
322                 }
323
324                 readonly static MethodInfo get_runtime_object = typeof (ConfigurationSection).GetMethod ("GetRuntimeObject", BindingFlags.NonPublic | BindingFlags.Instance);
325
326                 public static object GetWebApplicationSection (string sectionName)
327                 {
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;
333
334                         return GetSection (sectionName, path);
335                 }
336
337                 public static NameValueCollection AppSettings {
338                         get { return ConfigurationManager.AppSettings; }
339                 }
340
341                 public static ConnectionStringSettingsCollection ConnectionStrings {
342                         get { return ConfigurationManager.ConnectionStrings; }
343                 }
344
345                 internal static IInternalConfigConfigurationFactory ConfigurationFactory {
346                         get { return configFactory; }
347                 }
348
349                 static void AddSectionToCache (string key, object section)
350                 {
351                         if (sectionCache [key] != null)
352                                 return;
353
354                         Hashtable tmpTable = (Hashtable) sectionCache.Clone ();
355                         if (tmpTable.Contains (key))
356                                 return;
357
358                         tmpTable.Add (key, section);
359                         sectionCache = tmpTable;
360                 }
361
362                 static string GetSectionCacheKey (string sectionName, string path)
363                 {
364                         return string.Concat (path, "/", sectionName);
365                 }
366
367                 
368 #region stuff copied from WebConfigurationSettings
369 #if TARGET_J2EE
370                 static internal IConfigurationSystem oldConfig {
371                         get {
372                                 return (IConfigurationSystem)AppDomain.CurrentDomain.GetData("WebConfigurationManager.oldConfig");
373                         }
374                         set {
375                                 AppDomain.CurrentDomain.SetData("WebConfigurationManager.oldConfig", value);
376                         }
377                 }
378
379                 static private Web20DefaultConfig config {
380                         get {
381                                 return (Web20DefaultConfig) AppDomain.CurrentDomain.GetData ("Web20DefaultConfig.config");
382                         }
383                         set {
384                                 AppDomain.CurrentDomain.SetData ("Web20DefaultConfig.config", value);
385                         }
386                 }
387
388                 static private IInternalConfigSystem configSystem {
389                         get {
390                                 return (IInternalConfigSystem) AppDomain.CurrentDomain.GetData ("IInternalConfigSystem.configSystem");
391                         }
392                         set {
393                                 AppDomain.CurrentDomain.SetData ("IInternalConfigSystem.configSystem", value);
394                         }
395                 }
396 #else
397                 static internal IConfigurationSystem oldConfig;
398                 static Web20DefaultConfig config;
399                 //static IInternalConfigSystem configSystem;
400 #endif
401                 const BindingFlags privStatic = BindingFlags.NonPublic | BindingFlags.Static;
402                 static readonly object lockobj = new object ();
403
404                 internal static void Init ()
405                 {
406                         lock (lockobj) {
407                                 if (config != null)
408                                         return;
409
410                                 /* deal with the ConfigurationSettings stuff */
411                                 {
412                                         Web20DefaultConfig settings = Web20DefaultConfig.GetInstance ();
413                                         Type t = typeof (ConfigurationSettings);
414                                         MethodInfo changeConfig = t.GetMethod ("ChangeConfigurationSystem",
415                                                                                privStatic);
416
417                                         if (changeConfig == null)
418                                                 throw new ConfigurationException ("Cannot find method CCS");
419
420                                         object [] args = new object [] {settings};
421                                         oldConfig = (IConfigurationSystem)changeConfig.Invoke (null, args);
422                                         config = settings;
423
424                                         config.Init ();
425                                 }
426
427                                 /* deal with the ConfigurationManager stuff */
428                                 {
429                                         HttpConfigurationSystem system = new HttpConfigurationSystem ();
430                                         Type t = typeof (ConfigurationManager);
431                                         MethodInfo changeConfig = t.GetMethod ("ChangeConfigurationSystem",
432                                                                                privStatic);
433
434                                         if (changeConfig == null)
435                                                 throw new ConfigurationException ("Cannot find method CCS");
436
437                                         object [] args = new object [] {system};
438                                         changeConfig.Invoke (null, args);
439                                         //configSystem = system;
440                                 }
441                         }
442                 }
443         }
444
445         class Web20DefaultConfig : IConfigurationSystem
446         {
447 #if TARGET_J2EE
448                 static private Web20DefaultConfig instance {
449                         get {
450                                 Web20DefaultConfig val = (Web20DefaultConfig)AppDomain.CurrentDomain.GetData("Web20DefaultConfig.instance");
451                                 if (val == null) {
452                                         val = new Web20DefaultConfig();
453                                         AppDomain.CurrentDomain.SetData("Web20DefaultConfig.instance", val);
454                                 }
455                                 return val;
456                         }
457                         set {
458                                 AppDomain.CurrentDomain.SetData("Web20DefaultConfig.instance", value);
459                         }
460                 }
461 #else
462                 static Web20DefaultConfig instance;
463 #endif
464
465                 static Web20DefaultConfig ()
466                 {
467                         instance = new Web20DefaultConfig ();
468                 }
469
470                 public static Web20DefaultConfig GetInstance ()
471                 {
472                         return instance;
473                 }
474
475                 public object GetConfig (string sectionName)
476                 {
477                         object o = WebConfigurationManager.GetWebApplicationSection (sectionName);
478
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
486                                  * for it.
487                                  */
488                                 object o1 = WebConfigurationManager.oldConfig.GetConfig (sectionName);
489                                 if (o1 != null)
490                                         return o1;
491                         }
492
493                         return o;
494                 }
495
496                 public void Init ()
497                 {
498                         // nothing. We need a context.
499                 }
500         }
501
502 #endregion
503 }
504
505 #endif