Code:
/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / ServiceModel / System / ServiceModel / Channels / MtomMessageEncoder.cs / 1 / MtomMessageEncoder.cs
//------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //----------------------------------------------------------- namespace System.ServiceModel.Channels { using System.IO; using System.ServiceModel.Description; using System.Collections.Generic; using System.Runtime.Serialization; using System.ServiceModel; using System.ServiceModel.Diagnostics; using System.Text; using System.Xml; using System.Globalization; using System.Threading; class MtomMessageEncoderFactory : MessageEncoderFactory { MtomMessageEncoder messageEncoder; public MtomMessageEncoderFactory(MessageVersion version, Encoding writeEncoding, int maxReadPoolSize, int maxWritePoolSize, int maxBufferSize, XmlDictionaryReaderQuotas quotas) { messageEncoder = new MtomMessageEncoder(version, writeEncoding, maxReadPoolSize, maxWritePoolSize, maxBufferSize, quotas); } public override MessageEncoder Encoder { get { return messageEncoder; } } public override MessageVersion MessageVersion { get { return messageEncoder.MessageVersion; } } public int MaxWritePoolSize { get { return messageEncoder.MaxWritePoolSize; } } public int MaxReadPoolSize { get { return messageEncoder.MaxReadPoolSize; } } public XmlDictionaryReaderQuotas ReaderQuotas { get { return messageEncoder.ReaderQuotas; } } public int MaxBufferSize { get { return messageEncoder.MaxBufferSize; } } public static Encoding[] GetSupportedEncodings() { Encoding[] supported = TextEncoderDefaults.SupportedEncodings; Encoding[] enc = new Encoding[supported.Length]; Array.Copy(supported, enc, supported.Length); return enc; } } // Some notes: // The Encoding passed in is used for the SOAP envelope class MtomMessageEncoder : MessageEncoder { Encoding writeEncoding; SynchronizedPoolstreamedWriterPool; SynchronizedPool streamedReaderPool; SynchronizedPool bufferedReaderPool; SynchronizedPool bufferedWriterPool; SynchronizedPool recycledStatePool; object thisLock; MessageVersion version; const int maxPooledXmlReadersPerMessage = 2; int maxReadPoolSize; int maxWritePoolSize; static UriGenerator mimeBoundaryGenerator; XmlDictionaryReaderQuotas readerQuotas; int maxBufferSize; OnXmlDictionaryReaderClose onStreamedReaderClose; internal TextMessageEncoderFactory.ContentEncoding[] contentEncodingMap; const string mtomMediaType = "multipart/related"; const string mtomContentType = mtomMediaType + "; type=\"application/xop+xml\""; const string mtomStartUri = NamingHelper.DefaultNamespace + "0"; public MtomMessageEncoder(MessageVersion version, Encoding writeEncoding, int maxReadPoolSize, int maxWritePoolSize, int maxBufferSize, XmlDictionaryReaderQuotas quotas) { if (version == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("version"); if (writeEncoding == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("writeEncoding"); TextEncoderDefaults.ValidateEncoding(writeEncoding); this.writeEncoding = writeEncoding; this.maxReadPoolSize = maxReadPoolSize; this.maxWritePoolSize = maxWritePoolSize; this.readerQuotas = new XmlDictionaryReaderQuotas(); quotas.CopyTo(this.readerQuotas); this.maxBufferSize = maxBufferSize; this.onStreamedReaderClose = new OnXmlDictionaryReaderClose(ReturnStreamedReader); this.thisLock = new object(); if (version.Envelope == EnvelopeVersion.Soap12) { this.contentEncodingMap = TextMessageEncoderFactory.Soap12Content; } else if (version.Envelope == EnvelopeVersion.Soap11) { this.contentEncodingMap = TextMessageEncoderFactory.Soap11Content; } else { DiagnosticUtility.DebugAssert("Invalid MessageVersion"); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Invalid MessageVersion"))); } this.version = version; } static UriGenerator MimeBoundaryGenerator { get { if (mimeBoundaryGenerator == null) mimeBoundaryGenerator = new UriGenerator("uuid", "+"); return mimeBoundaryGenerator; } } public override string ContentType { get { return mtomContentType; } } public int MaxWritePoolSize { get { return maxWritePoolSize; } } public int MaxReadPoolSize { get { return maxReadPoolSize; } } public XmlDictionaryReaderQuotas ReaderQuotas { get { return readerQuotas; } } public int MaxBufferSize { get { return maxBufferSize; } } public override string MediaType { get { return mtomMediaType; } } public override MessageVersion MessageVersion { get { return version; } } internal bool IsMTOMContentType(string contentType) { // check for MTOM contentType: multipart/related; type=\"application/xop+xml\" return IsContentTypeSupported(contentType, this.ContentType, this.MediaType); } internal bool IsTextContentType(string contentType) { // check for Text contentType: text/xml or application/soap+xml string textMediaType = TextMessageEncoderFactory.GetMediaType(version); string textContentType = TextMessageEncoderFactory.GetContentType(textMediaType, writeEncoding); return IsContentTypeSupported(contentType, textContentType, textMediaType); } public override bool IsContentTypeSupported(string contentType) { if (contentType == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("contentType")); return (IsMTOMContentType(contentType) || IsTextContentType(contentType)); } internal override bool IsCharSetSupported(string charSet) { if (charSet == null || charSet.Length == 0) return true; Encoding tmp; return TextEncoderDefaults.TryGetEncoding(charSet, out tmp); } string GenerateStartInfoString() { return (version.Envelope == EnvelopeVersion.Soap12) ? TextMessageEncoderFactory.Soap12MediaType : TextMessageEncoderFactory.Soap11MediaType; } public override Message ReadMessage(ArraySegment buffer, BufferManager bufferManager, string contentType) { if (bufferManager == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("bufferManager"); if (contentType == this.ContentType) contentType = null; MtomBufferedMessageData messageData = TakeBufferedReader(); messageData.ContentType = contentType; messageData.Open(buffer, bufferManager); RecycledMessageState messageState = messageData.TakeMessageState(); if (messageState == null) messageState = new RecycledMessageState(); Message message = new BufferedMessage(messageData, messageState); message.Properties.Encoder = this; if (MessageLogger.LogMessagesAtTransportLevel) MessageLogger.LogMessage(ref message, MessageLoggingSource.TransportReceive); return message; } public override Message ReadMessage(Stream stream, int maxSizeOfHeaders, string contentType) { if (stream == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("stream")); if (contentType == this.ContentType) contentType = null; XmlReader reader = TakeStreamedReader(stream, contentType); Message message = Message.CreateMessage(reader, maxSizeOfHeaders, version); message.Properties.Encoder = this; if (MessageLogger.LogMessagesAtTransportLevel) MessageLogger.LogMessage(ref message, MessageLoggingSource.TransportReceive); return message; } public override ArraySegment WriteMessage(Message message, int maxMessageSize, BufferManager bufferManager, int messageOffset) { return WriteMessage(message, maxMessageSize, bufferManager, messageOffset, GenerateStartInfoString(), null, null, true /*writeMessageHeaders*/); } internal string GetContentType(out string boundary) { string startInfo = GenerateStartInfoString(); boundary = MimeBoundaryGenerator.Next(); return FormatContentType(boundary, startInfo); } internal string FormatContentType(string boundary, string startInfo) { return String.Format(CultureInfo.InvariantCulture, "{0};start=\"<{1}>\";boundary=\"{2}\";start-info=\"{3}\"", mtomContentType, mtomStartUri, boundary, startInfo); } internal ArraySegment WriteMessage(Message message, int maxMessageSize, BufferManager bufferManager, int messageOffset, string boundary) { return WriteMessage(message, maxMessageSize, bufferManager, messageOffset, GenerateStartInfoString(), boundary, mtomStartUri, false /*writeMessageHeaders*/); } ArraySegment WriteMessage(Message message, int maxMessageSize, BufferManager bufferManager, int messageOffset, string startInfo, string boundary, string startUri, bool writeMessageHeaders) { if (message == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("message"); if (bufferManager == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("bufferManager"); if (maxMessageSize < 0) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("maxMessageSize", maxMessageSize, SR.GetString(SR.ValueMustBeNonNegative))); if (messageOffset < 0 || messageOffset > maxMessageSize) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("messageOffset", messageOffset, SR.GetString(SR.ValueMustBeInRange, 0, maxMessageSize))); ThrowIfMismatchedMessageVersion(message); message.Properties.Encoder = this; MtomBufferedMessageWriter messageWriter = TakeBufferedWriter(); messageWriter.StartInfo = startInfo; messageWriter.Boundary = boundary; messageWriter.StartUri = startUri; messageWriter.WriteMessageHeaders = writeMessageHeaders; messageWriter.MaxSizeInBytes = maxMessageSize; ArraySegment messageData = messageWriter.WriteMessage(message, bufferManager, messageOffset, maxMessageSize); ReturnMessageWriter(messageWriter); if (MessageLogger.LogMessagesAtTransportLevel) { string contentType = null; if (boundary != null) contentType = FormatContentType(boundary, startInfo ?? GenerateStartInfoString()); XmlDictionaryReader xmlDictionaryReader = XmlDictionaryReader.CreateMtomReader(messageData.Array, messageData.Offset, messageData.Count, MtomMessageEncoderFactory.GetSupportedEncodings(), contentType, XmlDictionaryReaderQuotas.Max, int.MaxValue, null); MessageLogger.LogMessage(ref message, xmlDictionaryReader, MessageLoggingSource.TransportSend); } return messageData; } public override void WriteMessage(Message message, Stream stream) { WriteMessage(message, stream, GenerateStartInfoString(), null, null, true /*writeMessageHeaders*/); } internal void WriteMessage(Message message, Stream stream, string boundary) { WriteMessage(message, stream, GenerateStartInfoString(), boundary, mtomStartUri, false /*writeMessageHeaders*/); } void WriteMessage(Message message, Stream stream, string startInfo, string boundary, string startUri, bool writeMessageHeaders) { if (message == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("message")); if (stream == null) throw TraceUtility.ThrowHelperError(new ArgumentNullException("stream"), message); ThrowIfMismatchedMessageVersion(message); message.Properties.Encoder = this; if (MessageLogger.LogMessagesAtTransportLevel) MessageLogger.LogMessage(ref message, MessageLoggingSource.TransportSend); XmlDictionaryWriter xmlWriter = TakeStreamedWriter(stream, startInfo, boundary, startUri, writeMessageHeaders); if (this.writeEncoding.WebName == "utf-8") { message.WriteMessage(xmlWriter); } else { xmlWriter.WriteStartDocument(); message.WriteMessage(xmlWriter); xmlWriter.WriteEndDocument(); } xmlWriter.Flush(); ReturnStreamedWriter(xmlWriter); } XmlDictionaryWriter TakeStreamedWriter(Stream stream, string startInfo, string boundary, string startUri, bool writeMessageHeaders) { if (streamedWriterPool == null) { lock (thisLock) { if (streamedWriterPool == null) { streamedWriterPool = new SynchronizedPool (maxWritePoolSize); } } } XmlDictionaryWriter xmlWriter = streamedWriterPool.Take(); if (xmlWriter == null) { xmlWriter = XmlDictionaryWriter.CreateMtomWriter(stream, this.writeEncoding, int.MaxValue, startInfo, boundary, startUri, writeMessageHeaders, false); } else { ((IXmlMtomWriterInitializer)xmlWriter).SetOutput(stream, this.writeEncoding, int.MaxValue, startInfo, boundary, startUri, writeMessageHeaders, false); } return xmlWriter; } void ReturnStreamedWriter(XmlDictionaryWriter xmlWriter) { xmlWriter.Close(); streamedWriterPool.Return(xmlWriter); } MtomBufferedMessageWriter TakeBufferedWriter() { if (bufferedWriterPool == null) { lock (thisLock) { if (bufferedWriterPool == null) { bufferedWriterPool = new SynchronizedPool (maxWritePoolSize); } } } MtomBufferedMessageWriter messageWriter = bufferedWriterPool.Take(); if (messageWriter == null) messageWriter = new MtomBufferedMessageWriter(this); return messageWriter; } void ReturnMessageWriter(MtomBufferedMessageWriter messageWriter) { bufferedWriterPool.Return(messageWriter); } MtomBufferedMessageData TakeBufferedReader() { if (bufferedReaderPool == null) { lock (thisLock) { if (bufferedReaderPool == null) { bufferedReaderPool = new SynchronizedPool (maxReadPoolSize); } } } MtomBufferedMessageData messageData = bufferedReaderPool.Take(); if (messageData == null) messageData = new MtomBufferedMessageData(this, maxPooledXmlReadersPerMessage); return messageData; } void ReturnBufferedData(MtomBufferedMessageData messageData) { bufferedReaderPool.Return(messageData); } XmlReader TakeStreamedReader(Stream stream, string contentType) { if (streamedReaderPool == null) { lock (thisLock) { if (streamedReaderPool == null) { streamedReaderPool = new SynchronizedPool (maxReadPoolSize); } } } XmlDictionaryReader xmlReader = streamedReaderPool.Take(); try { if (contentType == null || IsMTOMContentType(contentType)) { if (xmlReader != null && xmlReader is IXmlMtomReaderInitializer) { ((IXmlMtomReaderInitializer)xmlReader).SetInput(stream, MtomMessageEncoderFactory.GetSupportedEncodings(), contentType, this.readerQuotas, this.maxBufferSize, onStreamedReaderClose); } else { xmlReader = XmlDictionaryReader.CreateMtomReader(stream, MtomMessageEncoderFactory.GetSupportedEncodings(), contentType, this.readerQuotas, this.maxBufferSize, onStreamedReaderClose); } } else { if (xmlReader != null && xmlReader is IXmlTextReaderInitializer) { ((IXmlTextReaderInitializer)xmlReader).SetInput(stream, TextMessageEncoderFactory.GetEncodingFromContentType(contentType, this.contentEncodingMap), this.readerQuotas, onStreamedReaderClose); } else { xmlReader = XmlDictionaryReader.CreateTextReader(stream, TextMessageEncoderFactory.GetEncodingFromContentType(contentType, this.contentEncodingMap), this.readerQuotas, onStreamedReaderClose); } } } catch (FormatException fe) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException( SR.GetString(SR.SFxErrorCreatingMtomReader), fe)); } catch (XmlException xe) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException( SR.GetString(SR.SFxErrorCreatingMtomReader), xe)); } return xmlReader; } void ReturnStreamedReader(XmlDictionaryReader xmlReader) { streamedReaderPool.Return(xmlReader); } SynchronizedPool RecycledStatePool { get { if (recycledStatePool == null) { lock (thisLock) { if (recycledStatePool == null) { recycledStatePool = new SynchronizedPool (maxReadPoolSize); } } } return recycledStatePool; } } class MtomBufferedMessageData : BufferedMessageData { MtomMessageEncoder messageEncoder; Pool readerPool; internal string ContentType; OnXmlDictionaryReaderClose onClose; public MtomBufferedMessageData(MtomMessageEncoder messageEncoder, int maxReaderPoolSize) : base(messageEncoder.RecycledStatePool) { this.messageEncoder = messageEncoder; readerPool = new Pool (maxReaderPoolSize); onClose = new OnXmlDictionaryReaderClose(OnXmlReaderClosed); } public override MessageEncoder MessageEncoder { get { return messageEncoder; } } public override XmlDictionaryReaderQuotas Quotas { get { return messageEncoder.ReaderQuotas; } } protected override void OnClosed() { messageEncoder.ReturnBufferedData(this); } protected override XmlDictionaryReader TakeXmlReader() { try { ArraySegment buffer = this.Buffer; XmlDictionaryReader xmlReader = readerPool.Take(); if (ContentType == null || messageEncoder.IsMTOMContentType(ContentType)) { if (xmlReader != null && xmlReader is IXmlMtomReaderInitializer) { ((IXmlMtomReaderInitializer)xmlReader).SetInput(buffer.Array, buffer.Offset, buffer.Count, MtomMessageEncoderFactory.GetSupportedEncodings(), ContentType, this.messageEncoder.ReaderQuotas, this.messageEncoder.MaxBufferSize, onClose); } else { xmlReader = XmlDictionaryReader.CreateMtomReader(buffer.Array, buffer.Offset, buffer.Count, MtomMessageEncoderFactory.GetSupportedEncodings(), ContentType, this.messageEncoder.ReaderQuotas, this.messageEncoder.MaxBufferSize, onClose); } } else { if (xmlReader != null && xmlReader is IXmlTextReaderInitializer) { ((IXmlTextReaderInitializer)xmlReader).SetInput(buffer.Array, buffer.Offset, buffer.Count, TextMessageEncoderFactory.GetEncodingFromContentType(ContentType, this.messageEncoder.contentEncodingMap), this.messageEncoder.ReaderQuotas, onClose); } else { xmlReader = XmlDictionaryReader.CreateTextReader(buffer.Array, buffer.Offset, buffer.Count, TextMessageEncoderFactory.GetEncodingFromContentType(ContentType, this.messageEncoder.contentEncodingMap), this.messageEncoder.ReaderQuotas, onClose); } } return xmlReader; } catch (FormatException fe) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException( SR.GetString(SR.SFxErrorCreatingMtomReader), fe)); } catch (XmlException xe) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException( SR.GetString(SR.SFxErrorCreatingMtomReader), xe)); } } protected override void ReturnXmlReader(XmlDictionaryReader xmlReader) { if (xmlReader != null) readerPool.Return(xmlReader); } } class MtomBufferedMessageWriter : BufferedMessageWriter { MtomMessageEncoder messageEncoder; internal bool WriteMessageHeaders; internal string StartInfo; internal string StartUri; internal string Boundary; internal int MaxSizeInBytes = int.MaxValue; XmlDictionaryWriter writer; public MtomBufferedMessageWriter(MtomMessageEncoder messageEncoder) { this.messageEncoder = messageEncoder; } protected override XmlDictionaryWriter TakeXmlWriter(Stream stream) { XmlDictionaryWriter returnedWriter = writer; if (returnedWriter == null) { returnedWriter = XmlDictionaryWriter.CreateMtomWriter(stream, messageEncoder.writeEncoding, MaxSizeInBytes, StartInfo, Boundary, StartUri, WriteMessageHeaders, false); } else { writer = null; ((IXmlMtomWriterInitializer)returnedWriter).SetOutput(stream, messageEncoder.writeEncoding, MaxSizeInBytes, StartInfo, Boundary, StartUri, WriteMessageHeaders, false); } if (messageEncoder.writeEncoding.WebName != "utf-8") returnedWriter.WriteStartDocument(); return returnedWriter; } protected override void ReturnXmlWriter(XmlDictionaryWriter writer) { writer.Close(); if (this.writer == null) this.writer = writer; } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- LogicalTreeHelper.cs
- InvalidAsynchronousStateException.cs
- DataObjectPastingEventArgs.cs
- ViewUtilities.cs
- OracleTransaction.cs
- basemetadatamappingvisitor.cs
- EventLogPermissionAttribute.cs
- EntityCommand.cs
- DeferredRunTextReference.cs
- StorageAssociationTypeMapping.cs
- WebPartCancelEventArgs.cs
- ReaderContextStackData.cs
- DispatcherEventArgs.cs
- XmlChildEnumerator.cs
- CommonProperties.cs
- HashSet.cs
- mediaclock.cs
- MergeFailedEvent.cs
- DataGridViewCellCancelEventArgs.cs
- Encoding.cs
- PublisherMembershipCondition.cs
- DecimalKeyFrameCollection.cs
- TreeNodeBindingCollection.cs
- PathParser.cs
- EntityReference.cs
- keycontainerpermission.cs
- DecimalConverter.cs
- ScriptControl.cs
- ClientOptions.cs
- FixedBufferAttribute.cs
- VisualTreeHelper.cs
- ConnectionAcceptor.cs
- ServiceOperationInvoker.cs
- ImageKeyConverter.cs
- DefaultValidator.cs
- SelectionProcessor.cs
- PartialTrustVisibleAssembly.cs
- DefaultValueAttribute.cs
- ModifierKeysValueSerializer.cs
- SecurityHeaderLayout.cs
- TimeSpan.cs
- DisableDpiAwarenessAttribute.cs
- IndexerNameAttribute.cs
- Currency.cs
- PropertyDescriptorGridEntry.cs
- TimeSpanMinutesOrInfiniteConverter.cs
- TdsParserStateObject.cs
- SafeBitVector32.cs
- DNS.cs
- _BaseOverlappedAsyncResult.cs
- TabControlEvent.cs
- CompositeDataBoundControl.cs
- DataGridViewTextBoxCell.cs
- SocketSettings.cs
- UriParserTemplates.cs
- GreaterThanOrEqual.cs
- FormsAuthenticationModule.cs
- ParseElementCollection.cs
- OdbcErrorCollection.cs
- ZipIOLocalFileBlock.cs
- StringDictionaryWithComparer.cs
- Knowncolors.cs
- SByteConverter.cs
- BindingManagerDataErrorEventArgs.cs
- ClipboardProcessor.cs
- DelayedRegex.cs
- DataObjectPastingEventArgs.cs
- ButtonAutomationPeer.cs
- SqlTransaction.cs
- IEnumerable.cs
- _NTAuthentication.cs
- FileLogRecordHeader.cs
- ByteStack.cs
- PropertyOverridesTypeEditor.cs
- TemplateComponentConnector.cs
- RegexCompiler.cs
- FreeFormDragDropManager.cs
- ObjectQuery.cs
- AttributeCollection.cs
- AutomationEventArgs.cs
- ObjectListFieldsPage.cs
- FastEncoderWindow.cs
- DesignSurface.cs
- ScopedMessagePartSpecification.cs
- CapiSymmetricAlgorithm.cs
- WebBrowserDocumentCompletedEventHandler.cs
- XmlUtil.cs
- StringKeyFrameCollection.cs
- TextEditorParagraphs.cs
- GridViewPageEventArgs.cs
- Int32KeyFrameCollection.cs
- ZipIOEndOfCentralDirectoryBlock.cs
- ComboBoxAutomationPeer.cs
- AttributeUsageAttribute.cs
- SerializationException.cs
- NamedPipeProcessProtocolHandler.cs
- RSACryptoServiceProvider.cs
- PreservationFileWriter.cs
- EFDataModelProvider.cs
- GenericPrincipal.cs