The Labs \ Source Viewer \ SSCLI \ System.Configuration \ ConfigurationLockCollection

  1. //------------------------------------------------------------------------------
  2. // <copyright file="ConfigurationLockCollection.cs" company="Microsoft">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. //------------------------------------------------------------------------------
  15. using System;
  16. using System.Configuration.Internal;
  17. using System.Collections;
  18. using System.Collections.Specialized;
  19. using System.Collections.Generic;
  20. using System.IO;
  21. using System.Reflection;
  22. using System.Security.Permissions;
  23. using System.Xml;
  24. using System.Globalization;
  25. using System.ComponentModel;
  26. using System.Security;
  27. using System.Text;
  28. namespace System.Configuration
  29. {
  30.    
  31.     public sealed class ConfigurationLockCollection : IEnumerable, ICollection
  32.     {
  33.         private HybridDictionary internalDictionary;
  34.         private ArrayList internalArraylist;
  35.         private bool _bModified = false;
  36.         private bool _bExceptionList = false;
  37.         private string _ignoreName = String.Empty;
  38.         private ConfigurationElement _thisElement = null;
  39.         private ConfigurationLockCollectionType _lockType;
  40.         private string SeedList = String.Empty;
  41.         private const string LockAll = "*";
  42.        
  43.         internal ConfigurationLockCollection(ConfigurationElement thisElement) : this(thisElement, ConfigurationLockCollectionType.LockedAttributes)
  44.         {
  45.         }
  46.        
  47.         internal ConfigurationLockCollection(ConfigurationElement thisElement, ConfigurationLockCollectionType lockType) : this(thisElement, lockType, String.Empty)
  48.         {
  49.         }
  50.        
  51.         internal ConfigurationLockCollection(ConfigurationElement thisElement, ConfigurationLockCollectionType lockType, string ignoreName) : this(thisElement, lockType, ignoreName, null)
  52.         {
  53.         }
  54.        
  55.         internal ConfigurationLockCollection(ConfigurationElement thisElement, ConfigurationLockCollectionType lockType, string ignoreName, ConfigurationLockCollection parentCollection)
  56.         {
  57.             _thisElement = thisElement;
  58.             _lockType = lockType;
  59.             internalDictionary = new HybridDictionary();
  60.             internalArraylist = new ArrayList();
  61.             _bModified = false;
  62.            
  63.             _bExceptionList = _lockType == ConfigurationLockCollectionType.LockedExceptionList || _lockType == ConfigurationLockCollectionType.LockedElementsExceptionList;
  64.             _ignoreName = ignoreName;
  65.            
  66.             if (parentCollection != null) {
  67.                 // seed the new collection
  68.                 foreach (string key in parentCollection) {
  69.                     Add(key, ConfigurationValueFlags.Inherited);
  70.                     // add the local copy
  71.                     if (_bExceptionList) {
  72.                         if (SeedList.Length != 0)
  73.                             SeedList += ",";
  74.                         SeedList += key;
  75.                     }
  76.                 }
  77.             }
  78.            
  79.         }
  80.        
  81.         internal void ClearSeedList()
  82.         {
  83.             SeedList = String.Empty;
  84.         }
  85.        
  86.         internal ConfigurationLockCollectionType LockType {
  87.             get { return _lockType; }
  88.         }
  89.        
  90.         public void Add(string name)
  91.         {
  92.            
  93.             if (((_thisElement.ItemLocked & ConfigurationValueFlags.Locked) != 0) && ((_thisElement.ItemLocked & ConfigurationValueFlags.Inherited) != 0)) {
  94.                 throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_attribute_locked, name));
  95.             }
  96.            
  97.             ConfigurationValueFlags flags = ConfigurationValueFlags.Modified;
  98.            
  99.             string attribToLockTrim = name.Trim();
  100.             ConfigurationProperty propToLock = _thisElement.Properties[attribToLockTrim];
  101.             if (propToLock == null && attribToLockTrim != LockAll) {
  102.                 ConfigurationElementCollection collection = _thisElement as ConfigurationElementCollection;
  103.                 if (collection == null && _thisElement.Properties.DefaultCollectionProperty != null) {
  104.                     // this is not a collection but it may contain a default collection
  105.                     collection = _thisElement[_thisElement.Properties.DefaultCollectionProperty] as ConfigurationElementCollection;
  106.                 }
  107.                
  108.                 // If the collection type is not element then the lock is bogus
  109.                 if (collection == null || _lockType == ConfigurationLockCollectionType.LockedAttributes || _lockType == ConfigurationLockCollectionType.LockedExceptionList) {
  110.                     _thisElement.ReportInvalidLock(attribToLockTrim, _lockType, null, null);
  111.                 }
  112.                 else if (!collection.IsLockableElement(attribToLockTrim)) {
  113.                     _thisElement.ReportInvalidLock(attribToLockTrim, _lockType, null, collection.LockableElements);
  114.                 }
  115.             }
  116.             else {
  117.                 // the lock is in the property bag but is it the correct type?
  118.                 if (propToLock != null && propToLock.IsRequired)
  119.                     throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_required_attribute_lock_attempt, propToLock.Name));
  120.                
  121.                 if (attribToLockTrim != LockAll) {
  122.                     if ((_lockType == ConfigurationLockCollectionType.LockedElements) || (_lockType == ConfigurationLockCollectionType.LockedElementsExceptionList)) {
  123.                         // If it is an element then it must be derived from ConfigurationElement
  124.                         if (!typeof(ConfigurationElement).IsAssignableFrom(propToLock.Type)) {
  125.                             _thisElement.ReportInvalidLock(attribToLockTrim, _lockType, null, null);
  126.                         }
  127.                     }
  128.                     else {
  129.                         // if it is a property then it cannot be derived from ConfigurationElement
  130.                         if (typeof(ConfigurationElement).IsAssignableFrom(propToLock.Type)) {
  131.                             _thisElement.ReportInvalidLock(attribToLockTrim, _lockType, null, null);
  132.                         }
  133.                     }
  134.                 }
  135.             }
  136.            
  137.             if (internalDictionary.Contains(name)) {
  138.                 flags = ConfigurationValueFlags.Modified | (ConfigurationValueFlags)internalDictionary[name];
  139.                 internalDictionary.Remove(name);
  140.                 // not from parent
  141.                 internalArraylist.Remove(name);
  142.             }
  143.             internalDictionary.Add(name, flags);
  144.             // not from parent
  145.             internalArraylist.Add(name);
  146.             _bModified = true;
  147.         }
  148.        
  149.        
  150.         internal void Add(string name, ConfigurationValueFlags flags)
  151.         {
  152.             if ((flags != ConfigurationValueFlags.Inherited) && (internalDictionary.Contains(name))) {
  153.                 // the user has an item declared as locked below a level where it is already locked
  154.                 // keep enough info so we can write out the lock if they save in modified mode
  155.                 flags = ConfigurationValueFlags.Modified | (ConfigurationValueFlags)internalDictionary[name];
  156.                 internalDictionary.Remove(name);
  157.                 internalArraylist.Remove(name);
  158.             }
  159.            
  160.             internalDictionary.Add(name, flags);
  161.             // not from parent
  162.             internalArraylist.Add(name);
  163.         }
  164.        
  165.         internal bool DefinedInParent(string name)
  166.         {
  167.             if (name == null)
  168.                 return false;
  169.             if (_bExceptionList) {
  170.                 string ParentListEnclosed = "," + SeedList + ",";
  171.                 if (name.Equals(_ignoreName) || ParentListEnclosed.IndexOf("," + name + ",", StringComparison.Ordinal) >= 0) {
  172.                     return true;
  173.                 }
  174.             }
  175.             return (internalDictionary.Contains(name) && ((ConfigurationValueFlags)internalDictionary[name] & ConfigurationValueFlags.Inherited) != 0);
  176.         }
  177.        
  178.         internal bool IsValueModified(string name)
  179.         {
  180.             return (internalDictionary.Contains(name) && ((ConfigurationValueFlags)internalDictionary[name] & ConfigurationValueFlags.Modified) != 0);
  181.         }
  182.        
  183.         internal void RemoveInheritedLocks()
  184.         {
  185.             StringCollection removeList = new StringCollection();
  186.             foreach (string key in this) {
  187.                 if (DefinedInParent(key)) {
  188.                     removeList.Add(key);
  189.                 }
  190.             }
  191.             foreach (string key in removeList) {
  192.                 internalDictionary.Remove(key);
  193.                 internalArraylist.Remove(key);
  194.             }
  195.         }
  196.        
  197.        
  198.         public void Remove(string name)
  199.         {
  200.             if (!internalDictionary.Contains(name)) {
  201.                 throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_collection_entry_not_found, name));
  202.             }
  203.             // in a locked list you cannot remove items that were locked in the parent
  204.             // in an exception list this is legal because it makes the list more restrictive
  205.            
  206.             if (_bExceptionList == false && ((ConfigurationValueFlags)internalDictionary[name] & ConfigurationValueFlags.Inherited) != 0) {
  207.                 if (((ConfigurationValueFlags)internalDictionary[name] & ConfigurationValueFlags.Modified) != 0) {
  208.                     // allow the local one to be "removed" so it won't write out but throw if they try and remove
  209.                     // one that is only inherited
  210.                     ConfigurationValueFlags flags = (ConfigurationValueFlags)internalDictionary[name];
  211.                     flags &= ~ConfigurationValueFlags.Modified;
  212.                     internalDictionary[name] = flags;
  213.                     _bModified = true;
  214.                     return;
  215.                 }
  216.                 else {
  217.                     throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_attribute_locked, name));
  218.                 }
  219.             }
  220.            
  221.             internalDictionary.Remove(name);
  222.             internalArraylist.Remove(name);
  223.             _bModified = true;
  224.         }
  225.        
  226.         public IEnumerator GetEnumerator()
  227.         {
  228.             return internalArraylist.GetEnumerator();
  229.         }
  230.        
  231.         internal void ClearInternal(bool useSeedIfAvailble)
  232.         {
  233.             ArrayList removeList = new ArrayList();
  234.             foreach (DictionaryEntry de in internalDictionary) {
  235.                 if ((((ConfigurationValueFlags)de.Value & ConfigurationValueFlags.Inherited) == 0) || _bExceptionList == true) {
  236.                     removeList.Add(de.Key);
  237.                 }
  238.             }
  239.             foreach (object removeKey in removeList) {
  240.                 internalDictionary.Remove(removeKey);
  241.                 internalArraylist.Remove(removeKey);
  242.             }
  243.            
  244.             // Clearing an Exception list really means revert to parent
  245.             if (useSeedIfAvailble && !String.IsNullOrEmpty(SeedList)) {
  246.                 string[] Keys = SeedList.Split(new char[] {','});
  247.                 foreach (string key in Keys) {
  248.                     Add(key, ConfigurationValueFlags.Inherited);
  249.                     //
  250.                 }
  251.             }
  252.             _bModified = true;
  253.         }
  254.        
  255.         public void Clear()
  256.         {
  257.             ClearInternal(true);
  258.         }
  259.        
  260.         public bool Contains(string name)
  261.         {
  262.             if (_bExceptionList && name.Equals(_ignoreName)) {
  263.                 return true;
  264.             }
  265.             return internalDictionary.Contains(name);
  266.         }
  267.        
  268.         public int Count {
  269.             get { return internalDictionary.Count; }
  270.         }
  271.        
  272.         public bool IsSynchronized {
  273.             get { return false; }
  274.         }
  275.        
  276.         public object SyncRoot {
  277.             get { return this; }
  278.         }
  279.        
  280.         public void CopyTo(string[] array, int index)
  281.         {
  282.             ((ICollection)this).CopyTo(array, index);
  283.         }
  284.        
  285.         void ICollection.CopyTo(Array array, int index)
  286.         {
  287.             internalArraylist.CopyTo(array, index);
  288.         }
  289.        
  290.         public bool IsModified {
  291.             get { return _bModified; }
  292.         }
  293.        
  294.         internal void ResetModified()
  295.         {
  296.             _bModified = false;
  297.         }
  298.        
  299.         public bool IsReadOnly(string name)
  300.         {
  301.             if (!internalDictionary.Contains(name)) {
  302.                 throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_collection_entry_not_found, name));
  303.             }
  304.             return (bool)(((ConfigurationValueFlags)internalDictionary[name] & ConfigurationValueFlags.Inherited) != 0);
  305.         }
  306.        
  307.         internal bool ExceptionList {
  308.             get { return _bExceptionList; }
  309.         }
  310.        
  311.         public string AttributeList {
  312.             get {
  313.                 StringBuilder sb;
  314.                 sb = new StringBuilder();
  315.                
  316.                 foreach (DictionaryEntry de in internalDictionary) {
  317.                     if (sb.Length != 0) {
  318.                         sb.Append(',');
  319.                     }
  320.                     sb.Append(de.Key);
  321.                 }
  322.                 return sb.ToString();
  323.             }
  324.         }
  325.        
  326.         public void SetFromList(string attributeList)
  327.         {
  328.             string[] splits = attributeList.Split(new char[] {',', ';', ':'});
  329.             Clear();
  330.             foreach (string name in splits) {
  331.                 string attribTrim = name.Trim();
  332.                 if (!Contains(attribTrim)) {
  333.                     Add(attribTrim);
  334.                 }
  335.             }
  336.         }
  337.         public bool HasParentElements {
  338.             get {
  339.                 // return true if there is at least one element that was defined in the parent
  340.                 bool result = false;
  341.                 // Check to see if the exception list is empty as a result of a merge from config
  342.                 // If so the there were some parent elements because empty string is invalid in config.
  343.                 // and the only way to get an empty list is for the merged config to have no elements
  344.                 // in common.
  345.                 if (ExceptionList && internalDictionary.Count == 0 && !String.IsNullOrEmpty(SeedList))
  346.                     return true;
  347.                
  348.                 foreach (DictionaryEntry de in internalDictionary) {
  349.                     if ((bool)(((ConfigurationValueFlags)de.Value & ConfigurationValueFlags.Inherited) != 0)) {
  350.                         result = true;
  351.                         break;
  352.                     }
  353.                 }
  354.                
  355.                 return result;
  356.             }
  357.         }
  358.     }
  359. }

Developer Fusion