using System; using System.IO; using System.Xml; using System.Text; namespace Google.ProtocolBuffers.Serialization.Http { /// /// Extensions and helpers to abstract the reading/writing of messages by a client-specified content type. /// public static class MessageFormatFactory { /// /// Constructs an ICodedInputStream from the input stream based on the contentType provided /// /// Options specific to reading this message and/or content type /// The mime type of the input stream content /// The stream to read the message from /// The ICodedInputStream that can be given to the IBuilder.MergeFrom(...) method 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; } /// /// Writes the message instance to the stream using the content type provided /// /// Options specific to writing this message and/or content type /// The mime type of the content to be written /// The stream to write the message to /// If you do not dispose of ICodedOutputStream some formats may yield incomplete output 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(); Converter 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(); Converter 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); } } }