* BuildEngine.cs (BuildProjectFile): Use AddProperty method to specify
[mono.git] / mcs / class / System.XML / System.Xml / XmlTextReader2.cs
1 //
2 // System.Xml.XmlTextReader2.cs - XmlTextReader for .NET 2.0
3 //
4 // Author:
5 //   Atsushi Enomoto  (ginga@kit.hi-ho.ne.jp)
6 //
7 // Copyright (C) 2004-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
29 #if NET_2_0
30
31 using XmlTextReaderImpl = Mono.Xml2.XmlTextReader;
32
33 using System.Collections.Generic;
34 using System.Globalization;
35 using System.IO;
36 using System.Security.Permissions;
37 using System.Text;
38 using System.Xml.Schema;
39 using Mono.Xml;
40
41 namespace System.Xml
42 {
43         // FIXME: this implementation requires somewhat significant change
44         // to expand entities and merge sequential text and entity references
45         // especially to handle whitespace-only entities (such as bug #372839).
46         //
47         // To do it, we have to read ahead the next node when the input is
48         // text, whitespace or significant whitespace and check if the next
49         // node is EntityReference. If it is entref, then it have to merge
50         // the input entity if it is a text.
51         //
52         // This "read ahead" operation may result in proceeding to the next
53         // element, which badly affects IXmlNamespaceResolverimplementation.
54         // So we cannot fix this in simple way.
55
56         [PermissionSet (SecurityAction.InheritanceDemand, Unrestricted = true)]
57         public class XmlTextReader : XmlReader,
58                 IXmlLineInfo, IXmlNamespaceResolver, IHasXmlParserContext
59         {
60                 XmlTextReader entity;
61                 XmlTextReaderImpl source; // dtd2xsd expects this field's existence.
62                 bool entityInsideAttribute;
63                 bool insideAttribute;
64                 Stack<string> entityNameStack;
65
66                 protected XmlTextReader ()
67                 {
68                 }
69
70                 public XmlTextReader (Stream input)
71                         : this (new XmlStreamReader (input))
72                 {
73                 }
74
75                 public XmlTextReader (string url)
76                         : this(url, new NameTable ())
77                 {
78                 }
79
80                 public XmlTextReader (TextReader input)
81                         : this (input, new NameTable ())
82                 {
83                 }
84
85                 protected XmlTextReader (XmlNameTable nt)
86                         : this (String.Empty, XmlNodeType.Element, null)
87                 {
88                 }
89
90                 public XmlTextReader (Stream input, XmlNameTable nt)
91                         : this(new XmlStreamReader (input), nt)
92                 {
93                 }
94
95                 public XmlTextReader (string url, Stream input)
96                         : this (url, new XmlStreamReader (input))
97                 {
98                 }
99
100                 public XmlTextReader (string url, TextReader input)
101                         : this (url, input, new NameTable ())
102                 {
103                 }
104
105                 public XmlTextReader (string url, XmlNameTable nt)
106                 {
107                         source = new XmlTextReaderImpl (url, nt);
108                 }
109
110                 public XmlTextReader (TextReader input, XmlNameTable nt)
111                         : this (String.Empty, input, nt)
112                 {
113                 }
114
115                 public XmlTextReader (Stream xmlFragment, XmlNodeType fragType, XmlParserContext context)
116                 {
117                         source = new XmlTextReaderImpl (xmlFragment, fragType, context);
118                 }
119
120                 public XmlTextReader (string url, Stream input, XmlNameTable nt)
121                         : this (url, new XmlStreamReader (input), nt)
122                 {
123                 }
124
125                 public XmlTextReader (string url, TextReader input, XmlNameTable nt)
126                 {
127                         source = new XmlTextReaderImpl (url, input, nt);
128                 }
129
130                 public XmlTextReader (string xmlFragment, XmlNodeType fragType, XmlParserContext context)
131                 {
132                         source = new XmlTextReaderImpl (xmlFragment, fragType, context);
133                 }
134
135                 internal XmlTextReader (string baseURI, TextReader xmlFragment, XmlNodeType fragType)
136                 {
137                         source = new XmlTextReaderImpl (baseURI, xmlFragment, fragType);
138                 }
139
140                 internal XmlTextReader (string baseURI, TextReader xmlFragment, XmlNodeType fragType, XmlParserContext context)
141                 {
142                         source = new XmlTextReaderImpl (baseURI, xmlFragment, fragType, context);
143                 }
144
145                 internal XmlTextReader (bool dummy, XmlResolver resolver, string url, XmlNodeType fragType, XmlParserContext context)
146                 {
147                         source = new XmlTextReaderImpl (dummy, resolver, url, fragType, context);
148                 }
149
150                 private XmlTextReader (XmlTextReaderImpl entityContainer, bool insideAttribute)
151                 {
152                         source = entityContainer;
153                         this.entityInsideAttribute = insideAttribute;
154                 }
155
156                 #region Properties
157
158                 private XmlReader Current {
159                         get { return entity != null && entity.ReadState != ReadState.Initial ? (XmlReader) entity : source; }
160                 }
161
162                 public override int AttributeCount {
163                         get { return Current.AttributeCount; }
164                 }
165
166                 public override string BaseURI {
167                         get { return Current.BaseURI; }
168                 }
169
170                 public override bool CanReadBinaryContent {
171                         get { return true; }
172                 }
173
174                 public override bool CanReadValueChunk {
175                         get { return true; }
176                 }
177
178                 public override bool CanResolveEntity {
179                         get { return true; }
180                 }
181
182                 public override int Depth {
183                         get {
184                                 // On EndEntity, depth is the same as that 
185                                 // of EntityReference.
186                                 if (entity != null && entity.ReadState == ReadState.Interactive)
187                                         return source.Depth + entity.Depth + 1;
188                                 else
189                                         return source.Depth;
190                         }
191                 }
192
193                 public override bool EOF {
194                         get { return source.EOF; }
195                 }
196
197 #if !NET_2_1
198                 public override bool HasValue {
199                         get { return Current.HasValue; }
200                 }
201 #endif
202
203                 public override bool IsDefault {
204                         get { return Current.IsDefault; }
205                 }
206
207                 public override bool IsEmptyElement {
208                         get { return Current.IsEmptyElement; }
209                 }
210
211                 public override string LocalName {
212                         get { return Current.LocalName; }
213                 }
214
215                 public override string Name {
216                         get { return Current.Name; }
217                 }
218
219                 public override string NamespaceURI {
220                         get { return Current.NamespaceURI; }
221                 }
222
223                 public override XmlNameTable NameTable {
224                         get { return Current.NameTable; }
225                 }
226
227                 public override XmlNodeType NodeType {
228                         get {
229                                 if (entity != null)
230                                         return entity.ReadState == ReadState.Initial ?
231                                                 source.NodeType :
232                                                 entity.EOF ? XmlNodeType.EndEntity :
233                                                 entity.NodeType;
234                                 else
235                                         return source.NodeType;
236                         }
237                 }
238
239                 internal XmlParserContext ParserContext {
240                         get { return ((IHasXmlParserContext) Current).ParserContext; }
241                 }
242
243                 XmlParserContext IHasXmlParserContext.ParserContext {
244                         get { return this.ParserContext; }
245                 }
246
247                 public override string Prefix {
248                         get { return Current.Prefix; }
249                 }
250
251                 public override char QuoteChar {
252                         get { return Current.QuoteChar; }
253                 }
254
255                 public override ReadState ReadState {
256                         get { return entity != null ? ReadState.Interactive : source.ReadState; }
257                 }
258
259                 public override XmlReaderSettings Settings {
260                         get { return base.Settings; }
261                 }
262
263                 public override string Value {
264                         get { return Current.Value; }
265                 }
266
267                 public override string XmlLang {
268                         get { return Current.XmlLang; }
269                 }
270
271                 public override XmlSpace XmlSpace {
272                         get { return Current.XmlSpace; }
273                 }
274
275                 // non-overrides
276
277                 internal bool CharacterChecking {
278                         get {
279                                 if (entity != null)
280                                         return entity.CharacterChecking;
281                                 else
282                                         return source.CharacterChecking;
283                         }
284                         set {
285                                 if (entity != null)
286                                         entity.CharacterChecking = value;
287                                 source.CharacterChecking = value;
288                         }
289                 }
290
291                 internal bool CloseInput {
292                         get {
293                                 if (entity != null)
294                                         return entity.CloseInput;
295                                 else
296                                         return source.CloseInput;
297                         }
298                         set {
299                                 if (entity != null)
300                                         entity.CloseInput = value;
301                                 source.CloseInput = value;
302                         }
303                 }
304
305                 internal ConformanceLevel Conformance {
306                         get { return source.Conformance; }
307                         set {
308                                 if (entity != null)
309                                         entity.Conformance = value;
310                                 source.Conformance = value;
311                         }
312                 }
313
314                 internal XmlResolver Resolver {
315                         get { return source.Resolver; }
316                 }
317
318                 private void CopyProperties (XmlTextReader other)
319                 {
320                         CharacterChecking = other.CharacterChecking;
321                         CloseInput = other.CloseInput;
322                         if (other.Settings != null)
323                                 Conformance = other.Settings.ConformanceLevel;
324                         XmlResolver = other.Resolver;
325                 }
326
327                 // public members
328
329                 public Encoding Encoding {
330                         get {
331                                 if (entity != null)
332                                         return entity.Encoding;
333                                 else
334                                         return source.Encoding;
335                         }
336                 }
337
338                 public EntityHandling EntityHandling {
339                         get { return source.EntityHandling; }
340                         set {
341                                 if (entity != null)
342                                         entity.EntityHandling = value;
343                                 source.EntityHandling = value;
344                         }
345                 }
346
347                 public int LineNumber {
348                         get {
349                                 if (entity != null)
350                                         return entity.LineNumber;
351                                 else
352                                         return source.LineNumber;
353                         }
354                 }
355
356                 public int LinePosition {
357                         get {
358                                 if (entity != null)
359                                         return entity.LinePosition;
360                                 else
361                                         return source.LinePosition;
362                         }
363                 }
364
365                 public bool Namespaces {
366                         get { return source.Namespaces; }
367                         set {
368                                 if (entity != null)
369                                         entity.Namespaces = value;
370                                 source.Namespaces = value;
371                         }
372                 }
373
374                 public bool Normalization {
375                         get { return source.Normalization; }
376                         set {
377                                 if (entity != null)
378                                         entity.Normalization = value;
379                                 source.Normalization = value;
380                         }
381                 }
382
383                 public bool ProhibitDtd {
384                         get { return source.ProhibitDtd; }
385                         set {
386                                 if (entity != null)
387                                         entity.ProhibitDtd = value;
388                                 source.ProhibitDtd = value;
389                         }
390                 }
391
392                 public WhitespaceHandling WhitespaceHandling {
393                         get { return source.WhitespaceHandling; }
394                         set {
395                                 if (entity != null)
396                                         entity.WhitespaceHandling = value;
397                                 source.WhitespaceHandling = value;
398                         }
399                 }
400
401                 public XmlResolver XmlResolver {
402                         set {
403                                 if (entity != null)
404                                         entity.XmlResolver = value;
405                                 source.XmlResolver = value;
406                         }
407                 }
408
409                 #endregion
410
411                 #region Methods
412
413                 internal void AdjustLineInfoOffset (int lineNumberOffset, int linePositionOffset)
414                 {
415                         if (entity != null)
416                                 entity.AdjustLineInfoOffset (lineNumberOffset, linePositionOffset);
417                         source.AdjustLineInfoOffset (lineNumberOffset, linePositionOffset);
418                 }
419
420                 internal void SetNameTable (XmlNameTable nameTable)
421                 {
422                         if (entity != null)
423                                 entity.SetNameTable (nameTable);
424                         source.SetNameTable (nameTable);
425                 }
426
427                 internal void SkipTextDeclaration ()
428                 {
429                         if (entity != null)
430                                 entity.SkipTextDeclaration ();
431                         else
432                                 source.SkipTextDeclaration ();
433                 }
434
435                 // overrides
436
437                 public override void Close ()
438                 {
439                         if (entity != null)
440                                 entity.Close ();
441                         source.Close ();
442                 }
443
444                 public override string GetAttribute (int i)
445                 {
446                         return Current.GetAttribute (i);
447                 }
448
449                 // MS.NET 1.0 msdn says that this method returns String.Empty
450                 // for absent attribute, but in fact it returns null.
451                 // This description is corrected in MS.NET 1.1 msdn.
452                 public override string GetAttribute (string name)
453                 {
454                         return Current.GetAttribute (name);
455                 }
456
457                 public override string GetAttribute (string localName, string namespaceURI)
458                 {
459                         return Current.GetAttribute (localName, namespaceURI);
460                 }
461
462                 public IDictionary<string, string> GetNamespacesInScope (XmlNamespaceScope scope)
463                 {
464                         return ((IXmlNamespaceResolver) Current).GetNamespacesInScope (scope);
465                 }
466
467                 IDictionary<string, string> IXmlNamespaceResolver.GetNamespacesInScope (XmlNamespaceScope scope)
468                 {
469                         return GetNamespacesInScope (scope);
470                 }
471
472                 public override string LookupNamespace (string prefix)
473                 {
474                         return Current.LookupNamespace (prefix);
475                 }
476
477                 string IXmlNamespaceResolver.LookupPrefix (string ns)
478                 {
479                         return ((IXmlNamespaceResolver) Current).LookupPrefix (ns);
480                 }
481
482                 public override void MoveToAttribute (int i)
483                 {
484                         if (entity != null && entityInsideAttribute)
485                                 CloseEntity ();
486                         Current.MoveToAttribute (i);
487                         insideAttribute = true;
488                 }
489
490                 public override bool MoveToAttribute (string name)
491                 {
492                         if (entity != null && !entityInsideAttribute)
493                                 return entity.MoveToAttribute (name);
494                         if (!source.MoveToAttribute (name))
495                                 return false;
496                         if (entity != null && entityInsideAttribute)
497                                 CloseEntity ();
498                         insideAttribute = true;
499                         return true;
500                 }
501
502                 public override bool MoveToAttribute (string localName, string namespaceName)
503                 {
504                         if (entity != null && !entityInsideAttribute)
505                                 return entity.MoveToAttribute (localName, namespaceName);
506                         if (!source.MoveToAttribute (localName, namespaceName))
507                                 return false;
508                         if (entity != null && entityInsideAttribute)
509                                 CloseEntity ();
510                         insideAttribute = true;
511                         return true;
512                 }
513
514                 public override bool MoveToElement ()
515                 {
516                         if (entity != null && entityInsideAttribute)
517                                 CloseEntity ();
518                         if (!Current.MoveToElement ())
519                                 return false;
520                         insideAttribute = false;
521                         return true;
522                 }
523
524                 public override bool MoveToFirstAttribute ()
525                 {
526                         if (entity != null && !entityInsideAttribute)
527                                 return entity.MoveToFirstAttribute ();
528                         if (!source.MoveToFirstAttribute ())
529                                 return false;
530                         if (entity != null && entityInsideAttribute)
531                                 CloseEntity ();
532                         insideAttribute = true;
533                         return true;
534                 }
535
536                 public override bool MoveToNextAttribute ()
537                 {
538                         if (entity != null && !entityInsideAttribute)
539                                 return entity.MoveToNextAttribute ();
540                         if (!source.MoveToNextAttribute ())
541                                 return false;
542                         if (entity != null && entityInsideAttribute)
543                                 CloseEntity ();
544                         insideAttribute = true;
545                         return true;
546                 }
547
548                 public override bool Read ()
549                 {
550                         insideAttribute = false;
551
552                         if (entity != null && (entityInsideAttribute || entity.EOF))
553                                 CloseEntity ();
554                         if (entity != null) {
555                                 if (entity.Read ())
556                                         return true;
557                                 if (EntityHandling == EntityHandling.ExpandEntities) {
558                                         // EndEntity must be skipped
559                                         CloseEntity ();
560                                         return Read ();
561                                 }
562                                 else
563                                         return true; // either success or EndEntity
564                         }
565                         else {
566                                 if (!source.Read ())
567                                         return false;
568                                 if (EntityHandling == EntityHandling.ExpandEntities
569                                         && source.NodeType == XmlNodeType.EntityReference) {
570                                         ResolveEntity ();
571                                         return Read ();
572                                 }
573                                 return true;
574                         }
575                 }
576
577 #if !NET_2_1
578                 public override bool ReadAttributeValue ()
579                 {
580                         if (entity != null && entityInsideAttribute) {
581                                 if (entity.EOF)
582                                         CloseEntity ();
583                                 else {
584                                         entity.Read ();
585                                         return true; // either success or EndEntity
586                                 }
587                         }
588                         return Current.ReadAttributeValue ();
589                 }
590 #endif
591
592                 public override string ReadString ()
593                 {
594                         return base.ReadString ();
595                 }
596
597                 public void ResetState ()
598                 {
599                         if (entity != null)
600                                 CloseEntity ();
601                         source.ResetState ();
602                 }
603
604                 public override
605                 void ResolveEntity ()
606                 {
607                         if (entity != null)
608                                 entity.ResolveEntity ();
609                         else {
610                                 if (source.NodeType != XmlNodeType.EntityReference)
611                                         throw new InvalidOperationException ("The current node is not an Entity Reference");
612                                 XmlTextReaderImpl entReader = null;
613                                 if (ParserContext.Dtd != null)
614                                         entReader = ParserContext.Dtd.GenerateEntityContentReader (source.Name, ParserContext);
615                                 if (entReader == null)
616                                         throw new XmlException (this as IXmlLineInfo, this.BaseURI, String.Format ("Reference to undeclared entity '{0}'.", source.Name));
617                                 if (entityNameStack == null)
618                                         entityNameStack = new Stack<string> ();
619                                 else if (entityNameStack.Contains (Name))
620                                         throw new XmlException (String.Format ("General entity '{0}' has an invalid recursive reference to itself.", Name));
621                                 entityNameStack.Push (Name);
622                                 entity = new XmlTextReader (
623                                         entReader, insideAttribute);
624                                 entity.entityNameStack = entityNameStack;
625                                 entity.CopyProperties (this);
626                         }
627                 }
628
629                 void CloseEntity ()
630                 {
631                         entity.Close ();
632                         entity = null;
633                         entityNameStack.Pop ();
634                 }
635
636                 public override void Skip ()
637                 {
638                         base.Skip ();
639                 }
640
641                 [MonoTODO] // FIXME: Check how expanded entity is handled here.
642                 public TextReader GetRemainder ()
643                 {
644                         if (entity != null) {
645                                 entity.Close ();
646                                 entity = null;
647                                 entityNameStack.Pop ();
648                         }
649                         return source.GetRemainder ();
650                 }
651
652                 public bool HasLineInfo ()
653                 {
654                         return true;
655                 }
656
657                 [MonoTODO] // FIXME: Check how expanded entity is handled here.
658                 public int ReadBase64 (byte [] buffer, int offset, int length)
659                 {
660                         if (entity != null)
661                                 return entity.ReadBase64 (buffer, offset, length);
662                         else
663                                 return source.ReadBase64 (buffer, offset, length);
664                 }
665
666                 [MonoTODO] // FIXME: Check how expanded entity is handled here.
667                 public int ReadBinHex (byte [] buffer, int offset, int length)
668                 {
669                         if (entity != null)
670                                 return entity.ReadBinHex (buffer, offset, length);
671                         else
672                                 return source.ReadBinHex (buffer, offset, length);
673                 }
674
675                 [MonoTODO] // FIXME: Check how expanded entity is handled here.
676                 public int ReadChars (char [] buffer, int offset, int length)
677                 {
678                         if (entity != null)
679                                 return entity.ReadChars (buffer, offset, length);
680                         else
681                                 return source.ReadChars (buffer, offset, length);
682                 }
683
684
685                 [MonoTODO] // FIXME: Check how expanded entity is handled here.
686                 public override int ReadContentAsBase64 (byte [] buffer, int offset, int length)
687                 {
688                         if (entity != null)
689                                 return entity.ReadContentAsBase64 (buffer, offset, length);
690                         else
691                                 return source.ReadContentAsBase64 (buffer, offset, length);
692                 }
693
694                 [MonoTODO] // FIXME: Check how expanded entity is handled here.
695                 public override int ReadContentAsBinHex (byte [] buffer, int offset, int length)
696                 {
697                         if (entity != null)
698                                 return entity.ReadContentAsBinHex (buffer, offset, length);
699                         else
700                                 return source.ReadContentAsBinHex (buffer, offset, length);
701                 }
702
703                 [MonoTODO] // FIXME: Check how expanded entity is handled here.
704                 public override int ReadElementContentAsBase64 (byte [] buffer, int offset, int length)
705                 {
706                         if (entity != null)
707                                 return entity.ReadElementContentAsBase64 (buffer, offset, length);
708                         else
709                                 return source.ReadElementContentAsBase64 (buffer, offset, length);
710                 }
711
712                 [MonoTODO] // FIXME: Check how expanded entity is handled here.
713                 public override int ReadElementContentAsBinHex (byte [] buffer, int offset, int length)
714                 {
715                         if (entity != null)
716                                 return entity.ReadElementContentAsBinHex (buffer, offset, length);
717                         else
718                                 return source.ReadElementContentAsBinHex (buffer, offset, length);
719                 }
720                 #endregion
721         }
722 }
723
724 #endif