aboutsummaryrefslogtreecommitdiff
path: root/src/ProtocolBuffers.Serialization/Http/MessageFormatFactory.cs
diff options
context:
space:
mode:
authorcsharptest <roger@csharptest.net>2011-09-08 20:02:11 -0500
committerrogerk <devnull@localhost>2011-09-08 20:02:11 -0500
commitc2d2c1adaf447bbc80194d8bce6c4e0442a7f47a (patch)
treea00d169fff4221e3779cb48e0e4c6001a1d5f604 /src/ProtocolBuffers.Serialization/Http/MessageFormatFactory.cs
parent8f0dcf3df1548a1eff0bed54a9b992f55b8f72d5 (diff)
downloadprotobuf-c2d2c1adaf447bbc80194d8bce6c4e0442a7f47a.tar.gz
protobuf-c2d2c1adaf447bbc80194d8bce6c4e0442a7f47a.tar.bz2
protobuf-c2d2c1adaf447bbc80194d8bce6c4e0442a7f47a.zip
first pass at adding required changes
Diffstat (limited to 'src/ProtocolBuffers.Serialization/Http/MessageFormatFactory.cs')
-rw-r--r--src/ProtocolBuffers.Serialization/Http/MessageFormatFactory.cs168
1 files changed, 168 insertions, 0 deletions
diff --git a/src/ProtocolBuffers.Serialization/Http/MessageFormatFactory.cs b/src/ProtocolBuffers.Serialization/Http/MessageFormatFactory.cs
new file mode 100644
index 00000000..7173d478
--- /dev/null
+++ b/src/ProtocolBuffers.Serialization/Http/MessageFormatFactory.cs
@@ -0,0 +1,168 @@
+using System;
+using System.IO;
+using System.Xml;
+using System.Text;
+
+namespace Google.ProtocolBuffers.Serialization
+{
+ /// <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)
+ {
+ FormatType inputType = ContentTypeToFormat(contentType, options.DefaultContentType);
+
+ ICodedInputStream codedInput;
+ if (inputType == FormatType.ProtoBuffer)
+ {
+ codedInput = CodedInputStream.CreateInstance(input);
+ }
+ else if (inputType == FormatType.Json)
+ {
+ JsonFormatReader reader = JsonFormatReader.CreateInstance(input);
+ codedInput = reader.ReadStartMessage();
+ }
+ else if (inputType == FormatType.Xml)
+ {
+ XmlFormatReader reader = XmlFormatReader.CreateInstance(input);
+ reader.RootElementName = options.XmlReaderRootElementName;
+ reader.Options = options.XmlReaderOptions;
+ codedInput = reader.ReadStartMessage();
+ }
+ else
+ throw new NotSupportedException();
+
+ return codedInput;
+ }
+
+ /// <summary>
+ /// Merges the message from the input stream based on the contentType provided
+ /// </summary>
+ /// <typeparam name="TBuilder">A type derived from IBuilderLite</typeparam>
+ /// <param name="builder">An instance of a message builder</param>
+ /// <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 same builder instance that was supplied in the builder parameter</returns>
+ public static TBuilder MergeFrom<TBuilder>(this TBuilder builder, MessageFormatOptions options, string contentType, Stream input) where TBuilder : IBuilderLite
+ {
+ ICodedInputStream codedInput = CreateInputStream(options, contentType, input);
+ return (TBuilder)builder.WeakMergeFrom(codedInput, options.ExtensionRegistry);
+ }
+
+ /// <summary>
+ /// Writes the message instance to the stream using the content type provided
+ /// </summary>
+ /// <param name="message">An instance of a message</param>
+ /// <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>
+ public static void WriteTo(this IMessageLite message, MessageFormatOptions options, string contentType, Stream output)
+ {
+ FormatType outputType = ContentTypeToFormat(contentType, options.DefaultContentType);
+
+ ICodedOutputStream codedOutput;
+ if (outputType == FormatType.ProtoBuffer)
+ {
+ codedOutput = CodedOutputStream.CreateInstance(output);
+ }
+ else if (outputType == FormatType.Json)
+ {
+ JsonFormatWriter writer = JsonFormatWriter.CreateInstance(output);
+ if (options.FormattedOutput)
+ {
+ writer.Formatted();
+ }
+ writer.StartMessage();
+ codedOutput = writer;
+ }
+ else if (outputType == FormatType.Xml)
+ {
+ XmlFormatWriter writer;
+ if (options.FormattedOutput)
+ {
+ writer = XmlFormatWriter.CreateInstance(output);
+ }
+ else
+ {
+ XmlWriterSettings settings = new XmlWriterSettings()
+ {
+ CheckCharacters = false,
+ NewLineHandling = NewLineHandling.Entitize,
+ OmitXmlDeclaration = true,
+ Encoding = Encoding.UTF8,
+ Indent = true,
+ IndentChars = " ",
+ NewLineChars = Environment.NewLine,
+ };
+ writer = XmlFormatWriter.CreateInstance(XmlWriter.Create(output, settings));
+ }
+ writer.RootElementName = options.XmlWriterRootElementName;
+ writer.Options = options.XmlWriterOptions;
+ writer.StartMessage();
+ codedOutput = writer;
+ }
+ else
+ throw new NotSupportedException();
+
+ message.WriteTo(codedOutput);
+
+ if (codedOutput is AbstractWriter)
+ ((AbstractWriter) codedOutput).EndMessage();
+
+ codedOutput.Flush();
+ }
+
+
+ enum FormatType { ProtoBuffer, Json, Xml };
+
+ private static FormatType ContentTypeToFormat(string contentType, string defaultType)
+ {
+ switch ((contentType ?? String.Empty).Split(';')[0].Trim().ToLower())
+ {
+ case "application/json":
+ case "application/x-json":
+ case "application/x-javascript":
+ case "text/javascript":
+ case "text/x-javascript":
+ case "text/x-json":
+ case "text/json":
+ {
+ return FormatType.Json;
+ }
+
+ case "text/xml":
+ case "application/xml":
+ {
+ return FormatType.Xml;
+ }
+
+ case "application/binary":
+ case "application/x-protobuf":
+ case "application/vnd.google.protobuf":
+ {
+ return FormatType.ProtoBuffer;
+ }
+
+ case "":
+ case null:
+ if (!String.IsNullOrEmpty(defaultType))
+ {
+ return ContentTypeToFormat(defaultType, null);
+ }
+ break;
+ }
+
+ throw new ArgumentOutOfRangeException("contentType");
+ }
+ }
+} \ No newline at end of file