HttpSimpleProtocolImporter.cs 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. //
  2. // System.Web.Services.Description.HttpSimpleProtocolImporter.cs
  3. //
  4. // Author:
  5. // Lluis Sanchez Gual ([email protected])
  6. //
  7. // Copyright (C) 2003 Ximian, Inc.
  8. //
  9. using System.CodeDom;
  10. using System.Web.Services;
  11. using System.Web.Services.Protocols;
  12. using System.Web.Services.Configuration;
  13. using System.Xml;
  14. using System.Xml.Serialization;
  15. using System.Configuration;
  16. using System.Collections;
  17. namespace System.Web.Services.Description
  18. {
  19. internal abstract class HttpSimpleProtocolImporter : ProtocolImporter
  20. {
  21. #region Fields
  22. HttpBinding httpBinding;
  23. SoapCodeExporter soapExporter;
  24. SoapSchemaImporter soapImporter;
  25. XmlCodeExporter xmlExporter;
  26. XmlSchemaImporter xmlImporter;
  27. CodeIdentifiers memberIds;
  28. #endregion // Fields
  29. #region Constructors
  30. public HttpSimpleProtocolImporter ()
  31. {
  32. }
  33. #endregion // Constructors
  34. #region Methods
  35. protected override CodeTypeDeclaration BeginClass ()
  36. {
  37. httpBinding = (HttpBinding) Binding.Extensions.Find (typeof(HttpBinding));
  38. CodeTypeDeclaration codeClass = new CodeTypeDeclaration (ClassName);
  39. string location = null;
  40. HttpAddressBinding sab = (HttpAddressBinding) Port.Extensions.Find (typeof(HttpAddressBinding));
  41. if (sab != null) location = sab.Location;
  42. string url = GetServiceUrl (location);
  43. CodeConstructor cc = new CodeConstructor ();
  44. cc.Attributes = MemberAttributes.Public;
  45. CodeExpression ce = new CodeFieldReferenceExpression (new CodeThisReferenceExpression(), "Url");
  46. CodeAssignStatement cas = new CodeAssignStatement (ce, new CodePrimitiveExpression (url));
  47. cc.Statements.Add (cas);
  48. codeClass.Members.Add (cc);
  49. memberIds = new CodeIdentifiers ();
  50. return codeClass;
  51. }
  52. protected override void BeginNamespace ()
  53. {
  54. xmlImporter = new XmlSchemaImporter (LiteralSchemas, ClassNames);
  55. soapImporter = new SoapSchemaImporter (EncodedSchemas, ClassNames);
  56. xmlExporter = new XmlCodeExporter (CodeNamespace, null);
  57. }
  58. protected override void EndClass ()
  59. {
  60. }
  61. protected override void EndNamespace ()
  62. {
  63. }
  64. protected override bool IsBindingSupported ()
  65. {
  66. throw new NotImplementedException ();
  67. }
  68. [MonoTODO]
  69. protected override bool IsOperationFlowSupported (OperationFlow flow)
  70. {
  71. throw new NotImplementedException ();
  72. }
  73. protected override CodeMemberMethod GenerateMethod ()
  74. {
  75. try
  76. {
  77. HttpOperationBinding httpOper = OperationBinding.Extensions.Find (typeof (HttpOperationBinding)) as HttpOperationBinding;
  78. if (httpOper == null) throw new Exception ("Http operation binding not found");
  79. XmlMembersMapping inputMembers = ImportInMembersMapping (InputMessage);
  80. XmlMembersMapping outputMembers = ImportOutMembersMapping (OutputMessage);
  81. CodeMemberMethod met = GenerateMethod (memberIds, httpOper, inputMembers, outputMembers);
  82. xmlExporter.ExportMembersMapping (inputMembers);
  83. xmlExporter.ExportMembersMapping (outputMembers);
  84. return met;
  85. }
  86. catch (Exception ex)
  87. {
  88. Console.WriteLine (ex);
  89. UnsupportedOperationBindingWarning (ex.Message);
  90. return null;
  91. }
  92. }
  93. XmlMembersMapping ImportInMembersMapping (Message msg)
  94. {
  95. SoapSchemaMember[] mems = new SoapSchemaMember [msg.Parts.Count];
  96. for (int n=0; n<mems.Length; n++)
  97. {
  98. SoapSchemaMember mem = new SoapSchemaMember();
  99. mem.MemberName = msg.Parts[n].Name;
  100. mem.MemberType = msg.Parts[n].Type;
  101. mems[n] = mem;
  102. }
  103. return soapImporter.ImportMembersMapping (Operation.Name, "", mems);
  104. }
  105. XmlMembersMapping ImportOutMembersMapping (Message msg)
  106. {
  107. if (msg.Parts.Count == 1 && msg.Parts[0].Name == "Body" && msg.Parts[0].Element == XmlQualifiedName.Empty)
  108. return xmlImporter.ImportAnyType (XmlQualifiedName.Empty,"");
  109. XmlQualifiedName[] pnames = new XmlQualifiedName [msg.Parts.Count];
  110. for (int n=0; n<pnames.Length; n++)
  111. pnames[n] = msg.Parts[n].Element;
  112. return xmlImporter.ImportMembersMapping (pnames);
  113. }
  114. CodeMemberMethod GenerateMethod (CodeIdentifiers memberIds, HttpOperationBinding httpOper, XmlMembersMapping inputMembers, XmlMembersMapping outputMembers)
  115. {
  116. CodeIdentifiers pids = new CodeIdentifiers ();
  117. CodeMemberMethod method = new CodeMemberMethod ();
  118. CodeMemberMethod methodBegin = new CodeMemberMethod ();
  119. CodeMemberMethod methodEnd = new CodeMemberMethod ();
  120. method.Attributes = MemberAttributes.Public;
  121. methodBegin.Attributes = MemberAttributes.Public;
  122. methodEnd.Attributes = MemberAttributes.Public;
  123. // Find unique names for temporary variables
  124. for (int n=0; n<inputMembers.Count; n++)
  125. pids.AddUnique (inputMembers[n].MemberName, inputMembers[n]);
  126. for (int n=0; n<outputMembers.Count; n++)
  127. pids.AddUnique (outputMembers[n].MemberName, outputMembers[n]);
  128. string varAsyncResult = pids.AddUnique ("asyncResult","asyncResult");
  129. string varResults = pids.AddUnique ("results","results");
  130. string varCallback = pids.AddUnique ("callback","callback");
  131. string varAsyncState = pids.AddUnique ("asyncState","asyncState");
  132. string messageName = memberIds.AddUnique(CodeIdentifier.MakeValid(Operation.Name),method);
  133. method.Name = Operation.Name;
  134. methodBegin.Name = memberIds.AddUnique(CodeIdentifier.MakeValid("Begin" + Operation.Name),method);
  135. methodEnd.Name = memberIds.AddUnique(CodeIdentifier.MakeValid("End" + Operation.Name),method);
  136. method.ReturnType = new CodeTypeReference (typeof(void));
  137. methodEnd.ReturnType = new CodeTypeReference (typeof(void));
  138. methodEnd.Parameters.Add (new CodeParameterDeclarationExpression (typeof (IAsyncResult),varAsyncResult));
  139. CodeExpression[] paramArray = new CodeExpression [inputMembers.Count];
  140. CodeParameterDeclarationExpression[] outParams = new CodeParameterDeclarationExpression [outputMembers.Count];
  141. for (int n=0; n<inputMembers.Count; n++)
  142. {
  143. // CodeParameterDeclarationExpression param = new CodeParameterDeclarationExpression (inputMembers[n].TypeFullName, inputMembers[n].MemberName);
  144. // MS always use System.String for input parameters
  145. string ptype = inputMembers[n].TypeFullName;
  146. int i = ptype.IndexOf ('[');
  147. if (i == -1) i = ptype.Length;
  148. ptype = "System.String" + ptype.Substring (i);
  149. CodeParameterDeclarationExpression param = new CodeParameterDeclarationExpression (ptype, inputMembers[n].MemberName);
  150. param.Direction = FieldDirection.In;
  151. method.Parameters.Add (param);
  152. methodBegin.Parameters.Add (param);
  153. paramArray [n] = new CodeVariableReferenceExpression (param.Name);
  154. }
  155. bool isVoid = true;
  156. if (outputMembers.Count == 1)
  157. {
  158. method.ReturnType = new CodeTypeReference (outputMembers[0].TypeFullName);
  159. methodEnd.ReturnType = new CodeTypeReference (outputMembers[0].TypeFullName);
  160. xmlExporter.AddMappingMetadata (method.ReturnTypeCustomAttributes, outputMembers[0], outputMembers.Namespace, (outputMembers[0].ElementName != method.Name + "Result"));
  161. isVoid = false;
  162. }
  163. methodBegin.Parameters.Add (new CodeParameterDeclarationExpression (typeof (AsyncCallback),varCallback));
  164. methodBegin.Parameters.Add (new CodeParameterDeclarationExpression (typeof (object),varAsyncState));
  165. methodBegin.ReturnType = new CodeTypeReference (typeof(IAsyncResult));
  166. // Array of input parameters
  167. CodeArrayCreateExpression methodParams;
  168. if (paramArray.Length > 0)
  169. methodParams = new CodeArrayCreateExpression (typeof(object), paramArray);
  170. else
  171. methodParams = new CodeArrayCreateExpression (typeof(object), 0);
  172. // Generate method url
  173. CodeThisReferenceExpression ethis = new CodeThisReferenceExpression();
  174. CodeExpression thisURlExp = new CodeFieldReferenceExpression (ethis, "Url");
  175. CodePrimitiveExpression metUrl = new CodePrimitiveExpression (httpOper.Location);
  176. CodeBinaryOperatorExpression expMethodLocation = new CodeBinaryOperatorExpression (thisURlExp, CodeBinaryOperatorType.Add, metUrl);
  177. // Invoke call
  178. CodePrimitiveExpression varMsgName = new CodePrimitiveExpression (messageName);
  179. CodeMethodInvokeExpression inv;
  180. inv = new CodeMethodInvokeExpression (ethis, "Invoke", varMsgName, expMethodLocation, methodParams);
  181. if (!isVoid)
  182. method.Statements.Add (new CodeMethodReturnStatement (new CodeCastExpression (method.ReturnType, inv)));
  183. else
  184. method.Statements.Add (inv);
  185. // Begin Invoke Call
  186. CodeExpression expCallb = new CodeVariableReferenceExpression (varCallback);
  187. CodeExpression expAsyncs = new CodeVariableReferenceExpression (varAsyncState);
  188. inv = new CodeMethodInvokeExpression (ethis, "BeginInvoke", varMsgName, expMethodLocation, methodParams, expCallb, expAsyncs);
  189. methodBegin.Statements.Add (new CodeMethodReturnStatement (inv));
  190. // End Invoke call
  191. CodeExpression varAsyncr = new CodeVariableReferenceExpression (varAsyncResult);
  192. inv = new CodeMethodInvokeExpression (ethis, "EndInvoke", varAsyncr);
  193. if (!isVoid)
  194. methodEnd.Statements.Add (new CodeMethodReturnStatement (new CodeCastExpression (methodEnd.ReturnType, inv)));
  195. else
  196. methodEnd.Statements.Add (inv);
  197. // Attributes
  198. CodeAttributeDeclaration att = new CodeAttributeDeclaration ("System.Web.Services.Protocols.HttpMethodAttribute");
  199. att.Arguments.Add (new CodeAttributeArgument (new CodeTypeOfExpression(GetOutMimeFormatter ())));
  200. att.Arguments.Add (new CodeAttributeArgument (new CodeTypeOfExpression(GetInMimeFormatter ())));
  201. AddCustomAttribute (method, att, true);
  202. CodeTypeDeclaration.Members.Add (method);
  203. CodeTypeDeclaration.Members.Add (methodBegin);
  204. CodeTypeDeclaration.Members.Add (methodEnd);
  205. return method;
  206. }
  207. protected virtual Type GetInMimeFormatter ()
  208. {
  209. return null;
  210. }
  211. protected virtual Type GetOutMimeFormatter ()
  212. {
  213. if (OperationBinding.Output.Extensions.Find (typeof(MimeXmlBinding)) != null)
  214. return typeof (XmlReturnReader);
  215. MimeContentBinding bin = (MimeContentBinding) OperationBinding.Output.Extensions.Find (typeof(MimeContentBinding));
  216. if (bin != null && bin.Type == "text/xml")
  217. return typeof (XmlReturnReader);
  218. return typeof(NopReturnReader);
  219. }
  220. #endregion
  221. }
  222. }