|
//----------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//----------------------------------------------------------------
namespace System.ServiceModel.Discovery
{
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Runtime;
using System.ServiceModel.Description;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Schema;
using SR2 = System.ServiceModel.Discovery.SR;
[Fx.Tag.XamlVisible(false)]
public class FindCriteria
{
[SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)]
public static readonly Uri ScopeMatchByExact = new Uri(ProtocolStrings.VersionInternal.ScopeMatchByExact);
[SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)]
public static readonly Uri ScopeMatchByLdap = new Uri(ProtocolStrings.VersionInternal.ScopeMatchByLdap);
[SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)]
public static readonly Uri ScopeMatchByPrefix = new Uri(ProtocolStrings.VersionInternal.ScopeMatchByPrefix);
[SuppressMessage(FxCop.Category.Naming, FxCop.Rule.IdentifiersShouldBeSpelledCorrectly)]
[SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)]
public static readonly Uri ScopeMatchByUuid = new Uri(ProtocolStrings.VersionInternal.ScopeMatchByUuid);
[SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)]
public static readonly Uri ScopeMatchByNone = new Uri(ProtocolStrings.VersionInternal.ScopeMatchByNone);
ContractTypeNameCollection contractTypeNames;
NonNullItemCollection<XElement> extensions;
Uri scopeMatchBy;
ScopeCollection scopes;
int maxResults;
TimeSpan duration;
public FindCriteria()
{
Initialize(null, DiscoveryDefaults.ScopeMatchBy);
}
public FindCriteria(Type contractType)
{
if (contractType == null)
{
throw FxTrace.Exception.ArgumentNull("contractType");
}
ContractTypeNameCollection contractTypeNamesArg = new ContractTypeNameCollection();
contractTypeNamesArg.Add(GetContractTypeName(contractType));
Initialize(contractTypeNamesArg, DiscoveryDefaults.ScopeMatchBy);
}
public Collection<XmlQualifiedName> ContractTypeNames
{
get
{
if (this.contractTypeNames == null)
{
this.contractTypeNames = new ContractTypeNameCollection();
}
return this.contractTypeNames;
}
}
public Collection<XElement> Extensions
{
get
{
if (this.extensions == null)
{
this.extensions = new NonNullItemCollection<XElement>();
}
return this.extensions;
}
}
public Uri ScopeMatchBy
{
get
{
return this.scopeMatchBy;
}
set
{
if (value == null)
{
throw FxTrace.Exception.ArgumentNull("value");
}
this.scopeMatchBy = value;
}
}
public Collection<Uri> Scopes
{
get
{
if (this.scopes == null)
{
this.scopes = new ScopeCollection();
}
return this.scopes;
}
}
public int MaxResults
{
get
{
return this.maxResults;
}
set
{
if (value <= 0)
{
throw FxTrace.Exception.ArgumentOutOfRange("value", value, SR2.DiscoveryFindMaxResultsLessThanZero);
}
this.maxResults = value;
}
}
public TimeSpan Duration
{
get
{
return this.duration;
}
set
{
if (value.CompareTo(TimeSpan.Zero) <= 0)
{
throw FxTrace.Exception.ArgumentOutOfRange("duration", value, SR2.DiscoveryFindDurationLessThanZero);
}
this.duration = value;
}
}
internal Collection<Uri> InternalScopes
{
get
{
return this.scopes;
}
}
public static FindCriteria CreateMetadataExchangeEndpointCriteria()
{
FindCriteria criteria = new FindCriteria();
criteria.ContractTypeNames.Add(EndpointDiscoveryMetadata.MetadataContractName);
return criteria;
}
public static FindCriteria CreateMetadataExchangeEndpointCriteria(Type contractType)
{
FindCriteria criteria = CreateMetadataExchangeEndpointCriteria();
criteria.Scopes.Add(GetContractTypeNameScope(GetContractTypeName(contractType)));
return criteria;
}
public static FindCriteria CreateMetadataExchangeEndpointCriteria(IEnumerable<XmlQualifiedName> contractTypeNames)
{
if (contractTypeNames == null)
{
throw FxTrace.Exception.ArgumentNull("contractTypeNames");
}
FindCriteria criteria = CreateMetadataExchangeEndpointCriteria();
foreach (XmlQualifiedName item in contractTypeNames)
{
if (item == null)
{
throw FxTrace.Exception.ArgumentNull("item");
}
criteria.Scopes.Add(GetContractTypeNameScope(item));
}
return criteria;
}
public bool IsMatch(EndpointDiscoveryMetadata endpointDiscoveryMetadata)
{
if (endpointDiscoveryMetadata == null)
{
throw FxTrace.Exception.ArgumentNull("endpointDiscoveryMetadata");
}
return IsMatch(endpointDiscoveryMetadata, ScopeCompiler.CompileMatchCriteria(this.scopes, this.scopeMatchBy));
}
internal bool IsMatch(EndpointDiscoveryMetadata endpointDiscoveryMetadata, CompiledScopeCriteria[] compiledScopeMatchCriterias)
{
return (MatchTypes(endpointDiscoveryMetadata, this.contractTypeNames) &&
MatchScopes(endpointDiscoveryMetadata, compiledScopeMatchCriterias, this.scopeMatchBy));
}
static bool MatchTypes(EndpointDiscoveryMetadata endpointDiscoveryMetadata, Collection<XmlQualifiedName> contractTypeNames)
{
if ((contractTypeNames == null) || (contractTypeNames.Count == 0))
{
return true;
}
if ((endpointDiscoveryMetadata.InternalContractTypeNames == null) ||
(endpointDiscoveryMetadata.InternalContractTypeNames.Count == 0))
{
return false;
}
foreach (XmlQualifiedName contractTypeName in contractTypeNames)
{
if (!endpointDiscoveryMetadata.InternalContractTypeNames.Contains(contractTypeName))
{
return false;
}
}
return true;
}
static bool MatchScopes(EndpointDiscoveryMetadata endpointDiscoveryMetadata, CompiledScopeCriteria[] compiledScopeMatchCriterias, Uri scopeMatchBy)
{
if (compiledScopeMatchCriterias == null)
{
if (scopeMatchBy != FindCriteria.ScopeMatchByNone)
{
return true;
}
else
{
// the criteria matches any service with no scopes defined
return endpointDiscoveryMetadata.Scopes.Count == 0;
}
}
if (scopeMatchBy == FindCriteria.ScopeMatchByNone)
{
// if scopeMatchBy is None, the Probe shouldn't have any Scopes defined
return false;
}
string[] compiledScopes;
if (endpointDiscoveryMetadata.IsOpen)
{
compiledScopes = endpointDiscoveryMetadata.CompiledScopes;
}
else
{
compiledScopes = ScopeCompiler.Compile(endpointDiscoveryMetadata.Scopes);
}
if (compiledScopes == null)
{
// non-zero scopes in the criteria, but zero scopes in the metadata
return false;
}
for (int i = 0; i < compiledScopeMatchCriterias.Length; i++)
{
if (!ScopeCompiler.IsMatch(compiledScopeMatchCriterias[i], compiledScopes))
{
return false;
}
}
return true;
}
[Fx.Tag.Throws(typeof(XmlException), "throws on incorrect xml data")]
internal void ReadFrom(DiscoveryVersion discoveryVersion, XmlReader reader)
{
if (discoveryVersion == null)
{
throw FxTrace.Exception.ArgumentNull("discoveryVersion");
}
if (reader == null)
{
throw FxTrace.Exception.ArgumentNull("reader");
}
this.contractTypeNames = null;
this.scopes = null;
this.scopeMatchBy = DiscoveryDefaults.ScopeMatchBy;
this.extensions = null;
this.duration = TimeSpan.MaxValue;
this.maxResults = int.MaxValue;
reader.MoveToContent();
if (reader.IsEmptyElement)
{
reader.Read();
return;
}
int startDepth = reader.Depth;
reader.ReadStartElement();
if (reader.IsStartElement(ProtocolStrings.SchemaNames.TypesElement, discoveryVersion.Namespace))
{
this.contractTypeNames = new ContractTypeNameCollection();
SerializationUtility.ReadContractTypeNames(this.contractTypeNames, reader);
}
if (reader.IsStartElement(ProtocolStrings.SchemaNames.ScopesElement, discoveryVersion.Namespace))
{
this.scopes = new ScopeCollection();
Uri scopeMatchBy = SerializationUtility.ReadScopes(this.scopes, reader);
if (scopeMatchBy != null)
{
this.scopeMatchBy = discoveryVersion.Implementation.ToVersionIndependentScopeMatchBy(scopeMatchBy);
}
}
while (true)
{
reader.MoveToContent();
if ((reader.NodeType == XmlNodeType.EndElement) && (reader.Depth == startDepth))
{
break;
}
else if (reader.IsStartElement(ProtocolStrings.SchemaNames.MaxResultsElement, ProtocolStrings.VersionInternal.Namespace))
{
this.maxResults = SerializationUtility.ReadMaxResults(reader);
}
else if (reader.IsStartElement(ProtocolStrings.SchemaNames.DurationElement, ProtocolStrings.VersionInternal.Namespace))
{
this.duration = SerializationUtility.ReadDuration(reader);
}
else if (reader.IsStartElement())
{
XElement xElement = XElement.ReadFrom(reader) as XElement;
Extensions.Add(xElement);
}
else
{
reader.Read();
}
}
reader.ReadEndElement();
}
internal void WriteTo(DiscoveryVersion discoveryVersion, XmlWriter writer)
{
if (discoveryVersion == null)
{
throw FxTrace.Exception.ArgumentNull("discoveryVersion");
}
if (writer == null)
{
throw FxTrace.Exception.ArgumentNull("writer");
}
SerializationUtility.WriteContractTypeNames(discoveryVersion, this.contractTypeNames, writer);
SerializationUtility.WriteScopes(discoveryVersion, this.scopes, this.scopeMatchBy, writer);
if (this.maxResults != int.MaxValue)
{
writer.WriteElementString(
ProtocolStrings.SchemaNames.MaxResultsElement,
ProtocolStrings.VersionInternal.Namespace,
this.maxResults.ToString(CultureInfo.InvariantCulture));
}
if (this.duration != TimeSpan.MaxValue)
{
writer.WriteElementString(
ProtocolStrings.SchemaNames.DurationElement,
ProtocolStrings.VersionInternal.Namespace,
XmlConvert.ToString(this.Duration));
}
if (this.extensions != null)
{
foreach (XElement xElement in Extensions)
{
xElement.WriteTo(writer);
}
}
}
internal static XmlQualifiedName GetContractTypeName(Type contractType)
{
if (contractType == null)
{
throw FxTrace.Exception.ArgumentNull("contractType");
}
ContractDescription contract = ContractDescription.GetContract(contractType);
return new XmlQualifiedName(contract.Name, contract.Namespace);
}
internal static Uri GetContractTypeNameScope(XmlQualifiedName contractTypeName)
{
Fx.Assert(contractTypeName != null, "The contractTypeName must be non null.");
return new Uri(string.Format(CultureInfo.InvariantCulture, "urn:{0}", contractTypeName.ToString()));
}
internal FindCriteria Clone()
{
FindCriteria findCriteriaClone = new FindCriteria();
foreach (Uri scope in this.Scopes)
{
findCriteriaClone.Scopes.Add(scope);
}
foreach (XmlQualifiedName contractTypeName in this.ContractTypeNames)
{
findCriteriaClone.ContractTypeNames.Add(new XmlQualifiedName(contractTypeName.Name, contractTypeName.Namespace));
}
foreach (XElement extension in this.Extensions)
{
findCriteriaClone.Extensions.Add(new XElement(extension));
}
findCriteriaClone.ScopeMatchBy = this.ScopeMatchBy;
findCriteriaClone.Duration = this.Duration;
findCriteriaClone.MaxResults = this.MaxResults;
return findCriteriaClone;
}
void Initialize(ContractTypeNameCollection contractTypeNames, Uri scopeMatchBy)
{
this.contractTypeNames = contractTypeNames;
this.scopeMatchBy = scopeMatchBy;
this.maxResults = int.MaxValue;
this.duration = DiscoveryDefaults.DiscoveryOperationDuration;
}
}
}
|