JsonMessageEncoderFactory.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / NetFx35 / System.ServiceModel.Web / System / ServiceModel / Channels / JsonMessageEncoderFactory.cs / 1305376 / JsonMessageEncoderFactory.cs

                            //------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------

namespace System.ServiceModel.Channels 
{
    using System.Globalization; 
    using System.IO; 
    using System.Runtime;
    using System.Runtime.Serialization.Json; 
    using System.ServiceModel.Diagnostics;
    using System.Text;
    using System.Xml;
    using System.ServiceModel.Web; 
    using System.Net;
 
    class JsonMessageEncoderFactory : MessageEncoderFactory 
    {
        static readonly TextMessageEncoderFactory.ContentEncoding[] ApplicationJsonContentEncoding = GetContentEncodingMap(JsonGlobals.applicationJsonMediaType); 
        JsonMessageEncoder messageEncoder;

        public JsonMessageEncoderFactory(Encoding writeEncoding, int maxReadPoolSize, int maxWritePoolSize, XmlDictionaryReaderQuotas quotas, bool crossDomainScriptAccessEnabled)
        { 
            messageEncoder = new JsonMessageEncoder(writeEncoding, maxReadPoolSize, maxWritePoolSize, quotas, crossDomainScriptAccessEnabled);
        } 
 
        public override MessageEncoder Encoder
        { 
            get { return messageEncoder; }
        }

        public override MessageVersion MessageVersion 
        {
            get { return messageEncoder.MessageVersion; } 
        } 

        internal static string GetContentType(WebMessageEncodingBindingElement encodingElement) 
        {
            if (encodingElement == null)
            {
                return WebMessageEncoderFactory.GetContentType(JsonGlobals.applicationJsonMediaType, TextEncoderDefaults.Encoding); 
            }
            else 
            { 
                return WebMessageEncoderFactory.GetContentType(JsonGlobals.applicationJsonMediaType, encodingElement.WriteEncoding);
            } 
        }

        static TextMessageEncoderFactory.ContentEncoding[] GetContentEncodingMap(string mediaType)
        { 
            Encoding[] readEncodings = TextMessageEncoderFactory.GetSupportedEncodings();
            TextMessageEncoderFactory.ContentEncoding[] map = new TextMessageEncoderFactory.ContentEncoding[readEncodings.Length]; 
            for (int i = 0; i < readEncodings.Length; i++) 
            {
                TextMessageEncoderFactory.ContentEncoding contentEncoding = new TextMessageEncoderFactory.ContentEncoding(); 
                contentEncoding.contentType = WebMessageEncoderFactory.GetContentType(mediaType, readEncodings[i]);
                contentEncoding.encoding = readEncodings[i];
                map[i] = contentEncoding;
            } 
            return map;
        } 
 
        class JsonMessageEncoder : MessageEncoder
        { 
            const int maxPooledXmlReadersPerMessage = 2;
            SynchronizedPool bufferedReaderPool;
            SynchronizedPool bufferedWriterPool;
            string contentType; 
            int maxReadPoolSize;
            int maxWritePoolSize; 
            OnXmlDictionaryReaderClose onStreamedReaderClose; 
            XmlDictionaryReaderQuotas readerQuotas;
            SynchronizedPool recycledStatePool; 
            SynchronizedPool streamedReaderPool;
            SynchronizedPool streamedWriterPool;
            object thisLock;
            Encoding writeEncoding; 
            bool crossDomainScriptAccessEnabled;
            byte[] encodedClosingFunctionCall; 
 
            public JsonMessageEncoder(Encoding writeEncoding, int maxReadPoolSize, int maxWritePoolSize, XmlDictionaryReaderQuotas quotas, bool crossDomainScriptAccessEnabled)
            { 
                if (writeEncoding == null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("writeEncoding");
                } 

                thisLock = new object(); 
 
                TextEncoderDefaults.ValidateEncoding(writeEncoding);
                this.writeEncoding = writeEncoding; 

                this.maxReadPoolSize = maxReadPoolSize;
                this.maxWritePoolSize = maxWritePoolSize;
 
                this.readerQuotas = new XmlDictionaryReaderQuotas();
                this.onStreamedReaderClose = new OnXmlDictionaryReaderClose(ReturnStreamedReader); 
                quotas.CopyTo(this.readerQuotas); 

                this.contentType = WebMessageEncoderFactory.GetContentType(JsonGlobals.applicationJsonMediaType, writeEncoding); 
                this.crossDomainScriptAccessEnabled = crossDomainScriptAccessEnabled;
                this.encodedClosingFunctionCall = this.writeEncoding.GetBytes(");");
            }
 
            public override string ContentType
            { 
                get { return contentType; } 
            }
 
