MessageFormatFactory.cs 5.21 KB
Newer Older
1 2 3 4 5
using System;
using System.IO;
using System.Xml;
using System.Text;

6
namespace Google.ProtocolBuffers.Serialization.Http
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
{
    /// <summary>
    /// Extensions and helpers to abstract the reading/writing of messages by a client-specified content type.
    /// </summary>
    public static class MessageFormatFactory
    {
        /// <summary>
        /// Constructs an ICodedInputStream from the input stream based on the contentType provided
        /// </summary>
        /// <param name="options">Options specific to reading this message and/or content type</param>
        /// <param name="contentType">The mime type of the input stream content</param>
        /// <param name="input">The stream to read the message from</param>
        /// <returns>The ICodedInputStream that can be given to the IBuilder.MergeFrom(...) method</returns>
        public static ICodedInputStream CreateInputStream(MessageFormatOptions options, string contentType, Stream input)
        {
22
            ICodedInputStream codedInput = ContentTypeToInputStream(contentType, options, input);
23

24
            if (codedInput is XmlFormatReader)
25
            {
26
                XmlFormatReader reader = (XmlFormatReader)codedInput;
27 28 29 30 31 32
                reader.RootElementName = options.XmlReaderRootElementName;
                reader.Options = options.XmlReaderOptions;
            }

            return codedInput;
        }
33
        
34 35 36 37 38 39
        /// <summary>
        /// Writes the message instance to the stream using the content type provided
        /// </summary>
        /// <param name="options">Options specific to writing this message and/or content type</param>
        /// <param name="contentType">The mime type of the content to be written</param>
        /// <param name="output">The stream to write the message to</param>
40 41
        /// <remarks> If you do not dispose of ICodedOutputStream some formats may yield incomplete output </remarks>
        public static ICodedOutputStream CreateOutputStream(MessageFormatOptions options, string contentType, Stream output)
42
        {
43
            ICodedOutputStream codedOutput = ContentTypeToOutputStream(contentType, options, output);
44

45
            if (codedOutput is JsonFormatWriter)
46
            {
47
                JsonFormatWriter writer = (JsonFormatWriter)codedOutput;
48 49 50 51 52
                if (options.FormattedOutput)
                {
                    writer.Formatted();
                }
            }
53
            else if (codedOutput is XmlFormatWriter)
54
            {
55 56
                XmlFormatWriter writer = (XmlFormatWriter)codedOutput;
                if (options.FormattedOutput)
57 58
                {
                    XmlWriterSettings settings = new XmlWriterSettings()
59 60 61 62
                                                     {
                                                         CheckCharacters = false,
                                                         NewLineHandling = NewLineHandling.Entitize,
                                                         OmitXmlDeclaration = true,
63
                                                         Encoding = new UTF8Encoding(false),
64
                                                         Indent = true,
65
                                                         IndentChars = "    ",
66
                                                     };
67 68
                    // Don't know how else to change xml writer options?
                    codedOutput = writer = XmlFormatWriter.CreateInstance(XmlWriter.Create(output, settings));
69 70 71 72 73
                }
                writer.RootElementName = options.XmlWriterRootElementName;
                writer.Options = options.XmlWriterOptions;
            }

74 75 76
            return codedOutput;
        }

77 78 79
        private static ICodedInputStream ContentTypeToInputStream(string contentType, MessageFormatOptions options, Stream input)
        {
            contentType = (contentType ?? String.Empty).Split(';')[0].Trim();
80

csharptest's avatar
csharptest committed
81
            CodedInputBuilder factory;
82 83 84 85 86 87 88 89 90 91 92 93 94
            if(!options.MimeInputTypesReadOnly.TryGetValue(contentType, out factory) || factory == null)
            {
                if(String.IsNullOrEmpty(options.DefaultContentType) ||
                    !options.MimeInputTypesReadOnly.TryGetValue(options.DefaultContentType, out factory) || factory == null)
                {
                    throw new ArgumentOutOfRangeException("contentType");
                }
            }

            return factory(input);
        }

        private static ICodedOutputStream ContentTypeToOutputStream(string contentType, MessageFormatOptions options, Stream output)
95
        {
96 97
            contentType = (contentType ?? String.Empty).Split(';')[0].Trim();

csharptest's avatar
csharptest committed
98
            CodedOutputBuilder factory;
99
            if (!options.MimeOutputTypesReadOnly.TryGetValue(contentType, out factory) || factory == null)
100
            {
101 102 103 104 105
                if (String.IsNullOrEmpty(options.DefaultContentType) ||
                    !options.MimeOutputTypesReadOnly.TryGetValue(options.DefaultContentType, out factory) || factory == null)
                {
                    throw new ArgumentOutOfRangeException("contentType");
                }
106 107
            }

108
            return factory(output);
109
        }
110

111 112
    }
}