fixed tests
[mono.git] / mcs / class / System.Web.Services / System.Web.Services.Description / BasicProfileChecker.cs
1 // 
2 // System.Web.Services.Description.BasicProfileChecker.cs
3 //
4 // Author:
5 //   Lluis Sanchez (lluis@novell.com)
6 //   Atsushi Enomoto (atsushi@ximian.com)
7 //
8 // Copyright (C) Novell, Inc., 2004
9 //
10
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 // 
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31
32 #if NET_2_0
33
34 using System.Xml.Schema;
35 using System.Xml.Serialization;
36 using System.Xml;
37 using System.Collections;
38
39 namespace System.Web.Services.Description 
40 {
41         internal class BasicProfileChecker: ConformanceChecker
42         {
43                 public static BasicProfileChecker Instance = new BasicProfileChecker ();
44                 
45                 public override WsiProfiles Claims { 
46                         get { return WsiProfiles.BasicProfile1_1; }
47                 }
48                 
49                 public override void Check (ConformanceCheckContext ctx, Import value) 
50                 {
51                         if (value.Location == "" || value.Location == null) {
52                                 ctx.ReportRuleViolation (value, BasicProfileRules.R2007);
53                                 return;
54                         }
55                         
56                         if (!new Uri (value.Namespace, UriKind.RelativeOrAbsolute).IsAbsoluteUri)
57                                 ctx.ReportRuleViolation (value, BasicProfileRules.R2803);
58                         
59                         object doc = ctx.GetDocument (value.Location);
60                         if (doc == null) ctx.ReportError (value, "Document '" + value.Location + "' not found");
61                         
62                         if (doc is XmlSchema)
63                                 ctx.ReportRuleViolation (value, BasicProfileRules.R2002);
64                                 
65                         ServiceDescription imported = doc as ServiceDescription;
66                         if (imported == null) {
67                                 ctx.ReportRuleViolation (value, BasicProfileRules.R2001);
68                                 return;
69                         }
70                                 
71                         if (imported.TargetNamespace != value.Namespace)
72                                 ctx.ReportRuleViolation (value, BasicProfileRules.R2005);
73                 }
74                 
75                 public override void Check (ConformanceCheckContext ctx, ServiceDescription value)
76                 {
77                         // R4005 (and R1034, which turned out to be redundant)
78                         if (value.Namespaces != null)
79                                 foreach (XmlQualifiedName qname in value.Namespaces.ToArray ())
80                                         if (qname.Namespace == "http://www.w3.org/XML/1998/namespace")
81                                                 ctx.ReportRuleViolation (value, BasicProfileRules.R4005);
82
83                         CheckDuplicateSoapAddressBinding (ctx, value);
84                 }
85                 
86                 void CheckDuplicateSoapAddressBinding (ConformanceCheckContext ctx, ServiceDescription value)
87                 {
88                         ArrayList locations = new ArrayList ();
89                         foreach (PortType p in value.PortTypes) {
90                                 SoapAddressBinding b = (SoapAddressBinding) p.Extensions.Find (typeof (SoapAddressBinding));
91                                 if (b == null || b.Location == null || b.Location.Length == 0)
92                                         continue;
93                                 if (locations.Contains (b.Location)) {
94                                         ctx.ReportRuleViolation (value, BasicProfileRules.R2711);
95                                         // One report for one ServiceDescription should be enough.
96                                         return;
97                                 }
98                                 locations.Add (b.Location);
99                         }
100                 }
101
102                 public override void Check (ConformanceCheckContext ctx, ServiceDescriptionFormatExtension value)
103                 {
104                         if (value.Required)
105                                 ctx.ReportRuleViolation (value, BasicProfileRules.R2026);
106                 }
107                 
108                 public override void Check (ConformanceCheckContext ctx, MessagePart value)
109                 {
110                         CheckWsdlQName (ctx, value, value.Type);
111                         CheckWsdlQName (ctx, value, value.Element);
112                         
113                         if (value.DefinedByElement && value.Element.Namespace == XmlSchema.Namespace)
114                                 ctx.ReportRuleViolation (value, BasicProfileRules.R2206);
115
116                         if (value.Type != null && value.Type != XmlQualifiedName.Empty &&
117                             value.Element != null && value.Element != XmlQualifiedName.Empty)
118                                 ctx.ReportRuleViolation (value, BasicProfileRules.R2306);
119                 }
120                 
121                 public override void Check (ConformanceCheckContext ctx, Types value)
122                 {
123                 }
124                 
125                 public override void Check (ConformanceCheckContext ctx, Message value)
126                 {
127                 }
128                 
129                 public override void Check (ConformanceCheckContext ctx, Binding value)
130                 {
131                         SoapBinding sb = (SoapBinding) value.Extensions.Find (typeof(SoapBinding));
132                         if (sb == null) {
133                                 ctx.ReportRuleViolation (value, BasicProfileRules.R2401);
134                                 return;
135                         }
136                         if (sb.Transport == null || sb.Transport == "") {
137                                 ctx.ReportRuleViolation (value, BasicProfileRules.R2701);
138                                 return;
139                         }
140                         
141                         if (sb.Transport != "http://schemas.xmlsoap.org/soap/http")
142                                 ctx.ReportRuleViolation (value, BasicProfileRules.R2702);
143                         
144                         LiteralType type = GetLiteralBindingType (value);
145                         if (type == LiteralType.NotLiteral)
146                                 ctx.ReportRuleViolation (value, BasicProfileRules.R2706);
147                         else if (type == LiteralType.Inconsistent)
148                                 ctx.ReportRuleViolation (value, BasicProfileRules.R2705);
149                         
150                         // Collect all parts referenced from this type
151                         
152                         Hashtable parts = new Hashtable ();
153                         PortType port = ctx.Services.GetPortType (value.Type);
154                         foreach (Operation op in port.Operations) {
155                                 foreach (OperationMessage om in op.Messages) {
156                                         Message msg = ctx.Services.GetMessage (om.Message);
157                                         foreach (MessagePart part in msg.Parts)
158                                                 parts.Add (part,part);
159                                 }
160                         }
161                         
162                         foreach (OperationBinding ob in value.Operations) {
163                                 if (ob.Input != null) CheckMessageBinding (ctx, parts, ob.Input);
164                                 if (ob.Output != null) CheckMessageBinding (ctx, parts, ob.Output);
165                                 foreach (FaultBinding fb in ob.Faults)
166                                         CheckMessageBinding (ctx, parts, fb);
167                         }
168                         
169                         if (parts.Count > 0)
170                                 ctx.ReportRuleViolation (value, BasicProfileRules.R2209);
171
172                         // check existence of corresponding operation in portType for each binding operation
173                         if (CheckCorrespondingOperationsForBinding (ctx, value, port))
174                                 ctx.ReportRuleViolation (value, BasicProfileRules.R2718);
175
176                         // check duplicate operation signature.
177                         ArrayList sigs = new ArrayList ();
178                         foreach (OperationBinding ob in value.Operations) {
179                                 if (sigs.Contains (ob.Name))
180                                         ctx.ReportRuleViolation (value, BasicProfileRules.R2710);
181                                 sigs.Add (ob.Name);
182                         }
183
184                         // check namespace declarations.
185                         switch (type) {
186                         case LiteralType.Document:
187                         case LiteralType.Rpc:
188                                 CheckSoapBindingExtensions (ctx, value, type);
189                                 break;
190                         }
191                 }
192                 
193                 bool CheckCorrespondingOperationsForBinding (ConformanceCheckContext ctx, Binding value, PortType port)
194                 {
195                         if (value.Operations.Count != port.Operations.Count)
196                                 return true;
197                         foreach (OperationBinding b in value.Operations) {
198                                 Operation op = port.Operations.Find (b.Name);
199                                 if (op == null)
200                                         return true;
201
202                                 bool msg, bind;
203                                 // input
204                                 msg = op.Messages.Input != null;
205                                 bind = b.Input != null;
206                                 if (msg != bind)
207                                         return true;
208                                 // output
209                                 msg = op.Messages.Output != null;
210                                 bind = b.Output != null;
211                                 if (msg != bind)
212                                         return true;
213                                 // faults
214                                 foreach (FaultBinding fb in b.Faults)
215                                         if (op.Messages.Find (fb.Name) == null)
216                                                 return true;
217                         }
218                         return false;
219                 }
220                 
221                 void CheckSoapBindingExtensions (ConformanceCheckContext ctx, Binding value, LiteralType type)
222                 {
223                         bool violationNS = false;
224                         bool violation2717 = false;
225                         bool violation2720 = false;
226                         bool violation2721 = false;
227
228                         foreach (OperationBinding op in value.Operations) {
229                                 SoapBodyBinding sbb = op.Extensions.Find (typeof (SoapBodyBinding)) as SoapBodyBinding;
230                                 if (sbb != null) {
231                                         if (type == LiteralType.Document && sbb.Namespace != null)
232                                                 violationNS = true;
233                                         if (type == LiteralType.Rpc && sbb.Namespace == null)
234                                                 violation2717 = true;
235                                 }
236
237                                 SoapHeaderBinding shb = op.Extensions.Find (typeof (SoapHeaderBinding)) as SoapHeaderBinding;
238                                 if (shb != null) {
239                                         violationNS |= shb.Namespace != null;
240                                         violation2720 |= !IsValidPart (shb.Part);
241                                 }
242
243                                 SoapHeaderFaultBinding sfhb = op.Extensions.Find (typeof (SoapHeaderFaultBinding)) as SoapHeaderFaultBinding;
244                                 if (sfhb != null) {
245                                         violationNS |= sfhb.Namespace != null;
246                                         violation2720 |= !IsValidPart (sfhb.Part);
247                                 }
248
249                                 SoapFaultBinding sfb = op.Extensions.Find (typeof (SoapFaultBinding)) as SoapFaultBinding;
250                                 if (sfb != null) {
251                                         violation2721 |= sfb.Name == null;
252                                         violationNS |= sfb.Namespace != null;
253                                 }
254                         }
255                         if (violationNS)
256                                 ctx.ReportRuleViolation (value,
257                                         type == LiteralType.Document ?
258                                         BasicProfileRules.R2716 :
259                                         BasicProfileRules.R2726);
260                         if (violation2717)
261                                 ctx.ReportRuleViolation (value, BasicProfileRules.R2717);
262                         if (violation2720)
263                                 ctx.ReportRuleViolation (value, BasicProfileRules.R2720);
264                         if (violation2721)
265                                 ctx.ReportRuleViolation (value, BasicProfileRules.R2721);
266                 }
267                 
268                 bool IsValidPart (string part)
269                 {
270                         if (part == null)
271                                 return false;
272                         try {
273                                 XmlConvert.VerifyNMTOKEN (part);
274                                 return true;
275                         } catch (XmlException) {
276                                 return false;
277                         }
278                 }
279                 
280                 public override void Check (ConformanceCheckContext ctx, OperationBinding value) 
281                 {
282                         bool r2754 = false;
283                         bool r2723 = false;
284                         foreach (FaultBinding fb in value.Faults) {
285                                 SoapFaultBinding sfb = (SoapFaultBinding) value.Extensions.Find (typeof (SoapFaultBinding));
286                                 if (sfb == null)
287                                         continue;
288                                 r2754 |= sfb.Name != fb.Name;
289                                 r2723 |= sfb.Use == SoapBindingUse.Encoded;
290                         }
291                         if (r2754)
292                                 ctx.ReportRuleViolation (value, BasicProfileRules.R2754);
293                         if (r2723)
294                                 ctx.ReportRuleViolation (value, BasicProfileRules.R2723);
295                 }
296                 
297                 void CheckMessageBinding (ConformanceCheckContext ctx, Hashtable portParts, MessageBinding value)
298                 {
299                         SoapBodyBinding sbb = (SoapBodyBinding) value.Extensions.Find (typeof(SoapBodyBinding));
300                         Message msg = FindMessage (ctx, value);
301                         LiteralType bt = GetLiteralBindingType (value.OperationBinding.Binding);
302                         
303                         if (sbb != null) 
304                         {
305                                 if (bt == LiteralType.Document)
306                                 {
307                                         if (sbb.Parts != null && sbb.Parts.Length > 1)
308                                                 ctx.ReportRuleViolation (value, BasicProfileRules.R2201);
309
310                                         if (sbb.Parts == null) {
311                                                 if (msg.Parts != null && msg.Parts.Count > 1)
312                                                         ctx.ReportRuleViolation (value, BasicProfileRules.R2210);
313                                                 if (msg.Parts.Count == 1)
314                                                         portParts.Remove (msg.Parts[0]);
315                                         }
316                                         else {
317                                                 if (sbb.Parts.Length == 0 && msg.Parts.Count == 1) {
318                                                         portParts.Remove (msg.Parts[0]);
319                                                 } else {
320                                                         foreach (string part in sbb.Parts) {
321                                                                 MessagePart mp = msg.FindPartByName (part);
322                                                                 portParts.Remove (mp);
323                                                                 if (!mp.DefinedByElement)
324                                                                         ctx.ReportRuleViolation (value, BasicProfileRules.R2204);
325                                                         }
326                                                 }
327                                         }
328                                 }
329                                 else if (bt == LiteralType.Rpc) 
330                                 {
331                                         if (sbb.Parts != null) {
332                                                 foreach (string part in sbb.Parts) {
333                                                         MessagePart mp = msg.FindPartByName (part);
334                                                         portParts.Remove (mp);
335                                                         if (!mp.DefinedByType)
336                                                                 ctx.ReportRuleViolation (value, BasicProfileRules.R2203);
337                                                 }
338                                         }
339                                 }
340                         }
341                         
342                         SoapHeaderBinding shb = (SoapHeaderBinding) value.Extensions.Find (typeof(SoapHeaderBinding));
343                         if (shb != null) {
344                                 Message hm = ctx.Services.GetMessage (shb.Message);
345                                 MessagePart mp = hm.FindPartByName (shb.Part);
346                                 portParts.Remove (mp);
347                                 if (mp != null && !mp.DefinedByElement)
348                                         ctx.ReportRuleViolation (value, BasicProfileRules.R2205);
349                         }
350                         
351                         SoapHeaderFaultBinding shfb = (SoapHeaderFaultBinding) value.Extensions.Find (typeof(SoapHeaderFaultBinding));
352                         if (shfb != null) {
353                                 Message hm = ctx.Services.GetMessage (shfb.Message);
354                                 MessagePart mp = hm.FindPartByName (shfb.Part);
355                                 portParts.Remove (mp);
356                                 if (mp != null && !mp.DefinedByElement)
357                                         ctx.ReportRuleViolation (value, BasicProfileRules.R2205);
358                         }
359                         
360                         // TODO: SoapFaultBinding ??
361                 }
362                 
363                 Message FindMessage (ConformanceCheckContext ctx, MessageBinding mb)
364                 {
365                         PortType pt = ctx.Services.GetPortType (mb.OperationBinding.Binding.Type);
366                         foreach (Operation op in pt.Operations)
367                                 if (op.IsBoundBy (mb.OperationBinding)) {
368                                         OperationMessage om;
369                                         if (mb is InputBinding) om = op.Messages.Input;
370                                         else if (mb is OutputBinding) om = op.Messages.Output;
371                                         else if (mb is FaultBinding) om = op.Faults [mb.Name];
372                                         else return null;
373                                         if (om != null)
374                                                 return ctx.Services.GetMessage (om.Message);
375                                         else
376                                                 return null;
377                                 }
378                         return null;
379                 }
380                 
381                 public override void Check (ConformanceCheckContext ctx, Operation value)
382                 {
383                         switch (value.Messages.Flow) {
384                         case OperationFlow.SolicitResponse:
385                         case OperationFlow.Notification:
386                                 ctx.ReportRuleViolation (value, BasicProfileRules.R2303);
387                                 break;
388                         }
389
390                         CheckR2305 (ctx, value);
391                 }
392
393                 void CheckR2305 (ConformanceCheckContext ctx, Operation value)
394                 {
395                         string [] order = value.ParameterOrder;
396                         if (order == null || order.Length == 0)
397                                 return;
398                         bool omitted = false;
399                         bool violation = false;
400                         for (int i = 0; i < value.Messages.Count; i++) {
401                                 OperationMessage msg = value.Messages [i];
402                                 if (msg.Name == null) {
403                                         if (omitted)
404                                                 violation = true;
405                                         else
406                                                 omitted = true;
407                                 }
408                                 else if (order [omitted ? i - 1 : i] != msg.Name)
409                                         violation = true;
410                         }
411                         if (violation)
412                                 ctx.ReportRuleViolation (value, BasicProfileRules.R2305);
413                 }
414
415                 public override void Check (ConformanceCheckContext ctx, OperationMessage value) { }
416                 public override void Check (ConformanceCheckContext ctx, Port value) { }
417
418                 public override void Check (ConformanceCheckContext ctx, PortType value)
419                 {
420                         ArrayList names = new ArrayList ();
421                         foreach (Operation o in value.Operations) {
422                                 if (names.Contains (o.Name))
423                                         ctx.ReportRuleViolation (value, BasicProfileRules.R2304);
424                                 else
425                                         names.Add (o.Name);
426                         }
427                 }
428
429                 public override void Check (ConformanceCheckContext ctx, Service value) { }
430                 
431                 public override void Check (ConformanceCheckContext ctx, XmlSchema s)
432                 {
433                         if (s.TargetNamespace == null || s.TargetNamespace == "") {
434                                 foreach (XmlSchemaObject ob in s.Items)
435                                         if (!(ob is XmlSchemaImport) && !(ob is XmlSchemaAnnotation)) {
436                                                 ctx.ReportRuleViolation (s, BasicProfileRules.R2105);
437                                                 break;
438                                         }
439                         }
440                 }
441                 
442                 public override void Check (ConformanceCheckContext ctx, XmlSchemaImport value)
443                 {
444                         XmlSchema doc = ctx.GetDocument (value.SchemaLocation) as XmlSchema;
445                         if (doc == null) ctx.ReportError (value, "Schema '" + value.SchemaLocation + "' not found");
446                 }
447                 
448                 public override void Check (ConformanceCheckContext ctx, XmlSchemaAttribute value)
449                 {
450                         CheckSchemaQName (ctx, value, value.RefName);
451                         CheckSchemaQName (ctx, value, value.SchemaTypeName);
452                         
453                         XmlAttribute[] uatts = value.UnhandledAttributes;
454                         if (uatts != null) {
455                                 foreach (XmlAttribute at in uatts)
456                                         if (at.LocalName == "arrayType" && at.NamespaceURI == "http://schemas.xmlsoap.org/wsdl/")
457                                                 ctx.ReportRuleViolation (value, BasicProfileRules.R2111);
458                         }
459                 }
460                 
461                 public override void Check (ConformanceCheckContext ctx, XmlSchemaAttributeGroupRef value)
462                 {
463                         CheckSchemaQName (ctx, value, value.RefName);
464                 }
465                 
466                 public override void Check (ConformanceCheckContext ctx, XmlSchemaComplexContentExtension value)
467                 {
468                         CheckSchemaQName (ctx, value, value.BaseTypeName);
469                         if (value.BaseTypeName.Namespace == "http://schemas.xmlsoap.org/soap/encoding/" && value.BaseTypeName.Name == "Array")
470                                 ctx.ReportRuleViolation (value, BasicProfileRules.R2110);
471                 }
472                 
473                 public override void Check (ConformanceCheckContext ctx, XmlSchemaComplexContentRestriction value)
474                 {
475                         CheckSchemaQName (ctx, value, value.BaseTypeName);
476                         if (value.BaseTypeName.Namespace == "http://schemas.xmlsoap.org/soap/encoding/" && value.BaseTypeName.Name == "Array")
477                                 ctx.ReportRuleViolation (value, BasicProfileRules.R2110);
478                 }
479                 
480                 public override void Check (ConformanceCheckContext ctx, XmlSchemaElement value)
481                 {
482                         CheckSchemaQName (ctx, value, value.RefName);
483                         CheckSchemaQName (ctx, value, value.SubstitutionGroup);
484                         CheckSchemaQName (ctx, value, value.SchemaTypeName);
485                         if (value.Name != null && value.Name.StartsWith ("ArrayOf", StringComparison.Ordinal))
486                                 ctx.ReportRuleViolation (value, BasicProfileRules.R2112);
487                 }
488                 
489                 public override void Check (ConformanceCheckContext ctx, XmlSchemaGroupRef value)
490                 {
491                         CheckSchemaQName (ctx, value, value.RefName);
492                 }
493                 
494                 public override void Check (ConformanceCheckContext ctx, XmlSchemaKeyref value)
495                 {
496                         CheckSchemaQName (ctx, value, value.Refer);
497                 }
498                 
499                 public override void Check (ConformanceCheckContext ctx, XmlSchemaSimpleContentExtension value)
500                 {
501                         CheckSchemaQName (ctx, value, value.BaseTypeName);
502                 }
503                 
504                 public override void Check (ConformanceCheckContext ctx, XmlSchemaSimpleContentRestriction value)
505                 {
506                         CheckSchemaQName (ctx, value, value.BaseTypeName);
507                 }
508                 
509                 public override void Check (ConformanceCheckContext ctx, XmlSchemaSimpleTypeList value)
510                 {
511                         CheckSchemaQName (ctx, value, value.ItemTypeName);
512                 }
513                 
514                 public override void Check (ConformanceCheckContext ctx, XmlSchemaSimpleTypeRestriction value)
515                 {
516                         CheckSchemaQName (ctx, value, value.BaseTypeName);
517                 }
518                 
519                 public override void Check (ConformanceCheckContext ctx, XmlSchemaSimpleTypeUnion value)
520                 {
521                         if (value.MemberTypes != null) {
522                                 foreach (XmlQualifiedName name in value.MemberTypes)
523                                         CheckSchemaQName (ctx, value, name);
524                         }
525                 }
526                 
527                 // Helper methods
528                 
529                 void CheckWsdlQName (ConformanceCheckContext ctx, object element, XmlQualifiedName name)
530                 {
531                         if (name == null || name == XmlQualifiedName.Empty) return;
532                         if (name.Namespace == "" || name.Namespace == XmlSchema.Namespace) return;
533                         
534                         if (ctx.ServiceDescription.Types != null && ctx.ServiceDescription.Types.Schemas != null) 
535                         {
536                                 foreach (XmlSchema s in ctx.ServiceDescription.Types.Schemas)
537                                 {
538                                         if (s.TargetNamespace == name.Namespace) return;
539                                         foreach (XmlSchemaObject i in s.Includes)
540                                                 if ((i is XmlSchemaImport) && ((XmlSchemaImport)i).Namespace == name.Namespace) return;
541                                 }
542                         }
543                         ctx.ReportRuleViolation (element, BasicProfileRules.R2101);
544                 }
545                 
546                 void CheckSchemaQName (ConformanceCheckContext ctx, object element, XmlQualifiedName name)
547                 {
548                         if (name == null || name == XmlQualifiedName.Empty) return;
549                         if (name.Namespace == "" || name.Namespace == XmlSchema.Namespace) return;
550                         if (ctx.CurrentSchema.TargetNamespace == name.Namespace) return;
551                         
552                         foreach (XmlSchemaObject i in ctx.CurrentSchema.Includes)
553                                 if ((i is XmlSchemaImport) && ((XmlSchemaImport)i).Namespace == name.Namespace) return;
554                                 
555                         ctx.ReportRuleViolation (element, BasicProfileRules.R2102);
556                 }
557                 
558                 LiteralType GetLiteralBindingType (Binding b)
559                 {
560                         SoapBinding sb = (SoapBinding) b.Extensions.Find (typeof(SoapBinding));
561                         SoapBindingStyle style = (sb != null) ? sb.Style : SoapBindingStyle.Document;
562                         if (style == SoapBindingStyle.Default) style = SoapBindingStyle.Document;
563                         
564                         foreach (OperationBinding ob in b.Operations) {
565                                 SoapOperationBinding sob = (SoapOperationBinding) ob.Extensions.Find (typeof(SoapOperationBinding));
566                                 if (sob.Style != SoapBindingStyle.Default && sob.Style != style)
567                                         return LiteralType.Inconsistent;
568                                 if (ob.Input != null) {
569                                         SoapBodyBinding sbb = (SoapBodyBinding) ob.Input.Extensions.Find (typeof(SoapBodyBinding));
570                                         if (sbb != null && sbb.Use != SoapBindingUse.Literal) return LiteralType.NotLiteral;
571                                         SoapFaultBinding sfb = (SoapFaultBinding) ob.Input.Extensions.Find (typeof(SoapFaultBinding));
572                                         if (sfb != null && sfb.Use != SoapBindingUse.Literal) return LiteralType.NotLiteral;
573                                         SoapHeaderBinding shb = (SoapHeaderBinding) ob.Input.Extensions.Find (typeof(SoapHeaderBinding));
574                                         if (shb != null && shb.Use != SoapBindingUse.Literal) return LiteralType.NotLiteral;
575                                         SoapHeaderFaultBinding shfb = (SoapHeaderFaultBinding) ob.Input.Extensions.Find (typeof(SoapHeaderFaultBinding));
576                                         if (shfb != null && shfb.Use != SoapBindingUse.Literal) return LiteralType.NotLiteral;
577                                 }
578                                 if (ob.Output != null) {
579                                         SoapBodyBinding sbb = (SoapBodyBinding) ob.Output.Extensions.Find (typeof(SoapBodyBinding));
580                                         if (sbb != null && sbb.Use != SoapBindingUse.Literal) return LiteralType.NotLiteral;
581                                         SoapFaultBinding sfb = (SoapFaultBinding) ob.Input.Extensions.Find (typeof(SoapFaultBinding));
582                                         if (sfb != null && sfb.Use != SoapBindingUse.Literal) return LiteralType.NotLiteral;
583                                         SoapHeaderBinding shb = (SoapHeaderBinding) ob.Input.Extensions.Find (typeof(SoapHeaderBinding));
584                                         if (shb != null && shb.Use != SoapBindingUse.Literal) return LiteralType.NotLiteral;
585                                         SoapHeaderFaultBinding shfb = (SoapHeaderFaultBinding) ob.Input.Extensions.Find (typeof(SoapHeaderFaultBinding));
586                                         if (shfb != null && shfb.Use != SoapBindingUse.Literal) return LiteralType.NotLiteral;
587                                 }
588                         }
589                         if (style == SoapBindingStyle.Document) return LiteralType.Document;
590                         else return LiteralType.Rpc;
591                 }
592                 
593                 enum LiteralType {
594                         NotLiteral,
595                         Inconsistent,
596                         Rpc,
597                         Document
598                 }
599         }
600         
601         internal class BasicProfileRules
602         {
603                 #region "Basic Profile 1.1 Section 4 (Service Description)"
604
605                 // (BTW R1034 turned out to be a spec bug.)
606
607         // 4.1 Required Description
608                 // Can't check: R0001
609
610         // 4.2 Document Structure
611
612                 // R2028, R2029: schema conformance, depends on underlying XML
613
614                 public static readonly ConformanceRule R2001 = new ConformanceRule (
615                         "R2001", 
616                         "A DESCRIPTION MUST only use the WSDL \"import\" statement to import another WSDL description",
617                         "");
618
619                 public static readonly ConformanceRule R2803 = new ConformanceRule (
620                         "R2803", 
621                         "In a DESCRIPTION, the namespace attribute of the wsdl:import MUST NOT be a relative URI.",
622                         "");
623
624                 public static readonly ConformanceRule R2002 = new ConformanceRule (
625                         "R2002", 
626                         "To import XML Schema Definitions, a DESCRIPTION MUST use the XML Schema \"import\" statement",
627                         "");
628
629                 // R2003: depends on ServiceDescription raw XML.
630                 // R2004, R2009, R2010, R2011: requires schema resolution
631                 // which depends on XmlResolver, while 1) XmlUrlResolver
632                 // might not always be proper (e.g. network resolution) and
633                 // 2) custom XmlResolver might resolve non-XML.
634
635                 public static readonly ConformanceRule R2007 = new ConformanceRule (
636                         "R2007", 
637                         "A DESCRIPTION MUST specify a non-empty location attribute on the wsdl:import element",
638                         "");
639
640                 // R2008: denotes a possibility that cannot be verified.
641
642                 // R2022, R2023, R4004: depends on underlying XML, which 
643                 // is impossible when ServiceDescription is already read
644                 // (WebServiceInteroperability.CheckConformance() is the case).
645
646                 public static readonly ConformanceRule R4005 = new ConformanceRule (
647                         "R4005",
648                         "A DESCRIPTION SHOULD NOT contain the namespace declaration xmlns:xml=\"http://www.w3.org/XML/1998/namespace\"",
649                         "");
650
651                 // R4002, R4003: depends on underlying XML
652
653                 public static readonly ConformanceRule R2005 = new ConformanceRule (
654                         "R2005", 
655                         "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",
656                         "");
657
658                 // R2030: is satisfied by API nature (DocumentableItem).
659
660                 // R2025: cannot be checked.
661
662                 public static readonly ConformanceRule R2026 = new ConformanceRule (
663                         "R2026", 
664                         "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",
665                         "");
666
667                 // R2027: is about the CONSUMER, cannot be checked.
668
669         // 4.3 Types
670
671                 public static readonly ConformanceRule R2101 = new ConformanceRule (
672                         "R2101", 
673                         "A DESCRIPTION MUST NOT use QName references to elements in namespaces that have been neither imported, nor defined in the referring WSDL document",
674                         "");
675                         
676                 public static readonly ConformanceRule R2102 = new ConformanceRule (
677                         "R2102", 
678                         "A QName reference to a Schema component in a DESCRIPTION MUST use the namespace defined in the targetNamespace attribute on the xsd:schema element, or to a namespace defined in the namespace attribute on an xsd:import element within the xsd:schema element",
679                         "");
680                         
681                 public static readonly ConformanceRule R2105 = new ConformanceRule (
682                         "R2105", 
683                         "All xsd:schema elements contained in a wsdl:types element of a DESCRIPTION MUST have a targetNamespace attribute with a valid and non-null value, UNLESS the xsd:schema element has xsd:import and/or xsd:annotation as its only child element(s)",
684                         "");
685                         
686                 public static readonly ConformanceRule R2110 = new ConformanceRule (
687                         "R2110", 
688                         "In a DESCRIPTION, array declarations MUST NOT extend or restrict the soapenc:Array type",
689                         "");
690                         
691                 public static readonly ConformanceRule R2111 = new ConformanceRule (
692                         "R2111", 
693                         "In a DESCRIPTION, array declarations MUST NOT use wsdl:arrayType attribute in the type declaration",
694                         "");
695                         
696                 public static readonly ConformanceRule R2112 = new ConformanceRule (
697                         "R2112", 
698                         "In a DESCRIPTION, elements SHOULD NOT be named using the convention ArrayOfXXX.",
699                         "");
700
701                 // R2113: is about ENVELOPE.
702
703                 // R2114: is satisfied by our processor.
704
705         // 4.4 Messages
706         
707                 public static readonly ConformanceRule R2201 = new ConformanceRule (
708                         "R2201", 
709                         "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",
710                         "");
711
712                 public static readonly ConformanceRule R2209 = new ConformanceRule (
713                         "R2209", 
714                         "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",
715                         "");
716                 
717                 public static readonly ConformanceRule R2210 = new ConformanceRule (
718                         "R2210", 
719                         "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",
720                         "");
721
722                 // R2202: Suggestion.
723
724                 public static readonly ConformanceRule R2203 = new ConformanceRule (
725                         "R2203", 
726                         "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",
727                         "");
728
729                 // R2211: Related to ENVELOPE
730                 // R2207: is about allowed condition (MAY).
731
732                 public static readonly ConformanceRule R2204 = new ConformanceRule (
733                         "R2204", 
734                         "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",
735                         "");
736
737                 // R2208: is about allowed condition (MAY).
738                 // R2212, R2213, R2214: related to ENVELOPE
739
740                 public static readonly ConformanceRule R2205 = new ConformanceRule (
741                         "R2205", 
742                         "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",
743                         "");
744
745                 public static readonly ConformanceRule R2206 = new ConformanceRule (
746                         "R2206", 
747                         "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",
748                         "");
749
750         // 4.5 Port Types
751
752                 // R2301: Related to ENVELOPE.
753                 // R2302: Optional
754
755                 // btw it's not on Basic Profile TAD
756                 public static readonly ConformanceRule R2303 = new ConformanceRule (
757                         "R2303", 
758                         "A DESCRIPTION MUST NOT use Solicit-Response and Notification type operations in a wsdl:portType definition.",
759                         "");
760
761                 public static readonly ConformanceRule R2304 = new ConformanceRule (
762                         "R2304", 
763                         "A wsdl:portType in a DESCRIPTION MUST have operations with distinct values for their name attributes.",
764                         "");
765
766                 public static readonly ConformanceRule R2305 = new ConformanceRule (
767                         "R2305", 
768                         "A wsdl:operation element child of a wsdl:portType element in a DESCRIPTION MUST be constructed so that the parameterOrder attribute, if present, omits at most 1 wsdl:part from the output message.",
769                         "");
770
771                 public static readonly ConformanceRule R2306 = new ConformanceRule (
772                         "R2306", 
773                         "A wsdl:message in a DESCRIPTION MUST NOT specify both type and element attributes on the same wsdl:part.",
774                         "");
775
776         // 4.6 Bindings
777
778                 public static readonly ConformanceRule R2401 = new ConformanceRule (
779                         "R2401", 
780                         "A wsdl:binding element in a DESCRIPTION MUST use WSDL SOAP Binding as defined in WSDL 1.1 Section 3.",
781                         "");
782
783         // 4.7 SOAP Binding
784                 
785                 public static readonly ConformanceRule R2701 = new ConformanceRule (
786                         "R2701", 
787                         "The wsdl:binding element in a DESCRIPTION MUST be constructed so that its soapbind:binding child element specifies the transport attribute",
788                         "");
789                         
790                 public static readonly ConformanceRule R2702 = new ConformanceRule (
791                         "R2702", 
792                         "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\"",
793                         "");
794                         
795                 public static readonly ConformanceRule R2705 = new ConformanceRule (
796                         "R2705", 
797                         "A wsdl:binding in a DESCRIPTION MUST use either be a rpc-literal binding or a document-literal binding",
798                         "");
799                         
800                 public static readonly ConformanceRule R2706 = new ConformanceRule (
801                         "R2706", 
802                         "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",
803                         "");
804                         
805                 // R2709: Suggestion.
806
807                 public static readonly ConformanceRule R2710 = new ConformanceRule (
808                         "R2710", 
809                         "The operations in a wsdl:binding in a DESCRIPTION MUST result in operation signatures that are different from one another.",
810                         "");
811                         
812                 public static readonly ConformanceRule R2711 = new ConformanceRule (
813                         "R2711", 
814                         "A DESCRIPTION SHOULD NOT have more than one wsdl:port with the same value for the location attribute of the soapbind:address element.",
815                         "");
816                         
817                 // R2712: related to ENVELOPE.
818                 // R2714: related to INSTANCE.
819                 // R2750, R2727: related to CONSUMER.
820
821                 public static readonly ConformanceRule R2716 = new ConformanceRule (
822                         "R2716", 
823                         "A document-literal binding in a DESCRIPTION MUST NOT have the namespace attribute specified on contained soapbind:body, soapbind:header, soapbind:headerfault and soapbind:fault elements.",
824                         "");
825                         
826                 public static readonly ConformanceRule R2717 = new ConformanceRule (
827                         "R2717", 
828                         "An rpc-literal binding in a DESCRIPTION MUST have the namespace attribute specified, the value of which MUST be an absolute URI, on contained  soapbind:body elements.",
829                         "");
830                         
831                 public static readonly ConformanceRule R2726 = new ConformanceRule (
832                         "R2726", 
833                         "An rpc-literal binding in a DESCRIPTION MUST NOT have the namespace attribute specified on contained soapbind:header,  soapbind:headerfault and soapbind:fault elements.",
834                         "");
835                         
836
837                 public static readonly ConformanceRule R2718 = new ConformanceRule (
838                         "R2718", 
839                         "A wsdl:binding in a DESCRIPTION MUST have the same set of wsdl:operations as the wsdl:portType to which it refers.",
840                         "");
841                         
842
843                 // R2719: is about allowed condition (MAY).
844                 // R2740, R2741: no way to detect known faults here.
845                 // R2742, R2743: related to ENVELOPE.
846
847                 public static readonly ConformanceRule R2720 = new ConformanceRule (
848                         "R2720", 
849                         "A wsdl:binding in a DESCRIPTION MUST use the part attribute with a schema type of \"NMTOKEN\" on all contained soapbind:header and soapbind:headerfault elements.",
850                         "");
851                         
852
853                 // R2749: is satisfied by API nature.
854
855                 public static readonly ConformanceRule R2721 = new ConformanceRule (
856                         "R2721", 
857                         "A wsdl:binding in a DESCRIPTION MUST have the name  attribute specified on all contained soapbind:fault elements.",
858                         "");
859
860                 public static readonly ConformanceRule R2754 = new ConformanceRule (
861                         "R2754", 
862                         "In a DESCRIPTION, the value of the name attribute on a soapbind:fault element MUST match the value of the name attribute on its parent wsdl:fault element.",
863                         "");
864
865                 // R2722: is about allowed condition (MAY).
866
867                 public static readonly ConformanceRule R2723 = new ConformanceRule (
868                         "R2723", 
869                         "f in a wsdl:binding in a DESCRIPTION the use attribute on a contained soapbind:fault element is present, its value MUST be \"literal\".",
870                         "");
871
872                 // R2707: is satisfied by our implementation.
873                 // R2724, R2725: related to INSTANCE.
874                 // R2729, R2735: related to ENVELOPE.
875                 // R2755: related to MESSAGE.
876                 // R2737, R2738, R2739, R2753: related to ENVELOPE.
877                 // R2751, R2752: related to ENVELOPE.
878                 // R2744, R2745: related to MESSAGE.
879                 // R2747, R2748: related to CONSUMER.
880
881         // 4.8 Use of XML Schema
882
883                 // R2800: satisfied by API nature.
884                 // R2801: ditto.
885
886                 #endregion
887
888                 /*
889
890                 Below are the combination of these documents:
891                 http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html
892                 http://www.ws-i.org/Testing/Tools/2005/01/BP11_TAD_1-1.htm
893
894                 TAD No. component       recomm. WS-I Req.
895                 BP2010  portType                R2304   
896                 BP2011  types                   R2011   
897                 BP2012  binding                 R2204   
898                 BP2013  binding                 R2203   
899                 BP2014  operation               R2305   
900                 BP2017  binding                 R2705,R2706
901                 BP2018  definitions             R2023,R2030
902                 BP2019  binding                 R2716   
903                 BP2020  binding                 R2717   
904                 BP2021  binding                 R2720,R2749
905                 BP2022  binding                 R2721   
906                 BP2032  binding                 R2754   
907                 BP2034  definitions     rec.    R1034,R4005
908                 BP2098  import                  R2007   
909                 BP2101  definitions             R2001   
910                 BP2103  definitions             R2003   
911                 BP2104  definitions             R2005   
912                 BP2105  definitions             R2022,R2030
913                 BP2107  types                   R2105   
914                 BP2108  types                   R2110,R2111
915                 BP2110  types           rec.    R2112   
916                 BP2111  binding                 R2201   
917                 BP2112  binding                 R2207   
918                 BP2113  binding                 R2205   
919                 BP2114  binding         rec.    R2209   
920                 BP2115  message                 R2206   
921                 BP2116  message                 R2306   
922                 BP2117  binding                 R2726   
923                 BP2118  binding                 R2718   
924                 BP2119  binding                 R2210   
925                 BP2120  binding                 R2710   
926                 BP2122  types                   R2801   
927                 BP2123  definitions     rec.    R2026   
928                 BP2803  import                  R2803   
929
930                 */
931         }
932 }
933
934 #endif