Sfoglia il codice sorgente

* BasicProfileChecker.cs: Implemented more rules.
* ConformanceChecker.cs: Added service list property in
ConformanceCheckContext.
* MessagePart.cs: Added some convenient internal properties.
* OperationMessageCollection.cs: Added property for getting the fault
message.
* ServiceDescriptionFormatExtensionCollection.cs: The find method now
can return subclasses of the provided class.
* WebServicesInteroperability.cs: Set the context schema when processing
a schema.

svn path=/trunk/mcs/; revision=32758

Lluis Sanchez 21 anni fa
parent
commit
ce02668fc1

+ 282 - 6
mcs/class/System.Web.Services/System.Web.Services.Description/BasicProfileChecker.cs

@@ -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
 	}
 	
 	/* 

+ 13 - 0
mcs/class/System.Web.Services/System.Web.Services.Description/ChangeLog

@@ -1,3 +1,16 @@
+2004-08-24  Lluis Sanchez Gual  <[email protected]>
+
+	* BasicProfileChecker.cs: Implemented more rules.
+	* ConformanceChecker.cs: Added service list property in 
+	  ConformanceCheckContext.
+	* MessagePart.cs: Added some convenient internal properties.
+	* OperationMessageCollection.cs: Added property for getting the fault
+	  message.
+	* ServiceDescriptionFormatExtensionCollection.cs: The find method now
+	  can return subclasses of the provided class.
+	* WebServicesInteroperability.cs: Set the context schema when processing
+	  a schema.
+
 2004-07-28  Lluis Sanchez Gual  <[email protected]>
 
 	* BasicProfileChecker.cs, ConformanceChecker.cs, 

+ 8 - 0
mcs/class/System.Web.Services/System.Web.Services.Description/ConformanceChecker.cs

@@ -106,6 +106,7 @@ namespace System.Web.Services.Description
 		public ServiceDescription ServiceDescription;
 		public XmlSchema CurrentSchema;
 		XmlSchemas schemas = new XmlSchemas ();
+		ServiceDescriptionCollection services;
 		
 		public ConformanceCheckContext (ServiceDescriptionCollection collection, BasicProfileViolationCollection violations)
 		{
@@ -115,12 +116,14 @@ namespace System.Web.Services.Description
 				if (sd.Types != null && sd.Types.Schemas != null)
 					schemas.Add (sd.Types.Schemas);
 			}
+			services = collection;
 		}
 		
 		public ConformanceCheckContext (WebReference webReference, BasicProfileViolationCollection violations)
 		{
 			this.webReference = webReference;
 			this.violations = violations;
+			services = new ServiceDescriptionCollection ();
 			
 			foreach (object doc in webReference.Documents.Values) 
 			{
@@ -128,6 +131,7 @@ namespace System.Web.Services.Description
 					schemas.Add ((XmlSchema)doc);
 				else if (doc is ServiceDescription) {
 					ServiceDescription sd = (ServiceDescription) doc;
+					services.Add (sd);
 					if (sd.Types != null && sd.Types.Schemas != null)
 						schemas.Add (sd.Types.Schemas);
 				}
@@ -147,6 +151,10 @@ namespace System.Web.Services.Description
 			get { return schemas; }
 		}
 		
+		public ServiceDescriptionCollection Services {
+			get { return services; }
+		}
+		
 		public object GetDocument (string url)
 		{
 			if (collection != null)

+ 8 - 0
mcs/class/System.Web.Services/System.Web.Services.Description/MessagePart.cs

@@ -92,6 +92,14 @@ namespace System.Web.Services.Description
 			get { return type; }
 			set { type = value; }
 		}
+		
+		internal bool DefinedByType {
+			get { return type != null && type != XmlQualifiedName.Empty; }
+		}
+
+		internal bool DefinedByElement {
+			get { return element != null && element != XmlQualifiedName.Empty; }
+		}
 
 		#endregion // Properties
 

+ 9 - 0
mcs/class/System.Web.Services/System.Web.Services.Description/OperationMessageCollection.cs

@@ -85,6 +85,15 @@ namespace System.Web.Services.Description {
 			}
 		}
 
+		internal OperationFault Fault {
+			get { 
+				foreach (object message in List)
+					if (message is OperationFault)
+						return (OperationFault) message;
+				return null;
+			}
+		}
+
 		#endregion // Properties
 
 		#region Methods

+ 1 - 1
mcs/class/System.Web.Services/System.Web.Services.Description/ServiceDescriptionFormatExtensionCollection.cs

@@ -79,7 +79,7 @@ namespace System.Web.Services.Description {
 		public object Find (Type type)
 		{
 			foreach (object value in List)
-				if (value.GetType () == type)
+				if (type.IsAssignableFrom (value.GetType ()))
 					return value;
 			return null;
 		}

+ 1 - 0
mcs/class/System.Web.Services/System.Web.Services.Description/WebServicesInteroperability.cs

@@ -152,6 +152,7 @@ namespace System.Web.Services.Description
 				checker.Check (ctx, sd.Types);
 				if (sd.Types.Schemas != null) {
 					foreach (XmlSchema s in sd.Types.Schemas) {
+						ctx.CurrentSchema = s;
 						checker.Check (ctx, s);
 						CheckObjects (ctx, checker, new Hashtable (), s.Items);
 					}