|
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------
namespace System.ServiceModel.Channels
{
using System.Runtime;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Dispatcher;
using System.Text;
using System.Xml;
public abstract class AddressHeader
{
ParameterHeader header;
protected AddressHeader()
{
}
internal bool IsReferenceProperty
{
get
{
BufferedAddressHeader bah = this as BufferedAddressHeader;
return bah != null && bah.IsReferencePropertyHeader;
}
}
public abstract string Name { get; }
public abstract string Namespace { get; }
public static AddressHeader CreateAddressHeader(object value)
{
Type type = GetObjectType(value);
return CreateAddressHeader(value, DataContractSerializerDefaults.CreateSerializer(type, int.MaxValue/*maxItems*/));
}
public static AddressHeader CreateAddressHeader(object value, XmlObjectSerializer serializer)
{
if (serializer == null)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("serializer"));
return new XmlObjectSerializerAddressHeader(value, serializer);
}
public static AddressHeader CreateAddressHeader(string name, string ns, object value)
{
return CreateAddressHeader(name, ns, value, DataContractSerializerDefaults.CreateSerializer(GetObjectType(value), name, ns, int.MaxValue/*maxItems*/));
}
internal static AddressHeader CreateAddressHeader(XmlDictionaryString name, XmlDictionaryString ns, object value)
{
return new DictionaryAddressHeader(name, ns, value);
}
public static AddressHeader CreateAddressHeader(string name, string ns, object value, XmlObjectSerializer serializer)
{
if (serializer == null)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("serializer"));
return new XmlObjectSerializerAddressHeader(name, ns, value, serializer);
}
static Type GetObjectType(object value)
{
return (value == null) ? typeof(object) : value.GetType();
}
public override bool Equals(object obj)
{
AddressHeader hdr = obj as AddressHeader;
if (hdr == null)
return false;
StringBuilder builder = new StringBuilder();
string hdr1 = GetComparableForm(builder);
builder.Remove(0, builder.Length);
string hdr2 = hdr.GetComparableForm(builder);
if (hdr1.Length != hdr2.Length)
return false;
if (string.CompareOrdinal(hdr1, hdr2) != 0)
return false;
return true;
}
internal string GetComparableForm()
{
return GetComparableForm(new StringBuilder());
}
internal string GetComparableForm(StringBuilder builder)
{
return EndpointAddressProcessor.GetComparableForm(builder, GetComparableReader());
}
public override int GetHashCode()
{
return GetComparableForm().GetHashCode();
}
public T GetValue<T>()
{
return GetValue<T>(DataContractSerializerDefaults.CreateSerializer(typeof(T), this.Name, this.Namespace, int.MaxValue/*maxItems*/));
}
public T GetValue<T>(XmlObjectSerializer serializer)
{
if (serializer == null)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("serializer"));
using (XmlDictionaryReader reader = GetAddressHeaderReader())
{
if (serializer.IsStartObject(reader))
return (T)serializer.ReadObject(reader);
else
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.ExpectedElementMissing, Name, Namespace)));
}
}
public virtual XmlDictionaryReader GetAddressHeaderReader()
{
XmlBuffer buffer = new XmlBuffer(int.MaxValue);
XmlDictionaryWriter writer = buffer.OpenSection(XmlDictionaryReaderQuotas.Max);
WriteAddressHeader(writer);
buffer.CloseSection();
buffer.Close();
return buffer.GetReader(0);
}
XmlDictionaryReader GetComparableReader()
{
XmlBuffer buffer = new XmlBuffer(int.MaxValue);
XmlDictionaryWriter writer = buffer.OpenSection(XmlDictionaryReaderQuotas.Max);
// WSAddressingAugust2004 does not write the IsReferenceParameter attribute,
// and that's good for a consistent comparable form
ParameterHeader.WriteStartHeader(writer, this, AddressingVersion.WSAddressingAugust2004);
ParameterHeader.WriteHeaderContents(writer, this);
writer.WriteEndElement();
buffer.CloseSection();
buffer.Close();
return buffer.GetReader(0);
}
protected virtual void OnWriteStartAddressHeader(XmlDictionaryWriter writer)
{
writer.WriteStartElement(Name, Namespace);
}
protected abstract void OnWriteAddressHeaderContents(XmlDictionaryWriter writer);
public MessageHeader ToMessageHeader()
{
if (header == null)
header = new ParameterHeader(this);
return header;
}
public void WriteAddressHeader(XmlWriter writer)
{
WriteAddressHeader(XmlDictionaryWriter.CreateDictionaryWriter(writer));
}
public void WriteAddressHeader(XmlDictionaryWriter writer)
{
if (writer == null)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("writer"));
WriteStartAddressHeader(writer);
WriteAddressHeaderContents(writer);
writer.WriteEndElement();
}
public void WriteStartAddressHeader(XmlDictionaryWriter writer)
{
if (writer == null)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("writer"));
OnWriteStartAddressHeader(writer);
}
public void WriteAddressHeaderContents(XmlDictionaryWriter writer)
{
if (writer == null)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("writer"));
OnWriteAddressHeaderContents(writer);
}
class ParameterHeader : MessageHeader
{
AddressHeader parameter;
public override bool IsReferenceParameter
{
get { return true; }
}
public override string Name
{
get { return parameter.Name; }
}
public override string Namespace
{
get { return parameter.Namespace; }
}
public ParameterHeader(AddressHeader parameter)
{
this.parameter = parameter;
}
protected override void OnWriteStartHeader(XmlDictionaryWriter writer, MessageVersion messageVersion)
{
if (messageVersion == null)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("messageVersion"));
WriteStartHeader(writer, parameter, messageVersion.Addressing);
}
protected override void OnWriteHeaderContents(XmlDictionaryWriter writer, MessageVersion messageVersion)
{
WriteHeaderContents(writer, parameter);
}
internal static void WriteStartHeader(XmlDictionaryWriter writer, AddressHeader parameter, AddressingVersion addressingVersion)
{
parameter.WriteStartAddressHeader(writer);
if (addressingVersion == AddressingVersion.WSAddressing10)
{
writer.WriteAttributeString(XD.AddressingDictionary.IsReferenceParameter, XD.Addressing10Dictionary.Namespace, "true");
}
}
internal static void WriteHeaderContents(XmlDictionaryWriter writer, AddressHeader parameter)
{
parameter.WriteAddressHeaderContents(writer);
}
}
class XmlObjectSerializerAddressHeader : AddressHeader
{
XmlObjectSerializer serializer;
object objectToSerialize;
string name;
string ns;
public XmlObjectSerializerAddressHeader(object objectToSerialize, XmlObjectSerializer serializer)
{
this.serializer = serializer;
this.objectToSerialize = objectToSerialize;
Type type = (objectToSerialize == null) ? typeof(object) : objectToSerialize.GetType();
XmlQualifiedName rootName = new XsdDataContractExporter().GetRootElementName(type);
this.name = rootName.Name;
this.ns = rootName.Namespace;
}
public XmlObjectSerializerAddressHeader(string name, string ns, object objectToSerialize, XmlObjectSerializer serializer)
{
if ((null == name) || (name.Length == 0))
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("name"));
}
this.serializer = serializer;
this.objectToSerialize = objectToSerialize;
this.name = name;
this.ns = ns;
}
public override string Name
{
get { return name; }
}
public override string Namespace
{
get { return ns; }
}
object ThisLock
{
get { return this; }
}
protected override void OnWriteAddressHeaderContents(XmlDictionaryWriter writer)
{
lock (ThisLock)
{
serializer.WriteObjectContent(writer, objectToSerialize);
}
}
}
// Microsoft, This will be kept internal for now. If the optimization needs to be public, we'll re-evaluate it.
class DictionaryAddressHeader : XmlObjectSerializerAddressHeader
{
XmlDictionaryString name;
XmlDictionaryString ns;
public DictionaryAddressHeader(XmlDictionaryString name, XmlDictionaryString ns, object value)
: base(name.Value, ns.Value, value, DataContractSerializerDefaults.CreateSerializer(GetObjectType(value), name, ns, int.MaxValue/*maxItems*/))
{
this.name = name;
this.ns = ns;
}
protected override void OnWriteStartAddressHeader(XmlDictionaryWriter writer)
{
writer.WriteStartElement(name, ns);
}
}
}
class BufferedAddressHeader : AddressHeader
{
string name;
string ns;
XmlBuffer buffer;
bool isReferenceProperty;
public BufferedAddressHeader(XmlDictionaryReader reader)
{
buffer = new XmlBuffer(int.MaxValue);
XmlDictionaryWriter writer = buffer.OpenSection(reader.Quotas);
Fx.Assert(reader.NodeType == XmlNodeType.Element, "");
name = reader.LocalName;
ns = reader.NamespaceURI;
Fx.Assert(name != null, "");
Fx.Assert(ns != null, "");
writer.WriteNode(reader, false);
buffer.CloseSection();
buffer.Close();
this.isReferenceProperty = false;
}
public BufferedAddressHeader(XmlDictionaryReader reader, bool isReferenceProperty)
: this(reader)
{
this.isReferenceProperty = isReferenceProperty;
}
public bool IsReferencePropertyHeader { get { return this.isReferenceProperty; } }
public override string Name
{
get { return name; }
}
public override string Namespace
{
get { return ns; }
}
public override XmlDictionaryReader GetAddressHeaderReader()
{
return buffer.GetReader(0);
}
protected override void OnWriteStartAddressHeader(XmlDictionaryWriter writer)
{
XmlDictionaryReader reader = GetAddressHeaderReader();
writer.WriteStartElement(reader.Prefix, reader.LocalName, reader.NamespaceURI);
writer.WriteAttributes(reader, false);
reader.Close();
}
protected override void OnWriteAddressHeaderContents(XmlDictionaryWriter writer)
{
XmlDictionaryReader reader = GetAddressHeaderReader();
reader.ReadStartElement();
while (reader.NodeType != XmlNodeType.EndElement)
writer.WriteNode(reader, false);
reader.ReadEndElement();
reader.Close();
}
}
}
|