first pass at adding required changes
diff --git a/src/ProtocolBuffers.Serialization/Http/MessageFormatFactory.cs b/src/ProtocolBuffers.Serialization/Http/MessageFormatFactory.cs
new file mode 100644
index 0000000..7173d47
--- /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
diff --git a/src/ProtocolBuffers.Serialization/Http/MessageFormatOptions.cs b/src/ProtocolBuffers.Serialization/Http/MessageFormatOptions.cs
new file mode 100644
index 0000000..5b88ac9
--- /dev/null
+++ b/src/ProtocolBuffers.Serialization/Http/MessageFormatOptions.cs
@@ -0,0 +1,82 @@
+using System;

+

+namespace Google.ProtocolBuffers.Serialization

+{

+    /// <summary>

+    /// Defines control information for the various formatting used with HTTP services

+    /// </summary>

+    public struct MessageFormatOptions

+    {

+        /// <summary>The mime type for xml content</summary>

+        /// <remarks>Other valid xml mime types include: application/binary, application/x-protobuf</remarks>

+        public const string ContentTypeProtoBuffer = "application/vnd.google.protobuf";

+

+        /// <summary>The mime type for xml content</summary>

+        /// <remarks>Other valid xml mime types include: text/xml</remarks>

+        public const string ContentTypeXml = "application/xml";

+        

+        /// <summary>The mime type for json content</summary>

+        /// <remarks>

+        /// Other valid json mime types include: application/json, application/x-json, 

+        /// application/x-javascript, text/javascript, text/x-javascript, text/x-json, text/json

+        /// </remarks>

+        public const string ContentTypeJson = "application/json";

+

+        private string _defaultContentType;

+        private string _xmlReaderRootElementName;

+        private string _xmlWriterRootElementName;

+        private ExtensionRegistry _extensionRegistry;

+

+        /// <summary>

+        /// The default content type to use if the input type is null or empty.  If this

+        /// value is not supplied an ArgumentOutOfRangeException exception will be raised.

+        /// </summary>

+        public string DefaultContentType

+        {

+            get { return _defaultContentType ?? String.Empty; }

+            set { _defaultContentType = value; }

+        }

+

+        /// <summary>

+        /// The extension registry to use when reading messages

+        /// </summary>

+        public ExtensionRegistry ExtensionRegistry

+        {

+            get { return _extensionRegistry ?? ExtensionRegistry.Empty; }

+            set { _extensionRegistry = value; }

+        }

+

+        /// <summary>

+        /// The name of the xml root element when reading messages

+        /// </summary>

+        public string XmlReaderRootElementName

+        {

+            get { return _xmlReaderRootElementName ?? XmlFormatReader.DefaultRootElementName; }

+            set { _xmlReaderRootElementName = value; }

+        }

+

+        /// <summary>

+        /// Xml reader options

+        /// </summary>

+        public XmlReaderOptions XmlReaderOptions { get; set; }

+

+        /// <summary>

+        /// True to use formatted output including new-lines and default indentation

+        /// </summary>

+        public bool FormattedOutput { get; set; }

+

+        /// <summary>

+        /// The name of the xml root element when writing messages

+        /// </summary>

+        public string XmlWriterRootElementName

+        {

+            get { return _xmlWriterRootElementName ?? XmlFormatWriter.DefaultRootElementName; }

+            set { _xmlWriterRootElementName = value; }

+        }

+

+        /// <summary>

+        /// Xml writer options

+        /// </summary>

+        public XmlWriterOptions XmlWriterOptions { get; set; }

+    }

+}
\ No newline at end of file
diff --git a/src/ProtocolBuffers.Serialization/Http/ServiceExtensions.cs b/src/ProtocolBuffers.Serialization/Http/ServiceExtensions.cs
new file mode 100644
index 0000000..3ca9964
--- /dev/null
+++ b/src/ProtocolBuffers.Serialization/Http/ServiceExtensions.cs
@@ -0,0 +1,32 @@
+using System.Collections.Generic;

+using System.Text;

+using Google.ProtocolBuffers;

+using System.IO;

+

+namespace Google.ProtocolBuffers.Serialization

+{

+    /// <summary>

+    /// Extensions for the IRpcServerStub

+    /// </summary>

+    public static class ServiceExtensions

+    {

+        /// <summary>

+        /// Used to implement a service endpoint on an HTTP server.  This works with services generated with the

+        /// service_generator_type option set to IRPCDISPATCH.

+        /// </summary>

+        /// <param name="stub">The service execution stub</param>

+        /// <param name="methodName">The name of the method being invoked</param>

+        /// <param name="options">optional arguments for the format reader/writer</param>

+        /// <param name="contentType">The mime type for the input stream</param>

+        /// <param name="input">The input stream</param>

+        /// <param name="responseType">The mime type for the output stream</param>

+        /// <param name="output">The output stream</param>

+        public static void HttpCallMethod(this IRpcServerStub stub, string methodName, MessageFormatOptions options, 

+            string contentType, Stream input, string responseType, Stream output)

+        {

+            ICodedInputStream codedInput = MessageFormatFactory.CreateInputStream(options, contentType, input);

+            IMessageLite response = stub.CallMethod(methodName, codedInput, options.ExtensionRegistry);

+            response.WriteTo(options, responseType, output);

+        }

+    }

+}