Merge pull request #2916 from ludovic-henry/fix-40306
[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 //      Marek Habersack <mhabersack@novell.com>
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 // 
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28 // Copyright (C) 2005-2009 Novell, Inc (http://www.novell.com)
29 //
30
31
32 using System;
33 using System.IO;
34 using System.Collections;
35 using System.Collections.Generic;
36 using System.Collections.Specialized;
37 using System.Reflection;
38 using Mono.Web.Util;
39 using System.Xml;
40 using System.Configuration;
41 using System.Configuration.Internal;
42 using _Configuration = System.Configuration.Configuration;
43 using System.Web.Util;
44 using System.Threading;
45 using System.Web.Hosting;
46
47 namespace System.Web.Configuration {
48
49         public static class WebConfigurationManager
50         {
51                 sealed class ConfigPath 
52                 {
53                         public string Path;
54                         public bool InAnotherApp;
55
56                         public ConfigPath (string path, bool inAnotherApp)
57                         {
58                                 this.Path = path;
59                                 this.InAnotherApp = inAnotherApp;
60                         }
61                 }
62                 
63                 const int SAVE_LOCATIONS_CHECK_INTERVAL = 6000; // milliseconds
64                 const int SECTION_CACHE_LOCK_TIMEOUT = 200; // milliseconds
65
66                 static readonly char[] pathTrimChars = { '/' };
67                 static readonly object suppressAppReloadLock = new object ();
68                 static readonly object saveLocationsCacheLock = new object ();
69                 static readonly object getSectionLock = new object ();
70                 
71                 // See comment for the cacheLock field at top of System.Web.Caching/Cache.cs
72                 static readonly ReaderWriterLockSlim sectionCacheLock;
73
74                 static IInternalConfigConfigurationFactory configFactory;
75                 static Hashtable configurations = Hashtable.Synchronized (new Hashtable ());
76                 static Hashtable configPaths = Hashtable.Synchronized (new Hashtable ());
77                 static bool suppressAppReload;
78                 static Dictionary <string, DateTime> saveLocationsCache;
79                 static Timer saveLocationsTimer;
80                 
81                 static ArrayList extra_assemblies = null;
82                 static internal ArrayList ExtraAssemblies {
83                         get {
84                                 if (extra_assemblies == null)
85                                         extra_assemblies = new ArrayList();
86                                 return extra_assemblies;
87                         }
88                 }
89
90                 const int DEFAULT_SECTION_CACHE_SIZE = 100;
91                 const string CACHE_SIZE_OVERRIDING_KEY = "MONO_ASPNET_WEBCONFIG_CACHESIZE";
92                 static LruCache<int, object> sectionCache;
93                 
94                 static WebConfigurationManager ()
95                 {
96                         var section_cache_size = DEFAULT_SECTION_CACHE_SIZE;
97                         int section_cache_size_override;
98                         bool size_overriden = false;
99                         if (int.TryParse (Environment.GetEnvironmentVariable (CACHE_SIZE_OVERRIDING_KEY), out section_cache_size_override)) {
100                                 section_cache_size = section_cache_size_override;
101                                 size_overriden = true;
102                                 Console.WriteLine ("WebConfigurationManager's LRUcache Size overriden to: {0} (via {1})", section_cache_size_override, CACHE_SIZE_OVERRIDING_KEY);
103                         }
104                         sectionCache = new LruCache<int, object> (section_cache_size);
105                         string eviction_warning = "WebConfigurationManager's LRUcache evictions count reached its max size";
106                         if (!size_overriden)
107                                 eviction_warning += String.Format ("{0}Cache Size: {1} (overridable via {2})",
108                                                                    Environment.NewLine, section_cache_size, CACHE_SIZE_OVERRIDING_KEY);
109                         sectionCache.EvictionWarning = eviction_warning;
110
111                         configFactory = ConfigurationManager.ConfigurationFactory;
112                         _Configuration.SaveStart += ConfigurationSaveHandler;
113                         _Configuration.SaveEnd += ConfigurationSaveHandler;
114                         
115                         // Part of fix for bug #491531
116                         Type type = Type.GetType ("System.Configuration.CustomizableFileSettingsProvider, System", false);
117                         if (type != null) {
118                                 FieldInfo fi = type.GetField ("webConfigurationFileMapType", BindingFlags.Static | BindingFlags.NonPublic);
119                                 if (fi != null && fi.FieldType == Type.GetType ("System.Type"))
120                                         fi.SetValue (null, typeof (ApplicationSettingsConfigurationFileMap));
121                         }
122
123                         sectionCacheLock = new ReaderWriterLockSlim ();
124                 }
125
126                 static void ReenableWatcherOnConfigLocation (object state)
127                 {
128                         string path = state as string;
129                         if (String.IsNullOrEmpty (path))
130                                 return;
131
132                         DateTime lastWrite;
133                         lock (saveLocationsCacheLock) {
134                                 if (!saveLocationsCache.TryGetValue (path, out lastWrite))
135                                         lastWrite = DateTime.MinValue;
136                         }
137
138                         DateTime now = DateTime.Now;
139                         if (lastWrite == DateTime.MinValue || now.Subtract (lastWrite).TotalMilliseconds >= SAVE_LOCATIONS_CHECK_INTERVAL) {
140                                 saveLocationsTimer.Dispose ();
141                                 saveLocationsTimer = null;
142                                 HttpApplicationFactory.EnableWatcher (VirtualPathUtility.RemoveTrailingSlash (HttpRuntime.AppDomainAppPath), "?eb.?onfig");
143                         } else
144                                 saveLocationsTimer.Change (SAVE_LOCATIONS_CHECK_INTERVAL, SAVE_LOCATIONS_CHECK_INTERVAL);
145                 }
146                 
147                 static void ConfigurationSaveHandler (_Configuration sender, ConfigurationSaveEventArgs args)
148                 {
149                         try {
150                                 sectionCacheLock.EnterWriteLock ();
151                                 sectionCache.Clear ();
152                         } finally {
153                                 sectionCacheLock.ExitWriteLock ();
154                         }
155                         
156                         lock (suppressAppReloadLock) {
157                                 string rootConfigPath = WebConfigurationHost.GetWebConfigFileName (HttpRuntime.AppDomainAppPath);
158                                 if (String.Compare (args.StreamPath, rootConfigPath, StringComparison.OrdinalIgnoreCase) == 0) {
159                                         SuppressAppReload (args.Start);
160                                         if (args.Start) {
161                                                 HttpApplicationFactory.DisableWatcher (VirtualPathUtility.RemoveTrailingSlash (HttpRuntime.AppDomainAppPath), "?eb.?onfig");
162
163                                                 lock (saveLocationsCacheLock) {
164                                                         if (saveLocationsCache == null)
165                                                                 saveLocationsCache = new Dictionary <string, DateTime> (StringComparer.Ordinal);
166                                                         if (saveLocationsCache.ContainsKey (rootConfigPath))
167                                                                 saveLocationsCache [rootConfigPath] = DateTime.Now;
168                                                         else
169                                                                 saveLocationsCache.Add (rootConfigPath, DateTime.Now);
170
171                                                         if (saveLocationsTimer == null)
172                                                                 saveLocationsTimer = new Timer (ReenableWatcherOnConfigLocation,
173                                                                                                 rootConfigPath,
174                                                                                                 SAVE_LOCATIONS_CHECK_INTERVAL,
175                                                                                                 SAVE_LOCATIONS_CHECK_INTERVAL);
176                                                 }
177                                         }
178                                 }
179                         }
180                 }
181                 
182                 public static _Configuration OpenMachineConfiguration ()
183                 {
184                         return ConfigurationManager.OpenMachineConfiguration ();
185                 }
186                 
187                 [MonoLimitation ("locationSubPath is not handled")]
188                 public static _Configuration OpenMachineConfiguration (string locationSubPath)
189                 {
190                         return OpenMachineConfiguration ();
191                 }
192
193                 [MonoLimitation("Mono does not support remote configuration")]
194                 public static _Configuration OpenMachineConfiguration (string locationSubPath,
195                                                                        string server)
196                 {
197                         if (server == null)
198                                 return OpenMachineConfiguration (locationSubPath);
199
200                         throw new NotSupportedException ("Mono doesn't support remote configuration");
201                 }
202
203                 [MonoLimitation("Mono does not support remote configuration")]
204                 public static _Configuration OpenMachineConfiguration (string locationSubPath,
205                                                                        string server,
206                                                                        IntPtr userToken)
207                 {
208                         if (server == null)
209                                 return OpenMachineConfiguration (locationSubPath);
210                         throw new NotSupportedException ("Mono doesn't support remote configuration");
211                 }
212
213                 [MonoLimitation("Mono does not support remote configuration")]
214                 public static _Configuration OpenMachineConfiguration (string locationSubPath,
215                                                                        string server,
216                                                                        string userName,
217                                                                        string password)
218                 {
219                         if (server == null)
220                                 return OpenMachineConfiguration (locationSubPath);
221                         throw new NotSupportedException ("Mono doesn't support remote configuration");
222                 }
223
224                 public static _Configuration OpenWebConfiguration (string path)
225                 {
226                         return OpenWebConfiguration (path, null, null, null, null, null);
227                 }
228                 
229                 public static _Configuration OpenWebConfiguration (string path, string site)
230                 {
231                         return OpenWebConfiguration (path, site, null, null, null, null);
232                 }
233                 
234                 public static _Configuration OpenWebConfiguration (string path, string site, string locationSubPath)
235                 {
236                         return OpenWebConfiguration (path, site, locationSubPath, null, null, null);
237                 }
238
239                 public static _Configuration OpenWebConfiguration (string path, string site, string locationSubPath, string server)
240                 {
241                         return OpenWebConfiguration (path, site, locationSubPath, server, null, null);
242                 }
243
244                 public static _Configuration OpenWebConfiguration (string path, string site, string locationSubPath, string server, IntPtr userToken)
245                 {
246                         return OpenWebConfiguration (path, site, locationSubPath, server, null, null);
247                 }
248                 
249                 public static _Configuration OpenWebConfiguration (string path, string site, string locationSubPath, string server, string userName, string password)
250                 {
251                         return OpenWebConfiguration (path, site, locationSubPath, server, null, null, false);
252                 }
253
254                 static _Configuration OpenWebConfiguration (string path, string site, string locationSubPath, string server, string userName, string password, bool fweb)
255                 {
256                         if (String.IsNullOrEmpty (path))
257                                 path = "/";
258
259                         bool inAnotherApp = false;
260                         if (!fweb && !String.IsNullOrEmpty (path))
261                                 path = FindWebConfig (path, out inAnotherApp);
262
263                         string confKey = path + site + locationSubPath + server + userName + password;
264                         _Configuration conf = null;
265                         conf = (_Configuration) configurations [confKey];
266                         if (conf == null) {
267                                 conf = ConfigurationFactory.Create (typeof (WebConfigurationHost), null, path, site, locationSubPath, server, userName, password, inAnotherApp);
268                                 configurations [confKey] = conf;
269                         }
270                         return conf;
271                 }
272
273                 public static _Configuration OpenMappedWebConfiguration (WebConfigurationFileMap fileMap, string path)
274                 {
275                         return ConfigurationFactory.Create (typeof(WebConfigurationHost), fileMap, path);
276                 }
277                 
278                 public static _Configuration OpenMappedWebConfiguration (WebConfigurationFileMap fileMap, string path, string site)
279                 {
280                         return ConfigurationFactory.Create (typeof(WebConfigurationHost), fileMap, path, site);
281                 }
282                 
283                 public static _Configuration OpenMappedWebConfiguration (WebConfigurationFileMap fileMap, string path, string site, string locationSubPath)
284                 {
285                         return ConfigurationFactory.Create (typeof(WebConfigurationHost), fileMap, path, site, locationSubPath);
286                 }
287                 
288                 public static _Configuration OpenMappedMachineConfiguration (ConfigurationFileMap fileMap)
289                 {
290                         return ConfigurationFactory.Create (typeof(WebConfigurationHost), fileMap);
291                 }
292
293                 public static _Configuration OpenMappedMachineConfiguration (ConfigurationFileMap fileMap,
294                                                                              string locationSubPath)
295                 {
296                         return OpenMappedMachineConfiguration (fileMap);
297                 }
298
299                 internal static object SafeGetSection (string sectionName, Type configSectionType)
300                 {
301                         try {
302                                 return GetSection (sectionName);
303                         } catch (Exception) {
304                                 if (configSectionType != null)
305                                         return Activator.CreateInstance (configSectionType);
306                                 return null;
307                         }
308                 }
309                 
310                 internal static object SafeGetSection (string sectionName, string path, Type configSectionType)
311                 {
312                         try {
313                                 return GetSection (sectionName, path);
314                         } catch (Exception) {
315                                 if (configSectionType != null)
316                                         return Activator.CreateInstance (configSectionType);
317                                 return null;
318                         }
319                 }
320                 
321                 public static object GetSection (string sectionName)
322                 {
323                         HttpContext context = HttpContext.Current;
324                         return GetSection (sectionName, GetCurrentPath (context), context);
325                 }
326
327                 public static object GetSection (string sectionName, string path)
328                 {
329                         return GetSection (sectionName, path, HttpContext.Current);
330                 }
331
332                 static bool LookUpLocation (string relativePath, ref _Configuration defaultConfiguration)
333                 {
334                         if (String.IsNullOrEmpty (relativePath))
335                                 return false;
336
337                         _Configuration cnew = defaultConfiguration.FindLocationConfiguration (relativePath, defaultConfiguration);
338                         if (cnew == defaultConfiguration)
339                                 return false;
340
341                         defaultConfiguration = cnew;
342                         return true;
343                 }
344                 
345                 internal static object GetSection (string sectionName, string path, HttpContext context)
346                 {
347                         if (String.IsNullOrEmpty (sectionName))
348                                 return null;
349                         
350                         _Configuration c = OpenWebConfiguration (path, null, null, null, null, null, false);
351                         string configPath = c.ConfigPath;
352                         int baseCacheKey = 0;
353                         int cacheKey;
354                         bool pathPresent = !String.IsNullOrEmpty (path);
355                         string locationPath = null;
356
357                         if (pathPresent)
358                                 locationPath = "location_" + path;
359                         
360                         baseCacheKey = sectionName.GetHashCode ();
361                         if (configPath != null)
362                                 baseCacheKey ^= configPath.GetHashCode ();
363                         
364                         try {
365                                 sectionCacheLock.EnterWriteLock ();
366                                 
367                                 object o;
368                                 if (pathPresent) {
369                                         cacheKey = baseCacheKey ^ locationPath.GetHashCode ();
370                                         if (sectionCache.TryGetValue (cacheKey, out o))
371                                                 return o;
372                                 
373                                         cacheKey = baseCacheKey ^ path.GetHashCode ();
374                                         if (sectionCache.TryGetValue (cacheKey, out o))
375                                                 return o;
376                                 }
377                                 
378                                 if (sectionCache.TryGetValue (baseCacheKey, out o))
379                                         return o;
380                         } finally {
381                                 sectionCacheLock.ExitWriteLock ();
382                         }
383
384                         string cachePath = null;
385                         if (pathPresent) {
386                                 string relPath;
387                                 
388                                 if (VirtualPathUtility.IsRooted (path)) {
389                                         if (path [0] == '~')
390                                                 relPath = path.Length > 1 ? path.Substring (2) : String.Empty;
391                                         else if (path [0] == '/')
392                                                 relPath = path.Substring (1);
393                                         else
394                                                 relPath = path;
395                                 } else
396                                         relPath = path;
397
398                                 HttpRequest req = context != null ? context.Request : null;
399                                 if (req != null) {
400                                         string vdir = VirtualPathUtility.GetDirectory (req.PathNoValidation);
401                                         if (vdir != null) {
402                                                 vdir = vdir.TrimEnd (pathTrimChars);
403                                                 if (String.Compare (c.ConfigPath, vdir, StringComparison.Ordinal) != 0 && LookUpLocation (vdir.Trim (pathTrimChars), ref c))
404                                                         cachePath = path;
405                                         }
406                                 }
407                                 
408                                 if (LookUpLocation (relPath, ref c))
409                                         cachePath = locationPath;
410                                 else
411                                         cachePath = path;
412                         }
413
414                         ConfigurationSection section;
415                         lock (getSectionLock) {
416                                 section = c.GetSection (sectionName);
417                         }
418                         if (section == null)
419                                 return null;
420
421                         object value = SettingsMappingManager.MapSection (section.GetRuntimeObject ());
422                         if (cachePath != null)
423                                 cacheKey = baseCacheKey ^ cachePath.GetHashCode ();
424                         else
425                                 cacheKey = baseCacheKey;
426                         
427                         AddSectionToCache (cacheKey, value);
428                         return value;
429                 }
430                 
431                 static string MapPath (HttpRequest req, string virtualPath)
432                 {
433                         if (req != null)
434                                 return req.MapPath (virtualPath);
435
436                         string appRoot = HttpRuntime.AppDomainAppVirtualPath;
437                         if (!String.IsNullOrEmpty (appRoot) && virtualPath.StartsWith (appRoot, StringComparison.Ordinal)) {
438                                 if (String.Compare (virtualPath, appRoot, StringComparison.Ordinal) == 0)
439                                         return HttpRuntime.AppDomainAppPath;
440                                 return UrlUtils.Combine (HttpRuntime.AppDomainAppPath, virtualPath.Substring (appRoot.Length));
441                         }
442                         
443                         return null;
444                 }
445
446                 static string GetParentDir (string rootPath, string curPath)
447                 {
448                         int len = curPath.Length - 1;
449                         if (len > 0 && curPath [len] == '/')
450                                 curPath = curPath.Substring (0, len);
451
452                         if (String.Compare (curPath, rootPath, StringComparison.Ordinal) == 0)
453                                 return null;
454                         
455                         int idx = curPath.LastIndexOf ('/');
456                         if (idx == -1)
457                                 return curPath;
458
459                         if (idx == 0)
460                                 return "/";
461                         
462                         return curPath.Substring (0, idx);
463                 }
464
465                 internal static string FindWebConfig (string path)
466                 {
467                         bool dummy;
468
469                         return FindWebConfig (path, out dummy);
470                 }
471                 
472                 internal static string FindWebConfig (string path, out bool inAnotherApp)
473                 {
474                         inAnotherApp = false;
475                         
476                         if (String.IsNullOrEmpty (path))
477                                 return path;
478                                 
479                         if (HostingEnvironment.VirtualPathProvider != null) {
480                                 if (HostingEnvironment.VirtualPathProvider.DirectoryExists (path))
481                                         path = VirtualPathUtility.AppendTrailingSlash (path);
482                         }
483                                 
484                         
485                         string rootPath = HttpRuntime.AppDomainAppVirtualPath;
486                         ConfigPath curPath;
487                         curPath = configPaths [path] as ConfigPath;
488                         if (curPath != null) {
489                                 inAnotherApp = curPath.InAnotherApp;
490                                 return curPath.Path;
491                         }
492                         
493                         HttpContext ctx = HttpContext.Current;
494                         HttpRequest req = ctx != null ? ctx.Request : null;
495                         string physPath = req != null ? VirtualPathUtility.AppendTrailingSlash (MapPath (req, path)) : null;
496                         string appDomainPath = HttpRuntime.AppDomainAppPath;
497                         
498                         if (physPath != null && appDomainPath != null && !physPath.StartsWith (appDomainPath, StringComparison.Ordinal))
499                                 inAnotherApp = true;
500                         
501                         string dir;
502                         if (inAnotherApp || path [path.Length - 1] == '/')
503                                 dir = path;
504                         else {
505                                 dir = VirtualPathUtility.GetDirectory (path, false);
506                                 if (dir == null)
507                                         return path;
508                         }
509                         
510                         curPath = configPaths [dir] as ConfigPath;
511                         if (curPath != null) {
512                                 inAnotherApp = curPath.InAnotherApp;
513                                 return curPath.Path;
514                         }
515                         
516                         if (req == null)
517                                 return path;
518
519                         curPath = new ConfigPath (path, inAnotherApp);
520                         while (String.Compare (curPath.Path, rootPath, StringComparison.Ordinal) != 0) {
521                                 physPath = MapPath (req, curPath.Path);
522                                 if (physPath == null) {
523                                         curPath.Path = rootPath;
524                                         break;
525                                 }
526
527                                 if (WebConfigurationHost.GetWebConfigFileName (physPath) != null)
528                                         break;
529                                 
530                                 curPath.Path = GetParentDir (rootPath, curPath.Path);
531                                 if (curPath.Path == null || curPath.Path == "~") {
532                                         curPath.Path = rootPath;
533                                         break;
534                                 }
535                         }
536
537                         if (String.Compare (curPath.Path, path, StringComparison.Ordinal) != 0)
538                                 configPaths [path] = curPath;
539                         else
540                                 configPaths [dir] = curPath;
541                         
542                         return curPath.Path;
543                 }
544                 
545                 static string GetCurrentPath (HttpContext ctx)
546                 {
547                         HttpRequest req = ctx != null ? ctx.Request : null;
548                         return req != null ? req.PathNoValidation : HttpRuntime.AppDomainAppVirtualPath;
549                 }
550                 
551                 internal static bool SuppressAppReload (bool newValue)
552                 {
553                         bool ret;
554                         
555                         lock (suppressAppReloadLock) {
556                                 ret = suppressAppReload;
557                                 suppressAppReload = newValue;
558                         }
559
560                         return ret;
561                 }
562                 
563                 internal static void RemoveConfigurationFromCache (HttpContext ctx)
564                 {
565                         configurations.Remove (GetCurrentPath (ctx));
566                 }
567
568
569                 public static object GetWebApplicationSection (string sectionName)
570                 {
571                         HttpContext ctx = HttpContext.Current;
572                         HttpRequest req = ctx != null ? ctx.Request : null;
573                         string applicationPath = req != null ? req.ApplicationPath : null;
574                         return GetSection (sectionName, String.IsNullOrEmpty (applicationPath) ? String.Empty : applicationPath);
575                 }
576
577                 public static NameValueCollection AppSettings {
578                         get { return ConfigurationManager.AppSettings; }
579                 }
580
581                 public static ConnectionStringSettingsCollection ConnectionStrings {
582                         get { return ConfigurationManager.ConnectionStrings; }
583                 }
584
585                 internal static IInternalConfigConfigurationFactory ConfigurationFactory {
586                         get { return configFactory; }
587                 }
588
589                 static void AddSectionToCache (int key, object section)
590                 {
591                         object cachedSection;
592
593                         bool locked = false;
594                         try {
595                                 if (!sectionCacheLock.TryEnterWriteLock (SECTION_CACHE_LOCK_TIMEOUT))
596                                         return;
597                                 locked = true;
598
599                                 if (sectionCache.TryGetValue (key, out cachedSection) && cachedSection != null)
600                                         return;
601
602                                 sectionCache.Add (key, section);
603                         } finally {
604                                 if (locked) {
605                                         sectionCacheLock.ExitWriteLock ();
606                                 }
607                         }
608                 }
609                 
610 #region stuff copied from WebConfigurationSettings
611                 static internal IConfigurationSystem oldConfig;
612                 static Web20DefaultConfig config;
613                 //static IInternalConfigSystem configSystem;
614                 const BindingFlags privStatic = BindingFlags.NonPublic | BindingFlags.Static;
615                 static readonly object lockobj = new object ();
616
617                 internal static void Init ()
618                 {
619                         lock (lockobj) {
620                                 if (config != null)
621                                         return;
622
623                                 /* deal with the ConfigurationSettings stuff */
624                                 {
625                                         Web20DefaultConfig settings = Web20DefaultConfig.GetInstance ();
626                                         Type t = typeof (ConfigurationSettings);
627                                         MethodInfo changeConfig = t.GetMethod ("ChangeConfigurationSystem",
628                                                                                privStatic);
629
630                                         if (changeConfig == null)
631                                                 throw new ConfigurationException ("Cannot find method CCS");
632
633                                         object [] args = new object [] {settings};
634                                         oldConfig = (IConfigurationSystem)changeConfig.Invoke (null, args);
635                                         config = settings;
636
637                                         config.Init ();
638                                 }
639
640                                 /* deal with the ConfigurationManager stuff */
641                                 {
642                                         HttpConfigurationSystem system = new HttpConfigurationSystem ();
643                                         Type t = typeof (ConfigurationManager);
644                                         MethodInfo changeConfig = t.GetMethod ("ChangeConfigurationSystem",
645                                                                                privStatic);
646
647                                         if (changeConfig == null)
648                                                 throw new ConfigurationException ("Cannot find method CCS");
649
650                                         object [] args = new object [] {system};
651                                         changeConfig.Invoke (null, args);
652                                         //configSystem = system;
653                                 }
654                         }
655                 }
656         }
657
658         class Web20DefaultConfig : IConfigurationSystem
659         {
660                 static Web20DefaultConfig instance;
661
662                 static Web20DefaultConfig ()
663                 {
664                         instance = new Web20DefaultConfig ();
665                 }
666
667                 public static Web20DefaultConfig GetInstance ()
668                 {
669                         return instance;
670                 }
671
672                 public object GetConfig (string sectionName)
673                 {
674                         object o = WebConfigurationManager.GetWebApplicationSection (sectionName);
675
676                         if (o == null || o is IgnoreSection) {
677                                 /* this can happen when the section
678                                  * handler doesn't subclass from
679                                  * ConfigurationSection.  let's be
680                                  * nice and try to load it using the
681                                  * 1.x style routines in case there's
682                                  * a 1.x section handler registered
683                                  * for it.
684                                  */
685                                 object o1 = WebConfigurationManager.oldConfig.GetConfig (sectionName);
686                                 if (o1 != null)
687                                         return o1;
688                         }
689
690                         return o;
691                 }
692
693                 public void Init ()
694                 {
695                         // nothing. We need a context.
696                 }
697         }
698 #endregion
699 }
700