* WebConfigurationManager.cs: fixed GetSection to execute GetRuntimeObject, refactore...
[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.Xml;
38 using System.Configuration;
39 using System.Configuration.Internal;
40 using _Configuration = System.Configuration.Configuration;
41
42 namespace System.Web.Configuration {
43
44         public static class WebConfigurationManager
45         {
46 #if !TARGET_J2EE
47                 static IInternalConfigConfigurationFactory configFactory;
48                 static Hashtable configurations = new Hashtable ();
49 #else
50                 static internal IInternalConfigConfigurationFactory configFactory
51                 {
52                         get{
53                                 IInternalConfigConfigurationFactory factory = (IInternalConfigConfigurationFactory)AppDomain.CurrentDomain.GetData("WebConfigurationManager.configFactory");
54                                 if (factory == null){
55                                         lock (AppDomain.CurrentDomain){
56                                                 object initialized = AppDomain.CurrentDomain.GetData("WebConfigurationManager.configFactory.initialized");
57                                                 if (initialized == null){
58                                                         PropertyInfo prop = typeof(ConfigurationManager).GetProperty("ConfigurationFactory", BindingFlags.Static | BindingFlags.NonPublic);
59                                                         if (prop != null){
60                                                                 factory = prop.GetValue(null, null) as IInternalConfigConfigurationFactory;
61                                                                 configFactory = factory;
62                                                         }
63                                                 }
64                                         }
65                                 }
66                                 return factory != null ? factory : configFactory;
67                         }
68                         set{
69                                 AppDomain.CurrentDomain.SetData("WebConfigurationManager.configFactory", value);
70                                 AppDomain.CurrentDomain.SetData("WebConfigurationManager.configFactory.initialized", true);
71                         }
72                 }
73
74                 static internal Hashtable configurations
75                 {
76                         get{
77                                 Hashtable table = (Hashtable)AppDomain.CurrentDomain.GetData("WebConfigurationManager.configurations");
78                                 if (table == null){
79                                         lock (AppDomain.CurrentDomain){
80                                                 object initialized = AppDomain.CurrentDomain.GetData("WebConfigurationManager.configurations.initialized");
81                                                 if (initialized == null){
82                                                         table = new Hashtable();
83                                                         configurations = table;
84                                                 }
85                                         }
86                                 }
87                                 return table != null ? table : configurations;
88
89                         }
90                         set{
91                                 AppDomain.CurrentDomain.SetData("WebConfigurationManager.configurations", value);
92                                 AppDomain.CurrentDomain.SetData("WebConfigurationManager.configurations.initialized", true);
93                         }
94                 }
95 #endif
96
97                 static internal ArrayList extra_assemblies = null;
98                 static internal ArrayList ExtraAssemblies {
99                         get {
100                                 if (extra_assemblies == null)
101                                         extra_assemblies = new ArrayList();
102                                 return extra_assemblies;
103                         }
104                 }
105                 
106                 static WebConfigurationManager ()
107                 {
108                         PropertyInfo prop = typeof(ConfigurationManager).GetProperty ("ConfigurationFactory", BindingFlags.Static | BindingFlags.NonPublic);
109                         if (prop != null)
110                                 configFactory = prop.GetValue (null, null) as IInternalConfigConfigurationFactory;
111                 }
112
113                 public static _Configuration OpenMachineConfiguration ()
114                 {
115                         return ConfigurationManager.OpenMachineConfiguration ();
116                 }
117                 
118                 [MonoTODO ("need to handle locationSubPath")]
119                 public static _Configuration OpenMachineConfiguration (string locationSubPath)
120                 {
121                         return OpenMachineConfiguration ();
122                 }
123
124                 [MonoTODO("Mono does not support remote configuration")]
125                 public static _Configuration OpenMachineConfiguration (string locationSubPath,
126                                                                        string server)
127                 {
128                         if (server == null)
129                                 return OpenMachineConfiguration (locationSubPath);
130
131                         throw new NotSupportedException ("Mono doesn't support remote configuration");
132                 }
133
134                 [MonoTODO("Mono does not support remote configuration")]
135                 public static _Configuration OpenMachineConfiguration (string locationSubPath,
136                                                                        string server,
137                                                                        IntPtr userToken)
138                 {
139                         if (server == null)
140                                 return OpenMachineConfiguration (locationSubPath);
141                         throw new NotSupportedException ("Mono doesn't support remote configuration");
142                 }
143
144                 [MonoTODO("Mono does not support remote configuration")]
145                 public static _Configuration OpenMachineConfiguration (string locationSubPath,
146                                                                        string server,
147                                                                        string userName,
148                                                                        string password)
149                 {
150                         if (server == null)
151                                 return OpenMachineConfiguration (locationSubPath);
152                         throw new NotSupportedException ("Mono doesn't support remote configuration");
153                 }
154
155                 public static _Configuration OpenWebConfiguration (string path)
156                 {
157                         return OpenWebConfiguration (path, null, null, null, null, null);
158                 }
159                 
160                 public static _Configuration OpenWebConfiguration (string path, string site)
161                 {
162                         return OpenWebConfiguration (path, site, null, null, null, null);
163                 }
164                 
165                 public static _Configuration OpenWebConfiguration (string path, string site, string locationSubPath)
166                 {
167                         return OpenWebConfiguration (path, site, locationSubPath, null, null, null);
168                 }
169
170                 public static _Configuration OpenWebConfiguration (string path, string site, string locationSubPath, string server)
171                 {
172                         return OpenWebConfiguration (path, site, locationSubPath, server, null, null);
173                 }
174
175                 public static _Configuration OpenWebConfiguration (string path, string site, string locationSubPath, string server, IntPtr userToken)
176                 {
177                         return OpenWebConfiguration (path, site, locationSubPath, server, null, null);
178                 }
179                 
180                 public static _Configuration OpenWebConfiguration (string path, string site, string locationSubPath, string server, string userName, string password)
181                 {
182                         if (path == null)
183                                 path = "";
184
185                         string basePath = GetBasePath (path);
186                         _Configuration conf;
187
188                         
189                         lock (configurations) {
190                                 conf = (_Configuration) configurations [basePath];
191                                 if (conf == null) {
192                                         conf = ConfigurationFactory.Create (typeof(WebConfigurationHost), null, basePath, site, locationSubPath, server, userName, password);
193                                         configurations [basePath] = conf;
194                                 }
195                         }
196                         if (basePath.Length < path.Length) {
197                         
198                                 // If the path has a file name, look for a location specific configuration
199                                 
200                                 int dif = path.Length - basePath.Length;
201                                 string file = path.Substring (path.Length - dif);
202                                 int i=0;
203                                 while (i < file.Length && file [i] == '/')
204                                         i++;
205                                 if (i != 0)
206                                         file = file.Substring (i);
207
208                                 if (file.Length != 0) {
209                                         foreach (ConfigurationLocation loc in conf.Locations) {
210                                                 if (loc.Path == file)
211                                                         return loc.OpenConfiguration ();
212                                         }
213                                 }
214                         }
215                         return conf;
216                 }
217
218                 public static _Configuration OpenMappedWebConfiguration (WebConfigurationFileMap fileMap, string path)
219                 {
220                         return ConfigurationFactory.Create (typeof(WebConfigurationHost), fileMap, path);
221                 }
222                 
223                 public static _Configuration OpenMappedWebConfiguration (WebConfigurationFileMap fileMap, string path, string site)
224                 {
225                         return ConfigurationFactory.Create (typeof(WebConfigurationHost), fileMap, path, site);
226                 }
227                 
228                 public static _Configuration OpenMappedWebConfiguration (WebConfigurationFileMap fileMap, string path, string site, string locationSubPath)
229                 {
230                         return ConfigurationFactory.Create (typeof(WebConfigurationHost), fileMap, path, site, locationSubPath);
231                 }
232                 
233                 public static _Configuration OpenMappedMachineConfiguration (ConfigurationFileMap fileMap)
234                 {
235                         return ConfigurationFactory.Create (typeof(WebConfigurationHost), fileMap);
236                 }
237
238                 public static _Configuration OpenMappedMachineConfiguration (ConfigurationFileMap fileMap,
239                                                                              string locationSubPath)
240                 {
241                         return OpenMappedMachineConfiguration (fileMap);
242                 }
243
244                 public static object GetSection (string sectionName)
245                 {
246                         string path = (HttpContext.Current != null
247                             && HttpContext.Current.Request != null) ?
248                                 HttpContext.Current.Request.Path : HttpRuntime.AppDomainAppVirtualPath;
249
250                         return GetSection (sectionName, path);
251                 }
252
253                 public static object GetSection (string sectionName, string path)
254                 {
255                         _Configuration c = OpenWebConfiguration (path);
256                         ConfigurationSection section = c.GetSection (sectionName);
257
258                         if (section == null)
259                                 return null;
260
261                         return get_runtime_object.Invoke (section, new object [0]);
262                 }
263
264                 readonly static MethodInfo get_runtime_object = typeof (ConfigurationSection).GetMethod ("GetRuntimeObject", BindingFlags.NonPublic | BindingFlags.Instance);
265
266                 public static object GetWebApplicationSection (string sectionName)
267                 {
268                         string path = (HttpContext.Current == null
269                                 || HttpContext.Current.Request == null
270                                 || HttpContext.Current.Request.ApplicationPath == null
271                                 || HttpContext.Current.Request.ApplicationPath == "") ?
272                                 String.Empty : HttpContext.Current.Request.ApplicationPath;
273
274                         return GetSection (sectionName, path);
275                 }
276
277                 public static NameValueCollection AppSettings {
278                         get { return ConfigurationManager.AppSettings; }
279                 }
280
281                 public static ConnectionStringSettingsCollection ConnectionStrings {
282                         get { return ConfigurationManager.ConnectionStrings; }
283                 }
284
285                 internal static IInternalConfigConfigurationFactory ConfigurationFactory {
286                         get { return configFactory; }
287                 }
288                 
289                 static string GetBasePath (string path)
290                 {
291                         if (path == "/" || path == "")
292                                 return path;
293
294                         /* first if we can, map it to a physical path
295                          * to see if it corresponds to a file */
296                         if (HttpContext.Current != null
297                             && HttpContext.Current.Request != null) {
298                                 string pd = HttpContext.Current.Request.MapPath (path);
299
300                                 if (!Directory.Exists (pd)) {
301                                         /* if it does, remove the file from the url */
302                                         int i = path.LastIndexOf ('/');
303                                         path = path.Substring (0, i);
304                                 } 
305                         }
306                         
307                         if (path.Length == 0)
308                                 return path;
309
310                         /* remove excess /'s from the end of the virtual path */
311                         while (path [path.Length - 1] == '/')
312                                 path = path.Substring (0, path.Length - 1);
313
314                         return path;
315                 }
316
317
318 #region stuff copied from WebConfigurationSettings
319 #if TARGET_J2EE
320                 static internal IConfigurationSystem oldConfig {
321                         get {
322                                 return (IConfigurationSystem)AppDomain.CurrentDomain.GetData("WebConfigurationManager.oldConfig");
323                         }
324                         set {
325                                 AppDomain.CurrentDomain.SetData("WebConfigurationManager.oldConfig", value);
326                         }
327                 }
328
329                 static private Web20DefaultConfig config {
330                         get {
331                                 return (Web20DefaultConfig) AppDomain.CurrentDomain.GetData ("Web20DefaultConfig.config");
332                         }
333                         set {
334                                 AppDomain.CurrentDomain.SetData ("Web20DefaultConfig.config", value);
335                         }
336                 }
337
338                 static private IInternalConfigSystem configSystem {
339                         get {
340                                 return (IInternalConfigSystem) AppDomain.CurrentDomain.GetData ("IInternalConfigSystem.configSystem");
341                         }
342                         set {
343                                 AppDomain.CurrentDomain.SetData ("IInternalConfigSystem.configSystem", value);
344                         }
345                 }
346 #else
347                 static internal IConfigurationSystem oldConfig;
348                 static Web20DefaultConfig config;
349                 static IInternalConfigSystem configSystem;
350 #endif
351                 const BindingFlags privStatic = BindingFlags.NonPublic | BindingFlags.Static;
352                 static readonly object lockobj = new object ();
353
354                 internal static void Init ()
355                 {
356                         lock (lockobj) {
357                                 if (config != null)
358                                         return;
359
360                                 /* deal with the ConfigurationSettings stuff */
361                                 {
362                                         Web20DefaultConfig settings = Web20DefaultConfig.GetInstance ();
363                                         Type t = typeof (ConfigurationSettings);
364                                         MethodInfo changeConfig = t.GetMethod ("ChangeConfigurationSystem",
365                                                                                privStatic);
366
367                                         if (changeConfig == null)
368                                                 throw new ConfigurationException ("Cannot find method CCS");
369
370                                         object [] args = new object [] {settings};
371                                         oldConfig = (IConfigurationSystem)changeConfig.Invoke (null, args);
372                                         config = settings;
373
374                                         config.Init ();
375                                 }
376
377                                 /* deal with the ConfigurationManager stuff */
378                                 {
379                                         HttpConfigurationSystem system = new HttpConfigurationSystem ();
380                                         Type t = typeof (ConfigurationManager);
381                                         MethodInfo changeConfig = t.GetMethod ("ChangeConfigurationSystem",
382                                                                                privStatic);
383
384                                         if (changeConfig == null)
385                                                 throw new ConfigurationException ("Cannot find method CCS");
386
387                                         object [] args = new object [] {system};
388                                         changeConfig.Invoke (null, args);
389                                         configSystem = system;
390                                 }
391                         }
392                 }
393         }
394
395         class Web20DefaultConfig : IConfigurationSystem
396         {
397 #if TARGET_J2EE
398                 static private Web20DefaultConfig instance {
399                         get {
400                                 Web20DefaultConfig val = (Web20DefaultConfig)AppDomain.CurrentDomain.GetData("Web20DefaultConfig.instance");
401                                 if (val == null) {
402                                         val = new Web20DefaultConfig();
403                                         AppDomain.CurrentDomain.SetData("Web20DefaultConfig.instance", val);
404                                 }
405                                 return val;
406                         }
407                         set {
408                                 AppDomain.CurrentDomain.SetData("Web20DefaultConfig.instance", value);
409                         }
410                 }
411 #else
412                 static Web20DefaultConfig instance;
413 #endif
414
415                 static Web20DefaultConfig ()
416                 {
417                         instance = new Web20DefaultConfig ();
418                 }
419
420                 public static Web20DefaultConfig GetInstance ()
421                 {
422                         return instance;
423                 }
424
425                 public object GetConfig (string sectionName)
426                 {
427                         object o = WebConfigurationManager.GetWebApplicationSection (sectionName);
428
429                         if (o == null || o is IgnoreSection) {
430                                 /* this can happen when the section
431                                  * handler doesn't subclass from
432                                  * ConfigurationSection.  let's be
433                                  * nice and try to load it using the
434                                  * 1.x style routines in case there's
435                                  * a 1.x section handler registered
436                                  * for it.
437                                  */
438                                 object o1 = WebConfigurationManager.oldConfig.GetConfig (sectionName);
439                                 if (o1 != null)
440                                         return o1;
441                         }
442
443                         return o;
444                 }
445
446                 public void Init ()
447                 {
448                         // nothing. We need a context.
449                 }
450         }
451
452 #endregion
453 }
454
455 #endif