HttpSimpleProtocolImporter.cs 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  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 (Schemas, ClassNames);
  55. soapImporter = new SoapSchemaImporter (Schemas, 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. XmlQualifiedName elem = null;
  96. SoapSchemaMember[] mems = new SoapSchemaMember [msg.Parts.Count];
  97. for (int n=0; n<mems.Length; n++)
  98. {
  99. SoapSchemaMember mem = new SoapSchemaMember();
  100. mem.MemberName = msg.Parts[n].Name;
  101. mem.MemberType = msg.Parts[n].Type;
  102. mems[n] = mem;
  103. }
  104. return soapImporter.ImportMembersMapping (Operation.Name, "", mems);
  105. }
  106. XmlMembersMapping ImportOutMembersMapping (Message msg)
  107. {
  108. if (msg.Parts.Count == 1 && msg.Parts[0].Name == "Body" && msg.Parts[0].Element == XmlQualifiedName.Empty)
  109. return xmlImporter.ImportAnyType (XmlQualifiedName.Empty,"");
  110. XmlQualifiedName[] pnames = new XmlQualifiedName [msg.Parts.Count];
  111. for (int n=0; n<pnames.Length; n++)
  112. pnames[n] = msg.Parts[n].Element;
  113. return xmlImporter.ImportMembersMapping (pnames);
  114. }
  115. CodeMemberMethod GenerateMethod (CodeIdentifiers memberIds, HttpOperationBinding httpOper, XmlMembersMapping inputMembers, XmlMembersMapping outputMembers)
  116. {
  117. CodeIdentifiers pids = new CodeIdentifiers ();
  118. CodeMemberMethod method = new CodeMemberMethod ();
  119. CodeMemberMethod methodBegin = new CodeMemberMethod ();
  120. CodeMemberMethod methodEnd = new CodeMemberMethod ();
  121. method.Attributes = MemberAttributes.Public;
  122. methodBegin.Attributes = MemberAttributes.Public;
  123. methodEnd.Attributes = MemberAttributes.Public;
  124. // Find unique names for temporary variables
  125. for (int n=0; n<inputMembers.Count; n++)
  126. pids.AddUnique (inputMembers[n].MemberName, inputMembers[n]);
  127. for (int n=0; n<outputMembers.Count; n++)
  128. pids.AddUnique (outputMembers[n].MemberName, outputMembers[n]);
  129. string varAsyncResult = pids.AddUnique ("asyncResult","asyncResult");
  130. string varResults = pids.AddUnique ("results","results");
  131. string varCallback = pids.AddUnique ("callback","callback");
  132. string varAsyncState = pids.AddUnique ("asyncState","asyncState");
  133. string messageName = memberIds.AddUnique(CodeIdentifier.MakeValid(Operation.Name),method);
  134. method.Name = Operation.Name;
  135. methodBegin.Name = memberIds.AddUnique(CodeIdentifier.MakeValid("Begin" + memberIds.MakeRightCase(Operation.Name)),method);
  136. methodEnd.Name = memberIds.AddUnique(CodeIdentifier.MakeValid("End" + memberIds.MakeRightCase(Operation.Name)),method);
  137. method.ReturnType = new CodeTypeReference (typeof(void));
  138. methodEnd.ReturnType = new CodeTypeReference (typeof(void));
  139. methodEnd.Parameters.Add (new CodeParameterDeclarationExpression (typeof (IAsyncResult),varAsyncResult));
  140. CodeExpression[] paramArray = new CodeExpression [inputMembers.Count];
  141. CodeParameterDeclarationExpression[] outParams = new CodeParameterDeclarationExpression [outputMembers.Count];
  142. for (int n=0; n<inputMembers.Count; n++)
  143. {
  144. CodeParameterDeclarationExpression param = new CodeParameterDeclarationExpression (inputMembers[n].TypeFullName, inputMembers[n].MemberName);
  145. param.Direction = FieldDirection.In;
  146. method.Parameters.Add (param);
  147. methodBegin.Parameters.Add (param);
  148. paramArray [n] = new CodeVariableReferenceExpression (param.Name);
  149. }
  150. bool isVoid = true;
  151. if (outputMembers.Count == 1)
  152. {
  153. method.ReturnType = new CodeTypeReference (outputMembers[0].TypeFullName);
  154. methodEnd.ReturnType = new CodeTypeReference (outputMembers[0].TypeFullName);
  155. xmlExporter.AddMappingMetadata (method.ReturnTypeCustomAttributes, outputMembers[0], outputMembers.Namespace, (outputMembers[0].ElementName != method.Name + "Result"));
  156. isVoid = false;
  157. }
  158. methodBegin.Parameters.Add (new CodeParameterDeclarationExpression (typeof (AsyncCallback),varCallback));
  159. methodBegin.Parameters.Add (new CodeParameterDeclarationExpression (typeof (object),varAsyncState));
  160. methodBegin.ReturnType = new CodeTypeReference (typeof(IAsyncResult));
  161. // Array of input parameters
  162. CodeArrayCreateExpression methodParams;
  163. if (paramArray.Length > 0)
  164. methodParams = new CodeArrayCreateExpression (typeof(object), paramArray);
  165. else
  166. methodParams = new CodeArrayCreateExpression (typeof(object), 0);
  167. // Generate method url
  168. CodeThisReferenceExpression ethis = new CodeThisReferenceExpression();
  169. CodeExpression thisURlExp = new CodeFieldReferenceExpression (ethis, "Url");
  170. CodePrimitiveExpression metUrl = new CodePrimitiveExpression (httpOper.Location);
  171. CodeBinaryOperatorExpression expMethodLocation = new CodeBinaryOperatorExpression (thisURlExp, CodeBinaryOperatorType.Add, metUrl);
  172. // Invoke call
  173. CodePrimitiveExpression varMsgName = new CodePrimitiveExpression (messageName);
  174. CodeMethodInvokeExpression inv;
  175. inv = new CodeMethodInvokeExpression (ethis, "Invoke", varMsgName, expMethodLocation, methodParams);
  176. if (!isVoid)
  177. method.Statements.Add (new CodeMethodReturnStatement (new CodeCastExpression (method.ReturnType, inv)));
  178. else
  179. method.Statements.Add (inv);
  180. // Begin Invoke Call
  181. CodeExpression expCallb = new CodeVariableReferenceExpression (varCallback);
  182. CodeExpression expAsyncs = new CodeVariableReferenceExpression (varAsyncState);
  183. inv = new CodeMethodInvokeExpression (ethis, "BeginInvoke", varMsgName, expMethodLocation, methodParams, expCallb, expAsyncs);
  184. methodBegin.Statements.Add (new CodeMethodReturnStatement (inv));
  185. // End Invoke call
  186. CodeExpression varAsyncr = new CodeVariableReferenceExpression (varAsyncResult);
  187. inv = new CodeMethodInvokeExpression (ethis, "EndInvoke", varAsyncr);
  188. if (!isVoid)
  189. methodEnd.Statements.Add (new CodeMethodReturnStatement (new CodeCastExpression (methodEnd.ReturnType, inv)));
  190. else
  191. methodEnd.Statements.Add (inv);
  192. // Attributes
  193. CodeAttributeDeclaration att = new CodeAttributeDeclaration ("System.Web.Services.Protocols.HttpMethodAttribute");
  194. att.Arguments.Add (new CodeAttributeArgument (new CodeTypeOfExpression(GetOutMimeFormatter ())));
  195. att.Arguments.Add (new CodeAttributeArgument (new CodeTypeOfExpression(GetInMimeFormatter ())));
  196. AddCustomAttribute (method, att, true);
  197. CodeTypeDeclaration.Members.Add (method);
  198. CodeTypeDeclaration.Members.Add (methodBegin);
  199. CodeTypeDeclaration.Members.Add (methodEnd);
  200. return method;
  201. }
  202. protected virtual Type GetInMimeFormatter ()
  203. {
  204. return null;
  205. }
  206. protected virtual Type GetOutMimeFormatter ()
  207. {
  208. if (OperationBinding.Output.Extensions.Find (typeof(MimeXmlBinding)) != null)
  209. return typeof (XmlReturnReader);
  210. MimeContentBinding bin = (MimeContentBinding) OperationBinding.Output.Extensions.Find (typeof(MimeContentBinding));
  211. if (bin != null && bin.Type == "text/xml")
  212. return typeof (XmlReturnReader);
  213. return typeof(NopReturnReader);
  214. }
  215. #endregion
  216. }
  217. }