2010-06-21 Atsushi Enomoto <atsushi@ximian.com>
[mcs.git] / class / System.Runtime.Serialization / System.Xml / XmlMtomDictionaryWriter.cs
blob301c5275607da0ede7fc4844626f6d54e8fe986c
1 //
2 // XmlMtomDictionaryWriter.cs
3 //
4 // Author:
5 // Atsushi Enomoto <atsushi@ximian.com>
6 //
7 // Copyright (C) 2009 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.Text;
33 namespace System.Xml
35 internal class XmlMtomDictionaryWriter : XmlDictionaryWriter
37 public XmlMtomDictionaryWriter (Stream stream, Encoding encoding, int maxSizeInBytes, string startInfo, string boundary, string startUri, bool writeMessageHeaders, bool ownsStream)
39 writer = new StreamWriter (stream, encoding);
40 max_bytes = maxSizeInBytes;
41 write_headers = writeMessageHeaders;
42 owns_stream = ownsStream;
44 var settings = new XmlWriterSettings ();
45 settings.Encoding = encoding;
46 settings.OmitXmlDeclaration = true;
47 xml_writer_settings = settings;
49 // FIXME: actually it does not likely use ContentType.ToString() but writes those header items by own.
50 // (so that it could generate "start" header dynamically)
51 var c = new ContentType ("multipart/related");
52 c.Parameters ["type"] = "application/xop+xml";
53 c.Boundary = boundary;
54 c.Parameters ["start"] = "<" + startUri + ">";
55 c.Parameters ["start-info"] = startInfo;
56 content_type = c;
59 // constructor arguments
60 TextWriter writer;
61 XmlWriterSettings xml_writer_settings;
62 Encoding encoding;
63 int max_bytes;
64 bool write_headers;
65 bool owns_stream;
66 ContentType content_type;
68 // state
69 XmlWriter w;
70 int depth;
71 int section_count;
73 XmlWriter CreateWriter ()
75 return XmlWriter.Create (writer, xml_writer_settings);
78 public override void Close ()
80 w.Close ();
81 if (owns_stream)
82 writer.Close ();
85 public override void Flush ()
87 w.Flush ();
90 public override string LookupPrefix (string namespaceUri)
92 return w.LookupPrefix (namespaceUri);
95 public override void WriteBase64 (byte [] bytes, int start, int length)
97 CheckState ();
98 w.WriteBase64 (bytes, start, length);
101 public override void WriteCData (string text)
103 CheckState ();
104 w.WriteCData (text);
107 public override void WriteCharEntity (char c)
109 CheckState ();
110 w.WriteCharEntity (c);
113 public override void WriteChars (char [] buffer, int index, int count)
115 CheckState ();
116 w.WriteChars (buffer, index, count);
119 public override void WriteComment (string comment)
121 CheckState ();
122 w.WriteComment (comment);
125 public override void WriteDocType (string name, string pubid, string sysid, string intSubset)
127 throw new NotSupportedException (); // indeed
130 public override void WriteEndAttribute ()
132 w.WriteEndAttribute ();
135 public override void WriteEndDocument ()
137 w.WriteEndDocument ();
140 public override void WriteEndElement ()
142 w.WriteEndElement ();
143 if (--depth == 0)
144 WriteEndOfMimeSection ();
147 public override void WriteEntityRef (string name)
149 w.WriteEntityRef (name);
152 public override void WriteFullEndElement ()
154 w.WriteFullEndElement ();
155 if (--depth == 0)
156 WriteEndOfMimeSection ();
159 public override void WriteProcessingInstruction (string name, string data)
161 throw new NotSupportedException ();
164 public override void WriteRaw (string raw)
166 CheckState ();
167 w.WriteRaw (raw);
170 public override void WriteRaw (char [] chars, int index, int count)
172 CheckState ();
173 w.WriteRaw (chars, index, count);
176 public override void WriteStartAttribute (string prefix, string localName, string namespaceURI)
178 CheckState ();
179 w.WriteStartAttribute (prefix, localName, namespaceURI);
182 public override void WriteStartDocument ()
184 CheckState ();
185 w.WriteStartDocument ();
188 public override void WriteStartDocument (bool standalone)
190 CheckState ();
191 w.WriteStartDocument (standalone);
194 public override void WriteStartElement (string prefix, string localName, string namespaceURI)
196 CheckState ();
198 if (depth == 0)
199 WriteStartOfMimeSection ();
201 w.WriteStartElement (prefix, localName, namespaceURI);
202 depth++;
205 public override WriteState WriteState {
206 get { return w.WriteState; }
209 public override void WriteString (string text)
211 CheckState ();
213 int i1, i2 = 0;
214 do {
215 i1 = text.IndexOf ('\r', i2);
216 if (i1 >= 0) {
217 w.WriteString (text.Substring (i2, i1 - i2));
218 WriteCharEntity ('\r');
219 i2 = i1 + 1;
220 } else {
221 w.WriteString (text.Substring (i2));
222 break;
224 } while (true);
227 public override void WriteSurrogateCharEntity (char low, char high)
229 CheckState ();
230 w.WriteSurrogateCharEntity (low, high);
233 public override void WriteWhitespace (string text)
235 CheckState ();
236 w.WriteWhitespace (text);
239 public override string XmlLang {
240 get { return w.XmlLang; }
243 public override XmlSpace XmlSpace {
244 get { return w.XmlSpace; }
247 void CheckState ()
249 if (w == null && write_headers)
250 WriteMimeHeaders ();
251 if (w == null || w.WriteState == WriteState.Closed || w.WriteState == WriteState.Error)
252 w = CreateWriter ();
255 void WriteMimeHeaders ()
257 writer.Write ("MIME-Version: 1.0\r\n");
258 writer.Write ("Content-Type: ");
259 writer.Write (content_type.ToString ());
260 writer.Write ("\r\n\r\n\r\n");
263 void WriteStartOfMimeSection ()
265 section_count++;
267 // I'm not sure what's the expected behavior of this
268 // strange XmlWriter, but so far - it outputs only one
269 // section.
270 if (section_count > 1)
271 return;
273 writer.Write ("\r\n");
274 writer.Write ("--");
275 writer.Write (content_type.Boundary);
276 writer.Write ("\r\n");
277 writer.Write ("Content-ID: ");
278 writer.Write (content_type.Parameters ["start"]);
279 writer.Write ("\r\n");
280 writer.Write ("Content-Transfer-Encoding: 8bit\r\n");
281 writer.Write ("Content-Type: application/xop+xml;charset=");
282 writer.Write (xml_writer_settings.Encoding.HeaderName);
283 writer.Write (";type=\"");
284 writer.Write (content_type.Parameters ["start-info"].Replace ("\"", "\\\""));
285 writer.Write ("\"\r\n\r\n");
288 void WriteEndOfMimeSection ()
290 // I'm not sure what's the expected behavior of this
291 // strange XmlWriter, but so far - it outputs only one
292 // section.
293 if (section_count > 1)
294 return;
296 writer.Write ("\r\n");
297 writer.Write ("--");
298 writer.Write (content_type.Boundary);
299 writer.Write ("--\r\n");