| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645 |
- //-----------------------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //-----------------------------------------------------------------------------
- namespace System.ServiceModel.Configuration
- {
- using System;
- using System.Collections.Generic;
- using System.Configuration;
- using System.Diagnostics;
- using System.Runtime;
- using System.Runtime.Diagnostics;
- using System.Security;
- using System.ServiceModel;
- using System.ServiceModel.Diagnostics;
- using System.Xml;
- public abstract class ServiceModelExtensionCollectionElement<TServiceModelExtensionElement> : ConfigurationElement, ICollection<TServiceModelExtensionElement>, IConfigurationContextProviderInternal
- where TServiceModelExtensionElement : ServiceModelExtensionElement
- {
- [Fx.Tag.SecurityNote(Critical = "Stores information used in a security decision.")]
- [SecurityCritical]
- EvaluationContextHelper contextHelper;
- string extensionCollectionName = null;
- bool modified = false;
- List<TServiceModelExtensionElement> items = null;
- ConfigurationPropertyCollection properties = null;
- internal ServiceModelExtensionCollectionElement(string extensionCollectionName)
- {
- this.extensionCollectionName = extensionCollectionName;
- }
- public TServiceModelExtensionElement this[int index]
- {
- get { return this.Items[index]; }
- }
- public TServiceModelExtensionElement this[Type extensionType]
- {
- get
- {
- if (extensionType == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("extensionType");
- }
- if (!this.CollectionElementBaseType.IsAssignableFrom(extensionType))
- {
- #pragma warning disable 56506 //[....]; Variable 'extensionType' checked for null previously
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("extensionType",
- SR.GetString(SR.ConfigInvalidExtensionType,
- extensionType.ToString(),
- this.CollectionElementBaseType.FullName,
- this.extensionCollectionName));
- #pragma warning restore
- }
- TServiceModelExtensionElement retval = null;
- foreach (TServiceModelExtensionElement collectionElement in this)
- {
- if (null != collectionElement)
- {
- if (collectionElement.GetType() == extensionType)
- {
- retval = collectionElement;
- }
- }
- }
- return retval;
- }
- }
- public int Count
- {
- get { return this.Items.Count; }
- }
- bool ICollection<TServiceModelExtensionElement>.IsReadOnly
- {
- get { return this.IsReadOnly(); }
- }
- internal List<TServiceModelExtensionElement> Items
- {
- get
- {
- if (this.items == null)
- {
- this.items = new List<TServiceModelExtensionElement>();
- }
- return this.items;
- }
- }
- protected override ConfigurationPropertyCollection Properties
- {
- get
- {
- if (this.properties == null)
- {
- this.properties = new ConfigurationPropertyCollection();
- }
- return this.properties;
- }
- }
- public virtual void Add(TServiceModelExtensionElement element)
- {
- if (this.IsReadOnly())
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ConfigurationErrorsException(SR.GetString(SR.ConfigReadOnly)));
- }
- if (element == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("element");
- }
- element.ExtensionCollectionName = this.extensionCollectionName;
- if (this.Contains(element))
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("element", SR.GetString(SR.ConfigDuplicateKey, element.ConfigurationElementName));
- }
- else if (!this.CanAdd(element))
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("element",
- SR.GetString(SR.ConfigElementTypeNotAllowed,
- element.ConfigurationElementName,
- this.extensionCollectionName));
- }
- else
- {
- element.ContainingEvaluationContext = ConfigurationHelpers.GetEvaluationContext(this);
- ConfigurationProperty configProperty = new ConfigurationProperty(element.ConfigurationElementName, element.GetType(), null);
- this.Properties.Add(configProperty);
- this[configProperty] = element;
- this.Items.Add(element);
- this.modified = true;
- }
- }
- internal void AddItem(TServiceModelExtensionElement element)
- {
- if (this.IsReadOnly())
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ConfigurationErrorsException(SR.GetString(SR.ConfigReadOnly)));
- }
- element.ExtensionCollectionName = this.extensionCollectionName;
- element.ContainingEvaluationContext = ConfigurationHelpers.GetEvaluationContext(this);
- this.Items.Add(element);
- this.modified = true;
- }
- public virtual bool CanAdd(TServiceModelExtensionElement element)
- {
- if (null == element)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("element");
- }
- bool retval = false;
- Type elementType = element.GetType();
- if (!this.IsReadOnly())
- {
- if (!this.ContainsKey(elementType))
- {
- retval = element.CanAdd(this.extensionCollectionName, ConfigurationHelpers.GetEvaluationContext(this));
- }
- else if (DiagnosticUtility.ShouldTraceWarning)
- {
- TraceUtility.TraceEvent(TraceEventType.Warning,
- TraceCode.ExtensionElementAlreadyExistsInCollection,
- SR.GetString(SR.TraceCodeExtensionElementAlreadyExistsInCollection),
- this.CreateCanAddRecord(this[elementType]), this, null);
- }
- }
- else if (DiagnosticUtility.ShouldTraceWarning)
- {
- TraceUtility.TraceEvent(TraceEventType.Warning,
- TraceCode.ConfigurationIsReadOnly,
- SR.GetString(SR.TraceCodeConfigurationIsReadOnly),
- null, this, null);
- }
- return retval;
- }
- DictionaryTraceRecord CreateCanAddRecord(TServiceModelExtensionElement element)
- {
- return this.CreateCanAddRecord(element, new Dictionary<string, string>(3));
- }
- DictionaryTraceRecord CreateCanAddRecord(TServiceModelExtensionElement element, Dictionary<string, string> values)
- {
- values["ElementType"] = System.Runtime.Diagnostics.DiagnosticTraceBase.XmlEncode(typeof(TServiceModelExtensionElement).AssemblyQualifiedName);
- values["ConfiguredSectionName"] = element.ConfigurationElementName;
- values["CollectionName"] = ConfigurationStrings.ExtensionsSectionPath + "/" + this.extensionCollectionName;
- return new DictionaryTraceRecord(values);
- }
- public void Clear()
- {
- if (this.IsReadOnly())
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ConfigurationErrorsException(SR.GetString(SR.ConfigReadOnly)));
- }
- if (this.Properties.Count > 0)
- {
- this.modified = true;
- }
- List<string> propertiesToRemove = new List<string>(this.Items.Count);
- foreach (TServiceModelExtensionElement item in this.Items)
- {
- propertiesToRemove.Add(item.ConfigurationElementName);
- }
- this.Items.Clear();
- foreach (string name in propertiesToRemove)
- {
- this.Properties.Remove(name);
- }
- }
- internal Type CollectionElementBaseType
- {
- get { return typeof(TServiceModelExtensionElement); }
- }
- public bool Contains(TServiceModelExtensionElement element)
- {
- if (element == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("element");
- }
- return this.ContainsKey(element.GetType());
- }
- public bool ContainsKey(Type elementType)
- {
- if (elementType == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("elementType");
- }
- return (this[elementType] != null);
- }
- public bool ContainsKey(string elementName)
- {
- if (string.IsNullOrEmpty(elementName))
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("elementName");
- }
- bool retval = false;
- foreach (TServiceModelExtensionElement element in this)
- {
- if (null != element)
- {
- string configuredSectionName = element.ConfigurationElementName;
- if (configuredSectionName.Equals(elementName, StringComparison.Ordinal))
- {
- retval = true;
- break;
- }
- }
- }
- return retval;
- }
- public void CopyTo(TServiceModelExtensionElement[] elements, int start)
- {
- if (elements == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("elements");
- }
- if (start < 0 || start >= elements.Length)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("start",
- SR.GetString(SR.ConfigInvalidStartValue,
- elements.Length - 1,
- start));
- }
- foreach (TServiceModelExtensionElement element in this)
- {
- if (null != element)
- {
- string configuredSectionName = element.ConfigurationElementName;
- TServiceModelExtensionElement copiedElement = this.CreateNewSection(configuredSectionName);
- if ((copiedElement != null) && (start < elements.Length))
- {
- copiedElement.CopyFrom(element);
- elements[start] = copiedElement;
- ++start;
- }
- }
- }
- }
- /// <summary>
- /// Returns the extension element, or null if the type cannot be loaded in certain situations (see the code for details).
- /// </summary>
- TServiceModelExtensionElement CreateNewSection(string name)
- {
- if (this.ContainsKey(name) && !(name == ConfigurationStrings.Clear || name == ConfigurationStrings.Remove))
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ConfigurationErrorsException(SR.GetString(SR.ConfigDuplicateItem,
- name,
- this.GetType().Name),
- this.ElementInformation.Source,
- this.ElementInformation.LineNumber));
- }
- TServiceModelExtensionElement retval = null;
- Type elementType;
- ContextInformation evaluationContext = ConfigurationHelpers.GetEvaluationContext(this);
- try
- {
- elementType = GetExtensionType(evaluationContext, name);
- }
- catch (ConfigurationErrorsException e)
- {
- // Work-around for bug 219506@CSDMain: if the extension type cannot be loaded, we'll ignore
- // the exception when running in win8 app container and reading from machine.config.
- if (System.ServiceModel.Channels.AppContainerInfo.IsRunningInAppContainer && evaluationContext.IsMachineLevel)
- {
- DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
- return null;
- }
- else
- {
- throw;
- }
- }
- if (null != elementType)
- {
- if (this.CollectionElementBaseType.IsAssignableFrom(elementType))
- {
- retval = (TServiceModelExtensionElement)Activator.CreateInstance(elementType);
- retval.ExtensionCollectionName = this.extensionCollectionName;
- retval.ConfigurationElementName = name;
- retval.InternalInitializeDefault();
- }
- else
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ConfigurationErrorsException(SR.GetString(SR.ConfigInvalidExtensionElement,
- name,
- this.CollectionElementBaseType.FullName),
- this.ElementInformation.Source,
- this.ElementInformation.LineNumber));
- }
- }
- else
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ConfigurationErrorsException(SR.GetString(SR.ConfigInvalidExtensionElementName,
- name,
- this.extensionCollectionName),
- this.ElementInformation.Source,
- this.ElementInformation.LineNumber));
- }
- return retval;
- }
- [Fx.Tag.SecurityNote(Critical = "Calls SecurityCritical method UnsafeLookupCollection which elevates in order to load config.",
- Safe = "Does not leak any config objects.")]
- [SecuritySafeCritical]
- Type GetExtensionType(ContextInformation evaluationContext, string name)
- {
- ExtensionElementCollection collection = ExtensionsSection.UnsafeLookupCollection(this.extensionCollectionName, evaluationContext);
- if (collection.ContainsKey(name))
- {
- ExtensionElement element = collection[name];
- Type elementType = Type.GetType(element.Type, false);
- if (null == elementType)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ConfigurationErrorsException(SR.GetString(SR.ConfigInvalidType, element.Type, element.Name),
- this.ElementInformation.Source,
- this.ElementInformation.LineNumber));
- }
- return elementType;
- }
- return null;
- }
- internal void MergeWith(List<TServiceModelExtensionElement> parentExtensionElements)
- {
- ServiceModelExtensionCollectionElement<TServiceModelExtensionElement>.Merge(parentExtensionElements, this);
- this.Clear();
- foreach (TServiceModelExtensionElement parentExtensionElement in parentExtensionElements)
- {
- this.Add(parentExtensionElement);
- }
- }
- static void Merge(List<TServiceModelExtensionElement> parentExtensionElements, IEnumerable<TServiceModelExtensionElement> childExtensionElements)
- {
- foreach (TServiceModelExtensionElement childExtensionElement in childExtensionElements)
- {
- if (childExtensionElement is ClearBehaviorElement)
- {
- parentExtensionElements.Clear();
- }
- else if (childExtensionElement is RemoveBehaviorElement)
- {
- string childExtensionElementName = (childExtensionElement as RemoveBehaviorElement).Name;
- if (!string.IsNullOrEmpty(childExtensionElementName))
- {
- parentExtensionElements.RemoveAll(element => element != null && element.ConfigurationElementName == childExtensionElementName);
- }
- }
- else
- {
- Type childExtensionElementType = childExtensionElement.GetType();
- parentExtensionElements.RemoveAll(element => element != null && element.GetType() == childExtensionElementType);
- parentExtensionElements.Add(childExtensionElement);
- }
- }
- }
- [Fx.Tag.SecurityNote(Critical = "Uses the critical helper SetIsPresent.",
- Safe = "Controls how/when SetIsPresent is used, not arbitrarily callable from PT (method is protected and class is sealed).")]
- [SecuritySafeCritical]
- protected override void DeserializeElement(XmlReader reader, bool serializeCollectionKey)
- {
- SetIsPresent();
- DeserializeElementCore(reader);
- }
- private void DeserializeElementCore(XmlReader reader)
- {
- if (reader.HasAttributes && 0 < reader.AttributeCount)
- {
- while (reader.MoveToNextAttribute())
- {
- if (this.Properties.Contains(reader.Name))
- {
- this[reader.Name] = this.Properties[reader.Name].Converter.ConvertFromString(reader.Value);
- }
- else
- {
- this.OnDeserializeUnrecognizedAttribute(reader.Name, reader.Value);
- }
- }
- }
- if (XmlNodeType.Element != reader.NodeType)
- {
- reader.MoveToElement();
- }
- XmlReader subTree = reader.ReadSubtree();
- if (subTree.Read())
- {
- while (subTree.Read())
- {
- if (XmlNodeType.Element == subTree.NodeType)
- {
- // Create new child element and add it to the property collection to
- // associate the element with an EvaluationContext. Then deserialize
- // XML further to set actual values.
- TServiceModelExtensionElement collectionElement = this.CreateNewSection(subTree.Name);
- if (collectionElement != null)
- {
- this.Add(collectionElement);
- collectionElement.DeserializeInternal(subTree, false);
- }
- }
- }
- }
- }
- [Fx.Tag.SecurityNote(Critical = "Calls ConfigurationHelpers.SetIsPresent which elevates in order to set a property.")]
- [SecurityCritical]
- void SetIsPresent()
- {
- ConfigurationHelpers.SetIsPresent(this);
- }
- public System.Collections.Generic.IEnumerator<TServiceModelExtensionElement> GetEnumerator()
- {
- for (int index = 0; index < this.Items.Count; ++index)
- {
- TServiceModelExtensionElement currentValue = items[index];
- yield return currentValue;
- }
- }
- protected override bool IsModified()
- {
- bool retval = this.modified;
- if (!retval)
- {
- for (int i = 0; i < this.Items.Count; i++)
- {
- TServiceModelExtensionElement element = this.Items[i];
- if (element.IsModifiedInternal())
- {
- retval = true;
- break;
- }
- }
- }
- return retval;
- }
- protected override bool OnDeserializeUnrecognizedElement(string elementName, XmlReader reader)
- {
- // When this is used as a DefaultCollection (i.e. CommonBehaviors)
- // the element names are unrecognized by the parent tag, which delegates
- // to the collection's OnDeserializeUnrecognizedElement. In this case,
- // an unrecognized element may be expected, simply try to deserialize the
- // element and let DeserializeElement() throw the appropriate exception if
- // an error is hit.
- this.DeserializeElement(reader, false);
- return true;
- }
- public bool Remove(TServiceModelExtensionElement element)
- {
- if (element == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("element");
- }
- bool retval = false;
- if (this.Contains(element))
- {
- string configuredSectionName = element.ConfigurationElementName;
- TServiceModelExtensionElement existingElement = (TServiceModelExtensionElement)this[element.GetType()];
- this.Items.Remove(existingElement);
- this.Properties.Remove(configuredSectionName);
- this.modified = true;
- retval = true;
- }
- return retval;
- }
- [Fx.Tag.SecurityNote(Critical = "Accesses critical field contextHelper.")]
- [SecurityCritical]
- protected override void Reset(ConfigurationElement parentElement)
- {
- ServiceModelExtensionCollectionElement<TServiceModelExtensionElement> collection =
- (ServiceModelExtensionCollectionElement<TServiceModelExtensionElement>)parentElement;
- foreach (TServiceModelExtensionElement collectionElement in collection.Items)
- {
- this.Items.Add(collectionElement);
- }
- // Update my properties
- this.UpdateProperties(collection);
- this.contextHelper.OnReset(parentElement);
- base.Reset(parentElement);
- }
- protected override void ResetModified()
- {
- for (int i = 0; i < this.Items.Count; i++)
- {
- TServiceModelExtensionElement collectionElement = this.Items[i];
- collectionElement.ResetModifiedInternal();
- }
- this.modified = false;
- }
- protected void SetIsModified()
- {
- this.modified = true;
- }
- protected override void SetReadOnly()
- {
- base.SetReadOnly();
- for (int i = 0; i < this.Items.Count; i++)
- {
- TServiceModelExtensionElement element = this.Items[i];
- element.SetReadOnlyInternal();
- }
- }
- System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
- {
- return this.GetEnumerator();
- }
- protected override void Unmerge(ConfigurationElement sourceElement, ConfigurationElement parentElement, ConfigurationSaveMode saveMode)
- {
- if (sourceElement == null)
- {
- return;
- }
- ServiceModelExtensionCollectionElement<TServiceModelExtensionElement> sourceCollectionElement = (ServiceModelExtensionCollectionElement<TServiceModelExtensionElement>)sourceElement;
- this.UpdateProperties(sourceCollectionElement);
- base.Unmerge(sourceElement, parentElement, saveMode);
- }
- void UpdateProperties(ServiceModelExtensionCollectionElement<TServiceModelExtensionElement> sourceElement)
- {
- foreach (ConfigurationProperty property in sourceElement.Properties)
- {
- if (!this.Properties.Contains(property.Name))
- {
- this.Properties.Add(property);
- }
- }
- foreach (TServiceModelExtensionElement extension in this.Items)
- {
- if (extension is ClearBehaviorElement || extension is RemoveBehaviorElement)
- continue;
- string configuredSectionName = extension.ConfigurationElementName;
- if (!this.Properties.Contains(configuredSectionName))
- {
- ConfigurationProperty configProperty = new ConfigurationProperty(configuredSectionName, extension.GetType(), null);
- this.Properties.Add(configProperty);
- }
- }
- }
- ContextInformation IConfigurationContextProviderInternal.GetEvaluationContext()
- {
- return this.EvaluationContext;
- }
- [Fx.Tag.SecurityNote(Critical = "Accesses critical field contextHelper.",
- Miscellaneous = "RequiresReview -- the return value will be used for a security decision -- see comment in interface definition.")]
- [SecurityCritical]
- ContextInformation IConfigurationContextProviderInternal.GetOriginalEvaluationContext()
- {
- return this.contextHelper.GetOriginalContext(this);
- }
- }
- }
|