479 lines
18 KiB
C#
479 lines
18 KiB
C#
|
//----------------------------------------------------------------
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
//----------------------------------------------------------------
|
||
|
namespace System.ServiceModel.Discovery
|
||
|
{
|
||
|
using System;
|
||
|
using System.Collections.ObjectModel;
|
||
|
using System.Globalization;
|
||
|
using System.Runtime;
|
||
|
using System.Text;
|
||
|
using System.Xml;
|
||
|
using SR2 = System.ServiceModel.Discovery.SR;
|
||
|
|
||
|
static class SerializationUtility
|
||
|
{
|
||
|
static char[] whiteSpaceChars = new char[] { ' ', '\t', '\n', '\r' };
|
||
|
|
||
|
public static XmlQualifiedName ParseQName(string prefixedQName, XmlReader reader)
|
||
|
{
|
||
|
Fx.Assert(prefixedQName != null, "The prefixedQName must be non null.");
|
||
|
Fx.Assert(reader != null, "The reader must be non null.");
|
||
|
int index = prefixedQName.IndexOf(':');
|
||
|
|
||
|
string ns;
|
||
|
string localname;
|
||
|
if (index != -1)
|
||
|
{
|
||
|
string prefix = prefixedQName.Substring(0, index);
|
||
|
ns = reader.LookupNamespace(prefix);
|
||
|
if (ns == null)
|
||
|
{
|
||
|
throw FxTrace.Exception.AsError(new XmlException(SR2.DiscoveryXmlQNamePrefixNotDefined(prefix, prefixedQName)));
|
||
|
}
|
||
|
localname = prefixedQName.Substring(index + 1);
|
||
|
if (localname == string.Empty)
|
||
|
{
|
||
|
throw FxTrace.Exception.AsError(new XmlException(SR2.DiscoveryXmlQNameLocalnameNotDefined(prefixedQName)));
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ns = string.Empty;
|
||
|
localname = prefixedQName;
|
||
|
}
|
||
|
|
||
|
localname = XmlConvert.DecodeName(localname);
|
||
|
return new XmlQualifiedName(localname, ns);
|
||
|
}
|
||
|
|
||
|
public static void ParseQNameList(string listOfQNamesAsString, Collection<XmlQualifiedName> qNameCollection, XmlReader reader)
|
||
|
{
|
||
|
Fx.Assert(listOfQNamesAsString != null, "The listOfQNamesAsString must be non null.");
|
||
|
Fx.Assert(qNameCollection != null, "The qNameCollection must be non null.");
|
||
|
Fx.Assert(reader != null, "The reader must be non null.");
|
||
|
|
||
|
string[] prefixedQNames = listOfQNamesAsString.Split(whiteSpaceChars, StringSplitOptions.RemoveEmptyEntries);
|
||
|
if (prefixedQNames.Length > 0)
|
||
|
{
|
||
|
for (int i = 0; i < prefixedQNames.Length; i++)
|
||
|
{
|
||
|
qNameCollection.Add(ParseQName(prefixedQNames[i], reader));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static void ParseUriList(string listOfUrisAsString, Collection<Uri> uriCollection, UriKind uriKind)
|
||
|
{
|
||
|
Fx.Assert(listOfUrisAsString != null, "The listOfUrisAsString must be non null.");
|
||
|
Fx.Assert(uriCollection != null, "The uriCollection must be non null.");
|
||
|
|
||
|
string[] uriStrings = listOfUrisAsString.Split(whiteSpaceChars, StringSplitOptions.RemoveEmptyEntries);
|
||
|
if (uriStrings.Length > 0)
|
||
|
{
|
||
|
for (int i = 0; i < uriStrings.Length; i++)
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
uriCollection.Add(new Uri(uriStrings[i], uriKind));
|
||
|
}
|
||
|
catch (FormatException fe)
|
||
|
{
|
||
|
if (uriKind == UriKind.Absolute)
|
||
|
{
|
||
|
throw FxTrace.Exception.AsError(new XmlException(SR2.DiscoveryXmlAbsoluteUriFormatError(uriStrings[i]), fe));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
throw FxTrace.Exception.AsError(new XmlException(SR2.DiscoveryXmlUriFormatError(uriStrings[i]), fe));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static long ReadUInt(string uintString, string notFoundExceptionString, string exceptionString)
|
||
|
{
|
||
|
long result;
|
||
|
|
||
|
if (uintString == null)
|
||
|
{
|
||
|
throw FxTrace.Exception.AsError(new XmlException(notFoundExceptionString));
|
||
|
}
|
||
|
|
||
|
try
|
||
|
{
|
||
|
result = XmlConvert.ToUInt32(uintString);
|
||
|
}
|
||
|
catch (FormatException fe)
|
||
|
{
|
||
|
throw FxTrace.Exception.AsError(new XmlException(exceptionString, fe));
|
||
|
}
|
||
|
catch (OverflowException oe)
|
||
|
{
|
||
|
throw FxTrace.Exception.AsError(new XmlException(exceptionString, oe));
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
static void PrepareQNameString(StringBuilder listOfQNamesString, ref bool emptyNsDeclared, ref int prefixCount, XmlWriter writer, XmlQualifiedName qname)
|
||
|
{
|
||
|
string prefix;
|
||
|
string encodedLocalName = XmlConvert.EncodeLocalName(qname.Name.Trim());
|
||
|
if (qname.Namespace.Length == 0)
|
||
|
{
|
||
|
if (!emptyNsDeclared)
|
||
|
{
|
||
|
writer.WriteAttributeString("xmlns", string.Empty, null, string.Empty);
|
||
|
emptyNsDeclared = true;
|
||
|
}
|
||
|
|
||
|
prefix = null;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
prefix = writer.LookupPrefix(qname.Namespace);
|
||
|
if (prefix == null)
|
||
|
{
|
||
|
prefix = "dp" + prefixCount++;
|
||
|
writer.WriteAttributeString("xmlns", prefix, null, qname.Namespace);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!string.IsNullOrEmpty(prefix))
|
||
|
{
|
||
|
listOfQNamesString.AppendFormat(CultureInfo.InvariantCulture, "{0}:{1}", prefix, encodedLocalName);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
listOfQNamesString.AppendFormat(CultureInfo.InvariantCulture, "{0}", encodedLocalName);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static void WriteQName(XmlWriter writer, XmlQualifiedName qname)
|
||
|
{
|
||
|
Fx.Assert(writer != null, "The writer must be non null.");
|
||
|
Fx.Assert(qname != null, "The qnames must be non null.");
|
||
|
|
||
|
StringBuilder qNameString = new StringBuilder();
|
||
|
int prefixCount = 0;
|
||
|
bool emptyNsDeclared = false;
|
||
|
PrepareQNameString(qNameString, ref emptyNsDeclared, ref prefixCount, writer, qname);
|
||
|
writer.WriteString(qNameString.ToString());
|
||
|
}
|
||
|
|
||
|
public static void WriteListOfQNames(XmlWriter writer, Collection<XmlQualifiedName> qnames)
|
||
|
{
|
||
|
Fx.Assert(writer != null, "The writer must be non null.");
|
||
|
Fx.Assert(qnames != null, "The qnames must be non null.");
|
||
|
|
||
|
int prefixCount = 0;
|
||
|
bool emptyNsDeclared = false;
|
||
|
StringBuilder listOfQNamesString = new StringBuilder();
|
||
|
foreach (XmlQualifiedName qname in qnames)
|
||
|
{
|
||
|
if (listOfQNamesString.Length != 0)
|
||
|
{
|
||
|
listOfQNamesString.Append(' ');
|
||
|
}
|
||
|
PrepareQNameString(listOfQNamesString, ref emptyNsDeclared, ref prefixCount, writer, qname);
|
||
|
}
|
||
|
writer.WriteString(listOfQNamesString.ToString());
|
||
|
}
|
||
|
|
||
|
public static void WriteListOfUris(XmlWriter writer, Collection<Uri> uris)
|
||
|
{
|
||
|
Fx.Assert(writer != null, "The writer must be non null.");
|
||
|
Fx.Assert(uris != null, "The uris must be non null.");
|
||
|
|
||
|
if (uris.Count > 0)
|
||
|
{
|
||
|
for (int i = 0; i < uris.Count - 1; i++)
|
||
|
{
|
||
|
writer.WriteString(uris[i].GetComponents(UriComponents.SerializationInfoString, UriFormat.UriEscaped));
|
||
|
writer.WriteWhitespace(" ");
|
||
|
}
|
||
|
|
||
|
writer.WriteString(uris[uris.Count - 1].GetComponents(UriComponents.SerializationInfoString, UriFormat.UriEscaped));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static int ReadMaxResults(XmlReader reader)
|
||
|
{
|
||
|
int maxResults = int.MaxValue;
|
||
|
if (reader.IsEmptyElement)
|
||
|
{
|
||
|
reader.Read();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
reader.ReadStartElement();
|
||
|
maxResults = reader.ReadContentAsInt();
|
||
|
if (maxResults <= 0)
|
||
|
{
|
||
|
throw FxTrace.Exception.AsError(new XmlException(SR2.DiscoveryXmlMaxResultsLessThanZero(maxResults)));
|
||
|
}
|
||
|
reader.ReadEndElement();
|
||
|
}
|
||
|
return maxResults;
|
||
|
}
|
||
|
|
||
|
public static TimeSpan ReadDuration(XmlReader reader)
|
||
|
{
|
||
|
TimeSpan timeout = TimeSpan.MaxValue;
|
||
|
if (reader.IsEmptyElement)
|
||
|
{
|
||
|
reader.Read();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
reader.ReadStartElement();
|
||
|
string timeoutString = reader.ReadString();
|
||
|
timeout = SerializationUtility.ReadTimespan(timeoutString, SR2.DiscoveryXmlDurationDeserializationError(timeoutString));
|
||
|
if (timeout <= TimeSpan.Zero)
|
||
|
{
|
||
|
throw FxTrace.Exception.AsError(new XmlException(SR2.DiscoveryXmlDurationLessThanZero(timeout)));;
|
||
|
}
|
||
|
reader.ReadEndElement();
|
||
|
}
|
||
|
return timeout;
|
||
|
}
|
||
|
|
||
|
public static TimeSpan ReadTimespan(string timespanString, string exceptionString)
|
||
|
{
|
||
|
TimeSpan result;
|
||
|
|
||
|
try
|
||
|
{
|
||
|
result = XmlConvert.ToTimeSpan(timespanString);
|
||
|
}
|
||
|
catch (FormatException fe)
|
||
|
{
|
||
|
throw FxTrace.Exception.AsError(new XmlException(exceptionString, fe));
|
||
|
}
|
||
|
catch (OverflowException oe)
|
||
|
{
|
||
|
throw FxTrace.Exception.AsError(new XmlException(exceptionString, oe));
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
public static EndpointAddress ReadEndpointAddress(DiscoveryVersion discoveryVersion, XmlReader reader)
|
||
|
{
|
||
|
Fx.Assert(discoveryVersion != null, "The discoveryVersion must be non null");
|
||
|
Fx.Assert(reader != null, "The reader must be non null");
|
||
|
|
||
|
if (discoveryVersion == DiscoveryVersion.WSDiscoveryApril2005 || discoveryVersion == DiscoveryVersion.WSDiscoveryCD1)
|
||
|
{
|
||
|
EndpointAddressAugust2004 endpoint = discoveryVersion.Implementation.EprSerializer.ReadObject(reader) as EndpointAddressAugust2004;
|
||
|
if (endpoint == null)
|
||
|
{
|
||
|
throw FxTrace.Exception.AsError(new XmlException(SR2.DiscoveryXmlEndpointNull));
|
||
|
}
|
||
|
return endpoint.ToEndpointAddress();
|
||
|
}
|
||
|
else if (discoveryVersion == DiscoveryVersion.WSDiscovery11)
|
||
|
{
|
||
|
EndpointAddress10 endpoint = discoveryVersion.Implementation.EprSerializer.ReadObject(reader) as EndpointAddress10;
|
||
|
if (endpoint == null)
|
||
|
{
|
||
|
throw FxTrace.Exception.AsError(new XmlException(SR2.DiscoveryXmlEndpointNull));
|
||
|
}
|
||
|
return endpoint.ToEndpointAddress();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Fx.Assert("The discoveryVersion parameter cannot be null.");
|
||
|
return null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static void ReadContractTypeNames(Collection<XmlQualifiedName> contractTypeNames, XmlReader reader)
|
||
|
{
|
||
|
if (reader.IsEmptyElement)
|
||
|
{
|
||
|
reader.Read();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
reader.ReadStartElement();
|
||
|
|
||
|
string listOfQNamesAsStr = reader.ReadString();
|
||
|
if (!string.IsNullOrEmpty(listOfQNamesAsStr))
|
||
|
{
|
||
|
SerializationUtility.ParseQNameList(listOfQNamesAsStr, contractTypeNames, reader);
|
||
|
}
|
||
|
|
||
|
reader.ReadEndElement();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static Uri ReadScopes(Collection<Uri> scopes, XmlReader reader)
|
||
|
{
|
||
|
Uri scopeMatchBy = null;
|
||
|
if (reader.HasAttributes)
|
||
|
{
|
||
|
while (reader.MoveToNextAttribute())
|
||
|
{
|
||
|
if ((reader.NamespaceURI.Length == 0) &&
|
||
|
(reader.Name.Equals(ProtocolStrings.SchemaNames.MatchByAttribute)))
|
||
|
{
|
||
|
string scopeMatchByStr = reader.Value;
|
||
|
try
|
||
|
{
|
||
|
scopeMatchBy = new Uri(scopeMatchByStr, UriKind.RelativeOrAbsolute);
|
||
|
}
|
||
|
catch (FormatException fe)
|
||
|
{
|
||
|
throw FxTrace.Exception.AsError(new XmlException(SR2.DiscoveryXmlUriFormatError(scopeMatchByStr), fe));
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
reader.MoveToElement();
|
||
|
}
|
||
|
|
||
|
if (reader.IsEmptyElement)
|
||
|
{
|
||
|
reader.Read();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
reader.ReadStartElement();
|
||
|
|
||
|
string listOfUrisAsString = reader.ReadString();
|
||
|
if (!string.IsNullOrEmpty(listOfUrisAsString))
|
||
|
{
|
||
|
SerializationUtility.ParseUriList(listOfUrisAsString, scopes, UriKind.Absolute);
|
||
|
}
|
||
|
|
||
|
reader.ReadEndElement();
|
||
|
}
|
||
|
|
||
|
return scopeMatchBy;
|
||
|
}
|
||
|
|
||
|
public static void ReadListenUris(Collection<Uri> listenUris, XmlReader reader)
|
||
|
{
|
||
|
if (reader.IsEmptyElement)
|
||
|
{
|
||
|
reader.Read();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
reader.ReadStartElement();
|
||
|
|
||
|
string listOfUrisAsString = reader.ReadString();
|
||
|
if (!string.IsNullOrEmpty(listOfUrisAsString))
|
||
|
{
|
||
|
SerializationUtility.ParseUriList(listOfUrisAsString, listenUris, UriKind.RelativeOrAbsolute);
|
||
|
}
|
||
|
|
||
|
reader.ReadEndElement();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static int ReadMetadataVersion(XmlReader reader)
|
||
|
{
|
||
|
reader.ReadStartElement();
|
||
|
|
||
|
int metadataVersion = reader.ReadContentAsInt();
|
||
|
|
||
|
if (metadataVersion < 0)
|
||
|
{
|
||
|
throw FxTrace.Exception.AsError(new XmlException(SR2.DiscoveryXmlMetadataVersionLessThanZero(metadataVersion)));
|
||
|
}
|
||
|
|
||
|
reader.ReadEndElement();
|
||
|
|
||
|
return metadataVersion;
|
||
|
}
|
||
|
|
||
|
public static void WriteEndPointAddress(DiscoveryVersion discoveryVersion, EndpointAddress endpointAddress, XmlWriter writer)
|
||
|
{
|
||
|
Fx.Assert(discoveryVersion != null, "The discoveryVersion must be non null");
|
||
|
Fx.Assert(writer != null, "The writer must be non null");
|
||
|
|
||
|
if (discoveryVersion == DiscoveryVersion.WSDiscoveryApril2005 || discoveryVersion == DiscoveryVersion.WSDiscoveryCD1)
|
||
|
{
|
||
|
EndpointAddressAugust2004 endpoint = EndpointAddressAugust2004.FromEndpointAddress(endpointAddress);
|
||
|
discoveryVersion.Implementation.EprSerializer.WriteObject(writer, endpoint);
|
||
|
}
|
||
|
else if (discoveryVersion == DiscoveryVersion.WSDiscovery11)
|
||
|
{
|
||
|
EndpointAddress10 endpoint = EndpointAddress10.FromEndpointAddress(endpointAddress);
|
||
|
discoveryVersion.Implementation.EprSerializer.WriteObject(writer, endpoint);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Fx.Assert("The discoveryVersion parameter cannot be null.");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static void WriteContractTypeNames(DiscoveryVersion discoveryVersion, Collection<XmlQualifiedName> contractTypeNames, XmlWriter writer)
|
||
|
{
|
||
|
if ((contractTypeNames != null) && (contractTypeNames.Count > 0))
|
||
|
{
|
||
|
// using the prefix here allows us to redefine the empty namespace
|
||
|
// for serializing the QNames is required.
|
||
|
writer.WriteStartElement(
|
||
|
ProtocolStrings.SchemaNames.DefaultPrefix,
|
||
|
ProtocolStrings.SchemaNames.TypesElement,
|
||
|
discoveryVersion.Namespace);
|
||
|
SerializationUtility.WriteListOfQNames(writer, contractTypeNames);
|
||
|
writer.WriteEndElement();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static void WriteScopes(DiscoveryVersion discoveryVersion, Collection<Uri> scopes, Uri scopeMatchBy, XmlWriter writer)
|
||
|
{
|
||
|
bool writeScopes = true;
|
||
|
if (scopes == null || scopes.Count == 0)
|
||
|
{
|
||
|
// If there are no scopes defined, we write the Scopes section only if matchBy contract is None.
|
||
|
writeScopes = (scopeMatchBy == FindCriteria.ScopeMatchByNone);
|
||
|
}
|
||
|
|
||
|
if (writeScopes)
|
||
|
{
|
||
|
writer.WriteStartElement(ProtocolStrings.SchemaNames.ScopesElement, discoveryVersion.Namespace);
|
||
|
if (scopeMatchBy != null)
|
||
|
{
|
||
|
Uri versionDependentScopeMatchBy = discoveryVersion.Implementation.ToVersionDependentScopeMatchBy(scopeMatchBy);
|
||
|
writer.WriteAttributeString(
|
||
|
ProtocolStrings.SchemaNames.MatchByAttribute,
|
||
|
string.Empty,
|
||
|
versionDependentScopeMatchBy.GetComponents(UriComponents.SerializationInfoString, UriFormat.UriEscaped));
|
||
|
}
|
||
|
|
||
|
if (scopes != null)
|
||
|
{
|
||
|
SerializationUtility.WriteListOfUris(writer, scopes);
|
||
|
}
|
||
|
|
||
|
writer.WriteEndElement();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static void WriteListenUris(DiscoveryVersion discoveryVersion, Collection<Uri> listenUris, XmlWriter writer)
|
||
|
{
|
||
|
if ((listenUris != null) && (listenUris.Count > 0))
|
||
|
{
|
||
|
writer.WriteStartElement(ProtocolStrings.SchemaNames.XAddrsElement, discoveryVersion.Namespace);
|
||
|
SerializationUtility.WriteListOfUris(writer, listenUris);
|
||
|
writer.WriteEndElement();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static void WriteMetadataVersion(DiscoveryVersion discoveryVersion, int metadataVersion, XmlWriter writer)
|
||
|
{
|
||
|
writer.WriteStartElement(ProtocolStrings.SchemaNames.MetadataVersionElement, discoveryVersion.Namespace);
|
||
|
writer.WriteValue(metadataVersion);
|
||
|
writer.WriteEndElement();
|
||
|
}
|
||
|
}
|
||
|
}
|