|
|
@@ -32,6 +32,7 @@
|
|
|
|
|
|
using System.Xml.Schema;
|
|
|
using System.Xml;
|
|
|
+using System.Collections;
|
|
|
|
|
|
namespace System.Web.Services.Description
|
|
|
{
|
|
|
@@ -83,6 +84,9 @@ namespace System.Web.Services.Description
|
|
|
{
|
|
|
CheckWsdlQName (ctx, value, value.Type);
|
|
|
CheckWsdlQName (ctx, value, value.Element);
|
|
|
+
|
|
|
+ if (value.DefinedByElement && value.Element.Namespace == XmlSchema.Namespace)
|
|
|
+ ctx.ReportRuleViolation (value, BasicProfileRules.R2206);
|
|
|
}
|
|
|
|
|
|
public override void Check (ConformanceCheckContext ctx, Types value)
|
|
|
@@ -94,10 +98,126 @@ namespace System.Web.Services.Description
|
|
|
// TODO: R2113
|
|
|
}
|
|
|
|
|
|
- public override void Check (ConformanceCheckContext ctx, Binding value) { }
|
|
|
- public override void Check (ConformanceCheckContext ctx, MessageBinding value) { }
|
|
|
+ public override void Check (ConformanceCheckContext ctx, Binding value)
|
|
|
+ {
|
|
|
+ SoapBinding sb = (SoapBinding) value.Extensions.Find (typeof(SoapBinding));
|
|
|
+ if (sb == null || sb.Transport == null || sb.Transport == "") {
|
|
|
+ ctx.ReportRuleViolation (value, BasicProfileRules.R2701);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (sb.Transport != "http://schemas.xmlsoap.org/soap/http")
|
|
|
+ ctx.ReportRuleViolation (value, BasicProfileRules.R2702);
|
|
|
+
|
|
|
+ LiteralType type = GetLiteralBindingType (value);
|
|
|
+ if (type == LiteralType.NotLiteral)
|
|
|
+ ctx.ReportRuleViolation (value, BasicProfileRules.R2706);
|
|
|
+ else if (type == LiteralType.Inconsistent)
|
|
|
+ ctx.ReportRuleViolation (value, BasicProfileRules.R2705);
|
|
|
+
|
|
|
+ // Collect all parts referenced from this type
|
|
|
+
|
|
|
+ Hashtable parts = new Hashtable ();
|
|
|
+ PortType port = ctx.Services.GetPortType (value.Type);
|
|
|
+ foreach (Operation op in port.Operations) {
|
|
|
+ foreach (OperationMessage om in op.Messages) {
|
|
|
+ Message msg = ctx.Services.GetMessage (om.Message);
|
|
|
+ foreach (MessagePart part in msg.Parts)
|
|
|
+ parts.Add (part,part);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ foreach (OperationBinding ob in value.Operations) {
|
|
|
+ if (ob.Input != null) CheckMessageBinding (ctx, parts, ob.Input);
|
|
|
+ if (ob.Output != null) CheckMessageBinding (ctx, parts, ob.Output);
|
|
|
+ foreach (FaultBinding fb in ob.Faults)
|
|
|
+ CheckMessageBinding (ctx, parts, fb);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (parts.Count > 0)
|
|
|
+ ctx.ReportRuleViolation (value, BasicProfileRules.R2209);
|
|
|
+ }
|
|
|
+
|
|
|
+ public override void Check (ConformanceCheckContext ctx, OperationBinding ob)
|
|
|
+ {
|
|
|
+ }
|
|
|
+
|
|
|
+ void CheckMessageBinding (ConformanceCheckContext ctx, Hashtable portParts, MessageBinding value)
|
|
|
+ {
|
|
|
+ SoapBodyBinding sbb = (SoapBodyBinding) value.Extensions.Find (typeof(SoapBodyBinding));
|
|
|
+ Message msg = FindMessage (ctx, value);
|
|
|
+ LiteralType bt = GetLiteralBindingType (value.OperationBinding.Binding);
|
|
|
+
|
|
|
+ if (sbb != null)
|
|
|
+ {
|
|
|
+ if (bt == LiteralType.Document)
|
|
|
+ {
|
|
|
+ if (sbb.Parts != null && sbb.Parts.Length > 1)
|
|
|
+ ctx.ReportRuleViolation (value, BasicProfileRules.R2201);
|
|
|
+
|
|
|
+ if (sbb.Parts == null) {
|
|
|
+ if (msg.Parts != null && msg.Parts.Count > 1)
|
|
|
+ ctx.ReportRuleViolation (value, BasicProfileRules.R2210);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ foreach (string part in sbb.Parts) {
|
|
|
+ MessagePart mp = msg.FindPartByName (part);
|
|
|
+ portParts.Remove (mp);
|
|
|
+ if (!mp.DefinedByElement)
|
|
|
+ ctx.ReportRuleViolation (value, BasicProfileRules.R2204);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (bt == LiteralType.Rpc)
|
|
|
+ {
|
|
|
+ if (sbb.Parts != null) {
|
|
|
+ foreach (string part in sbb.Parts) {
|
|
|
+ MessagePart mp = msg.FindPartByName (part);
|
|
|
+ portParts.Remove (mp);
|
|
|
+ if (!mp.DefinedByType)
|
|
|
+ ctx.ReportRuleViolation (value, BasicProfileRules.R2203);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ SoapHeaderBinding shb = (SoapHeaderBinding) value.Extensions.Find (typeof(SoapHeaderBinding));
|
|
|
+ if (shb != null) {
|
|
|
+ Message hm = ctx.Services.GetMessage (shb.Message);
|
|
|
+ MessagePart mp = hm.FindPartByName (shb.Part);
|
|
|
+ portParts.Remove (mp);
|
|
|
+ if (mp != null && !mp.DefinedByElement)
|
|
|
+ ctx.ReportRuleViolation (value, BasicProfileRules.R2205);
|
|
|
+ }
|
|
|
+
|
|
|
+ SoapHeaderFaultBinding shfb = (SoapHeaderFaultBinding) value.Extensions.Find (typeof(SoapHeaderFaultBinding));
|
|
|
+ if (shfb != null) {
|
|
|
+ Message hm = ctx.Services.GetMessage (shfb.Message);
|
|
|
+ MessagePart mp = hm.FindPartByName (shfb.Part);
|
|
|
+ portParts.Remove (mp);
|
|
|
+ if (mp != null && !mp.DefinedByElement)
|
|
|
+ ctx.ReportRuleViolation (value, BasicProfileRules.R2205);
|
|
|
+ }
|
|
|
+
|
|
|
+ // TODO: SoapFaultBinding ??
|
|
|
+ }
|
|
|
+
|
|
|
+ Message FindMessage (ConformanceCheckContext ctx, MessageBinding mb)
|
|
|
+ {
|
|
|
+ PortType pt = ctx.Services.GetPortType (mb.OperationBinding.Binding.Type);
|
|
|
+ foreach (Operation op in pt.Operations)
|
|
|
+ if (op.IsBoundBy (mb.OperationBinding)) {
|
|
|
+ OperationMessage om;
|
|
|
+ if (mb is InputBinding) om = op.Messages.Input;
|
|
|
+ else if (mb is OutputBinding) om = op.Messages.Output;
|
|
|
+ else if (mb is FaultBinding) om = op.Messages.Fault;
|
|
|
+ else return null;
|
|
|
+ return ctx.Services.GetMessage (om.Message);
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
public override void Check (ConformanceCheckContext ctx, Operation value) { }
|
|
|
- public override void Check (ConformanceCheckContext ctx, OperationBinding value) { }
|
|
|
public override void Check (ConformanceCheckContext ctx, OperationMessage value) { }
|
|
|
public override void Check (ConformanceCheckContext ctx, Port value) { }
|
|
|
public override void Check (ConformanceCheckContext ctx, PortType value) { }
|
|
|
@@ -200,7 +320,7 @@ namespace System.Web.Services.Description
|
|
|
void CheckWsdlQName (ConformanceCheckContext ctx, object element, XmlQualifiedName name)
|
|
|
{
|
|
|
if (name == null || name == XmlQualifiedName.Empty) return;
|
|
|
- if (name.Namespace == "") return;
|
|
|
+ if (name.Namespace == "" || name.Namespace == XmlSchema.Namespace) return;
|
|
|
|
|
|
if (ctx.ServiceDescription.Types != null && ctx.ServiceDescription.Types.Schemas != null)
|
|
|
{
|
|
|
@@ -217,7 +337,7 @@ namespace System.Web.Services.Description
|
|
|
void CheckSchemaQName (ConformanceCheckContext ctx, object element, XmlQualifiedName name)
|
|
|
{
|
|
|
if (name == null || name == XmlQualifiedName.Empty) return;
|
|
|
- if (name.Namespace == "") return;
|
|
|
+ if (name.Namespace == "" || name.Namespace == XmlSchema.Namespace) return;
|
|
|
if (ctx.CurrentSchema.TargetNamespace == name.Namespace) return;
|
|
|
|
|
|
foreach (XmlSchemaObject i in ctx.CurrentSchema.Includes)
|
|
|
@@ -225,10 +345,83 @@ namespace System.Web.Services.Description
|
|
|
|
|
|
ctx.ReportRuleViolation (element, BasicProfileRules.R2102);
|
|
|
}
|
|
|
+
|
|
|
+ LiteralType GetLiteralBindingType (Binding b)
|
|
|
+ {
|
|
|
+ SoapBinding sb = (SoapBinding) b.Extensions.Find (typeof(SoapBinding));
|
|
|
+ SoapBindingStyle style = (sb != null) ? sb.Style : SoapBindingStyle.Document;
|
|
|
+ if (style == SoapBindingStyle.Default) style = SoapBindingStyle.Document;
|
|
|
+
|
|
|
+ foreach (OperationBinding ob in b.Operations) {
|
|
|
+ SoapOperationBinding sob = (SoapOperationBinding) ob.Extensions.Find (typeof(SoapOperationBinding));
|
|
|
+ if (sob.Style != SoapBindingStyle.Default && sob.Style != style)
|
|
|
+ return LiteralType.Inconsistent;
|
|
|
+ if (ob.Input != null) {
|
|
|
+ SoapBodyBinding sbb = (SoapBodyBinding) ob.Input.Extensions.Find (typeof(SoapBodyBinding));
|
|
|
+ if (sbb != null && sbb.Use != SoapBindingUse.Literal) return LiteralType.NotLiteral;
|
|
|
+ SoapFaultBinding sfb = (SoapFaultBinding) ob.Input.Extensions.Find (typeof(SoapFaultBinding));
|
|
|
+ if (sfb != null && sfb.Use != SoapBindingUse.Literal) return LiteralType.NotLiteral;
|
|
|
+ SoapHeaderBinding shb = (SoapHeaderBinding) ob.Input.Extensions.Find (typeof(SoapHeaderBinding));
|
|
|
+ if (shb != null && shb.Use != SoapBindingUse.Literal) return LiteralType.NotLiteral;
|
|
|
+ SoapHeaderFaultBinding shfb = (SoapHeaderFaultBinding) ob.Input.Extensions.Find (typeof(SoapHeaderFaultBinding));
|
|
|
+ if (shfb != null && shfb.Use != SoapBindingUse.Literal) return LiteralType.NotLiteral;
|
|
|
+ }
|
|
|
+ if (ob.Output != null) {
|
|
|
+ SoapBodyBinding sbb = (SoapBodyBinding) ob.Output.Extensions.Find (typeof(SoapBodyBinding));
|
|
|
+ if (sbb != null && sbb.Use != SoapBindingUse.Literal) return LiteralType.NotLiteral;
|
|
|
+ SoapFaultBinding sfb = (SoapFaultBinding) ob.Input.Extensions.Find (typeof(SoapFaultBinding));
|
|
|
+ if (sfb != null && sfb.Use != SoapBindingUse.Literal) return LiteralType.NotLiteral;
|
|
|
+ SoapHeaderBinding shb = (SoapHeaderBinding) ob.Input.Extensions.Find (typeof(SoapHeaderBinding));
|
|
|
+ if (shb != null && shb.Use != SoapBindingUse.Literal) return LiteralType.NotLiteral;
|
|
|
+ SoapHeaderFaultBinding shfb = (SoapHeaderFaultBinding) ob.Input.Extensions.Find (typeof(SoapHeaderFaultBinding));
|
|
|
+ if (shfb != null && shfb.Use != SoapBindingUse.Literal) return LiteralType.NotLiteral;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (style == SoapBindingStyle.Document) return LiteralType.Document;
|
|
|
+ else return LiteralType.Rpc;
|
|
|
+ }
|
|
|
+
|
|
|
+ enum LiteralType {
|
|
|
+ NotLiteral,
|
|
|
+ Inconsistent,
|
|
|
+ Rpc,
|
|
|
+ Document
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
internal class BasicProfileRules
|
|
|
{
|
|
|
+
|
|
|
+ // 3.2 Conformance of Services, Consumers and Registries
|
|
|
+
|
|
|
+ // Can't check: R0001
|
|
|
+
|
|
|
+ // 3.3 Conformance Annotation in Descriptions
|
|
|
+
|
|
|
+ // Can't check: R0002, R0003
|
|
|
+
|
|
|
+ // 3.4 Conformance Annotation in Messages
|
|
|
+
|
|
|
+ // Can't check: R0004, R0005, R0006, R0007
|
|
|
+
|
|
|
+ // 3.5 Conformance Annotation in Registry Data
|
|
|
+
|
|
|
+ // UDDI related: R3020, R3030, R3021, R3005, R3004.
|
|
|
+
|
|
|
+ // 4.1 XML Representation of SOAP Messages
|
|
|
+
|
|
|
+ // Rules not related to service description
|
|
|
+
|
|
|
+ // 4.2 SOAP Processing Model
|
|
|
+
|
|
|
+ // Rules not related to service description
|
|
|
+
|
|
|
+ // 4.3 Use of SOAP in HTTP
|
|
|
+
|
|
|
+ // Rules not related to service description
|
|
|
+
|
|
|
+ // 5.1 Document structure
|
|
|
+
|
|
|
public static readonly ConformanceRule R2001 = new ConformanceRule (
|
|
|
"R2001",
|
|
|
"A DESCRIPTION MUST only use the WSDL \"import\" statement to import another WSDL description",
|
|
|
@@ -248,12 +441,14 @@ namespace System.Web.Services.Description
|
|
|
"R2005",
|
|
|
"The targetNamespace attribute on the wsdl:definitions element of a description that is being imported MUST have same the value as the namespace attribute on the wsdl:import element in the importing DESCRIPTION",
|
|
|
"");
|
|
|
-
|
|
|
+
|
|
|
public static readonly ConformanceRule R2026 = new ConformanceRule (
|
|
|
"R2026",
|
|
|
"A DESCRIPTION SHOULD NOT include extension elements with a wsdl:required attribute value of \"true\" on any WSDL construct (wsdl:binding, wsdl:portType, wsdl:message, wsdl:types or wsdl:import) that claims conformance to the Profile",
|
|
|
"");
|
|
|
|
|
|
+ // 5.2 Types
|
|
|
+
|
|
|
public static readonly ConformanceRule R2101 = new ConformanceRule (
|
|
|
"R2101",
|
|
|
"A DESCRIPTION MUST NOT use QName references to elements in namespaces that have been neither imported, nor defined in the referring WSDL document",
|
|
|
@@ -278,6 +473,87 @@ namespace System.Web.Services.Description
|
|
|
"R2111",
|
|
|
"In a DESCRIPTION, array declarations MUST NOT use wsdl:arrayType attribute in the type declaration",
|
|
|
"");
|
|
|
+
|
|
|
+ // R2112: Suggestion.
|
|
|
+ // R2113: Not related to servide description
|
|
|
+ // R2114: Suggestion.
|
|
|
+
|
|
|
+ // 5.3 Messages
|
|
|
+
|
|
|
+ public static readonly ConformanceRule R2201 = new ConformanceRule (
|
|
|
+ "R2201",
|
|
|
+ "A document-literal binding in a DESCRIPTION MUST, in each of its soapbind:body element(s), have at most one part listed in the parts attribute, if the parts attribute is specified",
|
|
|
+ "");
|
|
|
+
|
|
|
+ public static readonly ConformanceRule R2210 = new ConformanceRule (
|
|
|
+ "R2210",
|
|
|
+ "If a document-literal binding in a DESCRIPTION does not specify the parts attribute on a soapbind:body element, the corresponding abstract wsdl:message MUST define zero or one wsdl:parts",
|
|
|
+ "");
|
|
|
+
|
|
|
+ public static readonly ConformanceRule R2203 = new ConformanceRule (
|
|
|
+ "R2203",
|
|
|
+ "An rpc-literal binding in a DESCRIPTION MUST refer, in its soapbind:body element(s), only to wsdl:part element(s) that have been defined using the type attribute",
|
|
|
+ "");
|
|
|
+
|
|
|
+ public static readonly ConformanceRule R2204 = new ConformanceRule (
|
|
|
+ "R2204",
|
|
|
+ "A document-literal binding in a DESCRIPTION MUST refer, in each of its soapbind:body element(s), only to wsdl:part element(s) that have been defined using the element attribute",
|
|
|
+ "");
|
|
|
+
|
|
|
+ public static readonly ConformanceRule R2205 = new ConformanceRule (
|
|
|
+ "R2205",
|
|
|
+ "A wsdl:binding in a DESCRIPTION MUST refer, in each of its soapbind:header, soapbind:headerfault and soapbind:fault elements, only to wsdl:part element(s) that have been defined using the element attribute",
|
|
|
+ "");
|
|
|
+
|
|
|
+ public static readonly ConformanceRule R2209 = new ConformanceRule (
|
|
|
+ "R2209",
|
|
|
+ "A wsdl:binding in a DESCRIPTION SHOULD bind every wsdl:part of a wsdl:message in the wsdl:portType to which it refers to one of soapbind:body, soapbind:header, soapbind:fault or soapbind:headerfault",
|
|
|
+ "");
|
|
|
+
|
|
|
+ public static readonly ConformanceRule R2206 = new ConformanceRule (
|
|
|
+ "R2206",
|
|
|
+ "A wsdl:message in a DESCRIPTION containing a wsdl:part that uses the element attribute MUST refer, in that attribute, to a global element declaration",
|
|
|
+ "");
|
|
|
+
|
|
|
+ // R2211: Related to message structure
|
|
|
+ // R2202: Suggestion.
|
|
|
+ // R2207: Optional
|
|
|
+ // R2208: Optional
|
|
|
+
|
|
|
+ // 5.4 Port Types
|
|
|
+
|
|
|
+ // TODO
|
|
|
+
|
|
|
+ // 5.5 Bindings
|
|
|
+
|
|
|
+ // TODO
|
|
|
+
|
|
|
+ // 5.6 SOAP Binding
|
|
|
+
|
|
|
+ public static readonly ConformanceRule R2701 = new ConformanceRule (
|
|
|
+ "R2701",
|
|
|
+ "The wsdl:binding element in a DESCRIPTION MUST be constructed so that its soapbind:binding child element specifies the transport attribute",
|
|
|
+ "");
|
|
|
+
|
|
|
+ public static readonly ConformanceRule R2702 = new ConformanceRule (
|
|
|
+ "R2702",
|
|
|
+ "A wsdl:binding element in a DESCRIPTION MUST specify the HTTP transport protocol with SOAP binding. Specifically, the transport attribute of its soapbind:binding child MUST have the value \"http://schemas.xmlsoap.org/soap/http\"",
|
|
|
+ "");
|
|
|
+
|
|
|
+ public static readonly ConformanceRule R2705 = new ConformanceRule (
|
|
|
+ "R2705",
|
|
|
+ "A wsdl:binding in a DESCRIPTION MUST use either be a rpc-literal binding or a document-literal binding",
|
|
|
+ "");
|
|
|
+
|
|
|
+ public static readonly ConformanceRule R2706 = new ConformanceRule (
|
|
|
+ "R2706",
|
|
|
+ "A wsdl:binding in a DESCRIPTION MUST use the value of \"literal\" for the use attribute in all soapbind:body, soapbind:fault, soapbind:header and soapbind:headerfault elements",
|
|
|
+ "");
|
|
|
+
|
|
|
+ // R2707: Interpretation rule: A wsdl:binding in a DESCRIPTION that contains one or more soapbind:body, soapbind:fault, soapbind:header or soapbind:headerfault elements that do not specify the use attribute MUST be interpreted as though the value "literal" had been specified in each case
|
|
|
+ // R2709: Suggestion.
|
|
|
+
|
|
|
+ // TODO
|
|
|
}
|
|
|
|
|
|
/*
|