// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
+using System.Collections.Generic;
+using System.Linq;
using System.Runtime.Serialization;
using System.Xml;
using System.IO;
namespace System.ServiceModel.Channels
{
- // Apparently Microsoft should have split Message class into
- // two diffferent public classes such as IncomingMessage and
- // OutgoingMessage.
+ internal class AttributeInfo
+ {
+ public string Prefix, Name, Namespace, Value;
+ }
+
+ internal class AttributeCollection : List<AttributeInfo>
+ {
+ public AttributeCollection ()
+ {
+ }
+
+ public AttributeCollection (AttributeCollection copy)
+ : base (copy)
+ {
+ }
+ }
+
internal class XmlReaderMessage : Message
{
MessageVersion version;
MessageProperties properties = new MessageProperties ();
bool is_empty, is_fault, body_started, body_consumed;
int max_headers;
-
- string body;
+ AttributeCollection attributes;
public XmlReaderMessage (MessageVersion version, XmlDictionaryReader reader, int maxSizeOfHeaders)
{
this.max_headers = maxSizeOfHeaders;
ReadEnvelopeStart ();
- // Headers and IsEmpty are consumed at this stage.
- // Body content is not.
- ReadBodyStart ();
-
- StringWriter sw = new StringWriter ();
- using (XmlDictionaryWriter bodyXml = XmlDictionaryWriter.CreateDictionaryWriter (XmlWriter.Create (sw))) {
- while (!reader.EOF && reader.NodeType != XmlNodeType.EndElement)
- bodyXml.WriteNode (reader, false);
- }
- this.body = sw.ToString ();
}
public override MessageHeaders Headers {
public override bool IsEmpty {
get {
- if (!body_started)
- ReadBodyStart ();
+ ReadBodyStart ();
return is_empty;
}
}
public override bool IsFault {
get {
- if (!body_started)
- ReadBodyStart ();
+ ReadBodyStart ();
return is_fault;
}
}
get { return version; }
}
+ protected override MessageBuffer OnCreateBufferedCopy (
+ int maxBufferSize)
+ {
+ ReadBodyStart ();
+ var headers = new MessageHeaders (Headers);
+ var props = new MessageProperties (Properties);
+ return new DefaultMessageBuffer (maxBufferSize, headers, props, new XmlReaderBodyWriter (reader), IsFault, attributes);
+ }
+
protected override string OnGetBodyAttribute (
string localName, string ns)
{
- if (headers == null)
- ReadHeaders ();
- return reader.GetAttribute (localName, ns);
+ ReadBodyStart ();
+ var att = attributes.FirstOrDefault (a => a.Name == localName && a.Namespace == ns);
+ return att != null ? att.Value : null;
}
protected override XmlDictionaryReader OnGetReaderAtBodyContents ()
{
- XmlDictionaryReader newReader = XmlDictionaryReader.CreateDictionaryReader (XmlReader.Create (new StringReader (this.body)));
- newReader.MoveToContent();
- return newReader;
+ if (reader.ReadState == ReadState.Closed)
+ return reader; // silly, but that's what our test expects.
+ ReadBodyStart ();
+ if (is_empty)
+ throw new InvalidOperationException ("The message body is empty.");
+ body_consumed = true;
+ return reader;
}
protected override void OnWriteBodyContents (
string envNS = Version.Envelope.Namespace;
- headers = new MessageHeaders (version, max_headers);
+ headers = new MessageHeaders (version);
if (reader.LocalName != "Header" || reader.NamespaceURI != envNS)
return;
if (isEmptyHeader)
return;
- XmlDocument doc = null;
+ int nHeaders = 0;
while (!reader.EOF && reader.NodeType != XmlNodeType.EndElement) {
- if (doc == null)
- doc = new XmlDocument ();
- XmlElement el = doc.ReadNode (reader) as XmlElement;
- if (el != null)
- headers.Add (MessageHeader.CreateInternalHeader (el, envNS));
+ if (reader.NodeType == XmlNodeType.Element) {
+ if (nHeaders++ == max_headers)
+ throw new InvalidOperationException (String.Format ("Message header size has exceeded the maximum header size {0}", max_headers));
+ headers.Add (new MessageHeader.XmlMessageHeader (reader, Version));
+ }
+ else
+ reader.Skip ();
// FIXME: handle UnderstoodHeaders as well.
reader.MoveToContent ();
}
void ReadBodyStart ()
{
+ if (body_consumed)
+ throw new InvalidOperationException ("The message body XmlReader is already consumed.");
+
+ if (body_started)
+ return;
+
// read headers in advance.
if (headers == null)
ReadHeaders ();
// SOAP Body
body_started = true;
is_empty = reader.IsEmptyElement;
- if (reader.MoveToAttribute ("Id", Constants.WsuNamespace)) {
- BodyId = reader.Value;
+ attributes = new AttributeCollection ();
+ reader.MoveToContent ();
+ if (reader.MoveToFirstAttribute ()) {
+ do {
+ attributes.Add (new AttributeInfo () { Prefix = reader.Prefix, Name = reader.LocalName, Namespace = reader.NamespaceURI, Value = reader.Value});
+ } while (reader.MoveToNextAttribute ());
reader.MoveToElement ();
}
reader.ReadStartElement ("Body", Version.Envelope.Namespace);
is_fault = true;
}
}
+
+ protected override void OnWriteStartBody (
+ XmlDictionaryWriter writer)
+ {
+ ReadBodyStart (); // consume up to attributes
+
+ base.OnWriteStartBody (writer);
+ foreach (var p in attributes)
+ writer.WriteAttributeString (p.Prefix, p.Name, p.Namespace, p.Value);
+ }
}
internal abstract class MessageImplBase : Message
{
MessageHeaders headers;
MessageProperties properties = new MessageProperties ();
+ AttributeCollection attributes;
- public MessageImplBase (MessageVersion version, string action)
+ public MessageImplBase (MessageVersion version, string action, AttributeCollection attributes)
{
headers = new MessageHeaders (version);
if (action != null)
headers.Action = action;
+ this.attributes = attributes;
+ }
+
+ internal AttributeCollection Attributes {
+ get { return attributes; }
}
public override MessageHeaders Headers {
public override MessageVersion Version {
get { return Headers.MessageVersion; }
}
+
+ protected override string OnGetBodyAttribute (
+ string localName, string ns)
+ {
+ var att = attributes.FirstOrDefault (a => a.Name == localName && a.Namespace == ns);
+ return att != null ? att.Value : null;
+ }
+
+ protected override void OnWriteStartBody (
+ XmlDictionaryWriter writer)
+ {
+ var dic = Constants.SoapDictionary;
+ writer.WriteStartElement ("s", dic.Add ("Body"), dic.Add (Version.Envelope.Namespace));
+ foreach (var p in Attributes)
+ writer.WriteAttributeString (p.Prefix, p.Name, p.Namespace, p.Value);
+ }
}
internal class EmptyMessage : MessageImplBase
{
+ static readonly AttributeCollection empty_attributes = new AttributeCollection ();
+
public EmptyMessage (MessageVersion version, string action)
- : base (version, action)
+ : base (version, action, empty_attributes)
{
}
protected override MessageBuffer OnCreateBufferedCopy (
int maxBufferSize)
{
- return new DefaultMessageBuffer (Headers, Properties);
+ return new DefaultMessageBuffer (Headers, Properties, Attributes);
}
}
bool is_fault;
public SimpleMessage (MessageVersion version,
- string action, BodyWriter body, bool isFault)
- : base (version, action)
+ string action, BodyWriter body, bool isFault, AttributeCollection attributes)
+ : base (version, action, attributes)
{
this.body = body;
this.is_fault = isFault;
{
body.WriteBodyContents (writer);
}
+
+ protected override MessageBuffer OnCreateBufferedCopy (
+ int maxBufferSize)
+ {
+ var headers = new MessageHeaders (Headers);
+ var props = new MessageProperties (Properties);
+ var atts = new AttributeCollection (Attributes);
+ return new DefaultMessageBuffer (maxBufferSize, headers, props, body.CreateBufferedCopy (maxBufferSize), IsFault, atts);
+ }
}
}
+