Browse Source

* ConformanceChecker.cs, BasicProfileChecker.cs: New files that implement
the basic infrastructure for basic profile conformance checking.
* BasicProfileViolation.cs: Take normative information from the rule object.
* BasicProfileViolationCollection.cs: Added Add method.
* ServiceDescriptionFormatExtension.cs: Little fix.
* WebServicesInteroperability.cs: Implemented basic support for conformance
checking.

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

Lluis Sanchez 21 years ago
parent
commit
18de07ff81

+ 129 - 0
mcs/class/System.Web.Services/System.Web.Services.Description/BasicProfileChecker.cs

@@ -0,0 +1,129 @@
+// 
+// System.Web.Services.Description.BasicProfileChecker.cs
+//
+// Author:
+//   Lluis Sanchez ([email protected])
+//
+// Copyright (C) Novell, Inc., 2004
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#if NET_2_0
+
+using System.Xml.Schema;
+
+namespace System.Web.Services.Description 
+{
+	internal class BasicProfileChecker: ConformanceChecker
+	{
+		public static BasicProfileChecker Instance = new BasicProfileChecker ();
+		
+		public override WsiClaims Claims { 
+			get { return WsiClaims.BP10; }
+		}
+		
+		public override void Check (ConformanceCheckContext ctx, Import value) 
+		{
+			if (value.Location == "" || value.Location == null) {
+				ctx.ReportRuleViolation (value, BasicProfileRules.R2007);
+				return;
+			}
+			
+			object doc = ctx.GetDocument (value.Location);
+			if (doc == null) ctx.ReportError (value, "Document '" + value.Location + "' not found");
+			
+			if (doc is XmlSchema)
+				ctx.ReportRuleViolation (value, BasicProfileRules.R2002);
+				
+			ServiceDescription imported = doc as ServiceDescription;
+			if (imported == null) {
+				ctx.ReportRuleViolation (value, BasicProfileRules.R2001);
+				return;
+			}
+				
+			// TODO: rule R2003
+			
+			if (imported.TargetNamespace != value.Namespace)
+				ctx.ReportRuleViolation (value, BasicProfileRules.R2005);
+		}
+		
+		public override void Check (ConformanceCheckContext ctx, ServiceDescription value)
+		{
+			
+		}
+		
+		public override void Check (ConformanceCheckContext ctx, ServiceDescriptionFormatExtension value)
+		{
+			if (value.Required)
+				ctx.ReportRuleViolation (value, BasicProfileRules.R2026);
+		}
+		
+		public override void Check (ConformanceCheckContext ctx, XmlSchemaObject value)
+		{
+			if (value is XmlSchemaImport) {
+				XmlSchemaImport import = (XmlSchemaImport) value;
+				XmlSchema doc = ctx.GetDocument (import.SchemaLocation) as XmlSchema;
+				if (doc == null) ctx.ReportError (value, "Schema '" + import.SchemaLocation + "' not found");
+				
+				// TODO: rule R2004, R2010, R2011
+				
+			}
+		}
+	}
+	
+	internal class BasicProfileRules
+	{
+		public static readonly ConformanceRule R2001 = new ConformanceRule (
+			"R2001", 
+			"A DESCRIPTION MUST only use the WSDL \"import\" statement to import another WSDL description",
+			"");
+			
+		public static readonly ConformanceRule R2002 = new ConformanceRule (
+			"R2002", 
+			"To import XML Schema Definitions, a DESCRIPTION MUST use the XML Schema \"import\" statement",
+			"");
+			
+		public static readonly ConformanceRule R2007 = new ConformanceRule (
+			"R2007", 
+			"A DESCRIPTION MUST specify a non-empty location attribute on the wsdl:import element",
+			"");
+			
+		public static readonly ConformanceRule R2005 = new ConformanceRule (
+			"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",
+			"");
+	}
+	
+	/* 
+		The following rules cannot be checked:
+		R2002, R2003, R4004, R4003
+			There is no access to the unerlying xml 
+	*/
+}
+
+#endif

+ 9 - 13
mcs/class/System.Web.Services/System.Web.Services.Description/BasicProfileViolation.cs

