New tests, update
[mono.git] / mcs / class / System / System.Configuration / CustomizableFileSettingsProvider.cs
1 //
2 // CustomizableLocalFileSettingsProvider.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.
28 //
29
30 #if NET_2_0 && CONFIGURATION_DEP
31
32 #if !TARGET_JVM
33 extern alias PrebuiltSystem;
34 #endif
35
36 using System;
37 using System.Collections;
38 using System.Collections.Generic;
39 using System.Configuration;
40 using System.IO;
41 using System.Reflection;
42 using System.Security.Cryptography;
43 using System.Text;
44 using System.Xml;
45
46 #if TARGET_JVM
47 using NameValueCollection = System.Collections.Specialized.NameValueCollection;
48 #else
49 using NameValueCollection = PrebuiltSystem.System.Collections.Specialized.NameValueCollection;
50 #endif
51
52 namespace System.Configuration
53 {
54         // location to store user configuration settings.
55         internal enum UserConfigLocationOption : uint
56         {
57                 Product = 0x20,
58                 Product_VersionMajor = 0x21,
59                 Product_VersionMinor = 0x22,
60                 Product_VersionBuild = 0x24,
61                 Product_VersionRevision = 0x28,
62                 Company_Product = 0x30,
63                 Company_Product_VersionMajor = 0x31,
64                 Company_Product_VersionMinor = 0x32,
65                 Company_Product_VersionBuild = 0x34,
66                 Company_Product_VersionRevision = 0x38,
67                 Other = 0x8000
68         }
69         
70         internal class CustomizableFileSettingsProvider : SettingsProvider, IApplicationSettingsProvider
71         {
72                 private static string userRoamingPath = "";
73                 private static string userLocalPath = "";
74                 private static string userRoamingPathPrevVersion = "";
75                 private static string userLocalPathPrevVersion = "";
76                 private static string userRoamingName = "user.config";
77                 private static string userLocalName = "user.config";
78                 private static string userRoamingBasePath = "";
79                 private static string userLocalBasePath = "";
80                 private static string CompanyName = "";
81                 private static string ProductName = "";
82                 private static string ForceVersion = "";
83                 private static string[] ProductVersion;
84
85                 // whether to include parts in the folder name or not:
86                 private static bool isVersionMajor = false;     // 0x0001       major version
87                 private static bool isVersionMinor = false;     // 0x0002       minor version
88                 private static bool isVersionBuild = false;     // 0x0004       build version
89                 private static bool isVersionRevision = false;  // 0x0008       revision
90                 private static bool isCompany = true;           // 0x0010       corporate name
91                 private static bool isProduct = true;           // 0x0020       product name
92
93                 private static bool userDefine = false;         // 0x8000       ignore all above and use user definition
94
95                 private static UserConfigLocationOption userConfig = UserConfigLocationOption.Company_Product;
96
97                 public override void Initialize (string name, NameValueCollection config)
98                 {
99                         base.Initialize (name, config);
100                 }
101
102                 // full path to roaming user.config
103                 internal static string UserRoamingFullPath {
104                         get { return Path.Combine (userRoamingPath, userRoamingName); }
105                 }
106
107                 // full path to local user.config
108                 internal static string UserLocalFullPath {
109                         get { return Path.Combine (userLocalPath, userLocalName); }
110                 }
111
112                 // previous full path to roaming user.config
113                 public static string PrevUserRoamingFullPath {
114                         get { return Path.Combine (userRoamingPathPrevVersion, userRoamingName); }
115                 }
116
117                 // previous full path to local user.config
118                 public static string PrevUserLocalFullPath {
119                         get { return Path.Combine (userLocalPathPrevVersion, userLocalName); }
120                 }
121
122                 // path to roaming user.config
123                 public static string UserRoamingPath {
124                         get { return userRoamingPath; }
125                 }
126
127                 // path to local user.config
128                 public static string UserLocalPath {
129                         get { return userLocalPath; }
130                 }
131
132                 // file name which is equivalent to user.config, for roaming user
133                 public static string UserRoamingName {
134                         get { return userRoamingName; }
135                 }
136
137                 // file name which is equivalent to user.config, for local user
138                 public static string UserLocalName {
139                         get { return userLocalName; }
140                 }
141
142                 public static UserConfigLocationOption UserConfigSelector
143                 {
144                         get { return userConfig; }
145                         set {
146                                 userConfig = value;
147
148                                 if (((uint) userConfig & 0x8000) != 0) {
149                                         isVersionMajor = false;
150                                         isVersionMinor = false;
151                                         isVersionBuild = false;
152                                         isVersionRevision = false;
153                                         isCompany = false;
154                                         return;
155                                 }
156
157                                 isVersionRevision = ((uint) userConfig & 0x0008) != 0;
158                                 isVersionBuild = isVersionRevision | ((uint)userConfig & 0x0004) != 0;
159                                 isVersionMinor = isVersionBuild | ((uint)userConfig & 0x0002) != 0;
160                                 isVersionMajor = IsVersionMinor | ((uint)userConfig & 0x0001) != 0;
161
162                                 isCompany = ((uint) userConfig & 0x0010) != 0;
163                                 isProduct = ((uint) userConfig & 0x0020) != 0;
164                         }
165                 }
166
167                 // whether the path to include the major version.
168                 public static bool IsVersionMajor
169                 {
170                         get { return isVersionMajor; }
171                         set
172                         {
173                                 isVersionMajor = value;
174                                 isVersionMinor = false;
175                                 isVersionBuild = false;
176                                 isVersionRevision = false;
177                         }
178                 }
179
180                 // whether the path to include minor version.
181                 public static bool IsVersionMinor
182                 {
183                         get { return isVersionMinor; }
184                         set
185                         {
186                                 isVersionMinor = value;
187                                 if (isVersionMinor)
188                                         isVersionMajor = true;
189                                 isVersionBuild = false;
190                                 isVersionRevision = false;
191                         }
192                 }
193
194                 // whether the path to include build version.
195                 public static bool IsVersionBuild
196                 {
197                         get { return isVersionBuild; }
198                         set
199                         {
200                                 isVersionBuild = value;
201                                 if (isVersionBuild) {
202                                         isVersionMajor = true;
203                                         isVersionMinor = true;
204                                 }
205                                 isVersionRevision = false;
206                         }
207                 }
208
209                 // whether the path to include revision.
210                 public static bool IsVersionRevision
211                 {
212                         get { return isVersionRevision; }
213                         set
214                         {
215                                 isVersionRevision = value;
216                                 if (isVersionRevision) {
217                                         isVersionMajor = true;
218                                         isVersionMinor = true;
219                                         isVersionBuild = true;
220                                 }
221                         }
222                 }
223
224                 // whether the path to include company name.
225                 public static bool IsCompany
226                 {
227                         get { return isCompany; }
228                         set { isCompany = value; }
229                 }
230
231                 // AssemblyCompanyAttribute->Namespace->"Program"
232                 private static string GetCompanyName ()
233                 {
234                         Assembly assembly = Assembly.GetEntryAssembly ();
235                         if (assembly == null)
236                                 assembly = Assembly.GetCallingAssembly ();
237
238                         AssemblyCompanyAttribute [] attrs = (AssemblyCompanyAttribute []) assembly.GetCustomAttributes (typeof (AssemblyCompanyAttribute), true);
239                 
240                         if ((attrs != null) && attrs.Length > 0) {
241                                 return attrs [0].Company;
242                         }
243
244 #if !TARGET_JVM
245                         MethodInfo entryPoint = assembly.EntryPoint;
246                         Type entryType = entryPoint != null ? entryPoint.DeclaringType : null;
247                         if (entryType != null && !String.IsNullOrEmpty (entryType.Namespace)) {
248                                 int end = entryType.Namespace.IndexOf ('.');
249                                 return end < 0 ? entryType.Namespace : entryType.Namespace.Substring (0, end);
250                         }
251                         return "Program";
252 #else
253                         return assembly.GetName ().Name;
254 #endif
255                 }
256
257                 private static string GetProductName ()
258                 {
259                         Assembly assembly = Assembly.GetEntryAssembly ();
260                         if (assembly == null)
261                                 assembly = Assembly.GetCallingAssembly ();
262
263 #if !TARGET_JVM
264
265                         byte [] pkt = assembly.GetName ().GetPublicKeyToken ();
266                         byte [] hash = SHA1.Create ().ComputeHash (pkt != null ? pkt : Encoding.UTF8.GetBytes (assembly.EscapedCodeBase));
267                         return String.Format ("{0}_{1}_{2}",
268                                 AppDomain.CurrentDomain.FriendlyName,
269                                 pkt != null ? "StrongName" : "Url",
270                                 // FIXME: it seems that something else is used
271                                 // here, to convert hash bytes to string.
272                                 Convert.ToBase64String (hash));
273
274 #else // AssemblyProductAttribute-based code
275                         AssemblyProductAttribute [] attrs = (AssemblyProductAttribute[]) assembly.GetCustomAttributes (typeof (AssemblyProductAttribute), true);
276                 
277                         if ((attrs != null) && attrs.Length > 0) {
278                                 return attrs [0].Product;
279                         }
280                         return assembly.GetName ().Name;
281 #endif
282                 }
283
284                 private static string GetProductVersion ()
285                 {
286                         Assembly assembly = Assembly.GetEntryAssembly ();
287                         if (assembly == null)
288                                 assembly = Assembly.GetCallingAssembly ();
289                         if (assembly == null)
290                                 return string.Empty;
291
292                         return assembly.GetName ().Version.ToString ();
293                 }
294
295                 private static void CreateUserConfigPath ()
296                 {
297                         if (userDefine)
298                                 return;
299
300                         if (ProductName == "")
301                                 ProductName = GetProductName ();
302                         if (CompanyName == "")
303                                 CompanyName = GetCompanyName ();
304                         if (ForceVersion == "")
305                                 ProductVersion = GetProductVersion ().Split('.');
306
307                         // C:\Documents and Settings\(user)\Application Data
308 #if !TARGET_JVM
309                         if (userRoamingBasePath == "")
310                                 userRoamingPath = Environment.GetFolderPath (Environment.SpecialFolder.ApplicationData);
311                         else
312 #endif
313                                 userRoamingPath = userRoamingBasePath;
314
315                         // C:\Documents and Settings\(user)\Local Settings\Application Data (on Windows)
316 #if !TARGET_JVM
317                         if (userLocalBasePath == "")
318                                 userLocalPath = Environment.GetFolderPath (Environment.SpecialFolder.LocalApplicationData);
319                         else
320 #endif
321                                 userLocalPath = userLocalBasePath;
322
323                         if (isCompany) {
324                                 userRoamingPath = Path.Combine (userRoamingPath, CompanyName);
325                                 userLocalPath = Path.Combine (userLocalPath, CompanyName);
326                         }
327
328                         if (isProduct) {
329                                 userRoamingPath = Path.Combine (userRoamingPath, ProductName);
330                                 userLocalPath = Path.Combine (userLocalPath, ProductName);
331                         }
332
333                         string versionName;
334
335                         if (ForceVersion == "") {
336                                 if (isVersionRevision)
337                                         versionName = String.Format ("{0}.{1}.{2}.{3}", ProductVersion [0], ProductVersion [1], ProductVersion [2], ProductVersion [3]);
338                                 else if (isVersionBuild)
339                                         versionName = String.Format ("{0}.{1}.{2}", ProductVersion [0], ProductVersion [1], ProductVersion [2]);
340                                 else if (isVersionMinor)
341                                         versionName = String.Format ("{0}.{1}", ProductVersion [0], ProductVersion [1]);
342                                 else if (isVersionMajor)
343                                         versionName = ProductVersion [0];
344                                 else
345                                         versionName = "";
346                         }
347                         else
348                                 versionName = ForceVersion;
349
350                         string prevVersionRoaming = PrevVersionPath (userRoamingPath, versionName);
351                         string prevVersionLocal = PrevVersionPath (userLocalPath, versionName);
352                         
353                         userRoamingPath = Path.Combine (userRoamingPath, versionName);
354                         userLocalPath = Path.Combine (userLocalPath, versionName);
355                         if (prevVersionRoaming != "")
356                                 userRoamingPathPrevVersion = Path.Combine(userRoamingPath, prevVersionRoaming);
357                         if (prevVersionLocal != "")
358                                 userLocalPathPrevVersion = Path.Combine(userLocalPath, prevVersionLocal);
359                 }
360
361                 // string for the previous version. It ignores newer ones.
362                 private static string PrevVersionPath (string dirName, string currentVersion)
363                 {
364                         string prevVersionString = "";
365
366                         if (!Directory.Exists(dirName))
367                                 return prevVersionString;
368                         DirectoryInfo currentDir = new DirectoryInfo (dirName);
369                         foreach (DirectoryInfo dirInfo in currentDir.GetDirectories ())
370                                 if (String.Compare (currentVersion, dirInfo.Name, StringComparison.Ordinal) > 0)
371                                         if (String.Compare (prevVersionString, dirInfo.Name, StringComparison.Ordinal) < 0)
372                                                 prevVersionString = dirInfo.Name;
373
374                         return prevVersionString;
375                 }
376
377                 // sets the explicit path to store roaming user.config or equivalent.
378                 // (returns the path validity.)
379                 public static bool SetUserRoamingPath (string configPath)
380                 {
381                         if (CheckPath (configPath))
382                         {
383                                 userRoamingBasePath = configPath;
384                                 return true;
385                         }
386                         else
387                                 return false;
388                 }
389
390                 // sets the explicit path to store local user.config or equivalent.
391                 // (returns the path validity.)
392                 public static bool SetUserLocalPath (string configPath)
393                 {
394                         if (CheckPath (configPath))
395                         {
396                                 userLocalBasePath = configPath;
397                                 return true;
398                         }
399                         else
400                                 return false;
401                 }
402
403                 private static bool CheckFileName (string configFile)
404                 {
405                         /*
406                         char[] invalidFileChars = Path.GetInvalidFileNameChars();
407
408                         foreach (char invalidChar in invalidFileChars)
409                         {
410                                 if (configFile.Contains(invalidChar.ToString()))
411                                 {
412                                         return false;
413                                 }
414                         }
415                         return true;
416                         */
417                         return configFile.IndexOfAny (Path.GetInvalidFileNameChars ()) < 0;
418                 }
419
420                 // sets the explicit roaming file name which is user.config equivalent.
421                 // (returns the file name validity.)
422                 public static bool SetUserRoamingFileName (string configFile)
423                 {
424                         if (CheckFileName (configFile))
425                         {
426                                 userRoamingName = configFile;
427                                 return true;
428                         }
429                         else
430                                 return false;
431                 }
432
433                 // sets the explicit local file name which is user.config equivalent.
434                 // (returns the file name validity.)
435                 public static bool SetUserLocalFileName (string configFile)
436                 {
437                         if (CheckFileName (configFile))
438                         {
439                                 userLocalName = configFile;
440                                 return true;
441                         }
442                         else
443                                 return false;
444                 }
445
446                 // sets the explicit company name for folder.
447                 // (returns the file name validity.)
448                 public static bool SetCompanyName (string companyName)
449                 {
450                         if (CheckFileName (companyName))
451                         {
452                                 CompanyName = companyName;
453                                 return true;
454                         }
455                         else
456                                 return false;
457                 }
458
459                 // sets the explicit product name for folder.
460                 // (returns the file name validity.)
461                 public static bool SetProductName (string productName)
462                 {
463                         if (CheckFileName (productName))
464                         {
465                                 ProductName = productName;
466                                 return true;
467                         }
468                         else
469                                 return false;
470                 }
471
472                 // sets the explicit major version for folder.
473                 public static bool SetVersion (int major)
474                 {
475                         ForceVersion = string.Format ("{0}", major);
476                         return true;
477                 }
478
479                 // sets the explicit major and minor versions for folder.
480                 public static bool SetVersion (int major, int minor)
481                 {
482                         ForceVersion = string.Format ("{0}.{1}", major, minor);
483                         return true;
484                 }
485
486                 // sets the explicit major/minor/build numbers for folder.
487                 public static bool SetVersion (int major, int minor, int build)
488                 {
489                         ForceVersion = string.Format ("{0}.{1}.{2}", major, minor, build);
490                         return true;
491                 }
492
493                 // sets the explicit major/minor/build/revision numbers for folder.
494                 public static bool SetVersion (int major, int minor, int build, int revision)
495                 {
496                         ForceVersion = string.Format ("{0}.{1}.{2}.{3}", major, minor, build, revision);
497                         return true;
498                 }
499
500                 // sets the explicit version number string for folder.
501                 public static bool SetVersion (string forceVersion)
502                 {
503                         if (CheckFileName (forceVersion))
504                         {
505                                 ForceVersion = forceVersion;
506                                 return true;
507                         }
508                         else
509                                 return false;
510                 }
511
512                 private static bool CheckPath (string configPath)
513                 {
514                         char[] invalidPathChars = Path.GetInvalidPathChars ();
515
516                         /*
517                         foreach (char invalidChar in invalidPathChars)
518                         {
519                                 if (configPath.Contains (invalidChar.ToString()))
520                                 {
521                                         return false;
522                                 }
523                         }
524                         */
525                         if (configPath.IndexOfAny (invalidPathChars) >= 0)
526                                 return false;
527
528                         string folder = configPath;
529                         string fileName;
530                         while ((fileName = Path.GetFileName (folder)) != "")
531                         {
532                                 if (!CheckFileName (fileName))
533                                 {
534                                         return false;
535                                 }
536                                 folder = Path.GetDirectoryName (folder);
537                         }
538
539                         return true;
540                 }
541
542
543                 public override string Name {
544                         get { return base.Name; }
545                 }
546
547                 string app_name = String.Empty;//"OJK.CustomSetting.CustomizableLocalFileSettingsProvider";
548                 public override string ApplicationName {
549                         get { return app_name; }
550                         set { app_name = value; }
551                 }
552
553                 private ExeConfigurationFileMap exeMapCurrent = null;
554                 private ExeConfigurationFileMap exeMapPrev = null;
555                 private SettingsPropertyValueCollection values = null;
556
557                 private void SaveProperties (ExeConfigurationFileMap exeMap, SettingsPropertyValueCollection collection, ConfigurationUserLevel level, SettingsContext context, bool checkUserLevel)
558                 {
559                         Configuration config = ConfigurationManager.OpenMappedExeConfiguration (exeMap, level);
560                         
561                         UserSettingsGroup userGroup = config.GetSectionGroup ("userSettings") as UserSettingsGroup;
562                         bool isRoaming = (level == ConfigurationUserLevel.PerUserRoaming);
563
564 #if true // my reimplementation
565
566                         if (userGroup == null) {
567                                 userGroup = new UserSettingsGroup ();
568                                 config.SectionGroups.Add ("userSettings", userGroup);
569                                 ApplicationSettingsBase asb = context.CurrentSettings;
570                                 ClientSettingsSection cs = new ClientSettingsSection ();
571                                 userGroup.Sections.Add (asb.GetType ().FullName, cs);
572                         }
573
574                         bool hasChanges = false;
575
576                         foreach (ConfigurationSection section in userGroup.Sections) {
577                                 ClientSettingsSection userSection = section as ClientSettingsSection;
578                                 if (userSection == null)
579                                         continue;
580
581                                 XmlDocument doc = new XmlDocument ();
582
583                                 foreach (SettingsPropertyValue value in collection) {
584                                         if (checkUserLevel && value.Property.Attributes.Contains (typeof (SettingsManageabilityAttribute)) != isRoaming)
585                                                 continue;
586                                         hasChanges = true;
587                                         SettingElement element = userSection.Settings.Get (value.Name);
588                                         if (element == null) {
589                                                 element = new SettingElement (value.Name, value.Property.SerializeAs);
590                                                 userSection.Settings.Add (element);
591                                         }
592                                         if (element.Value.ValueXml == null)
593                                                 element.Value.ValueXml = new XmlDocument ().CreateDocumentFragment ();
594                                         doc = element.Value.ValueXml.OwnerDocument;
595                                         switch (value.Property.SerializeAs) {
596                                         case SettingsSerializeAs.Xml:
597                                                 element.Value.ValueXml.InnerXml = value.SerializedValue as string;
598                                                 break;
599                                         case SettingsSerializeAs.String:
600                                                 element.Value.ValueXml.InnerText = value.SerializedValue as string;
601                                                 break;
602                                         case SettingsSerializeAs.Binary:
603                                                 element.Value.ValueXml.InnerText = Convert.ToBase64String (value.SerializedValue as byte []);
604                                                 break;
605                                         default:
606                                                 throw new NotImplementedException ();
607                                         }
608                                 }
609                         }
610                         if (hasChanges)
611                                 config.Save (ConfigurationSaveMode.Minimal, true);
612
613 #else // original impl. - likely buggy to miss some properties to save
614
615                         foreach (ConfigurationSection configSection in userGroup.Sections)
616                         {
617                                 ClientSettingsSection userSection = configSection as ClientSettingsSection;
618                                 if (userSection != null)
619                                 {
620 /*
621                                         userSection.Settings.Clear();
622
623                                         foreach (SettingsPropertyValue propertyValue in collection)
624                                         {
625                                                 if (propertyValue.IsDirty)
626                                                 {
627                                                         SettingElement element = new SettingElement(propertyValue.Name, SettingsSerializeAs.String);
628                                                         element.Value.ValueXml = new XmlDocument();
629                                                         element.Value.ValueXml.InnerXml = (string)propertyValue.SerializedValue;
630                                                         userSection.Settings.Add(element);
631                                                 }
632                                         }
633 */
634                                         foreach (SettingElement element in userSection.Settings)
635                                         {
636                                                 if (collection [element.Name] != null) {
637                                                         if (collection [element.Name].Property.Attributes.Contains (typeof (SettingsManageabilityAttribute)) != isRoaming)
638                                                                 continue;
639
640                                                         element.SerializeAs = SettingsSerializeAs.String;
641                                                         element.Value.ValueXml.InnerXml = (string) collection [element.Name].SerializedValue;   ///Value = XmlElement
642                                                 }
643                                         }
644  
645                                 }
646                         }
647                         config.Save (ConfigurationSaveMode.Minimal, true);
648 #endif
649                 }
650
651                 private void LoadPropertyValue (SettingsPropertyCollection collection, SettingElement element, bool allowOverwrite)
652                 {
653                         SettingsProperty prop = collection [element.Name];
654                         SettingsPropertyValue value = new SettingsPropertyValue (prop);
655                         value.IsDirty = false;
656                         value.SerializedValue = element.Value.ValueXml != null ? element.Value.ValueXml.InnerText : prop.DefaultValue;
657                         try
658                         {
659                                 if (allowOverwrite)
660                                         values.Remove (element.Name);
661                                 values.Add (value);
662                         } catch (ArgumentException) {
663                                 throw new ConfigurationErrorsException ();
664                         }
665                 }
666
667                 private void LoadProperies (ExeConfigurationFileMap exeMap, SettingsPropertyCollection collection, ConfigurationUserLevel level, string sectionGroupName, bool allowOverwrite)
668                 {
669                         Configuration config = ConfigurationManager.OpenMappedExeConfiguration (exeMap,level);
670                         
671                         ConfigurationSectionGroup sectionGroup = config.GetSectionGroup (sectionGroupName);
672                         if (sectionGroup != null) {
673                                 foreach (ConfigurationSection configSection in sectionGroup.Sections) {
674                                         ClientSettingsSection clientSection = configSection as ClientSettingsSection;
675                                         if (clientSection != null)
676                                                 foreach (SettingElement element in clientSection.Settings)
677                                                         LoadPropertyValue(collection, element, allowOverwrite);
678                                 }
679                         }
680
681                 }
682
683                 public override void SetPropertyValues (SettingsContext context, SettingsPropertyValueCollection collection)
684                 {
685                         CreateExeMap ();
686
687                         if (UserLocalFullPath == UserRoamingFullPath)
688                         {
689                                 SaveProperties (exeMapCurrent, collection, ConfigurationUserLevel.PerUserRoaming, context, false);
690                         } else {
691                                 SaveProperties (exeMapCurrent, collection, ConfigurationUserLevel.PerUserRoaming, context, true);
692                                 SaveProperties (exeMapCurrent, collection, ConfigurationUserLevel.PerUserRoamingAndLocal, context, true);
693                         }
694                 }
695
696                 public override SettingsPropertyValueCollection GetPropertyValues (SettingsContext context, SettingsPropertyCollection collection)
697                 {
698                         CreateExeMap ();
699
700                         if (values == null) {
701                                 values = new SettingsPropertyValueCollection ();
702                                 LoadProperies (exeMapCurrent, collection, ConfigurationUserLevel.None, "applicationSettings", false);
703                                 LoadProperies (exeMapCurrent, collection, ConfigurationUserLevel.None, "userSettings", false);
704
705                                 LoadProperies (exeMapCurrent, collection, ConfigurationUserLevel.PerUserRoaming, "userSettings", true);
706                                 LoadProperies (exeMapCurrent, collection, ConfigurationUserLevel.PerUserRoamingAndLocal, "userSettings", true);
707
708                                 // create default values if not exist
709                                 foreach (SettingsProperty p in collection)
710                                         if (values [p.Name] == null)
711                                                 values.Add (new SettingsPropertyValue (p));
712                         }
713                         return values;
714                 }
715
716                 /// creates an ExeConfigurationFileMap
717                 private void CreateExeMap ()
718                 {
719                         if (exeMapCurrent == null) {
720                                 CreateUserConfigPath ();
721
722                                 // current version
723                                 exeMapCurrent = new ExeConfigurationFileMap ();
724                                 // exeMapCurrent.ExeConfigFilename = System.Windows.Forms.Application.ExecutablePath + ".config";
725                                 Assembly entry = Assembly.GetEntryAssembly () ?? Assembly.GetExecutingAssembly ();
726                                 exeMapCurrent.ExeConfigFilename = entry.Location + ".config";
727                                 exeMapCurrent.LocalUserConfigFilename = UserLocalFullPath;
728                                 exeMapCurrent.RoamingUserConfigFilename = UserRoamingFullPath;
729
730                                 // previous version
731                                 if ((PrevUserLocalFullPath != "") && (PrevUserRoamingFullPath != ""))
732                                 {
733                                         exeMapPrev = new ExeConfigurationFileMap();
734                                         // exeMapPrev.ExeConfigFilename = System.Windows.Forms.Application.ExecutablePath + ".config";
735                                         exeMapPrev.ExeConfigFilename = entry.Location + ".config";
736                                         exeMapPrev.LocalUserConfigFilename = PrevUserLocalFullPath;
737                                         exeMapPrev.RoamingUserConfigFilename = PrevUserRoamingFullPath;
738                                 }
739                         }
740                 }
741
742                 // FIXME: implement
743                 public SettingsPropertyValue GetPreviousVersion (SettingsContext context, SettingsProperty property)
744                 {
745                         return null;
746                 }
747
748                 public void Reset (SettingsContext context)
749                 {
750                         CreateExeMap ();
751                         foreach (SettingsPropertyValue propertyValue in values) {
752                                 propertyValue.PropertyValue = propertyValue.Property.DefaultValue;
753                                 propertyValue.IsDirty = true;
754                         }
755                         SetPropertyValues (context, values);
756                 }
757
758                 // FIXME: implement
759                 public void Upgrade (SettingsContext context, SettingsPropertyCollection properties)
760                 {
761                 }
762
763                 public static void setCreate ()
764                 {
765                         CreateUserConfigPath();
766                 }
767         }
768 }
769
770 #endif