| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320 |
- //-----------------------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //-----------------------------------------------------------------------------
- namespace System.ServiceModel.Description
- {
- using System.Collections;
- using System.Collections.Generic;
- using System.Globalization;
- using System.Runtime;
- using System.ServiceModel.Channels;
- using System.Xml;
- public abstract partial class MetadataImporter
- {
- //Consider, [....]: make this public
- internal static IEnumerable<PolicyConversionContext> GetPolicyConversionContextEnumerator(ServiceEndpoint endpoint, PolicyAlternatives policyAlternatives)
- {
- return ImportedPolicyConversionContext.GetPolicyConversionContextEnumerator(endpoint, policyAlternatives, MetadataImporterQuotas.Defaults);
- }
- internal static IEnumerable<PolicyConversionContext> GetPolicyConversionContextEnumerator(ServiceEndpoint endpoint, PolicyAlternatives policyAlternatives,
- MetadataImporterQuotas quotas)
- {
- return ImportedPolicyConversionContext.GetPolicyConversionContextEnumerator(endpoint, policyAlternatives, quotas);
- }
- internal sealed class ImportedPolicyConversionContext : PolicyConversionContext
- {
- BindingElementCollection bindingElements = new BindingElementCollection();
- readonly PolicyAssertionCollection endpointAssertions;
- readonly Dictionary<OperationDescription, PolicyAssertionCollection> operationBindingAssertions = new Dictionary<OperationDescription, PolicyAssertionCollection>();
- readonly Dictionary<MessageDescription, PolicyAssertionCollection> messageBindingAssertions = new Dictionary<MessageDescription, PolicyAssertionCollection>();
- readonly Dictionary<FaultDescription, PolicyAssertionCollection> faultBindingAssertions = new Dictionary<FaultDescription, PolicyAssertionCollection>();
- ImportedPolicyConversionContext(ServiceEndpoint endpoint, IEnumerable<XmlElement> endpointAssertions,
- Dictionary<OperationDescription, IEnumerable<XmlElement>> operationBindingAssertions,
- Dictionary<MessageDescription, IEnumerable<XmlElement>> messageBindingAssertions,
- Dictionary<FaultDescription, IEnumerable<XmlElement>> faultBindingAssertions,
- MetadataImporterQuotas quotas)
- : base(endpoint)
- {
- int remainingAssertionsAllowed = quotas.MaxPolicyAssertions;
- this.endpointAssertions = new PolicyAssertionCollection(new MaxItemsEnumerable<XmlElement>(endpointAssertions, remainingAssertionsAllowed));
- remainingAssertionsAllowed -= this.endpointAssertions.Count;
- foreach (OperationDescription operationDescription in endpoint.Contract.Operations)
- {
- this.operationBindingAssertions.Add(operationDescription, new PolicyAssertionCollection());
- foreach (MessageDescription messageDescription in operationDescription.Messages)
- {
- this.messageBindingAssertions.Add(messageDescription, new PolicyAssertionCollection());
- }
- foreach (FaultDescription faultDescription in operationDescription.Faults)
- {
- this.faultBindingAssertions.Add(faultDescription, new PolicyAssertionCollection());
- }
- }
- foreach (KeyValuePair<OperationDescription, IEnumerable<XmlElement>> entry in operationBindingAssertions)
- {
- this.operationBindingAssertions[entry.Key].AddRange(new MaxItemsEnumerable<XmlElement>(entry.Value, remainingAssertionsAllowed));
- remainingAssertionsAllowed -= this.operationBindingAssertions[entry.Key].Count;
- }
- foreach (KeyValuePair<MessageDescription, IEnumerable<XmlElement>> entry in messageBindingAssertions)
- {
- this.messageBindingAssertions[entry.Key].AddRange(new MaxItemsEnumerable<XmlElement>(entry.Value, remainingAssertionsAllowed));
- remainingAssertionsAllowed -= this.messageBindingAssertions[entry.Key].Count;
- }
- foreach (KeyValuePair<FaultDescription, IEnumerable<XmlElement>> entry in faultBindingAssertions)
- {
- this.faultBindingAssertions[entry.Key].AddRange(new MaxItemsEnumerable<XmlElement>(entry.Value, remainingAssertionsAllowed));
- remainingAssertionsAllowed -= this.faultBindingAssertions[entry.Key].Count;
- }
- }
- //
- // PolicyConversionContext implementation
- //
- public override BindingElementCollection BindingElements { get { return this.bindingElements; } }
- public override PolicyAssertionCollection GetBindingAssertions()
- {
- return this.endpointAssertions;
- }
- public override PolicyAssertionCollection GetOperationBindingAssertions(OperationDescription operation)
- {
- return this.operationBindingAssertions[operation];
- }
- public override PolicyAssertionCollection GetMessageBindingAssertions(MessageDescription message)
- {
- return this.messageBindingAssertions[message];
- }
- public override PolicyAssertionCollection GetFaultBindingAssertions(FaultDescription message)
- {
- return this.faultBindingAssertions[message];
- }
- //
- // Policy Alternative Enumeration code
- //
- public static IEnumerable<PolicyConversionContext> GetPolicyConversionContextEnumerator(ServiceEndpoint endpoint,
- PolicyAlternatives policyAlternatives, MetadataImporterQuotas quotas)
- {
- IEnumerable<Dictionary<MessageDescription, IEnumerable<XmlElement>>> messageAssertionEnumerator;
- IEnumerable<Dictionary<FaultDescription, IEnumerable<XmlElement>>> faultAssertionEnumerator;
- IEnumerable<Dictionary<OperationDescription, IEnumerable<XmlElement>>> operationAssertionEnumerator;
- faultAssertionEnumerator = PolicyIterationHelper.GetCartesianProduct<FaultDescription, IEnumerable<XmlElement>>(policyAlternatives.FaultBindingAlternatives);
- messageAssertionEnumerator = PolicyIterationHelper.GetCartesianProduct<MessageDescription, IEnumerable<XmlElement>>(policyAlternatives.MessageBindingAlternatives);
- operationAssertionEnumerator = PolicyIterationHelper.GetCartesianProduct<OperationDescription, IEnumerable<XmlElement>>(policyAlternatives.OperationBindingAlternatives);
- foreach (Dictionary<FaultDescription, IEnumerable<XmlElement>> faultAssertionsSelection in faultAssertionEnumerator)
- {
- foreach (Dictionary<MessageDescription, IEnumerable<XmlElement>> messageAssertionsSelection in messageAssertionEnumerator)
- {
- foreach (Dictionary<OperationDescription, IEnumerable<XmlElement>> operationAssertionsSelection in operationAssertionEnumerator)
- {
- foreach (IEnumerable<XmlElement> endpointAssertionsSelection in policyAlternatives.EndpointAlternatives)
- {
- ImportedPolicyConversionContext conversionContext;
- try
- {
- conversionContext = new ImportedPolicyConversionContext(endpoint, endpointAssertionsSelection,
- operationAssertionsSelection, messageAssertionsSelection, faultAssertionsSelection,
- quotas);
- }
- catch (MaxItemsEnumeratorExceededMaxItemsException) { yield break; }
- yield return conversionContext;
- }
- }
- }
- }
- }
- internal class MaxItemsEnumerable<T> : IEnumerable<T>
- {
- IEnumerable<T> inner;
- int maxItems;
- public MaxItemsEnumerable(IEnumerable<T> inner, int maxItems)
- {
- this.inner = inner;
- this.maxItems = maxItems;
- }
- public IEnumerator<T> GetEnumerator()
- {
- return new MaxItemsEnumerator<T>(inner.GetEnumerator(), maxItems);
- }
- IEnumerator IEnumerable.GetEnumerator()
- {
- return (IEnumerator)GetEnumerator();
- }
- }
- internal class MaxItemsEnumerator<T> : IEnumerator<T>
- {
- int maxItems;
- int currentItem;
- IEnumerator<T> inner;
- public MaxItemsEnumerator(IEnumerator<T> inner, int maxItems)
- {
- this.maxItems = maxItems;
- this.currentItem = 0;
- this.inner = inner;
- }
- public T Current
- {
- get { return inner.Current; }
- }
- public void Dispose()
- {
- inner.Dispose();
- }
- object IEnumerator.Current
- {
- get { return ((IEnumerator)inner).Current; }
- }
- public bool MoveNext()
- {
- bool moveNext = inner.MoveNext();
- if (++currentItem > maxItems)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MaxItemsEnumeratorExceededMaxItemsException());
- }
- return moveNext;
- }
- public void Reset()
- {
- currentItem = 0;
- inner.Reset();
- }
- }
- internal class MaxItemsEnumeratorExceededMaxItemsException : Exception { }
- static class PolicyIterationHelper
- {
- // This method returns an iterator over the cartesian product of a colleciton of sets.
- // e.g. If the following 3 sets are provided:
- // i) { 1, 2, 3 }
- // ii) { a, b }
- // iii) { x, y, z }
- //
- // You would get an enumerator that returned the following 18 collections:
- // { 1, a, x}, { 2, a, x}, { 3, a, x}, { 1, b, x}, { 2, b, x}, { 3, b, x},
- // { 1, a, y}, { 2, a, y}, { 3, a, y}, { 1, b, y}, { 2, b, y}, { 3, b, y},
- // { 1, a, z}, { 2, a, z}, { 3, a, z}, { 1, b, z}, { 2, b, z}, { 3, b, z}
- //
- // This method allows us to enumerate over all the possible policy selections in a
- // dictiaonary of policy alternatives.
- // e.g. given all the policy alternatives in all the messages in a contract,
- // we can enumerate over all the possilbe policy selections.
- //
- // Note: A general implementation of this method would differ in that it would probably use a List<T> or an array instead of
- // a dictionary and it would yield clones of the the counterValue.
- // - We don't clone because we know that we don't need to based on our useage
- // - We use a dictionary because we need to correlate the selections with the alternative source.
- //
- internal static IEnumerable<Dictionary<K, V>> GetCartesianProduct<K, V>(Dictionary<K, IEnumerable<V>> sets)
- {
- Dictionary<K, V> counterValue = new Dictionary<K, V>(sets.Count);
- // The iterator is implemented as a counter with each digit being an IEnumerator over one of the sets.
- KeyValuePair<K, IEnumerator<V>>[] digits = InitializeCounter<K, V>(sets, counterValue);
- do
- {
- yield return (Dictionary<K, V>)counterValue;
- } while (IncrementCounter<K, V>(digits, sets, counterValue));
- }
- static KeyValuePair<K, IEnumerator<V>>[] InitializeCounter<K, V>(Dictionary<K, IEnumerable<V>> sets, Dictionary<K, V> counterValue)
- {
- KeyValuePair<K, IEnumerator<V>>[] digits = new KeyValuePair<K, IEnumerator<V>>[sets.Count];
- // Initialize the digit enumerators and set the counter's current Value.
- int i = 0;
- foreach (KeyValuePair<K, IEnumerable<V>> kvp in sets)
- {
- digits[i] = new KeyValuePair<K, IEnumerator<V>>(kvp.Key, kvp.Value.GetEnumerator());
- if (!(digits[i].Value.MoveNext()))
- {
- Fx.Assert("each set must have at least one item in it");
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Each set must have at least one item in it")));
- }
- counterValue[digits[i].Key] = digits[i].Value.Current;
- i++;
- }
- return digits;
- }
- static bool IncrementCounter<K, V>(KeyValuePair<K, IEnumerator<V>>[] digits, Dictionary<K, IEnumerable<V>> sets, Dictionary<K, V> counterValue)
- {
- //
- // Do rollover and carryying for digits.
- // - starting at least significant digit, move digits to next value.
- // if digit rolls over, carry to next digit and repeat.
- //
- int currentDigit;
- for (currentDigit = 0; currentDigit < digits.Length && !digits[currentDigit].Value.MoveNext(); currentDigit++)
- {
- IEnumerator<V> newDigit = sets[digits[currentDigit].Key].GetEnumerator();
- digits[currentDigit] = new KeyValuePair<K, IEnumerator<V>>(digits[currentDigit].Key, newDigit);
- digits[currentDigit].Value.MoveNext();
- }
- //
- // if we just rolled over on the most significant digit, return false
- //
- if (currentDigit == digits.Length)
- return false;
- //
- // update countervalue stores for all digits that changed.
- //
- for (int i = currentDigit; i >= 0; i--)
- {
- counterValue[digits[i].Key] = digits[i].Value.Current;
- }
- return true;
- }
- }
- }
- internal class PolicyAlternatives
- {
- public IEnumerable<IEnumerable<XmlElement>> EndpointAlternatives;
- public Dictionary<OperationDescription, IEnumerable<IEnumerable<XmlElement>>> OperationBindingAlternatives;
- public Dictionary<MessageDescription, IEnumerable<IEnumerable<XmlElement>>> MessageBindingAlternatives;
- public Dictionary<FaultDescription, IEnumerable<IEnumerable<XmlElement>>> FaultBindingAlternatives;
- }
- }
- }
|