aboutsummaryrefslogblamecommitdiff
path: root/csharp/src/ProtocolBuffers.Serialization/Http/MessageFormatFactory.cs
blob: 270af64bf2a68911c522374fae2d6523c3941b1e (plain) (tree)
1
2
3
4
5
6




                   
                                                    














                                                                                                                          
                                                                                                  
 
                                               
              
                                                                      

                                                                           
              


                               
         


                                                                                      


                                                                                                       

                                                                                                                             
          
                                                                                                      
 
                                                 
              
                                                                         



                                             
              
                                                     
              

                                                                       

                                                                         



                                                                                                     
                                                                                             
                                                                        
                                                                               
                                                        

                                                                                                               


                                                                           
              
 


                                


                                                                                                                                  
 
                                       












                                                                                                                                     
          

                                                                              
                                        
                                                                                                           
              




                                                                                                                              

              
                                    
          
 

      
using System;
using System.IO;
using System.Xml;
using System.Text;

namespace Google.ProtocolBuffers.Serialization.Http
{
    /// <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)
        {
            ICodedInputStream codedInput = ContentTypeToInputStream(contentType, options, input);

            if (codedInput is XmlFormatReader)
            {
                XmlFormatReader reader = (XmlFormatReader)codedInput;
                reader.RootElementName = options.XmlReaderRootElementName;
                reader.Options = options.XmlReaderOptions;
            }

            return codedInput;
        }
        
        /// <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>
        /// <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)
        {
            ICodedOutputStream codedOutput = ContentTypeToOutputStream(contentType, options, output);

            if (codedOutput is JsonFormatWriter)
            {
                JsonFormatWriter writer = (JsonFormatWriter)codedOutput;
                if (options.FormattedOutput)
                {
                    writer.Formatted();
                }
            }
            else if (codedOutput is XmlFormatWriter)
            {
                XmlFormatWriter writer = (XmlFormatWriter)codedOutput;
                if (options.FormattedOutput)
                {
                    XmlWriterSettings settings = new XmlWriterSettings()
                                                     {
                                                         CheckCharacters = false,
                                                         NewLineHandling = NewLineHandling.Entitize,
                                                         OmitXmlDeclaration = true,
                                                         Encoding = new UTF8Encoding(false),
                                                         Indent = true,
                                                         IndentChars = "    ",
                                                     };
                    // Don't know how else to change xml writer options?
                    codedOutput = writer = XmlFormatWriter.CreateInstance(XmlWriter.Create(output, settings));
                }
                writer.RootElementName = options.XmlWriterRootElementName;
                writer.Options = options.XmlWriterOptions;
            }

            return codedOutput;
        }

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

            CodedInputBuilder factory;
            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)
        {
            contentType = (contentType ?? String.Empty).Split(';')[0].Trim();

            CodedOutputBuilder factory;
            if (!options.MimeOutputTypesReadOnly.TryGetValue(contentType, out factory) || factory == null)
            {
                if (String.IsNullOrEmpty(options.DefaultContentType) ||
                    !options.MimeOutputTypesReadOnly.TryGetValue(options.DefaultContentType, out factory) || factory == null)
                {
                    throw new ArgumentOutOfRangeException("contentType");
                }
            }

            return factory(output);
        }

    }
}