2010-06-21 Atsushi Enomoto <atsushi@ximian.com>
[mcs.git] / class / System.ServiceModel.Web / System.ServiceModel.Channels / WebMessageEncoder.cs
blob45ce9448b9d34b3e7b61d2dae4dfdacfec233aa5
1 //
2 // WebMessageEncoder.cs
3 //
4 // Author:
5 // Atsushi Enomoto <atsushi@ximian.com>
6 //
7 // Copyright (C) 2008 Novell, Inc (http://www.novell.com)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 using System;
29 using System.IO;
30 using System.Net.Mime;
31 using System.Runtime.Serialization.Json;
32 using System.ServiceModel;
33 using System.Text;
34 using System.Xml;
36 namespace System.ServiceModel.Channels
38 internal class WebMessageEncoder : MessageEncoder
40 internal const string ScriptPropertyName = "618BC2B0-38AA-21A3-DB4A-404FC87B9B11"; // randomly generated
42 WebMessageEncodingBindingElement source;
44 public WebMessageEncoder (WebMessageEncodingBindingElement source)
46 this.source = source;
49 public override string ContentType {
50 #if NET_2_1
51 get { return MediaType; }
52 #else
53 get { return MediaType + "; charset=" + source.WriteEncoding.HeaderName; }
54 #endif
57 // FIXME: find out how it can be customized.
58 public override string MediaType {
59 get { return "application/xml"; }
62 public override MessageVersion MessageVersion {
63 get { return MessageVersion.None; }
66 public override Message ReadMessage (ArraySegment<byte> buffer, BufferManager bufferManager, string contentType)
68 throw new NotImplementedException ();
71 public override Message ReadMessage (Stream stream, int maxSizeOfHeaders, string contentType)
73 if (stream == null)
74 throw new ArgumentNullException ("stream");
75 if (contentType == null)
76 throw new ArgumentNullException ("contentType");
78 Encoding enc = Encoding.UTF8;
79 ContentType ct = new ContentType (contentType);
80 if (ct.CharSet != null)
81 enc = Encoding.GetEncoding (ct.CharSet);
83 WebContentFormat fmt = WebContentFormat.Xml;
84 if (source.ContentTypeMapper != null)
85 fmt = source.ContentTypeMapper.GetMessageFormatForContentType (contentType);
86 else {
87 switch (ct.MediaType) {
88 case "application/json":
89 fmt = WebContentFormat.Json;
90 break;
91 case "application/xml":
92 fmt = WebContentFormat.Xml;
93 break;
94 case "application/octet-stream":
95 fmt = WebContentFormat.Raw;
96 break;
100 Message msg = null;
101 WebBodyFormatMessageProperty wp = null;
102 switch (fmt) {
103 case WebContentFormat.Xml:
104 // FIXME: is it safe/unsafe/required to keep XmlReader open?
105 msg = Message.CreateMessage (MessageVersion.None, null, XmlReader.Create (new StreamReader (stream, enc)));
106 wp = new WebBodyFormatMessageProperty (WebContentFormat.Xml);
107 break;
108 case WebContentFormat.Json:
109 // FIXME: is it safe/unsafe/required to keep XmlReader open?
110 #if NET_2_1
111 msg = Message.CreateMessage (MessageVersion.None, null, JsonReaderWriterFactory.CreateJsonReader (stream, source.ReaderQuotas));
112 #else
113 msg = Message.CreateMessage (MessageVersion.None, null, JsonReaderWriterFactory.CreateJsonReader (stream, enc, source.ReaderQuotas, null));
114 #endif
115 wp = new WebBodyFormatMessageProperty (WebContentFormat.Json);
116 break;
117 case WebContentFormat.Raw:
118 throw new NotImplementedException ();
119 default:
120 throw new SystemException ("INTERNAL ERROR: cannot determine content format");
122 if (wp != null)
123 msg.Properties.Add (WebBodyFormatMessageProperty.Name, wp);
124 return msg;
127 WebContentFormat GetContentFormat (Message message)
129 string name = WebBodyFormatMessageProperty.Name;
130 if (message.Properties.ContainsKey (name))
131 return ((WebBodyFormatMessageProperty) message.Properties [name]).Format;
133 switch (MediaType) {
134 case "application/xml":
135 case "text/xml":
136 return WebContentFormat.Xml;
137 case "application/json":
138 case "text/json":
139 return WebContentFormat.Json;
140 case "application/octet-stream":
141 return WebContentFormat.Raw;
142 default:
143 return WebContentFormat.Default;
147 public override void WriteMessage (Message message, Stream stream)
149 if (message == null)
150 throw new ArgumentNullException ("message");
152 // Handle /js and /jsdebug as the special cases.
153 var script = message.Properties [ScriptPropertyName] as string;
154 if (script != null) {
155 var bytes = source.WriteEncoding.GetBytes (script);
156 stream.Write (bytes, 0, bytes.Length);
157 return;
160 if (!MessageVersion.Equals (message.Version))
161 throw new ProtocolException (String.Format ("MessageVersion {0} is not supported", message.Version));
162 if (stream == null)
163 throw new ArgumentNullException ("stream");
165 switch (GetContentFormat (message)) {
166 case WebContentFormat.Xml:
167 #if NET_2_1
168 using (XmlWriter w = XmlDictionaryWriter.CreateDictionaryWriter (XmlWriter.Create (new StreamWriter (stream, source.WriteEncoding))))
169 message.WriteMessage (w);
170 #else
171 using (XmlWriter w = XmlDictionaryWriter.CreateTextWriter (stream, source.WriteEncoding))
172 message.WriteMessage (w);
173 #endif
174 break;
175 case WebContentFormat.Json:
176 using (XmlWriter w = JsonReaderWriterFactory.CreateJsonWriter (stream, source.WriteEncoding))
177 message.WriteMessage (w);
178 break;
179 case WebContentFormat.Raw:
180 throw new NotImplementedException ();
181 case WebContentFormat.Default:
182 throw new SystemException ("INTERNAL ERROR: cannot determine content format");
186 public override ArraySegment<byte> WriteMessage (Message message, int maxMessageSize, BufferManager bufferManager,
187 int messageOffset)
189 throw new NotImplementedException ();