@@ -38,18 +38,14 @@ namespace System.Web.Services.Description
 	public class BasicProfileViolation
 	{
 		WsiClaims _claims;
-		string _details;
 		StringCollection _elements;
-		string _statement;
-		string _recommendation;
+		ConformanceRule _rule;
 		
-		internal BasicProfileViolation (WsiClaims claims, string details, StringCollection elements, string statement, string recommendation)
+		internal BasicProfileViolation (WsiClaims claims, ConformanceRule rule)
 		{
 			_claims = claims;
-			_details = details;
-			_statement = statement;
-			_recommendation = recommendation;
-			_elements = elements;
+			_rule = rule;
+			_elements = new StringCollection ();
 		}
 		
 		public WsiClaims Claims {
@@ -57,7 +53,7 @@ namespace System.Web.Services.Description
 		}
 		
 		public string Details {
-			get { return _details; }
+			get { return _rule.Details; }
 		}
 		
 		public StringCollection Elements {
@@ -65,17 +61,17 @@ namespace System.Web.Services.Description
 		}
 		
 		public string NormativeStatement {
-			get { return _statement; }
+			get { return _rule.NormativeStatement ; }
 		}
 
 		public string Recommendation {
-			get { return _recommendation; }
+			get { return _rule.Recommendation; }
 		}
 		
 		public override string ToString ()
 		{
-			string res = _statement + ": " + _details;
-			foreach (string s in _elements)
+			string res = NormativeStatement + ": " + Details;
+			foreach (string s in Elements)
 				res += "\n  -  " + s;
 			return res;
 		}

+ 5 - 0
mcs/class/System.Web.Services/System.Web.Services.Description/BasicProfileViolationCollection.cs

@@ -45,6 +45,11 @@ namespace System.Web.Services.Description
 			set { List [index] = value; }
 		}
 		
