[runtime] Overwrite stacktrace for exception on re-throw. Fixes #1856.
[mono.git] / mcs / class / System.Runtime.Serialization / System.Xml / XmlDictionaryWriter.cs
1 //
2 // XmlDictionaryWriter.cs
3 //
4 // Author:
5 //      Atsushi Enomoto <atsushi@ximian.com>
6 //
7 // Copyright (C) 2005 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.
27 //
28 using System;
29 using System.IO;
30 using System.Text;
31
32 namespace System.Xml
33 {
34         public abstract partial class XmlDictionaryWriter : XmlWriter
35         {
36                 static readonly Encoding utf8_unmarked = new UTF8Encoding (false);
37
38                 protected XmlDictionaryWriter ()
39                 {
40                 }
41
42                 internal int Depth { get; set; }
43
44                 internal int NSIndex { get; set; }
45
46                 public virtual bool CanCanonicalize {
47                         get { return false; }
48                 }
49
50                 public static XmlDictionaryWriter CreateBinaryWriter (
51                         Stream stream)
52                 {
53                         return CreateBinaryWriter (stream, null, null, false);
54                 }
55
56                 public static XmlDictionaryWriter CreateBinaryWriter (
57                         Stream stream, IXmlDictionary dictionary)
58                 {
59                         return CreateBinaryWriter (stream, dictionary, null, false);
60                 }
61
62                 public static XmlDictionaryWriter CreateBinaryWriter (
63                         Stream stream, IXmlDictionary dictionary,
64                         XmlBinaryWriterSession session)
65                 {
66                         return CreateBinaryWriter (stream, dictionary, session, false);
67                 }
68
69                 public static XmlDictionaryWriter CreateBinaryWriter (
70                         Stream stream, IXmlDictionary dictionary,
71                         XmlBinaryWriterSession session, bool ownsStream)
72                 {
73                         return new XmlBinaryDictionaryWriter (stream,
74                                 dictionary, session, ownsStream);
75                 }
76
77                 public static XmlDictionaryWriter CreateDictionaryWriter (XmlWriter writer)
78                 {
79                         return new XmlSimpleDictionaryWriter (writer);
80                 }
81 #if !NET_2_1
82                 public static XmlDictionaryWriter CreateMtomWriter (
83                         Stream stream, Encoding encoding, int maxSizeInBytes,
84                         string startInfo)
85                 {
86                         return CreateMtomWriter (stream, encoding,
87                                 maxSizeInBytes, startInfo, Guid.NewGuid () + "id=1", "http://tempuri.org/0/" + DateTime.Now.Ticks, true, false);
88                 }
89
90                 public static XmlDictionaryWriter CreateMtomWriter (
91                         Stream stream, Encoding encoding, int maxSizeInBytes,
92                         string startInfo, string boundary, string startUri,
93                         bool writeMessageHeaders, bool ownsStream)
94                 {
95                         return new XmlMtomDictionaryWriter (stream, encoding, maxSizeInBytes, startInfo, boundary, startUri, writeMessageHeaders, ownsStream);
96                 }
97 #endif
98                 public static XmlDictionaryWriter CreateTextWriter (
99                         Stream stream)
100                 {
101                         return CreateTextWriter (stream, Encoding.UTF8);
102                 }
103
104                 public static XmlDictionaryWriter CreateTextWriter (
105                         Stream stream, Encoding encoding)
106                 {
107                         return CreateTextWriter (stream, encoding, false);
108                 }
109
110                 // BTW looks like it creates an instance of different
111                 // implementation than those from XmlWriter.Create().
112                 public static XmlDictionaryWriter CreateTextWriter (
113                         Stream stream, Encoding encoding, bool ownsStream)
114                 {
115                         if (stream == null)
116                                 throw new ArgumentNullException ("stream");
117                         if (encoding == null)
118                                 throw new ArgumentNullException ("encoding");
119
120                         switch (encoding.CodePage) {
121                         case 1200:
122                         case 1201: // utf-16
123                         case 65001: // utf-8
124                                 encoding = utf8_unmarked;
125                                 break;
126                         default:
127                                 throw new XmlException (String.Format ("XML declaration is required for encoding code page {0} but this XmlWriter does not support XML declaration.", encoding.CodePage));
128                         }
129
130                         XmlWriterSettings s = new XmlWriterSettings ();
131                         s.Encoding = encoding;
132                         s.CloseOutput = ownsStream;
133                         s.OmitXmlDeclaration = true;
134                         return CreateDictionaryWriter (XmlWriter.Create (stream, s));
135                 }
136
137                 
138
139                 public virtual void EndCanonicalization ()
140                 {
141                         throw new NotSupportedException ();
142                 }
143
144                 public virtual void StartCanonicalization (
145                         Stream stream, bool includeComments,
146                         string [] inclusivePrefixes)
147                 {
148                         throw new NotSupportedException ();
149                 }
150
151                 public void WriteAttributeString (
152                         XmlDictionaryString localName,
153                         XmlDictionaryString namespaceUri,
154                         string value)
155                 {
156                         WriteAttributeString (null, localName, namespaceUri, value);
157                 }
158
159                 public void WriteAttributeString (string prefix,
160                         XmlDictionaryString localName,
161                         XmlDictionaryString namespaceUri,
162                         string value)
163                 {
164                         WriteStartAttribute (prefix, localName, namespaceUri);
165                         WriteString (value);
166                         WriteEndAttribute ();
167                 }
168
169                 public void WriteElementString (
170                         XmlDictionaryString localName,
171                         XmlDictionaryString namespaceUri,
172                         string value)
173                 {
174                         WriteElementString (null, localName, namespaceUri, value);
175                 }
176
177                 public void WriteElementString (string prefix,
178                         XmlDictionaryString localName,
179                         XmlDictionaryString namespaceUri,
180                         string value)
181                 {
182                         WriteStartElement (prefix, localName, namespaceUri);
183                         WriteString (value);
184                         WriteEndElement ();
185                 }
186
187                 public virtual void WriteNode (XmlDictionaryReader reader,
188                         bool defattr)
189                 {
190                         if (reader == null)
191                                 throw new ArgumentNullException ("reader");
192
193                         if (reader.ReadState == ReadState.Initial)
194                                 reader.Read ();
195                         
196                         switch (reader.NodeType) {
197                         case XmlNodeType.Element:
198                                 // gratuitously copied from System.XML/System.Xml/XmlWriter.cs:WriteNode(XmlReader,bool)
199                                 // as there doesn't seem to be a way to hook into attribute writing w/o handling Element.
200                                 XmlDictionaryString ename, ens;
201                                 if (reader.TryGetLocalNameAsDictionaryString (out ename) && reader.TryGetLocalNameAsDictionaryString (out ens))
202                                         WriteStartElement (reader.Prefix, ename, ens);
203                                 else
204                                         WriteStartElement (reader.Prefix, reader.LocalName, reader.NamespaceURI);
205                                 // Well, I found that MS.NET took this way, since
206                                 // there was a error-prone SgmlReader that fails
207                                 // MoveToNextAttribute().
208                                 if (reader.HasAttributes) {
209                                         for (int i = 0; i < reader.AttributeCount; i++) {
210                                                 reader.MoveToAttribute (i);
211                                                 WriteAttribute (reader, defattr);
212                                         }
213                                         reader.MoveToElement ();
214                                 }
215                                 if (reader.IsEmptyElement)
216                                         WriteEndElement ();
217                                 else {
218                                         int depth = reader.Depth;
219                                         reader.Read ();
220                                         if (reader.NodeType != XmlNodeType.EndElement) {
221                                                 do {
222                                                         WriteNode (reader, defattr);
223                                                 } while (depth < reader.Depth);
224                                         }
225                                         WriteFullEndElement ();
226                                 }
227                                 reader.Read ();
228                                 break;
229                         case XmlNodeType.Attribute:
230                         case XmlNodeType.Text:
231                                 WriteTextNode (reader, defattr);
232                                 break;
233                         default:
234                                 base.WriteNode (reader, defattr);
235                                 break;
236                         }
237                 }
238
239                 private void WriteAttribute (XmlDictionaryReader reader, bool defattr)
240                 {
241                         if (!defattr && reader.IsDefault)
242                                 return;
243
244                         XmlDictionaryString name, ns;
245                         if (reader.TryGetLocalNameAsDictionaryString (out name) && reader.TryGetLocalNameAsDictionaryString (out ns))
246                                 WriteStartAttribute (reader.Prefix, name, ns);
247                         else
248                                 WriteStartAttribute (reader.Prefix, reader.LocalName, reader.NamespaceURI);
249 #if NET_2_1
250                         // no ReadAttributeValue() in 2.1 profile.
251                         WriteTextNode (reader, true);
252 #else
253                         while (reader.ReadAttributeValue ()) {
254                                 switch (reader.NodeType) {
255                                 case XmlNodeType.Text:
256                                         WriteTextNode (reader, true);
257                                         break;
258                                 case XmlNodeType.EntityReference:
259                                         WriteEntityRef (reader.Name);
260                                         break;
261                                 }
262                         }
263 #endif
264                         WriteEndAttribute ();
265                 }
266
267                 public override void WriteNode (XmlReader reader, bool defattr)
268                 {
269                         if (reader == null)
270                                 throw new ArgumentNullException ("reader");
271
272                         XmlDictionaryReader dr = reader as XmlDictionaryReader;
273                         if (dr != null)
274                                 WriteNode (dr, defattr);
275                         else
276                                 base.WriteNode (reader, defattr);
277                 }
278
279                 public virtual void WriteQualifiedName (
280                         XmlDictionaryString localName,
281                         XmlDictionaryString namespaceUri)
282                 {
283                         WriteQualifiedName (localName.Value, namespaceUri.Value);
284                 }
285
286                 public void WriteStartAttribute (
287                         XmlDictionaryString localName,
288                         XmlDictionaryString namespaceUri)
289                 {
290                         WriteStartAttribute (localName.Value, namespaceUri.Value);
291                 }
292
293                 public virtual void WriteStartAttribute (string prefix,
294                         XmlDictionaryString localName,
295                         XmlDictionaryString namespaceUri)
296                 {
297                         WriteStartAttribute (prefix, localName.Value, namespaceUri.Value);
298                 }
299
300                 public void WriteStartElement (
301                         XmlDictionaryString localName,
302                         XmlDictionaryString namespaceUri)
303                 {
304                         WriteStartElement (null, localName, namespaceUri);
305                 }
306
307                 public virtual void WriteStartElement (string prefix,
308                         XmlDictionaryString localName,
309                         XmlDictionaryString namespaceUri)
310                 {
311                         if (localName == null)
312                                 throw new ArgumentException ("localName must not be null.", "localName");
313                         WriteStartElement (prefix, localName.Value,
314                                         namespaceUri != null ? namespaceUri.Value : null);
315                 }
316
317                 public virtual void WriteString (XmlDictionaryString value)
318                 {
319                         WriteString (value.Value);
320                 }
321
322                 protected virtual void WriteTextNode (XmlDictionaryReader reader, bool isAttribute)
323                 {
324                         WriteString (reader.Value);
325                         if (!isAttribute)
326                                 reader.Read ();
327                 }
328
329                 public virtual void WriteValue (Guid guid)
330                 {
331                         WriteString (guid.ToString ());
332                 }
333
334                 public virtual void WriteValue (IStreamProvider value)
335                 {
336                         if (value == null)
337                                 throw new ArgumentNullException ("value");
338
339                         Stream stream = value.GetStream ();
340                         byte[] buf = new byte [Math.Min (2048, stream.CanSeek ? stream.Length : 2048)];
341                         int read;
342                         while ((read = stream.Read (buf, 0, buf.Length)) > 0) {
343                                 WriteBase64 (buf, 0, read);
344                         }
345                         value.ReleaseStream (stream);
346                 }
347
348                 public virtual void WriteValue (TimeSpan duration)
349                 {
350                         WriteString (XmlConvert.ToString (duration));
351                 }
352
353                 public virtual void WriteValue (UniqueId id)
354                 {
355                         if (id == null)
356                                 throw new ArgumentNullException ("id");
357                         WriteString (id.ToString ());
358                 }
359
360                 public virtual void WriteValue (XmlDictionaryString value)
361                 {
362                         WriteValue (value.Value);
363                 }
364
365                 public virtual void WriteXmlAttribute (string localName, string value)
366                 {
367                         WriteAttributeString ("xml", localName, "http://www.w3.org/XML/1998/namespace", value);
368                 }
369
370                 public virtual void WriteXmlAttribute (XmlDictionaryString localName,
371                         XmlDictionaryString value)
372                 {
373                         WriteXmlAttribute (localName.Value, value.Value);
374                 }
375
376                 public virtual void WriteXmlnsAttribute (
377                         string prefix, string namespaceUri)
378                 {
379                         // BTW .NET 2.0 those XmlWriters from XmlWrite.Create()
380                         // rejects namespace overriding i.e.
381                         //
382                         //      xw.WriteStartElement ("foo", "urn:foo");
383                         //      xw.WriteXmlnsAttribute ("foo", "urn:bar");
384                         //
385                         // causes an XmlException. We need fix in sys.xml.dll
386
387                         // When the prefix is null, this writer must mock
388                         // a dummy namespace up. It is then up to the actual
389                         // writer how it is determined in the output. (When
390                         // there is a duplicate, then it will be further 
391                         // modified.)
392                         if (prefix == null && String.IsNullOrEmpty (namespaceUri))
393                                 prefix = String.Empty;
394                         else if (prefix == null)
395                                 prefix = "d" + Depth + "p" + (++NSIndex);
396
397                         if (prefix == String.Empty)
398                                 WriteAttributeString ("xmlns", namespaceUri);
399                         else
400                                 WriteAttributeString ("xmlns", prefix, "http://www.w3.org/2000/xmlns/", namespaceUri);
401                 }
402
403                 public virtual void WriteXmlnsAttribute (string prefix,
404                         XmlDictionaryString namespaceUri)
405                 {
406                         WriteXmlnsAttribute (prefix, namespaceUri.Value);
407                 }
408         }
409 }