File: ClientConfigurationSystem.cs

package info (click to toggle)
mono 6.12.0.199%2Bdfsg-6
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 1,296,836 kB
  • sloc: cs: 11,181,803; xml: 2,850,076; ansic: 699,709; cpp: 123,344; perl: 59,361; javascript: 30,841; asm: 21,853; makefile: 20,405; sh: 15,009; python: 4,839; pascal: 925; sql: 859; sed: 16; php: 1
file content (235 lines) | stat: -rw-r--r-- 10,548 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
//------------------------------------------------------------------------------
// <copyright file="ClientConfigurationSystem.cs" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
//------------------------------------------------------------------------------

namespace System.Configuration {
    using System.Configuration.Internal;
    using System.Globalization;
    using System.Collections;
    using System.IO;
    using System.Xml;
    using System.Security;
    using System.Security.Permissions;
    using System.Threading;
    using System.Net;
    using Assembly = System.Reflection.Assembly;
    using StringBuilder = System.Text.StringBuilder;

    internal sealed class ClientConfigurationSystem : IInternalConfigSystem {
        private const string            SystemDiagnosticsConfigKey = "system.diagnostics"; 
        private const string            SystemNetGroupKey = "system.net/";                 

        private IConfigSystem           _configSystem;
        private IInternalConfigRoot     _configRoot;
        private ClientConfigurationHost _configHost;
        private IInternalConfigRecord   _machineConfigRecord;
        private IInternalConfigRecord   _completeConfigRecord;
        private Exception               _initError;    
        private bool                    _isInitInProgress;      
        private bool                    _isMachineConfigInited; 
        private bool                	_isUserConfigInited;
        private bool                    _isAppConfigHttp;       
        

        internal ClientConfigurationSystem() {
            _configSystem = new ConfigSystem();
            _configSystem.Init(typeof(ClientConfigurationHost), null, null);

            _configHost = (ClientConfigurationHost) _configSystem.Host;
            _configRoot = _configSystem.Root;

            _configRoot.ConfigRemoved += OnConfigRemoved;

            _isAppConfigHttp = _configHost.IsAppConfigHttp;

            // VSWhidbey 606116: Config has a dependency on Uri class which has
            // a new static constructor that calls config.  We need a dummy reference
            // to Uri class so the static constructor would be involved first to
            // initialize config.
            string dummy = System.Uri.SchemeDelimiter;
        }

        // Return true if the section might be used during initialization of the configuration system,
        // and thus lead to deadlock if appropriate measures are not taken.
        bool IsSectionUsedInInit(string configKey) {
            return configKey == SystemDiagnosticsConfigKey || (_isAppConfigHttp && configKey.StartsWith(SystemNetGroupKey, StringComparison.Ordinal));
        }
        
        // Return true if the section should only use the machine configuration and not use the
        // application configuration. This is only true for system.net sections when the configuration
        // file for the application is downloaded via http using System.Net.WebClient.
        bool DoesSectionOnlyUseMachineConfig(string configKey) {
            return _isAppConfigHttp && configKey.StartsWith(SystemNetGroupKey, StringComparison.Ordinal);
        }