+		public int Add (BasicProfileViolation violation)
+		{
+			return List.Add (violation);
+		}
+
 		public bool Contains (BasicProfileViolation violation)
 		{
 			return List.Contains (violation);

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

@@ -1,3 +1,13 @@
+2004-07-14  Lluis Sanchez Gual  <[email protected]>
+
+	* ConformanceChecker.cs, BasicProfileChecker.cs: New files that implement
+	  the basic infrastructure for basic profile conformance checking.
+	* BasicProfileViolation.cs: Take normative information from the rule object.
+	* BasicProfileViolationCollection.cs: Added Add method.
+	* ServiceDescriptionFormatExtension.cs: Little fix.
+	* WebServicesInteroperability.cs: Implemented basic support for conformance
+	  checking.
+
 2004-07-13  Lluis Sanchez Gual  <[email protected]>
 
 	* Binding.cs, Message.cs, MessageBinding.cs, MessagePart.cs, Operation.cs,

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

@@ -0,0 +1,179 @@
+// 
+// System.Web.Services.Description.ConformanceChecker.cs
+//
+// Author:
+//   Lluis Sanchez ([email protected])
+//
+// Copyright (C) Novell, Inc., 2004
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#if NET_2_0
+
+using System.Xml.Schema;
+
+namespace System.Web.Services.Description 
+{
+	internal abstract class ConformanceChecker
+	{
+		public abstract WsiClaims Claims { get; }
+		public virtual void Check (ConformanceCheckContext ctx, Binding value) { }
+		public virtual void Check (ConformanceCheckContext ctx, MessageBinding value) { }
+		public virtual void Check (ConformanceCheckContext ctx, Import value) { }
+		public virtual void Check (ConformanceCheckContext ctx, Message value) { }
+		public virtual void Check (ConformanceCheckContext ctx, MessagePart value) { }
+		public virtual void Check (ConformanceCheckContext ctx, Operation value) { }
+		public virtual void Check (ConformanceCheckContext ctx, OperationBinding value) { }
+		public virtual void Check (ConformanceCheckContext ctx, OperationMessage value) { }
+		public virtual void Check (ConformanceCheckContext ctx, Port value) { }
+		public virtual void Check (ConformanceCheckContext ctx, PortType value) { }
+		public virtual void Check (ConformanceCheckContext ctx, Service value) { }
+		public virtual void Check (ConformanceCheckContext ctx, ServiceDescription value) { }
+		public virtual void Check (ConformanceCheckContext ctx, Types value) { }
+		public virtual void Check (ConformanceCheckContext ctx, ServiceDescriptionFormatExtension value) {}
+		public virtual void Check (ConformanceCheckContext ctx, XmlSchemaObject value) {}
+	}
+	
+	internal class ConformanceRule
+	{
+		public string NormativeStatement;
+		public string Details;
+		public string Recommendation;
+		
+		public ConformanceRule (string name, string desc, string rec)
+		{
+			NormativeStatement = name;
+			Details = desc;
+			Recommendation = rec;
+		}
+	}
+	
+	internal class ConformanceCheckContext
+	{
+		BasicProfileViolationCollection violations;
+		ServiceDescriptionCollection collection;
+		WebReference webReference;
+		ConformanceChecker checker;		
+		public ServiceDescription ServiceDescription;
+		
+		public ConformanceCheckContext (ServiceDescriptionCollection collection, BasicProfileViolationCollection violations)
+		{
+			this.collection = collection;
+			this.violations = violations;
+		}
+		
+		public ConformanceCheckContext (WebReference webReference, BasicProfileViolationCollection violations)
+		{
+			this.webReference = webReference;
+			this.violations = violations;
+		}
+		
+		public ConformanceChecker Checker {
+			get { return checker; }
+			set { checker = value; }
+		}
+		
+		public BasicProfileViolationCollection Violations {
+			get { return violations; }
+		}
+		
+		public object GetDocument (string url)
+		{
+			if (collection != null)
+				return null;
+			else
+				return webReference.Documents [url];
+		}
+		
+		public void ReportError (object currentObject, string msg)
+		{
+			throw new InvalidOperationException (msg + " (" + GetDescription (currentObject) + ")");
+		}
+		
+		public void ReportRuleViolation (object currentObject, ConformanceRule rule)
+		{
+			BasicProfileViolation v = null;
+			foreach (BasicProfileViolation bpv in violations) {
+				if (bpv.NormativeStatement == rule.NormativeStatement) {
+					v = bpv;
+					break;
+				}
+			}
+			
+			if (v == null) {
+				v = new BasicProfileViolation (checker.Claims, rule);
+				violations.Add (v);
+			}
+			
+			v.Elements.Add (GetDescription (currentObject));
+		}
+		
+		string GetDescription (object obj)
+		{
+			if (obj is ServiceDescription) {
+				return "Service Description '" + ServiceDescription.TargetNamespace + "'";
+			}
+			else if (obj is Binding || obj is Message || obj is PortType || obj is Service) {
+				return GetNamedItemDescription (obj, ServiceDescription);
+			}
+			else if (obj is Import) {
+				return GetItemDescription (obj, ServiceDescription, ((Import)obj).Location);
+			}
+			else if (obj is MessageBinding) {
+				return GetNamedItemDescription (obj, ((MessageBinding)obj).OperationBinding);
+			}
+			else if (obj is MessagePart) {
+				return GetNamedItemDescription (obj, ((MessagePart)obj).Message);
+			}
+			else if (obj is Operation) {
+				return GetNamedItemDescription (obj, ((Operation)obj).PortType);
+			}
+			else if (obj is OperationBinding) {
+				return GetNamedItemDescription (obj, ((OperationBinding)obj).Binding);
+			}
+			else if (obj is OperationMessage) {
+				return GetNamedItemDescription (obj, ((OperationMessage)obj).Operation);
+			}
+			else if (obj is Port) {
+				return GetNamedItemDescription (obj, ((Port)obj).Service);
+			}
+			else if (obj is ServiceDescriptionFormatExtension) {
+				ServiceDescriptionFormatExtension ext = (ServiceDescriptionFormatExtension) obj;
+				return GetItemDescription (ext, ext.Parent, ext.GetType().Name);
+			}
+			return obj.GetType().Name;
+		}
+		
+		string GetNamedItemDescription (object item, object parent)
+		{
+			return item.GetType().Name + " '" + ((NamedItem)item).Name + "', in " + GetDescription (parent);
+		}
+		
+		string GetItemDescription (object item, object parent, string name)
+		{
+			return item.GetType().Name + " '" + name + "' in " + GetDescription (parent);
+		}
+	}
+}
+
+#endif

+ 2 - 2
mcs/class/System.Web.Services/System.Web.Services.Description/ServiceDescriptionFormatExtension.cs

@@ -61,12 +61,12 @@ namespace System.Web.Services.Description {
 			set { handled = value; }
 		}
 
-#if NET_2_0
+#if !NET_2_0
 		[XmlIgnore]
+#endif
 		public object Parent {
 			get { return parent; }
 		}
-#endif
 
 		[DefaultValue (false)]
 		[XmlAttribute ("required", Namespace = "http://schemas.xmlsoap.org/wsdl/")]

+ 97 - 3
mcs/class/System.Web.Services/System.Web.Services.Description/WebServicesInteroperability.cs

@@ -30,6 +30,8 @@
 
 #if NET_2_0
 
+using System.Collections;
+
 namespace System.Web.Services.Description 
 {
 	public sealed class WebServicesInteroperability
@@ -41,19 +43,111 @@ namespace System.Web.Services.Description
 		[MonoTODO]
 		public static bool CheckConformance (WsiClaims claims, ServiceDescription service, BasicProfileViolationCollection violations)
 		{
-			throw new NotImplementedException ();
+			ServiceDescriptionCollection col = new ServiceDescriptionCollection ();
+			col.Add (service);
+			ConformanceCheckContext ctx = new ConformanceCheckContext (col, violations);
+			return Check (claims, ctx, col);
 		}
 
 		[MonoTODO]
 		public static bool CheckConformance (WsiClaims claims, ServiceDescriptionCollection services, BasicProfileViolationCollection violations)
 		{
-			throw new NotImplementedException ();
+			ConformanceCheckContext ctx = new ConformanceCheckContext (services, violations);
+			return Check (claims, ctx, services);
 		}
 
 		[MonoTODO]
 		public static bool CheckConformance (WsiClaims claims, WebReference webReference, BasicProfileViolationCollection violations)
 		{
-			throw new NotImplementedException ();
+			ConformanceCheckContext ctx = new ConformanceCheckContext (webReference, violations);
+			return Check (claims, ctx, webReference.Documents);
+		}
+		
+		static bool Check (WsiClaims claims, ConformanceCheckContext ctx, IEnumerable documents)
+		{
+			ConformanceChecker[] checkers = GetCheckers (claims);
+			if (checkers == null) return true;
+			
+			foreach (object doc in documents) {
+				if (!(doc is ServiceDescription)) continue;
+				
+				foreach (ConformanceChecker c in checkers)
+					Check (ctx, c, (ServiceDescription)doc);
+			}
+				
+			return ctx.Violations.Count == 0;
+		}
+		
+		static ConformanceChecker[] GetCheckers (WsiClaims claims)
+		{
+			if ((claims & WsiClaims.BP10) != 0)
+				return new ConformanceChecker[] { BasicProfileChecker.Instance };
+			return null;
+		}
+		
+		static void Check (ConformanceCheckContext ctx, ConformanceChecker checker, ServiceDescription sd)
+		{
+			ctx.ServiceDescription = sd;
+			ctx.Checker = checker;
+			
+			checker.Check (ctx, sd);
+			CheckExtensions (ctx, checker, sd.Extensions);
+			
+			foreach (Service s in sd.Services) {
+				checker.Check (ctx, s);
+				foreach (Port p in s.Ports) {
+					checker.Check (ctx, p);
+					CheckExtensions (ctx, checker, p.Extensions);
+				}
+			}
+			
+			foreach (Binding b in sd.Bindings)
+			{
+				checker.Check (ctx, b);
+				CheckExtensions (ctx, checker, b.Extensions);
+				
+				foreach (OperationBinding oper in b.Operations) {
+					CheckExtensions (ctx, checker, oper.Extensions);
+					
+					foreach (MessageBinding mb in oper.Faults) {
+						checker.Check (ctx, mb);
+						CheckExtensions (ctx, checker, mb.Extensions);
+					}
+					
+					checker.Check (ctx, oper.Input);
+					CheckExtensions (ctx, checker, oper.Input.Extensions);
+					
+					checker.Check (ctx, oper.Output);
+					CheckExtensions (ctx, checker, oper.Output.Extensions);
+				}
+			}
+			
+			foreach (PortType pt in sd.PortTypes)
+			{
+				checker.Check (ctx, pt);
+				
+				foreach (Operation oper in pt.Operations) {
+					checker.Check (ctx, oper);
+					foreach (OperationMessage msg in oper.Messages)
+						checker.Check (ctx, msg);
+					
+					foreach (OperationMessage msg in oper.Faults)
+						checker.Check (ctx, msg);
+				}
+			}
+			
+			foreach (Message msg in sd.Messages)
+			{
+				checker.Check (ctx, msg);
+				foreach (MessagePart part in msg.Parts)
+					checker.Check (ctx, part);
+			}
+		}
+		
+		static void CheckExtensions (ConformanceCheckContext ctx, ConformanceChecker checker, ServiceDescriptionFormatExtensionCollection extensions)
+		{
+			foreach (ServiceDescriptionFormatExtension ext in extensions)
+				checker.Check (ctx, ext);
 		}
 	}
 }