File: ImportedPolicyConversionContext.cs

package info (click to toggle)
mono 4.6.2.7%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 778,148 kB
  • ctags: 914,052
  • sloc: cs: 5,779,509; xml: 2,773,713; ansic: 432,645; sh: 14,749; makefile: 12,361; perl: 2,488; python: 1,434; cpp: 849; asm: 531; sql: 95; sed: 16; php: 1
file content (320 lines) | stat: -rw-r--r-- 16,007 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
//-----------------------------------------------------------------------------
// 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;
        }

    }
}