bring back CodeContracts to mobile profiles.
[mono-project.git] / mcs / class / System / System.Configuration / CustomizableFileSettingsProvider.cs
blob7d70eefabbc52486c9d53f816ccd82989cc8d6f9
1 //
2 // CustomizableFileSettingsProvider.cs
3 //
4 // Authors:
5 // Noriaki Okimoto <seara@ojk.sppd.ne.jp>
6 // Atsushi Enomoto <atsushi@ximian.com>
7 //
8 // (C)2007 Noriaki Okimoto
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 //
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 //
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 #if CONFIGURATION_DEP
32 #if !TARGET_JVM
33 extern alias PrebuiltSystem;
34 #endif
36 using System;
37 using System.Collections;
38 using System.Collections.Generic;
39 using System.Configuration;
40 using System.Globalization;
41 using System.IO;
42 using System.Reflection;
43 using System.Security.Cryptography;
44 using System.Text;
45 using System.Xml;
47 #if TARGET_JVM
48 using NameValueCollection = System.Collections.Specialized.NameValueCollection;
49 #else
50 using NameValueCollection = PrebuiltSystem.System.Collections.Specialized.NameValueCollection;
51 #endif
53 namespace System.Configuration
55 // location to store user configuration settings.
56 internal enum UserConfigLocationOption : uint
58 Product = 0x20,
59 Product_VersionMajor = 0x21,
60 Product_VersionMinor = 0x22,
61 Product_VersionBuild = 0x24,
62 Product_VersionRevision = 0x28,
63 Company_Product = 0x30,
64 Company_Product_VersionMajor = 0x31,
65 Company_Product_VersionMinor = 0x32,
66 Company_Product_VersionBuild = 0x34,
67 Company_Product_VersionRevision = 0x38,
68 Evidence = 0x40,
69 Other = 0x8000
72 internal class CustomizableFileSettingsProvider : SettingsProvider, IApplicationSettingsProvider
74 // KLUDGE WARNING.
76 // This is used from within System.Web to allow mapping of the ExeConfigFilename to
77 // the correct Web.config for the current request. Otherwise web applications will
78 // not be able to access settings from Web.config. The type assigned to this
79 // variable must descend from the ConfigurationFileMap class and its
80 // MachineConfigFilename will be used to set the ExeConfigFilename.
82 // This is necessary to fix bug #491531
83 #pragma warning disable 649
84 private static Type webConfigurationFileMapType;
85 #pragma warning restore 649
87 private static string userRoamingPath = "";
88 private static string userLocalPath = "";
89 private static string userRoamingPathPrevVersion = "";
90 private static string userLocalPathPrevVersion = "";
91 private static string userRoamingName = "user.config";
92 private static string userLocalName = "user.config";
93 private static string userRoamingBasePath = "";
94 private static string userLocalBasePath = "";
95 private static string CompanyName = "";
96 private static string ProductName = "";
97 private static string ForceVersion = "";
98 private static string[] ProductVersion;
100 // whether to include parts in the folder name or not:
101 private static bool isVersionMajor = false; // 0x0001 major version
102 private static bool isVersionMinor = false; // 0x0002 minor version
103 private static bool isVersionBuild = false; // 0x0004 build version
104 private static bool isVersionRevision = false; // 0x0008 revision
105 private static bool isCompany = true; // 0x0010 corporate name
106 private static bool isProduct = true; // 0x0020 product name
107 private static bool isEvidence = false; // 0x0040 evidence hash
109 private static bool userDefine = false; // 0x8000 ignore all above and use user definition
111 private static UserConfigLocationOption userConfig = UserConfigLocationOption.Company_Product;
113 public override void Initialize (string name, NameValueCollection config)
115 base.Initialize (name, config);
118 // full path to roaming user.config
119 internal static string UserRoamingFullPath {
120 get { return Path.Combine (userRoamingPath, userRoamingName); }
123 // full path to local user.config
124 internal static string UserLocalFullPath {
125 get { return Path.Combine (userLocalPath, userLocalName); }
128 // previous full path to roaming user.config
129 public static string PrevUserRoamingFullPath {
130 get { return Path.Combine (userRoamingPathPrevVersion, userRoamingName); }
133 // previous full path to local user.config
134 public static string PrevUserLocalFullPath {
135 get { return Path.Combine (userLocalPathPrevVersion, userLocalName); }
138 // path to roaming user.config
139 public static string UserRoamingPath {
140 get { return userRoamingPath; }
143 // path to local user.config
144 public static string UserLocalPath {
145 get { return userLocalPath; }
148 // file name which is equivalent to user.config, for roaming user
149 public static string UserRoamingName {
150 get { return userRoamingName; }
153 // file name which is equivalent to user.config, for local user
154 public static string UserLocalName {
155 get { return userLocalName; }
158 public static UserConfigLocationOption UserConfigSelector
160 get { return userConfig; }
161 set {
162 userConfig = value;
164 if (((uint) userConfig & 0x8000) != 0) {
165 isVersionMajor = false;
166 isVersionMinor = false;
167 isVersionBuild = false;
168 isVersionRevision = false;
169 isCompany = false;
170 return;
173 isVersionRevision = ((uint) userConfig & 0x0008) != 0;
174 isVersionBuild = isVersionRevision | ((uint)userConfig & 0x0004) != 0;
175 isVersionMinor = isVersionBuild | ((uint)userConfig & 0x0002) != 0;
176 isVersionMajor = IsVersionMinor | ((uint)userConfig & 0x0001) != 0;
178 isCompany = ((uint) userConfig & 0x0010) != 0;
179 isProduct = ((uint) userConfig & 0x0020) != 0;
183 // whether the path to include the major version.
184 public static bool IsVersionMajor
186 get { return isVersionMajor; }
189 isVersionMajor = value;
190 isVersionMinor = false;
191 isVersionBuild = false;
192 isVersionRevision = false;
196 // whether the path to include minor version.
197 public static bool IsVersionMinor
199 get { return isVersionMinor; }
202 isVersionMinor = value;
203 if (isVersionMinor)
204 isVersionMajor = true;
205 isVersionBuild = false;
206 isVersionRevision = false;
210 // whether the path to include build version.
211 public static bool IsVersionBuild
213 get { return isVersionBuild; }
216 isVersionBuild = value;
217 if (isVersionBuild) {
218 isVersionMajor = true;
219 isVersionMinor = true;
221 isVersionRevision = false;
225 // whether the path to include revision.
226 public static bool IsVersionRevision
228 get { return isVersionRevision; }
231 isVersionRevision = value;
232 if (isVersionRevision) {
233 isVersionMajor = true;
234 isVersionMinor = true;
235 isVersionBuild = true;
240 // whether the path to include company name.
241 public static bool IsCompany
243 get { return isCompany; }
244 set { isCompany = value; }
247 // whether the path to include evidence hash.
248 public static bool IsEvidence
250 get { return isEvidence; }
251 set { isEvidence = value; }
254 // AssemblyCompanyAttribute->Namespace->"Program"
255 private static string GetCompanyName ()
257 Assembly assembly = Assembly.GetEntryAssembly ();
258 if (assembly == null)
259 assembly = Assembly.GetCallingAssembly ();
261 AssemblyCompanyAttribute [] attrs = (AssemblyCompanyAttribute []) assembly.GetCustomAttributes (typeof (AssemblyCompanyAttribute), true);
263 if ((attrs != null) && attrs.Length > 0) {
264 return attrs [0].Company;
267 #if !TARGET_JVM
268 MethodInfo entryPoint = assembly.EntryPoint;
269 Type entryType = entryPoint != null ? entryPoint.DeclaringType : null;
270 if (entryType != null && !String.IsNullOrEmpty (entryType.Namespace)) {
271 int end = entryType.Namespace.IndexOf ('.');
272 return end < 0 ? entryType.Namespace : entryType.Namespace.Substring (0, end);
274 return "Program";
275 #else
276 return assembly.GetName ().Name;
277 #endif
280 private static string GetProductName ()
282 Assembly assembly = Assembly.GetEntryAssembly ();
283 if (assembly == null)
284 assembly = Assembly.GetCallingAssembly ();
286 #if !TARGET_JVM
287 byte [] pkt = assembly.GetName ().GetPublicKeyToken ();
288 return String.Format ("{0}_{1}_{2}",
289 AppDomain.CurrentDomain.FriendlyName,
290 pkt != null && pkt.Length > 0 ? "StrongName" : "Url",
291 GetEvidenceHash());
292 #else // AssemblyProductAttribute-based code
293 AssemblyProductAttribute [] attrs = (AssemblyProductAttribute[]) assembly.GetCustomAttributes (typeof (AssemblyProductAttribute), true);
295 if ((attrs != null) && attrs.Length > 0) {
296 return attrs [0].Product;
298 return assembly.GetName ().Name;
299 #endif
302 // Note: Changed from base64() to hex output to avoid unexpected chars like '\' or '/' with filesystem meaning.
303 // Otherwise eventually filenames, which are invalid on linux or windows, might be created.
304 // Signed-off-by: Carsten Schlote <schlote@vahanus.net>
305 // TODO: Compare with .NET. It might be also, that their way isn't suitable for Unix OS derivates (slahes in output)
306 private static string GetEvidenceHash ()
308 Assembly assembly = Assembly.GetEntryAssembly ();
309 if (assembly == null)
310 assembly = Assembly.GetCallingAssembly ();
312 byte [] pkt = assembly.GetName ().GetPublicKeyToken ();
313 byte [] hash = SHA1.Create ().ComputeHash (pkt != null && pkt.Length >0 ? pkt : Encoding.UTF8.GetBytes (assembly.EscapedCodeBase));
314 System.Text.StringBuilder evidence_string = new System.Text.StringBuilder();
315 foreach (byte b in hash)
316 evidence_string.AppendFormat("{0:x2}",b);
317 return evidence_string.ToString ();
320 private static string GetProductVersion ()
322 Assembly assembly = Assembly.GetEntryAssembly ();
323 if (assembly == null)
324 assembly = Assembly.GetCallingAssembly ();
325 if (assembly == null)
326 return string.Empty;
328 return assembly.GetName ().Version.ToString ();
331 private static void CreateUserConfigPath ()
333 if (userDefine)
334 return;
336 if (ProductName == "")
337 ProductName = GetProductName ();
338 if (CompanyName == "")
339 CompanyName = GetCompanyName ();
340 if (ForceVersion == "")
341 ProductVersion = GetProductVersion ().Split('.');
343 // C:\Documents and Settings\(user)\Application Data
344 #if !TARGET_JVM
345 if (userRoamingBasePath == "")
346 userRoamingPath = Environment.GetFolderPath (Environment.SpecialFolder.ApplicationData);
347 else
348 #endif
349 userRoamingPath = userRoamingBasePath;
351 // C:\Documents and Settings\(user)\Local Settings\Application Data (on Windows)
352 #if !TARGET_JVM
353 if (userLocalBasePath == "")
354 userLocalPath = Environment.GetFolderPath (Environment.SpecialFolder.LocalApplicationData);
355 else
356 #endif
357 userLocalPath = userLocalBasePath;
359 if (isCompany) {
360 userRoamingPath = Path.Combine (userRoamingPath, CompanyName);
361 userLocalPath = Path.Combine (userLocalPath, CompanyName);
364 if (isProduct) {
365 if (isEvidence) {
366 Assembly assembly = Assembly.GetEntryAssembly ();
367 if (assembly == null)
368 assembly = Assembly.GetCallingAssembly ();
369 #if !TARGET_JVM
370 byte [] pkt = assembly.GetName ().GetPublicKeyToken ();
371 ProductName = String.Format ("{0}_{1}_{2}",
372 ProductName,
373 pkt != null ? "StrongName" : "Url",
374 GetEvidenceHash());
375 #endif
377 userRoamingPath = Path.Combine (userRoamingPath, ProductName);
378 userLocalPath = Path.Combine (userLocalPath, ProductName);
382 string versionName;
384 if (ForceVersion == "") {
385 if (isVersionRevision)
386 versionName = String.Format ("{0}.{1}.{2}.{3}", ProductVersion [0], ProductVersion [1], ProductVersion [2], ProductVersion [3]);
387 else if (isVersionBuild)
388 versionName = String.Format ("{0}.{1}.{2}", ProductVersion [0], ProductVersion [1], ProductVersion [2]);
389 else if (isVersionMinor)
390 versionName = String.Format ("{0}.{1}", ProductVersion [0], ProductVersion [1]);
391 else if (isVersionMajor)
392 versionName = ProductVersion [0];
393 else
394 versionName = "";
396 else
397 versionName = ForceVersion;
399 string prevVersionRoaming = PrevVersionPath (userRoamingPath, versionName);
400 string prevVersionLocal = PrevVersionPath (userLocalPath, versionName);
402 userRoamingPath = Path.Combine (userRoamingPath, versionName);
403 userLocalPath = Path.Combine (userLocalPath, versionName);
404 if (prevVersionRoaming != "")
405 userRoamingPathPrevVersion = Path.Combine(userRoamingPath, prevVersionRoaming);
406 if (prevVersionLocal != "")
407 userLocalPathPrevVersion = Path.Combine(userLocalPath, prevVersionLocal);
410 // string for the previous version. It ignores newer ones.
411 private static string PrevVersionPath (string dirName, string currentVersion)
413 string prevVersionString = "";
415 if (!Directory.Exists(dirName))
416 return prevVersionString;
417 DirectoryInfo currentDir = new DirectoryInfo (dirName);
418 foreach (DirectoryInfo dirInfo in currentDir.GetDirectories ())
419 if (String.Compare (currentVersion, dirInfo.Name, StringComparison.Ordinal) > 0)
420 if (String.Compare (prevVersionString, dirInfo.Name, StringComparison.Ordinal) < 0)
421 prevVersionString = dirInfo.Name;
423 return prevVersionString;
426 // sets the explicit path to store roaming user.config or equivalent.
427 // (returns the path validity.)
428 public static bool SetUserRoamingPath (string configPath)
430 if (CheckPath (configPath))
432 userRoamingBasePath = configPath;
433 return true;
435 else
436 return false;
439 // sets the explicit path to store local user.config or equivalent.
440 // (returns the path validity.)
441 public static bool SetUserLocalPath (string configPath)
443 if (CheckPath (configPath))
445 userLocalBasePath = configPath;
446 return true;
448 else
449 return false;
452 private static bool CheckFileName (string configFile)
455 char[] invalidFileChars = Path.GetInvalidFileNameChars();
457 foreach (char invalidChar in invalidFileChars)
459 if (configFile.Contains(invalidChar.ToString()))
461 return false;
464 return true;
466 return configFile.IndexOfAny (Path.GetInvalidFileNameChars ()) < 0;
469 // sets the explicit roaming file name which is user.config equivalent.
470 // (returns the file name validity.)
471 public static bool SetUserRoamingFileName (string configFile)
473 if (CheckFileName (configFile))
475 userRoamingName = configFile;
476 return true;
478 else
479 return false;
482 // sets the explicit local file name which is user.config equivalent.
483 // (returns the file name validity.)
484 public static bool SetUserLocalFileName (string configFile)
486 if (CheckFileName (configFile))
488 userLocalName = configFile;
489 return true;
491 else
492 return false;
495 // sets the explicit company name for folder.
496 // (returns the file name validity.)
497 public static bool SetCompanyName (string companyName)
499 if (CheckFileName (companyName))
501 CompanyName = companyName;
502 return true;
504 else
505 return false;
508 // sets the explicit product name for folder.
509 // (returns the file name validity.)
510 public static bool SetProductName (string productName)
512 if (CheckFileName (productName))
514 ProductName = productName;
515 return true;
517 else
518 return false;
521 // sets the explicit major version for folder.
522 public static bool SetVersion (int major)
524 ForceVersion = string.Format ("{0}", major);
525 return true;
528 // sets the explicit major and minor versions for folder.
529 public static bool SetVersion (int major, int minor)
531 ForceVersion = string.Format ("{0}.{1}", major, minor);
532 return true;
535 // sets the explicit major/minor/build numbers for folder.
536 public static bool SetVersion (int major, int minor, int build)
538 ForceVersion = string.Format ("{0}.{1}.{2}", major, minor, build);
539 return true;
542 // sets the explicit major/minor/build/revision numbers for folder.
543 public static bool SetVersion (int major, int minor, int build, int revision)
545 ForceVersion = string.Format ("{0}.{1}.{2}.{3}", major, minor, build, revision);
546 return true;
549 // sets the explicit version number string for folder.
550 public static bool SetVersion (string forceVersion)
552 if (CheckFileName (forceVersion))
554 ForceVersion = forceVersion;
555 return true;
557 else
558 return false;
561 private static bool CheckPath (string configPath)
563 char[] invalidPathChars = Path.GetInvalidPathChars ();
566 foreach (char invalidChar in invalidPathChars)
568 if (configPath.Contains (invalidChar.ToString()))
570 return false;
574 if (configPath.IndexOfAny (invalidPathChars) >= 0)
575 return false;
577 string folder = configPath;
578 string fileName;
579 while ((fileName = Path.GetFileName (folder)) != "")
581 if (!CheckFileName (fileName))
583 return false;
585 folder = Path.GetDirectoryName (folder);
588 return true;
592 public override string Name {
593 get { return base.Name; }
596 string app_name = String.Empty;//"OJK.CustomSetting.CustomizableLocalFileSettingsProvider";
597 public override string ApplicationName {
598 get { return app_name; }
599 set { app_name = value; }
602 private ExeConfigurationFileMap exeMapCurrent = null;
603 private ExeConfigurationFileMap exeMapPrev = null;
604 private SettingsPropertyValueCollection values = null;
606 private void SaveProperties (ExeConfigurationFileMap exeMap, SettingsPropertyValueCollection collection, ConfigurationUserLevel level, SettingsContext context, bool checkUserLevel)
608 Configuration config = ConfigurationManager.OpenMappedExeConfiguration (exeMap, level);
610 UserSettingsGroup userGroup = config.GetSectionGroup ("userSettings") as UserSettingsGroup;
611 bool isRoaming = (level == ConfigurationUserLevel.PerUserRoaming);
613 #if true // my reimplementation
615 if (userGroup == null) {
616 userGroup = new UserSettingsGroup ();
617 config.SectionGroups.Add ("userSettings", userGroup);
618 ApplicationSettingsBase asb = context.CurrentSettings;
619 ClientSettingsSection cs = new ClientSettingsSection ();
620 string class_name = NormalizeInvalidXmlChars ((asb != null ? asb.GetType () : typeof (ApplicationSettingsBase)).FullName);
621 userGroup.Sections.Add (class_name, cs);
624 bool hasChanges = false;
626 foreach (ConfigurationSection section in userGroup.Sections) {
627 ClientSettingsSection userSection = section as ClientSettingsSection;
628 if (userSection == null)
629 continue;
631 foreach (SettingsPropertyValue value in collection) {
632 if (checkUserLevel && value.Property.Attributes.Contains (typeof (SettingsManageabilityAttribute)) != isRoaming)
633 continue;
634 // The default impl does not save the ApplicationScopedSetting properties
635 if (value.Property.Attributes.Contains (typeof (ApplicationScopedSettingAttribute)))
636 continue;
638 hasChanges = true;
639 SettingElement element = userSection.Settings.Get (value.Name);
640 if (element == null) {
641 element = new SettingElement (value.Name, value.Property.SerializeAs);
642 userSection.Settings.Add (element);
644 if (element.Value.ValueXml == null)
645 element.Value.ValueXml = new XmlDocument ().CreateElement ("value");
646 switch (value.Property.SerializeAs) {
647 case SettingsSerializeAs.Xml:
648 element.Value.ValueXml.InnerXml = (value.SerializedValue as string) ?? string.Empty;
649 break;
650 case SettingsSerializeAs.String:
651 element.Value.ValueXml.InnerText = value.SerializedValue as string;
652 break;
653 case SettingsSerializeAs.Binary:
654 element.Value.ValueXml.InnerText = value.SerializedValue != null ? Convert.ToBase64String (value.SerializedValue as byte []) : string.Empty;
655 break;
656 default:
657 throw new NotImplementedException ();
661 if (hasChanges)
662 config.Save (ConfigurationSaveMode.Minimal, true);
664 #else // original impl. - likely buggy to miss some properties to save
666 foreach (ConfigurationSection configSection in userGroup.Sections)
668 ClientSettingsSection userSection = configSection as ClientSettingsSection;
669 if (userSection != null)
672 userSection.Settings.Clear();
674 foreach (SettingsPropertyValue propertyValue in collection)
676 if (propertyValue.IsDirty)
678 SettingElement element = new SettingElement(propertyValue.Name, SettingsSerializeAs.String);
679 element.Value.ValueXml = new XmlDocument();
680 element.Value.ValueXml.InnerXml = (string)propertyValue.SerializedValue;
681 userSection.Settings.Add(element);
685 foreach (SettingElement element in userSection.Settings)
687 if (collection [element.Name] != null) {
688 if (collection [element.Name].Property.Attributes.Contains (typeof (SettingsManageabilityAttribute)) != isRoaming)
689 continue;
691 element.SerializeAs = SettingsSerializeAs.String;
692 element.Value.ValueXml.InnerXml = (string) collection [element.Name].SerializedValue; ///Value = XmlElement
698 config.Save (ConfigurationSaveMode.Minimal, true);
699 #endif
702 // NOTE: We should add here all the chars that are valid in a name of a class (Ecma-wise),
703 // but invalid in an xml element name, and provide a better impl if we get too many of them.
704 string NormalizeInvalidXmlChars (string str)
706 char [] invalid_chars = new char [] { '+' };
708 if (str == null || str.IndexOfAny (invalid_chars) == -1)
709 return str;
711 // Replace with its hexadecimal values.
712 str = str.Replace ("+", "_x002B_");
713 return str;
716 private void LoadPropertyValue (SettingsPropertyCollection collection, SettingElement element, bool allowOverwrite)
718 SettingsProperty prop = collection [element.Name];
719 if (prop == null) { // see bug #343459
720 prop = new SettingsProperty (element.Name);
721 collection.Add (prop);
724 SettingsPropertyValue value = new SettingsPropertyValue (prop);
725 value.IsDirty = false;
726 if (element.Value.ValueXml != null) {
727 switch (value.Property.SerializeAs) {
728 case SettingsSerializeAs.Xml:
729 value.SerializedValue = element.Value.ValueXml.InnerXml;
730 break;
731 case SettingsSerializeAs.String:
732 value.SerializedValue = element.Value.ValueXml.InnerText;
733 break;
734 case SettingsSerializeAs.Binary:
735 value.SerializedValue = Convert.FromBase64String (element.Value.ValueXml.InnerText);
736 break;
739 else
740 value.SerializedValue = prop.DefaultValue;
743 if (allowOverwrite)
744 values.Remove (element.Name);
745 values.Add (value);
746 } catch (ArgumentException ex) {
747 throw new ConfigurationErrorsException (string.Format (
748 CultureInfo.InvariantCulture,
749 "Failed to load value for '{0}'.",
750 element.Name), ex);
754 private void LoadProperties (ExeConfigurationFileMap exeMap, SettingsPropertyCollection collection, ConfigurationUserLevel level, string sectionGroupName, bool allowOverwrite, string groupName)
756 Configuration config = ConfigurationManager.OpenMappedExeConfiguration (exeMap,level);
758 ConfigurationSectionGroup sectionGroup = config.GetSectionGroup (sectionGroupName);
759 if (sectionGroup != null) {
760 foreach (ConfigurationSection configSection in sectionGroup.Sections) {
761 if (configSection.SectionInformation.Name != groupName)
762 continue;
764 ClientSettingsSection clientSection = configSection as ClientSettingsSection;
765 if (clientSection == null)
766 continue;
768 foreach (SettingElement element in clientSection.Settings) {
769 LoadPropertyValue(collection, element, allowOverwrite);
771 // Only the first one seems to be processed by MS
772 break;
778 public override void SetPropertyValues (SettingsContext context, SettingsPropertyValueCollection collection)
780 CreateExeMap ();
782 if (UserLocalFullPath == UserRoamingFullPath)
784 SaveProperties (exeMapCurrent, collection, ConfigurationUserLevel.PerUserRoaming, context, false);
785 } else {
786 SaveProperties (exeMapCurrent, collection, ConfigurationUserLevel.PerUserRoaming, context, true);
787 SaveProperties (exeMapCurrent, collection, ConfigurationUserLevel.PerUserRoamingAndLocal, context, true);
791 public override SettingsPropertyValueCollection GetPropertyValues (SettingsContext context, SettingsPropertyCollection collection)
793 CreateExeMap ();
795 if (values == null) {
796 values = new SettingsPropertyValueCollection ();
797 string groupName = context ["GroupName"] as string;
798 groupName = NormalizeInvalidXmlChars (groupName); // we likely saved the element removing the non valid xml chars.
799 LoadProperties (exeMapCurrent, collection, ConfigurationUserLevel.None, "applicationSettings", false, groupName);
800 LoadProperties (exeMapCurrent, collection, ConfigurationUserLevel.None, "userSettings", false, groupName);
802 LoadProperties (exeMapCurrent, collection, ConfigurationUserLevel.PerUserRoaming, "userSettings", true, groupName);
803 LoadProperties (exeMapCurrent, collection, ConfigurationUserLevel.PerUserRoamingAndLocal, "userSettings", true, groupName);
805 // create default values if not exist
806 foreach (SettingsProperty p in collection)
807 if (values [p.Name] == null)
808 values.Add (new SettingsPropertyValue (p));
810 return values;
813 /// creates an ExeConfigurationFileMap
814 private void CreateExeMap ()
816 if (exeMapCurrent == null) {
817 CreateUserConfigPath ();
819 // current version
820 exeMapCurrent = new ExeConfigurationFileMap ();
822 // exeMapCurrent.ExeConfigFilename = System.Windows.Forms.Application.ExecutablePath + ".config";
823 Assembly entry = Assembly.GetEntryAssembly () ?? Assembly.GetExecutingAssembly ();
824 exeMapCurrent.ExeConfigFilename = entry.Location + ".config";
825 exeMapCurrent.LocalUserConfigFilename = UserLocalFullPath;
826 exeMapCurrent.RoamingUserConfigFilename = UserRoamingFullPath;
828 if (webConfigurationFileMapType != null && typeof (ConfigurationFileMap).IsAssignableFrom (webConfigurationFileMapType)) {
829 try {
830 ConfigurationFileMap cfgFileMap = Activator.CreateInstance (webConfigurationFileMapType) as ConfigurationFileMap;
831 if (cfgFileMap != null) {
832 string fpath = cfgFileMap.MachineConfigFilename;
833 if (!String.IsNullOrEmpty (fpath))
834 exeMapCurrent.ExeConfigFilename = fpath;
836 } catch {
837 // ignore
841 // previous version
842 if ((PrevUserLocalFullPath != "") && (PrevUserRoamingFullPath != ""))
844 exeMapPrev = new ExeConfigurationFileMap();
845 // exeMapPrev.ExeConfigFilename = System.Windows.Forms.Application.ExecutablePath + ".config";
846 exeMapPrev.ExeConfigFilename = entry.Location + ".config";
847 exeMapPrev.LocalUserConfigFilename = PrevUserLocalFullPath;
848 exeMapPrev.RoamingUserConfigFilename = PrevUserRoamingFullPath;
853 // FIXME: implement
854 public SettingsPropertyValue GetPreviousVersion (SettingsContext context, SettingsProperty property)
856 return null;
859 public void Reset (SettingsContext context)
861 SettingsPropertyCollection coll = new SettingsPropertyCollection ();
862 GetPropertyValues (context, coll);
863 foreach (SettingsPropertyValue propertyValue in values) {
864 // Can't use propertyValue.Property.DefaultValue
865 // as it may cause InvalidCastException (see bug# 532180)
866 propertyValue.PropertyValue = propertyValue.Reset ();
868 SetPropertyValues (context, values);
871 // FIXME: implement
872 public void Upgrade (SettingsContext context, SettingsPropertyCollection properties)
876 public static void setCreate ()
878 CreateUserConfigPath();
883 #endif