            public override string MediaType
            {
                get { return JsonGlobals.applicationJsonMediaType; }
            } 

            public override MessageVersion MessageVersion 
            { 
                get { return MessageVersion.None; }
            } 

            SynchronizedPool RecycledStatePool
            {
                get 
                {
                    if (recycledStatePool == null) 
                    { 
                        lock (ThisLock)
                        { 
                            if (recycledStatePool == null)
                            {
                                recycledStatePool = new SynchronizedPool(maxReadPoolSize);
                            } 
                        }
                    } 
                    return recycledStatePool; 
                }
            } 

            object ThisLock
            {
                get { return thisLock; } 
            }
 
            public override bool IsContentTypeSupported(string contentType) 
            {
                if (contentType == null) 
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contentType");
                }
                return IsJsonContentType(contentType); 
            }
 
            public override Message ReadMessage(ArraySegment buffer, BufferManager bufferManager, string contentType) 
            {
                if (bufferManager == null) 
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("bufferManager"));
                }
 
                Message message;
 
                JsonBufferedMessageData messageData = TakeBufferedReader(); 
                messageData.Encoding = TextMessageEncoderFactory.GetEncodingFromContentType(contentType, JsonMessageEncoderFactory.ApplicationJsonContentEncoding);
                messageData.Open(buffer, bufferManager); 
                RecycledMessageState messageState = messageData.TakeMessageState();
                if (messageState == null)
                {
                    messageState = new RecycledMessageState(); 
                }
                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"));
                }
 
                XmlReader reader = TakeStreamedReader(stream, TextMessageEncoderFactory.GetEncodingFromContentType(contentType, JsonMessageEncoderFactory.ApplicationJsonContentEncoding));
                Message message = Message.CreateMessage(reader, maxSizeOfHeaders, MessageVersion.None); 
                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) 
            { 
                if (message == null)
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("message"));
                }
                if (bufferManager == null)
                { 
                    throw TraceUtility.ThrowHelperError(new ArgumentNullException("bufferManager"), message);
                } 
                if (maxMessageSize < 0) 
                {
                    throw TraceUtility.ThrowHelperError(new ArgumentOutOfRangeException("maxMessageSize", maxMessageSize, 
                        SR2.GetString(SR2.ValueMustBeNonNegative)), message);
                }
                if (messageOffset < 0 || messageOffset > maxMessageSize)
                { 
                    throw TraceUtility.ThrowHelperError(new ArgumentOutOfRangeException("messageOffset", messageOffset,
                        SR2.GetString(SR2.JsonValueMustBeInRange, 0, maxMessageSize)), message); 
                } 

                ThrowIfMismatchedMessageVersion(message); 
                message.Properties.Encoder = this;
                JsonBufferedMessageWriter messageWriter = TakeBufferedWriter();

                JavascriptCallbackResponseMessageProperty javascriptResponseMessageProperty; 
                if (message.Properties.TryGetValue(JavascriptCallbackResponseMessageProperty.Name, out javascriptResponseMessageProperty) &&
                    javascriptResponseMessageProperty != null) 
                { 
                    if (this.crossDomainScriptAccessEnabled)
                    { 
                        messageWriter.SetJavascriptCallbackProperty(javascriptResponseMessageProperty);
                    }
                    else
                    { 
                        throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR2.JavascriptCallbackNotEnabled), message);
                    } 
                } 

                ArraySegment messageData = messageWriter.WriteMessage(message, bufferManager, messageOffset, maxMessageSize); 
                ReturnMessageWriter(messageWriter);
                if (MessageLogger.LogMessagesAtTransportLevel)
                {
                    XmlDictionaryReader xmlDictionaryReader = JsonReaderWriterFactory.CreateJsonReader( 
                        messageData.Array, messageData.Offset, messageData.Count, null, XmlDictionaryReaderQuotas.Max, null);
                    MessageLogger.LogMessage(ref message, xmlDictionaryReader, MessageLoggingSource.TransportSend); 
                } 
                return messageData;
            } 

            public override void WriteMessage(Message message, Stream stream)
            {
                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; 
                XmlDictionaryWriter xmlWriter = TakeStreamedWriter(stream);
                JavascriptCallbackResponseMessageProperty javascriptResponseMessageProperty; 
                if (message.Properties.TryGetValue(JavascriptCallbackResponseMessageProperty.Name, out javascriptResponseMessageProperty) 
                    && javascriptResponseMessageProperty != null
                    && !String.IsNullOrEmpty(javascriptResponseMessageProperty.CallbackFunctionName)) 

                {
                    if (!this.crossDomainScriptAccessEnabled)
                    { 
                        throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR2.JavascriptCallbackNotEnabled), message);
                    } 
                    byte[] buffer = this.writeEncoding.GetBytes(String.Format(CultureInfo.InvariantCulture, "{0}(", javascriptResponseMessageProperty.CallbackFunctionName)); 
                    stream.Write(buffer, 0, buffer.Length);
                } 
                xmlWriter.WriteStartDocument();
                message.WriteMessage(xmlWriter);
                xmlWriter.WriteEndDocument();
                xmlWriter.Flush(); 
                ReturnStreamedWriter(xmlWriter);
                if (javascriptResponseMessageProperty != null 
                    && !String.IsNullOrEmpty(javascriptResponseMessageProperty.CallbackFunctionName)) 
                {
                    if (javascriptResponseMessageProperty.StatusCode != null && (int)javascriptResponseMessageProperty.StatusCode != 200) 
                    {
                        byte[] buffer = this.writeEncoding.GetBytes(String.Format(CultureInfo.InvariantCulture, ",{0}", (int)javascriptResponseMessageProperty.StatusCode));
                        stream.Write(buffer, 0, buffer.Length);
                    } 
                    stream.Write(this.encodedClosingFunctionCall, 0, this.encodedClosingFunctionCall.Length);
                } 
                if (MessageLogger.LogMessagesAtTransportLevel) 
                {
                    MessageLogger.LogMessage(ref message, MessageLoggingSource.TransportSend); 
                }
            }

            internal override bool IsCharSetSupported(string charSet) 
            {
                Encoding tmp; 
                return TextEncoderDefaults.TryGetEncoding(charSet, out tmp); 
            }
 
            bool IsJsonContentType(string contentType)
            {
                return IsContentTypeSupported(contentType, JsonGlobals.applicationJsonMediaType, JsonGlobals.applicationJsonMediaType) || IsContentTypeSupported(contentType, JsonGlobals.textJsonMediaType, JsonGlobals.textJsonMediaType);
            } 

            void ReturnBufferedData(JsonBufferedMessageData messageData) 
            { 
                bufferedReaderPool.Return(messageData);
            } 

            void ReturnMessageWriter(JsonBufferedMessageWriter messageWriter)
            {
                bufferedWriterPool.Return(messageWriter); 
            }
 
            void ReturnStreamedReader(XmlDictionaryReader xmlReader) 
            {
                streamedReaderPool.Return(xmlReader); 
            }

            void ReturnStreamedWriter(XmlWriter xmlWriter)
            { 
                xmlWriter.Close();
                streamedWriterPool.Return((XmlDictionaryWriter) xmlWriter); 
            } 

            JsonBufferedMessageData TakeBufferedReader() 
            {
                if (bufferedReaderPool == null)
                {
                    lock (ThisLock) 
                    {
                        if (bufferedReaderPool == null) 
                        { 
                            bufferedReaderPool = new SynchronizedPool(maxReadPoolSize);
                        } 
                    }
                }
                JsonBufferedMessageData messageData = bufferedReaderPool.Take();
                if (messageData == null) 
                {
                    messageData = new JsonBufferedMessageData(this, maxPooledXmlReadersPerMessage); 
                } 
                return messageData;
            } 

            JsonBufferedMessageWriter TakeBufferedWriter()
            {
                if (bufferedWriterPool == null) 
                {
                    lock (ThisLock) 
                    { 
                        if (bufferedWriterPool == null)
                        { 
                            bufferedWriterPool = new SynchronizedPool(maxWritePoolSize);
                        }
                    }
                } 
                JsonBufferedMessageWriter messageWriter = bufferedWriterPool.Take();
                if (messageWriter == null) 
                { 
                    messageWriter = new JsonBufferedMessageWriter(this);
                } 
                return messageWriter;
            }

            XmlDictionaryReader TakeStreamedReader(Stream stream, Encoding enc) 
            {
                if (streamedReaderPool == null) 
                { 
                    lock (ThisLock)
                    { 
                        if (streamedReaderPool == null)
                        {
                            streamedReaderPool = new SynchronizedPool(maxReadPoolSize);
                        } 
                    }
                } 
                XmlDictionaryReader xmlReader = streamedReaderPool.Take(); 
                if (xmlReader == null)
                { 
                    xmlReader = JsonReaderWriterFactory.CreateJsonReader(stream, enc, this.readerQuotas, this.onStreamedReaderClose);
                }
                else
                { 
                    ((IXmlJsonReaderInitializer) xmlReader).SetInput(stream, enc, this.readerQuotas, this.onStreamedReaderClose);
                } 
                return xmlReader; 
            }
 
            XmlDictionaryWriter TakeStreamedWriter(Stream stream)
            {
                if (streamedWriterPool == null)
                { 
                    lock (ThisLock)
                    { 
                        if (streamedWriterPool == null) 
                        {
                            streamedWriterPool = new SynchronizedPool(maxWritePoolSize); 
                        }
                    }
                }
                XmlDictionaryWriter xmlWriter = streamedWriterPool.Take(); 
                if (xmlWriter == null)
                { 
                    xmlWriter = JsonReaderWriterFactory.CreateJsonWriter(stream, this.writeEncoding, false); 
                }
                else 
                {
                    ((IXmlJsonWriterInitializer) xmlWriter).SetOutput(stream, this.writeEncoding, false);
                }
                return xmlWriter; 
            }
 
            class JsonBufferedMessageData : BufferedMessageData 
            {
                Encoding encoding; 
                JsonMessageEncoder messageEncoder;
                OnXmlDictionaryReaderClose onClose;
                Pool readerPool;
 
                public JsonBufferedMessageData(JsonMessageEncoder 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; }
                }
 
                internal Encoding Encoding
                { 
                    set 
                    {
                        this.encoding = value; 
                    }
                }

                protected override void OnClosed() 
                {
                    messageEncoder.ReturnBufferedData(this); 
                } 

                protected override void ReturnXmlReader(XmlDictionaryReader xmlReader) 
                {
                    if (xmlReader != null)
                    {
                        readerPool.Return(xmlReader); 
                    }
                } 
 
                protected override XmlDictionaryReader TakeXmlReader()
                { 
                    ArraySegment buffer = this.Buffer;

                    XmlDictionaryReader xmlReader = readerPool.Take();
                    if (xmlReader == null) 
                    {
                        xmlReader = JsonReaderWriterFactory.CreateJsonReader(buffer.Array, buffer.Offset, buffer.Count, this.encoding, messageEncoder.readerQuotas, onClose); 
                    } 
                    else
                    { 
                        ((IXmlJsonReaderInitializer) xmlReader).SetInput(buffer.Array, buffer.Offset, buffer.Count, this.encoding, messageEncoder.readerQuotas, onClose);
                    }

                    return xmlReader; 
                }
            } 
 
            class JsonBufferedMessageWriter : BufferedMessageWriter
            { 
                JsonMessageEncoder messageEncoder;
                XmlDictionaryWriter returnedWriter;
                JavascriptXmlWriterWrapper javascriptWrapper;
 
                public JsonBufferedMessageWriter(JsonMessageEncoder messageEncoder)
                { 
                    this.messageEncoder = messageEncoder; 
                }
 
                public void SetJavascriptCallbackProperty(JavascriptCallbackResponseMessageProperty javascriptResponseMessageProperty)
                {
                    if (this.javascriptWrapper == null)
                    { 
                        this.javascriptWrapper = new JavascriptXmlWriterWrapper(this.messageEncoder.writeEncoding)
                        { 
                            JavascriptResponseMessageProperty = javascriptResponseMessageProperty 
                        };
                    } 
                    else
                    {
                        this.javascriptWrapper.JavascriptResponseMessageProperty = javascriptResponseMessageProperty;
                    } 
                }
 
                protected override void OnWriteEndMessage(XmlDictionaryWriter writer) 
                {
                    writer.WriteEndDocument(); 
                }

                protected override void OnWriteStartMessage(XmlDictionaryWriter writer)
                { 
                    writer.WriteStartDocument();
                } 
 
                protected override void ReturnXmlWriter(XmlDictionaryWriter writer)
                { 
                    writer.Close();

                    if (writer is JavascriptXmlWriterWrapper)
                    { 
                        if (this.javascriptWrapper == null)
                        { 
                            this.javascriptWrapper = (JavascriptXmlWriterWrapper)writer; 
                            this.javascriptWrapper.JavascriptResponseMessageProperty = null;
                            writer = this.javascriptWrapper.XmlJsonWriter; 
                        }
                    }

                    if (this.returnedWriter == null) 
                    {
                        this.returnedWriter = writer; 
                    } 
                }
 
                protected override XmlDictionaryWriter TakeXmlWriter(Stream stream)
                {
                    XmlDictionaryWriter writer = null;
                    if (this.returnedWriter == null) 
                    {
                        writer = JsonReaderWriterFactory.CreateJsonWriter(stream, messageEncoder.writeEncoding, false); 
                    } 
                    else
                    { 
                        writer = this.returnedWriter;
                        ((IXmlJsonWriterInitializer)writer).SetOutput(stream, messageEncoder.writeEncoding, false);
                        this.returnedWriter = null;
                    } 

                    if (this.javascriptWrapper != null && this.javascriptWrapper.JavascriptResponseMessageProperty != null) 
                    { 
                        this.javascriptWrapper.SetOutput(stream, writer);
                        writer = this.javascriptWrapper; 
                        this.javascriptWrapper = null;
                    }

                    return writer; 
                }
            } 
        } 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK