1 //------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //------------------------------------------------------------
4 namespace System.ServiceModel.Channels
5 {
6     using System.Collections.Generic;
7     using System.ServiceModel.Description;
8     using System.Runtime.Serialization;
9     using System.ServiceModel.Channels;
10     using System.ServiceModel;
11     using System.Text;
12     using System.Xml;
13     using System.ComponentModel;
14 
15     public sealed class MtomMessageEncodingBindingElement : MessageEncodingBindingElement, IWsdlExportExtension, IPolicyExportExtension
16     {
17         int maxReadPoolSize;
18         int maxWritePoolSize;
19         XmlDictionaryReaderQuotas readerQuotas;
20         int maxBufferSize;
21         Encoding writeEncoding;
22         MessageVersion messageVersion;
23 
MtomMessageEncodingBindingElement()24         public MtomMessageEncodingBindingElement()
25             : this(MessageVersion.Default, TextEncoderDefaults.Encoding)
26         {
27         }
28 
MtomMessageEncodingBindingElement(MessageVersion messageVersion, Encoding writeEncoding)29         public MtomMessageEncodingBindingElement(MessageVersion messageVersion, Encoding writeEncoding)
30         {
31             if (messageVersion == null)
32                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("messageVersion");
33 
34             if (messageVersion == MessageVersion.None)
35                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.MtomEncoderBadMessageVersion, messageVersion.ToString()), "messageVersion"));
36 
37             if (writeEncoding == null)
38                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("writeEncoding");
39 
40             TextEncoderDefaults.ValidateEncoding(writeEncoding);
41             this.maxReadPoolSize = EncoderDefaults.MaxReadPoolSize;
42             this.maxWritePoolSize = EncoderDefaults.MaxWritePoolSize;
43             this.readerQuotas = new XmlDictionaryReaderQuotas();
44             EncoderDefaults.ReaderQuotas.CopyTo(this.readerQuotas);
45             this.maxBufferSize = MtomEncoderDefaults.MaxBufferSize;
46             this.messageVersion = messageVersion;
47             this.writeEncoding = writeEncoding;
48         }
49 
MtomMessageEncodingBindingElement(MtomMessageEncodingBindingElement elementToBeCloned)50         MtomMessageEncodingBindingElement(MtomMessageEncodingBindingElement elementToBeCloned)
51             : base(elementToBeCloned)
52         {
53             this.maxReadPoolSize = elementToBeCloned.maxReadPoolSize;
54             this.maxWritePoolSize = elementToBeCloned.maxWritePoolSize;
55             this.readerQuotas = new XmlDictionaryReaderQuotas();
56             elementToBeCloned.readerQuotas.CopyTo(this.readerQuotas);
57             this.maxBufferSize = elementToBeCloned.maxBufferSize;
58             this.writeEncoding = elementToBeCloned.writeEncoding;
59             this.messageVersion = elementToBeCloned.messageVersion;
60         }
61 
62         [DefaultValue(EncoderDefaults.MaxReadPoolSize)]
63         public int MaxReadPoolSize
64         {
65             get
66             {
67                 return this.maxReadPoolSize;
68             }
69             set
70             {
71                 if (value <= 0)
72                 {
73                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", value,
74                                                     SR.GetString(SR.ValueMustBePositive)));
75                 }
76                 this.maxReadPoolSize = value;
77             }
78         }
79 
80         [DefaultValue(EncoderDefaults.MaxWritePoolSize)]
81         public int MaxWritePoolSize
82         {
83             get
84             {
85                 return this.maxWritePoolSize;
86             }
87             set
88             {
89                 if (value <= 0)
90                 {
91                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", value,
92                                                     SR.GetString(SR.ValueMustBePositive)));
93                 }
94                 this.maxWritePoolSize = value;
95             }
96         }
97 
98         public XmlDictionaryReaderQuotas ReaderQuotas
99         {
100             get
101             {
102                 return this.readerQuotas;
103             }
104         }
105 
106         [DefaultValue(MtomEncoderDefaults.MaxBufferSize)]
107         public int MaxBufferSize
108         {
109             get
110             {
111                 return this.maxBufferSize;
112             }
113             set
114             {
115                 if (value <= 0)
116                 {
117                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", value,
118                                                     SR.GetString(SR.ValueMustBePositive)));
119                 }
120                 this.maxBufferSize = value;
121             }
122         }
123 
124         [TypeConverter(typeof(System.ServiceModel.Configuration.EncodingConverter))]
125         public Encoding WriteEncoding
126         {
127             get
128             {
129                 return this.writeEncoding;
130             }
131             set
132             {
133                 if (value == null)
134                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("value");
135 
136                 TextEncoderDefaults.ValidateEncoding(value);
137                 this.writeEncoding = value;
138             }
139         }
140 
141         public override MessageVersion MessageVersion
142         {
143             get
144             {
145                 return this.messageVersion;
146             }
147             set
148             {
149                 if (value == null)
150                 {
151                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("value");
152                 }
153                 if (value == MessageVersion.None)
154                 {
155                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.MtomEncoderBadMessageVersion, value.ToString()), "value"));
156                 }
157 
158                 this.messageVersion = value;
159             }
160         }
161 
BuildChannelFactory(BindingContext context)162         public override IChannelFactory<TChannel> BuildChannelFactory<TChannel>(BindingContext context)
163         {
164             return InternalBuildChannelFactory<TChannel>(context);
165         }
166 
CanBuildChannelFactory(BindingContext context)167         public override bool CanBuildChannelFactory<TChannel>(BindingContext context)
168         {
169             return InternalCanBuildChannelFactory<TChannel>(context);
170         }
171 
BuildChannelListener(BindingContext context)172         public override IChannelListener<TChannel> BuildChannelListener<TChannel>(BindingContext context)
173         {
174             return InternalBuildChannelListener<TChannel>(context);
175         }
176 
CanBuildChannelListener(BindingContext context)177         public override bool CanBuildChannelListener<TChannel>(BindingContext context)
178         {
179             return InternalCanBuildChannelListener<TChannel>(context);
180         }
181 
Clone()182         public override BindingElement Clone()
183         {
184             return new MtomMessageEncodingBindingElement(this);
185         }
186 
CreateMessageEncoderFactory()187         public override MessageEncoderFactory CreateMessageEncoderFactory()
188         {
189             return new MtomMessageEncoderFactory(MessageVersion, WriteEncoding, this.MaxReadPoolSize, this.MaxWritePoolSize, this.MaxBufferSize, this.ReaderQuotas);
190         }
191 
GetProperty(BindingContext context)192         public override T GetProperty<T>(BindingContext context)
193         {
194             if (context == null)
195             {
196                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("context");
197             }
198             if (typeof(T) == typeof(XmlDictionaryReaderQuotas))
199             {
200                 return (T)(object)this.readerQuotas;
201             }
202             else
203             {
204                 return base.GetProperty<T>(context);
205             }
206         }
207 
IPolicyExportExtension.ExportPolicy(MetadataExporter exporter, PolicyConversionContext policyContext)208         void IPolicyExportExtension.ExportPolicy(MetadataExporter exporter, PolicyConversionContext policyContext)
209         {
210             if (policyContext == null)
211             {
212                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("policyContext");
213             }
214             XmlDocument document = new XmlDocument();
215 
216             policyContext.GetBindingAssertions().Add(document.CreateElement(
217                 MessageEncodingPolicyConstants.OptimizedMimeSerializationPrefix,
218                 MessageEncodingPolicyConstants.MtomEncodingName,
219                 MessageEncodingPolicyConstants.OptimizedMimeSerializationNamespace));
220         }
221 
IWsdlExportExtension.ExportContract(WsdlExporter exporter, WsdlContractConversionContext context)222         void IWsdlExportExtension.ExportContract(WsdlExporter exporter, WsdlContractConversionContext context) { }
IWsdlExportExtension.ExportEndpoint(WsdlExporter exporter, WsdlEndpointConversionContext context)223         void IWsdlExportExtension.ExportEndpoint(WsdlExporter exporter, WsdlEndpointConversionContext context)
224         {
225             if (context == null)
226             {
227                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("context");
228             }
229 
230             SoapHelper.SetSoapVersion(context, exporter, this.messageVersion.Envelope);
231         }
232 
CheckEncodingVersion(EnvelopeVersion version)233         internal override bool CheckEncodingVersion(EnvelopeVersion version)
234         {
235             return messageVersion.Envelope == version;
236         }
237 
IsMatch(BindingElement b)238         internal override bool IsMatch(BindingElement b)
239         {
240             if (!base.IsMatch(b))
241                 return false;
242             MtomMessageEncodingBindingElement mtom = b as MtomMessageEncodingBindingElement;
243             if (mtom == null)
244                 return false;
245             if (this.maxReadPoolSize != mtom.MaxReadPoolSize)
246                 return false;
247             if (this.maxWritePoolSize != mtom.MaxWritePoolSize)
248                 return false;
249 
250             // compare XmlDictionaryReaderQuotas
251             if (this.readerQuotas.MaxStringContentLength != mtom.ReaderQuotas.MaxStringContentLength)
252                 return false;
253             if (this.readerQuotas.MaxArrayLength != mtom.ReaderQuotas.MaxArrayLength)
254                 return false;
255             if (this.readerQuotas.MaxBytesPerRead != mtom.ReaderQuotas.MaxBytesPerRead)
256                 return false;
257             if (this.readerQuotas.MaxDepth != mtom.ReaderQuotas.MaxDepth)
258                 return false;
259             if (this.readerQuotas.MaxNameTableCharCount != mtom.ReaderQuotas.MaxNameTableCharCount)
260                 return false;
261 
262             if (this.maxBufferSize != mtom.MaxBufferSize)
263                 return false;
264 
265             if (this.WriteEncoding.EncodingName != mtom.WriteEncoding.EncodingName)
266                 return false;
267             if (!this.MessageVersion.IsMatch(mtom.MessageVersion))
268                 return false;
269 
270             return true;
271         }
272 
273         [EditorBrowsable(EditorBrowsableState.Never)]
ShouldSerializeMessageVersion()274         public bool ShouldSerializeMessageVersion()
275         {
276             return (!this.messageVersion.IsMatch(MessageVersion.Default));
277         }
278 
279         [EditorBrowsable(EditorBrowsableState.Never)]
ShouldSerializeReaderQuotas()280         public bool ShouldSerializeReaderQuotas()
281         {
282             return (!EncoderDefaults.IsDefaultReaderQuotas(this.ReaderQuotas));
283         }
284 
285         [EditorBrowsable(EditorBrowsableState.Never)]
ShouldSerializeWriteEncoding()286         public bool ShouldSerializeWriteEncoding()
287         {
288             return (this.WriteEncoding != TextEncoderDefaults.Encoding);
289         }
290     }
291 }
292