//
// Author:
// Miguel de Icaza
+// Lluis Sanchez Gual (lluis@ximian.com)
//
// (C) 2003 Ximian, Inc.
//
// This class represents all the information we extract from a MethodInfo
// in the SoapHttpClientProtocol derivative stub class
//
- internal class MethodStubInfo {
- internal LogicalMethodInfo MethodInfo;
-
- // The name used bythe stub class to reference this method.
- internal string Name;
-
+ internal class SoapMethodStubInfo : MethodStubInfo
+ {
internal string Action;
internal string Binding;
internal string ResponseName;
internal string ResponseNamespace;
- internal bool OneWay;
+ internal bool OneWay;
internal SoapParameterStyle ParameterStyle;
+ internal SoapBindingStyle SoapBindingStyle;
+ internal SoapBindingUse Use;
internal XmlSerializer RequestSerializer;
internal XmlSerializer ResponseSerializer;
- static XmlSerializer _faultSerializer;
+ internal HeaderInfo[] Headers;
+
+ internal SoapExtensionRuntimeConfig[] SoapExtensions;
+
+ private XmlMembersMapping[] _membersMapping;
+
+ internal XmlMembersMapping InputMembersMapping
+ {
+ get { return _membersMapping[0]; }
+ }
+
+ internal XmlMembersMapping OutputMembersMapping
+ {
+ get { return _membersMapping[1]; }
+ }
//
// Constructor
//
- MethodStubInfo (TypeStubInfo parent, LogicalMethodInfo source, object kind, XmlReflectionImporter xmlImporter, SoapReflectionImporter soapImporter)
+ public SoapMethodStubInfo (TypeStubInfo typeStub, LogicalMethodInfo source, object kind, XmlReflectionImporter xmlImporter, SoapReflectionImporter soapImporter)
+ : base (typeStub, source)
{
- MethodInfo = source;
-
+ SoapTypeStubInfo parent = (SoapTypeStubInfo) typeStub;
XmlElementAttribute optional_ns = null;
- SoapBindingUse use;
-
- if (kind is SoapDocumentMethodAttribute){
+
+ if (kind == null) {
+ Use = parent.Use;
+ RequestName = "";
+ RequestNamespace = parent.WebServiceNamespace;
+ ResponseName = "";
+ ResponseNamespace = parent.WebServiceNamespace;
+ ParameterStyle = parent.ParameterStyle;
+ SoapBindingStyle = parent.SoapBindingStyle;
+ OneWay = false;
+ }
+ else if (kind is SoapDocumentMethodAttribute){
SoapDocumentMethodAttribute dma = (SoapDocumentMethodAttribute) kind;
- use = dma.Use;
- if (use == SoapBindingUse.Default)
- use = parent.Use;
+ Use = dma.Use;
+ if (Use == SoapBindingUse.Default)
+ Use = parent.Use;
Action = dma.Action;
Binding = dma.Binding;
if (ParameterStyle == SoapParameterStyle.Default)
ParameterStyle = parent.ParameterStyle;
OneWay = dma.OneWay;
+ SoapBindingStyle = SoapBindingStyle.Document;
} else {
SoapRpcMethodAttribute rma = (SoapRpcMethodAttribute) kind;
- use = SoapBindingUse.Encoded; // RPC always use encoded
+ Use = SoapBindingUse.Encoded; // RPC always use encoded
Action = rma.Action;
Binding = rma.Binding;
RequestNamespace = rma.RequestNamespace;
ResponseNamespace = rma.ResponseNamespace;
ResponseName = rma.ResponseElementName;
+ ParameterStyle = SoapParameterStyle.Wrapped;
OneWay = rma.OneWay;
+ SoapBindingStyle = SoapBindingStyle.Rpc;
// For RPC calls, make all arguments be part of the empty namespace
optional_ns = new XmlElementAttribute ();
optional_ns.Namespace = "";
}
- if (Binding == "")
- Binding = parent.BindingName;
- if (RequestName == "")
- RequestName = source.Name;
-
+
if (OneWay){
if (source.ReturnType != typeof (void))
throw new Exception ("OneWay methods should not have a return value");
throw new Exception ("OneWay methods should not have out/ref parameters");
}
- object [] o = source.GetCustomAttributes (typeof (WebMethodAttribute));
- if (o.Length == 1){
- WebMethodAttribute wma = (WebMethodAttribute) o [0];
-
- Name = wma.MessageName;
- if (Name == "")
- Name = source.Name;
- } else
- Name = source.Name;
-
- if (ResponseName == "")
- ResponseName = Name + "Response";
-
+ if (RequestNamespace == "") RequestNamespace = parent.WebServiceNamespace;
+ if (ResponseNamespace == "") ResponseNamespace = parent.WebServiceNamespace;
+ if (RequestName == "") RequestName = Name;
+ if (ResponseName == "") ResponseName = Name + "Response";
+ if (Binding == null || Binding == "") Binding = parent.DefaultBinding;
+ else if (parent.GetBinding (Binding) == null) throw new InvalidOperationException ("Type '" + parent.Type + "' is missing WebServiceBinding attribute that defines a binding named '" + Binding + "'");
+
+ if (Action == null || Action == "")
+ Action = RequestNamespace.EndsWith("/") ? (RequestNamespace + Name) : (RequestNamespace + "/" + Name);
+
+ bool hasWrappingElem = (ParameterStyle == SoapParameterStyle.Wrapped);
+
XmlReflectionMember [] in_members = BuildRequestReflectionMembers (optional_ns);
XmlReflectionMember [] out_members = BuildResponseReflectionMembers (optional_ns);
- XmlMembersMapping [] members = new XmlMembersMapping [2];
- try {
- if (use == SoapBindingUse.Literal) {
- members [0] = xmlImporter.ImportMembersMapping (RequestName, RequestNamespace, in_members, true);
- members [1] = xmlImporter.ImportMembersMapping (ResponseName, ResponseNamespace, out_members, true);
- }
- else {
- members [0] = soapImporter.ImportMembersMapping (RequestName, RequestNamespace, in_members, true, true);
- members [1] = soapImporter.ImportMembersMapping (ResponseName, ResponseNamespace, out_members, true, true);
- }
-
- XmlSerializer [] s = null;
- s = XmlSerializer.FromMappings (members);
- RequestSerializer = s [0];
- ResponseSerializer = s [1];
- } catch {
- Console.WriteLine ("Got exception while creating serializer");
- Console.WriteLine ("Method name: " + RequestName + " parameters are:");
+ _membersMapping = new XmlMembersMapping [2];
- for (int i = 0; i < in_members.Length; i++) {
- Console.WriteLine (" {0}: {1} {2}", i, in_members [i].MemberName, in_members [i].MemberType);
- }
+ if (Use == SoapBindingUse.Literal) {
+ _membersMapping [0] = xmlImporter.ImportMembersMapping (RequestName, RequestNamespace, in_members, hasWrappingElem);
+ _membersMapping [1] = xmlImporter.ImportMembersMapping (ResponseName, ResponseNamespace, out_members, hasWrappingElem);
+ }
+ else {
+ _membersMapping [0] = soapImporter.ImportMembersMapping (RequestName, RequestNamespace, in_members, hasWrappingElem, true);
+ _membersMapping [1] = soapImporter.ImportMembersMapping (ResponseName, ResponseNamespace, out_members, hasWrappingElem, true);
+ }
- Console.WriteLine ("Output parameters are:");
- for (int i = 0; i < out_members.Length; i++) {
- Console.WriteLine (" {0}: {1} {2}", i, out_members [i].MemberName, out_members [i].MemberType);
- }
- throw;
+ XmlSerializer [] s = null;
+ s = XmlSerializer.FromMappings (_membersMapping);
+ RequestSerializer = s [0];
+ ResponseSerializer = s [1];
+
+ object[] o = source.GetCustomAttributes (typeof (SoapHeaderAttribute));
+ Headers = new HeaderInfo[o.Length];
+ for (int i = 0; i < o.Length; i++) {
+ SoapHeaderAttribute att = (SoapHeaderAttribute) o[i];
+ MemberInfo[] mems = source.DeclaringType.GetMember (att.MemberName);
+ if (mems.Length == 0) throw new InvalidOperationException ("Member " + att.MemberName + " not found in class " + source.DeclaringType.FullName);
+
+ Type headerType = (mems[0] is FieldInfo) ? ((FieldInfo)mems[0]).FieldType : ((PropertyInfo)mems[0]).PropertyType;
+ Headers [i] = new HeaderInfo (mems[0], att);
+ parent.RegisterHeaderType (headerType);
}
-// ResponseSerializer.UnknownNode += new XmlNodeEventHandler (e);
- }
- static internal MethodStubInfo Create (TypeStubInfo parent, LogicalMethodInfo lmi, XmlReflectionImporter xmlImporter, SoapReflectionImporter soapImporter)
- {
- object [] o = lmi.GetCustomAttributes (typeof (SoapDocumentMethodAttribute));
- if (o.Length == 0){
- o = lmi.GetCustomAttributes (typeof (SoapRpcMethodAttribute));
- if (o.Length == 0)
- return null;
- return new MethodStubInfo (parent, lmi, o [0], xmlImporter, soapImporter);
- } else
- return new MethodStubInfo (parent, lmi, o [0], xmlImporter, soapImporter);
+ SoapExtensions = SoapExtension.GetMethodExtensions (source);
}
XmlReflectionMember [] BuildRequestReflectionMembers (XmlElementAttribute optional_ns)
return out_members;
}
- public XmlSerializer FaultSerializer
+ public HeaderInfo GetHeaderInfo (Type headerType)
{
- get
- {
- if (_faultSerializer != null) return _faultSerializer;
- _faultSerializer = new XmlSerializer (typeof(Fault));
- return _faultSerializer;
- }
+ foreach (HeaderInfo headerInfo in Headers)
+ if (headerInfo.HeaderType == headerType) return headerInfo;
+ return null;
+ }
+ }
+
+ internal class HeaderInfo
+ {
+ internal MemberInfo Member;
+ internal SoapHeaderAttribute AttributeInfo;
+ internal Type HeaderType;
+
+ public HeaderInfo (MemberInfo member, SoapHeaderAttribute attributeInfo)
+ {
+ Member = member;
+ AttributeInfo = attributeInfo;
+ if (Member is PropertyInfo) HeaderType = ((PropertyInfo)Member).PropertyType;
+ else HeaderType = ((FieldInfo)Member).FieldType;
+ }
+
+ public object GetHeaderValue (object ob)
+ {
+ if (Member is PropertyInfo) return ((PropertyInfo)Member).GetValue (ob, null);
+ else return ((FieldInfo)Member).GetValue (ob);
}
- static void e (object o, XmlNodeEventArgs a)
+ public void SetHeaderValue (object ob, object value)
{
- Console.WriteLine ("Unexpected Node: {5}:{6} {0}/{1}/{2}/{3}/{4}",
- a.LocalName, a.Name, a.NamespaceURI, a.NodeType, a.Text,
- a.LineNumber, a.LinePosition);
-// throw new Exception ();
+ if (Member is PropertyInfo) ((PropertyInfo)Member).SetValue (ob, value, null);
+ else ((FieldInfo)Member).SetValue (ob, value);
+ }
+
+ public SoapHeaderDirection Direction
+ {
+ get { return AttributeInfo.Direction; }
}
}
internal class Fault
{
+ public Fault () {}
+
+ public Fault (SoapException ex)
+ {
+ faultcode = ex.Code;
+ faultstring = ex.Message;
+ faultactor = ex.Actor;
+ detail = ex.Detail;
+ }
+
public XmlQualifiedName faultcode;
public string faultstring;
public string faultactor;
public XmlNode detail;
}
-
+
//
// Holds the metadata loaded from the type stub, as well as
// the metadata for all the methods in the type
//
- internal class TypeStubInfo {
- Hashtable name_to_method = new Hashtable ();
+ internal class SoapTypeStubInfo : TypeStubInfo
+ {
+ Hashtable header_serializers = new Hashtable ();
+ Hashtable header_serializers_byname = new Hashtable ();
// Precomputed
internal SoapParameterStyle ParameterStyle;
internal SoapServiceRoutingStyle RoutingStyle;
internal SoapBindingUse Use;
- internal string WebServiceName;
- internal string WebServiceNamespace;
- internal string BindingLocation;
- internal string BindingName;
- internal string BindingNamespace;
-
- void GetTypeAttributes (Type t)
+ internal XmlSerializer FaultSerializer;
+ internal SoapExtensionRuntimeConfig[][] SoapExtensions;
+ internal SoapBindingStyle SoapBindingStyle;
+ internal XmlReflectionImporter xmlImporter;
+ internal SoapReflectionImporter soapImporter;
+
+ public SoapTypeStubInfo (Type t)
+ : base (t)
{
+ xmlImporter = new XmlReflectionImporter ();
+ soapImporter = new SoapReflectionImporter ();
+
object [] o;
o = t.GetCustomAttributes (typeof (WebServiceBindingAttribute), false);
- if (o.Length != 1)
- throw new Exception ("Expected WebServiceBindingAttribute on "+ t.Name);
- WebServiceBindingAttribute b = (WebServiceBindingAttribute) o [0];
- BindingLocation = b.Location;
- BindingName = b.Name;
- BindingNamespace = b.Namespace;
-
- o = t.GetCustomAttributes (typeof (WebService), false);
- if (o.Length == 1){
- WebServiceAttribute a = (WebServiceAttribute) o [0];
-
- WebServiceName = a.Name;
- WebServiceNamespace = a.Namespace;
- } else {
- WebServiceName = t.Name;
- WebServiceNamespace = WebServiceAttribute.DefaultNamespace;
- }
+ foreach (WebServiceBindingAttribute at in o)
+ Bindings.Add (new BindingInfo (at, WebServiceNamespace));
o = t.GetCustomAttributes (typeof (SoapDocumentServiceAttribute), false);
if (o.Length == 1){
ParameterStyle = a.ParameterStyle;
RoutingStyle = a.RoutingStyle;
Use = a.Use;
+ SoapBindingStyle = SoapBindingStyle.Document;
} else {
o = t.GetCustomAttributes (typeof (SoapRpcServiceAttribute), false);
if (o.Length == 1){
ParameterStyle = SoapParameterStyle.Wrapped;
RoutingStyle = srs.RoutingStyle;
- Use = SoapBindingUse.Literal;
+ Use = SoapBindingUse.Encoded;
+ SoapBindingStyle = SoapBindingStyle.Rpc;
} else {
ParameterStyle = SoapParameterStyle.Wrapped;
RoutingStyle = SoapServiceRoutingStyle.SoapAction;
Use = SoapBindingUse.Literal;
+ SoapBindingStyle = SoapBindingStyle.Document;
}
}
+
+ if (ParameterStyle == SoapParameterStyle.Default) ParameterStyle = SoapParameterStyle.Wrapped;
+ if (Use == SoapBindingUse.Default) Use = SoapBindingUse.Literal;
+
+ FaultSerializer = new XmlSerializer (typeof(Fault));
+ SoapExtensions = SoapExtension.GetTypeExtensions (t);
}
- //
- // Extract all method information
- //
- void GetTypeMethods (Type t, XmlReflectionImporter xmlImporter, SoapReflectionImporter soapImporter)
+ public override XmlReflectionImporter XmlImporter
{
- MethodInfo [] type_methods = t.GetMethods (BindingFlags.Instance | BindingFlags.Public);
- LogicalMethodInfo [] methods = LogicalMethodInfo.Create (type_methods, LogicalMethodTypes.Sync);
-
- foreach (LogicalMethodInfo mi in methods){
- MethodStubInfo msi = MethodStubInfo.Create (this, mi, xmlImporter, soapImporter);
-
- if (msi == null)
- continue;
-
- name_to_method [msi.Name] = msi;
- }
+ get { return xmlImporter; }
}
-
- internal TypeStubInfo (Type t)
- {
- GetTypeAttributes (t);
- XmlReflectionImporter xmlImporter = new XmlReflectionImporter ();
- SoapReflectionImporter soapImporter = new SoapReflectionImporter ();
- GetTypeMethods (t, xmlImporter, soapImporter);
+ public override SoapReflectionImporter SoapImporter
+ {
+ get { return soapImporter; }
}
-
- internal MethodStubInfo GetMethod (string name)
+
+ public override string ProtocolName
{
- return (MethodStubInfo) name_to_method [name];
+ get { return "Soap"; }
}
- }
-
- //
- // Manages
- //
- internal class TypeStubManager {
- static Hashtable type_to_manager;
- static TypeStubManager ()
+ protected override MethodStubInfo CreateMethodStubInfo (TypeStubInfo parent, LogicalMethodInfo lmi, bool isClientProxy)
{
- type_to_manager = new Hashtable ();
+ object [] ats = lmi.GetCustomAttributes (typeof (SoapDocumentMethodAttribute));
+ if (ats.Length == 0) ats = lmi.GetCustomAttributes (typeof (SoapRpcMethodAttribute));
+
+ if (ats.Length == 0 && isClientProxy)
+ return null;
+ else if (ats.Length == 0)
+ return new SoapMethodStubInfo (parent, lmi, null, xmlImporter, soapImporter);
+ else
+ return new SoapMethodStubInfo (parent, lmi, ats[0], xmlImporter, soapImporter);
}
-
- //
- // This needs to be thread safe
- //
- static internal TypeStubInfo GetTypeStub (Type t)
+
+ internal void RegisterHeaderType (Type type)
{
- TypeStubInfo tm = (TypeStubInfo) type_to_manager [t];
-
- if (tm != null)
- return tm;
+ XmlSerializer s = (XmlSerializer) header_serializers [type];
+ if (s != null) return;
- lock (typeof (TypeStubInfo)){
- tm = (TypeStubInfo) type_to_manager [t];
+ XmlReflectionImporter ri = new XmlReflectionImporter ();
+ XmlTypeMapping tm = ri.ImportTypeMapping (type, WebServiceAttribute.DefaultNamespace);
+ s = new XmlSerializer (tm);
- if (tm != null)
- return tm;
-
- tm = new TypeStubInfo (t);
- type_to_manager [t] = tm;
+ header_serializers [type] = s;
+ header_serializers_byname [new XmlQualifiedName (tm.ElementName, tm.Namespace)] = s;
+ }
- return tm;
- }
+ internal XmlSerializer GetHeaderSerializer (Type type)
+ {
+ return (XmlSerializer) header_serializers [type];
}
+
+ internal XmlSerializer GetHeaderSerializer (XmlQualifiedName qname)
+ {
+ return (XmlSerializer) header_serializers_byname [qname];
+ }
}
}