        // Ensure that initialization has completed, while handling re-entrancy issues
        // for certain sections that may be used during initialization itself.
        void EnsureInit(string configKey) {
            bool doInit = false;

            lock (this) {
                // If the user config is not initialized, then we must either:
                //    a. Perform the initialization ourselves if no other thread is doing it, or
                //    b. Wait for the initialization to complete if we know the section is not used during initialization itself, or
                //    c. Ignore initialization if the section can be used during initialization. Note that GetSection()
                //       returns null is initialization has not completed.
                if (!_isUserConfigInited) {
                    if (!_isInitInProgress) {
                        _isInitInProgress = true;
                        doInit = true;
                    }
                    else if (!IsSectionUsedInInit(configKey)) {
                        // Wait for initialization to complete.
                        Monitor.Wait(this);
                    }
                }
            }

            if (doInit) {
                try {
                    try {
                        try {
                            // Initialize machine configuration.
                            _machineConfigRecord = _configRoot.GetConfigRecord(
                                    ClientConfigurationHost.MachineConfigPath);

                            _machineConfigRecord.ThrowIfInitErrors();

                            // Make machine configuration available to system.net sections
                            // when application configuration is downloaded via http.
                            _isMachineConfigInited = true;

                            //
                            // Prevent deadlocks in the networking classes by loading 
                            // networking config before making a networking request. 
                            // Any requests for sections used in initialization during 
                            // the call to EnsureConfigLoaded() will be served by 
                            // _machine.config or will return null.
                            //
                            if (_isAppConfigHttp) {
                                ConfigurationManagerHelperFactory.Instance.EnsureNetConfigLoaded();
                            }

                            //
                            // Now load the rest of configuration
                            //
                            _configHost.RefreshConfigPaths();
                            string configPath;
                            if (_configHost.HasLocalConfig) {
                                configPath = ClientConfigurationHost.LocalUserConfigPath;
                            }
                            else if (_configHost.HasRoamingConfig) {
                                configPath = ClientConfigurationHost.RoamingUserConfigPath;
                            }
                            else {
                                configPath = ClientConfigurationHost.ExeConfigPath;
                            }

                            _completeConfigRecord = _configRoot.GetConfigRecord(configPath);
                            _completeConfigRecord.ThrowIfInitErrors();

                            _isUserConfigInited = true;
                        }
                        catch (Exception e) {
                            _initError = new ConfigurationErrorsException(SR.GetString(SR.Config_client_config_init_error), e);
                            throw _initError;
                        }
                    }
                    catch {
                        ConfigurationManager.SetInitError(_initError);
                        _isMachineConfigInited = true;
                        _isUserConfigInited = true;
                        throw;
                    }
                }
                finally {
                    lock (this) {
                        try {
                            // Notify ConfigurationSettings that initialization has fully completed,
                            // even if unsuccessful.
                            ConfigurationManager.CompleteConfigInit();

                            _isInitInProgress = false;

                        }
                        finally {
                            // Wake up all threads waiting for initialization to complete.
                            Monitor.PulseAll(this);
                        }
                    }
                }
            }
        }

        private void PrepareClientConfigSystem(string sectionName) {
            // Ensure the configuration system is inited for this section.
            if (!_isUserConfigInited) {
                EnsureInit(sectionName);
            }

            // If an error occurred during initialzation, throw it.
            if (_initError != null) {
                throw _initError;
            }
        }

        //
        // If config has been removed because initialization was not complete,
        // fetch a new configuration record. The record will be created and
        // completely initialized as RequireCompleteInit() will have been called
        // on the ClientConfigurationHost before we receive this event.
        //
        private void OnConfigRemoved(object sender, InternalConfigEventArgs e) {
            try {
                IInternalConfigRecord newConfigRecord = _configRoot.GetConfigRecord(_completeConfigRecord.ConfigPath);
                _completeConfigRecord = newConfigRecord;
                _completeConfigRecord.ThrowIfInitErrors();
            }
            catch (Exception ex) {
                _initError = new ConfigurationErrorsException(SR.GetString(SR.Config_client_config_init_error), ex);
                ConfigurationManager.SetInitError(_initError);
                throw _initError;
            }
        }

        object IInternalConfigSystem.GetSection(string sectionName) {
            PrepareClientConfigSystem(sectionName);

            // Get the appropriate config record for the section.
            IInternalConfigRecord configRecord = null;
            if (DoesSectionOnlyUseMachineConfig(sectionName)) {
                if (_isMachineConfigInited) {
                    configRecord = _machineConfigRecord;
                }
            }
            else {
                if (_isUserConfigInited) {
                    configRecord = _completeConfigRecord;
                }
            }

            // Call GetSection(), or return null if no configuration is yet available.
            if (configRecord != null) {
                return configRecord.GetSection(sectionName);
            }
            else {
                return null;
            }
        }

        void IInternalConfigSystem.RefreshConfig(string sectionName) {
            PrepareClientConfigSystem(sectionName);

            if (_isMachineConfigInited) {
                _machineConfigRecord.RefreshSection(sectionName);
            }
        }

        // Supports user config
        bool IInternalConfigSystem.SupportsUserConfig {
            get {return true;}
        }
    }
}