You've already forked linux-packaging-mono
Imported Upstream version 4.0.0~alpha1
Former-commit-id: 806294f5ded97629b74c85c09952f2a74fe182d9
This commit is contained in:
425
external/referencesource/System.ServiceModel/System/ServiceModel/Description/PolicyReader.cs
vendored
Normal file
425
external/referencesource/System.ServiceModel/System/ServiceModel/Description/PolicyReader.cs
vendored
Normal file
@ -0,0 +1,425 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//-----------------------------------------------------------------------------
|
||||
namespace System.ServiceModel.Description
|
||||
{
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Xml;
|
||||
using WsdlNS = System.Web.Services.Description;
|
||||
using System.Globalization;
|
||||
|
||||
//
|
||||
// PolicyReader is a complex nested class in the MetadataImporter
|
||||
//
|
||||
public abstract partial class MetadataImporter
|
||||
{
|
||||
internal MetadataImporterQuotas Quotas;
|
||||
|
||||
PolicyReader policyNormalizer = null;
|
||||
|
||||
internal delegate void PolicyWarningHandler(XmlElement contextAssertion, string warningMessage);
|
||||
|
||||
// Consider, [....], make this public?
|
||||
internal event PolicyWarningHandler PolicyWarningOccured;
|
||||
|
||||
internal IEnumerable<IEnumerable<XmlElement>> NormalizePolicy(IEnumerable<XmlElement> policyAssertions)
|
||||
{
|
||||
if (this.policyNormalizer == null)
|
||||
{
|
||||
this.policyNormalizer = new PolicyReader(this);
|
||||
}
|
||||
|
||||
return this.policyNormalizer.NormalizePolicy(policyAssertions);
|
||||
}
|
||||
|
||||
//DevNote: The error handling goal for this class is to NEVER throw an exception.
|
||||
// * Any Ignored Policy should generate a warning
|
||||
// * All policy parsing errors should be logged as warnings in the WSDLImporter.Errors collection.
|
||||
sealed class PolicyReader
|
||||
{
|
||||
int nodesRead = 0;
|
||||
|
||||
readonly MetadataImporter metadataImporter;
|
||||
|
||||
internal PolicyReader(MetadataImporter metadataImporter)
|
||||
{
|
||||
this.metadataImporter = metadataImporter;
|
||||
}
|
||||
|
||||
static IEnumerable<XmlElement> Empty = new PolicyHelper.EmptyEnumerable<XmlElement>();
|
||||
static IEnumerable<IEnumerable<XmlElement>> EmptyEmpty = new PolicyHelper.SingleEnumerable<IEnumerable<XmlElement>>(new PolicyHelper.EmptyEnumerable<XmlElement>());
|
||||
|
||||
//
|
||||
// the core policy reading logic
|
||||
// each step returns a list of lists -- an "and of ors":
|
||||
// each inner list is a policy alternative: it contains the set of assertions that comprise the alternative
|
||||
// the outer list represents the choice between alternatives
|
||||
//
|
||||
|
||||
IEnumerable<IEnumerable<XmlElement>> ReadNode(XmlNode node, XmlElement contextAssertion, YieldLimiter yieldLimiter)
|
||||
{
|
||||
if (nodesRead >= this.metadataImporter.Quotas.MaxPolicyNodes)
|
||||
{
|
||||
if (nodesRead == this.metadataImporter.Quotas.MaxPolicyNodes)
|
||||
{
|
||||
// add wirning once
|
||||
string warningMsg = SR.GetString(SR.ExceededMaxPolicyComplexity, node.Name, PolicyHelper.GetFragmentIdentifier((XmlElement)node));
|
||||
metadataImporter.PolicyWarningOccured.Invoke(contextAssertion, warningMsg);
|
||||
nodesRead++;
|
||||
}
|
||||
return EmptyEmpty;
|
||||
}
|
||||
nodesRead++;
|
||||
IEnumerable<IEnumerable<XmlElement>> nodes = EmptyEmpty;
|
||||
switch (PolicyHelper.GetNodeType(node))
|
||||
{
|
||||
case PolicyHelper.NodeType.Policy:
|
||||
case PolicyHelper.NodeType.All:
|
||||
nodes = ReadNode_PolicyOrAll((XmlElement)node, contextAssertion, yieldLimiter);
|
||||
break;
|
||||
case PolicyHelper.NodeType.ExactlyOne:
|
||||
nodes = ReadNode_ExactlyOne((XmlElement)node, contextAssertion, yieldLimiter);
|
||||
break;
|
||||
case PolicyHelper.NodeType.Assertion:
|
||||
nodes = ReadNode_Assertion((XmlElement)node, yieldLimiter);
|
||||
break;
|
||||
case PolicyHelper.NodeType.PolicyReference:
|
||||
nodes = ReadNode_PolicyReference((XmlElement)node, contextAssertion, yieldLimiter);
|
||||
break;
|
||||
case PolicyHelper.NodeType.UnrecognizedWSPolicy:
|
||||
string warningMsg = SR.GetString(SR.UnrecognizedPolicyElementInNamespace, node.Name, node.NamespaceURI);
|
||||
metadataImporter.PolicyWarningOccured.Invoke(contextAssertion, warningMsg);
|
||||
break;
|
||||
//consider [....], add more error handling here. default?
|
||||
}
|
||||
return nodes;
|
||||
}
|
||||
|
||||
IEnumerable<IEnumerable<XmlElement>> ReadNode_PolicyReference(XmlElement element, XmlElement contextAssertion, YieldLimiter yieldLimiter)
|
||||
{
|
||||
string idRef = element.GetAttribute(MetadataStrings.WSPolicy.Attributes.URI);
|
||||
if (idRef == null)
|
||||
{
|
||||
string warningMsg = SR.GetString(SR.PolicyReferenceMissingURI, MetadataStrings.WSPolicy.Attributes.URI);
|
||||
metadataImporter.PolicyWarningOccured.Invoke(contextAssertion, warningMsg);
|
||||
return EmptyEmpty;
|
||||
}
|
||||
else if (idRef == string.Empty)
|
||||
{
|
||||
string warningMsg = SR.GetString(SR.PolicyReferenceInvalidId);
|
||||
metadataImporter.PolicyWarningOccured.Invoke(contextAssertion, warningMsg);
|
||||
return EmptyEmpty;
|
||||
}
|
||||
|
||||
XmlElement policy = metadataImporter.ResolvePolicyReference(idRef, contextAssertion);
|
||||
if (policy == null)
|
||||
{
|
||||
string warningMsg = SR.GetString(SR.UnableToFindPolicyWithId, idRef);
|
||||
metadataImporter.PolicyWarningOccured.Invoke(contextAssertion, warningMsg);
|
||||
return EmptyEmpty;
|
||||
}
|
||||
|
||||
//
|
||||
// Since we looked up a reference, the context assertion changes.
|
||||
//
|
||||
return ReadNode_PolicyOrAll(policy, policy, yieldLimiter);
|
||||
|
||||
}
|
||||
|
||||
IEnumerable<IEnumerable<XmlElement>> ReadNode_Assertion(XmlElement element, YieldLimiter yieldLimiter)
|
||||
{
|
||||
if (yieldLimiter.IncrementAndLogIfExceededLimit())
|
||||
yield return Empty;
|
||||
else
|
||||
yield return new PolicyHelper.SingleEnumerable<XmlElement>(element);
|
||||
}
|
||||
|
||||
IEnumerable<IEnumerable<XmlElement>> ReadNode_ExactlyOne(XmlElement element, XmlElement contextAssertion, YieldLimiter yieldLimiter)
|
||||
{
|
||||
foreach (XmlNode child in element.ChildNodes)
|
||||
{
|
||||
if (child.NodeType == XmlNodeType.Element)
|
||||
{
|
||||
foreach (IEnumerable<XmlElement> alternative in ReadNode(child, contextAssertion, yieldLimiter))
|
||||
{
|
||||
if (yieldLimiter.IncrementAndLogIfExceededLimit())
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
else
|
||||
{
|
||||
yield return alternative;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerable<IEnumerable<XmlElement>> ReadNode_PolicyOrAll(XmlElement element, XmlElement contextAssertion, YieldLimiter yieldLimiter)
|
||||
{
|
||||
IEnumerable<IEnumerable<XmlElement>> target = EmptyEmpty;
|
||||
|
||||
foreach (XmlNode child in element.ChildNodes)
|
||||
{
|
||||
if (child.NodeType == XmlNodeType.Element)
|
||||
{
|
||||
IEnumerable<IEnumerable<XmlElement>> childPolicy = ReadNode(child, contextAssertion, yieldLimiter);
|
||||
target = PolicyHelper.CrossProduct<XmlElement>(target, childPolicy, yieldLimiter);
|
||||
}
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
internal IEnumerable<IEnumerable<XmlElement>> NormalizePolicy(IEnumerable<XmlElement> policyAssertions)
|
||||
{
|
||||
IEnumerable<IEnumerable<XmlElement>> target = EmptyEmpty;
|
||||
YieldLimiter yieldLimiter = new YieldLimiter(this.metadataImporter.Quotas.MaxYields, this.metadataImporter);
|
||||
foreach (XmlElement child in policyAssertions)
|
||||
{
|
||||
IEnumerable<IEnumerable<XmlElement>> childPolicy = ReadNode(child, child, yieldLimiter);
|
||||
target = PolicyHelper.CrossProduct<XmlElement>(target, childPolicy, yieldLimiter);
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
}
|
||||
|
||||
internal class YieldLimiter
|
||||
{
|
||||
int maxYields;
|
||||
int yieldsHit;
|
||||
readonly MetadataImporter metadataImporter;
|
||||
|
||||
internal YieldLimiter(int maxYields, MetadataImporter metadataImporter)
|
||||
{
|
||||
this.metadataImporter = metadataImporter;
|
||||
this.yieldsHit = 0;
|
||||
this.maxYields = maxYields;
|
||||
}
|
||||
|
||||
internal bool IncrementAndLogIfExceededLimit()
|
||||
{
|
||||
if (++yieldsHit > maxYields)
|
||||
{
|
||||
string warningMsg = SR.GetString(SR.ExceededMaxPolicySize);
|
||||
metadataImporter.PolicyWarningOccured.Invoke(null, warningMsg);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static class PolicyHelper
|
||||
{
|
||||
|
||||
|
||||
internal static string GetFragmentIdentifier(XmlElement element)
|
||||
{
|
||||
string id = element.GetAttribute(MetadataStrings.Wsu.Attributes.Id, MetadataStrings.Wsu.NamespaceUri);
|
||||
|
||||
if (id == null)
|
||||
{
|
||||
id = element.GetAttribute(MetadataStrings.Xml.Attributes.Id, MetadataStrings.Xml.NamespaceUri);
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(id))
|
||||
return string.Empty;
|
||||
else
|
||||
return string.Format(CultureInfo.InvariantCulture, "#{0}", id);
|
||||
}
|
||||
|
||||
internal static bool IsPolicyURIs(XmlAttribute attribute)
|
||||
{
|
||||
return ((attribute.NamespaceURI == MetadataStrings.WSPolicy.NamespaceUri
|
||||
|| attribute.NamespaceURI == MetadataStrings.WSPolicy.NamespaceUri15)
|
||||
&& attribute.LocalName == MetadataStrings.WSPolicy.Attributes.PolicyURIs);
|
||||
}
|
||||
|
||||
internal static NodeType GetNodeType(XmlNode node)
|
||||
{
|
||||
XmlElement currentElement = node as XmlElement;
|
||||
|
||||
if (currentElement == null)
|
||||
return PolicyHelper.NodeType.NonElement;
|
||||
|
||||
if (currentElement.NamespaceURI != MetadataStrings.WSPolicy.NamespaceUri
|
||||
&& currentElement.NamespaceURI != MetadataStrings.WSPolicy.NamespaceUri15)
|
||||
return NodeType.Assertion;
|
||||
else if (currentElement.LocalName == MetadataStrings.WSPolicy.Elements.Policy)
|
||||
return NodeType.Policy;
|
||||
else if (currentElement.LocalName == MetadataStrings.WSPolicy.Elements.All)
|
||||
return NodeType.All;
|
||||
else if (currentElement.LocalName == MetadataStrings.WSPolicy.Elements.ExactlyOne)
|
||||
return NodeType.ExactlyOne;
|
||||
else if (currentElement.LocalName == MetadataStrings.WSPolicy.Elements.PolicyReference)
|
||||
return NodeType.PolicyReference;
|
||||
else
|
||||
return PolicyHelper.NodeType.UnrecognizedWSPolicy;
|
||||
}
|
||||
|
||||
//
|
||||
// some helpers for dealing with ands of ors
|
||||
//
|
||||
|
||||
internal static IEnumerable<IEnumerable<T>> CrossProduct<T>(IEnumerable<IEnumerable<T>> xs, IEnumerable<IEnumerable<T>> ys, YieldLimiter yieldLimiter)
|
||||
{
|
||||
foreach (IEnumerable<T> x in AtLeastOne<T>(xs, yieldLimiter))
|
||||
{
|
||||
foreach (IEnumerable<T> y in AtLeastOne<T>(ys, yieldLimiter))
|
||||
{
|
||||
if (yieldLimiter.IncrementAndLogIfExceededLimit())
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
else
|
||||
{
|
||||
yield return Merge<T>(x, y, yieldLimiter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static IEnumerable<IEnumerable<T>> AtLeastOne<T>(IEnumerable<IEnumerable<T>> xs, YieldLimiter yieldLimiter)
|
||||
{
|
||||
bool gotOne = false;
|
||||
foreach (IEnumerable<T> x in xs)
|
||||
{
|
||||
gotOne = true;
|
||||
|
||||
if (yieldLimiter.IncrementAndLogIfExceededLimit())
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
else
|
||||
{
|
||||
yield return x;
|
||||
}
|
||||
}
|
||||
if (!gotOne)
|
||||
{
|
||||
if (yieldLimiter.IncrementAndLogIfExceededLimit())
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
else
|
||||
{
|
||||
yield return new EmptyEnumerable<T>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static IEnumerable<T> Merge<T>(IEnumerable<T> e1, IEnumerable<T> e2, YieldLimiter yieldLimiter)
|
||||
{
|
||||
foreach (T t1 in e1)
|
||||
{
|
||||
if (yieldLimiter.IncrementAndLogIfExceededLimit())
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
else
|
||||
{
|
||||
yield return t1;
|
||||
}
|
||||
|
||||
}
|
||||
foreach (T t2 in e2)
|
||||
{
|
||||
if (yieldLimiter.IncrementAndLogIfExceededLimit())
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
else
|
||||
{
|
||||
yield return t2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// some helper enumerators
|
||||
//
|
||||
|
||||
internal class EmptyEnumerable<T> : IEnumerable<T>, IEnumerator<T>
|
||||
{
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return this.GetEnumerator();
|
||||
}
|
||||
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
object IEnumerator.Current
|
||||
{
|
||||
get { return this.Current; }
|
||||
}
|
||||
|
||||
public T Current
|
||||
{
|
||||
get
|
||||
{
|
||||
#pragma warning suppress 56503 // [....], IEnumerator guidelines, Current throws exception before calling MoveNext
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.NoValue0)));
|
||||
}
|
||||
}
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
void IEnumerator.Reset()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
internal class SingleEnumerable<T> : IEnumerable<T>
|
||||
{
|
||||
T value;
|
||||
|
||||
internal SingleEnumerable(T value)
|
||||
{
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return this.GetEnumerator();
|
||||
}
|
||||
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
yield return this.value;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// the NodeType enum
|
||||
//
|
||||
internal enum NodeType
|
||||
{
|
||||
NonElement,
|
||||
Policy,
|
||||
All,
|
||||
ExactlyOne,
|
||||
Assertion,
|
||||
PolicyReference,
|
||||
UnrecognizedWSPolicy,
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user