ProtocolReflector.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  1. //
  2. // System.Web.Services.Description.ProtocolReflector.cs
  3. //
  4. // Author:
  5. // Tim Coleman ([email protected])
  6. // Lluis Sanchez Gual ([email protected])
  7. //
  8. // Copyright (C) Tim Coleman, 2002
  9. //
  10. //
  11. // Permission is hereby granted, free of charge, to any person obtaining
  12. // a copy of this software and associated documentation files (the
  13. // "Software"), to deal in the Software without restriction, including
  14. // without limitation the rights to use, copy, modify, merge, publish,
  15. // distribute, sublicense, and/or sell copies of the Software, and to
  16. // permit persons to whom the Software is furnished to do so, subject to
  17. // the following conditions:
  18. //
  19. // The above copyright notice and this permission notice shall be
  20. // included in all copies or substantial portions of the Software.
  21. //
  22. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  23. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  24. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  25. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  26. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  27. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  28. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  29. //
  30. using System.Web.Services;
  31. using System.Web.Services.Protocols;
  32. using System.Xml.Serialization;
  33. using System.Xml;
  34. using System.Xml.Schema;
  35. using System.Collections;
  36. namespace System.Web.Services.Description {
  37. public abstract class ProtocolReflector {
  38. #region Fields
  39. Binding binding;
  40. string defaultNamespace;
  41. MessageCollection headerMessages;
  42. Message inputMessage;
  43. LogicalMethodInfo[] methods;
  44. Operation operation;
  45. OperationBinding operationBinding;
  46. Message outputMessage;
  47. Port port;
  48. PortType portType;
  49. string protocolName;
  50. XmlSchemaExporter schemaExporter;
  51. Service service;
  52. ServiceDescription serviceDescription;
  53. Type serviceType;
  54. string serviceUrl;
  55. SoapSchemaExporter soapSchemaExporter;
  56. MethodStubInfo methodStubInfo;
  57. TypeStubInfo typeInfo;
  58. ArrayList extensionReflectors;
  59. ServiceDescriptionReflector serviceReflector;
  60. XmlReflectionImporter reflectionImporter;
  61. SoapReflectionImporter soapReflectionImporter;
  62. CodeIdentifiers portNames;
  63. #endregion // Fields
  64. #region Constructors
  65. protected ProtocolReflector ()
  66. {
  67. defaultNamespace = WebServiceAttribute.DefaultNamespace;
  68. extensionReflectors = ExtensionManager.BuildExtensionReflectors ();
  69. }
  70. #endregion // Constructors
  71. #region Properties
  72. public Binding Binding {
  73. get { return binding; }
  74. }
  75. public string DefaultNamespace {
  76. get { return defaultNamespace; }
  77. }
  78. public MessageCollection HeaderMessages {
  79. get { return headerMessages; } // TODO: set
  80. }
  81. public Message InputMessage {
  82. get { return inputMessage; }
  83. }
  84. public LogicalMethodInfo Method {
  85. get { return methodStubInfo.MethodInfo; }
  86. }
  87. public WebMethodAttribute MethodAttribute {
  88. get { return methodStubInfo.MethodAttribute; }
  89. }
  90. public LogicalMethodInfo[] Methods {
  91. get { return typeInfo.LogicalType.LogicalMethods; }
  92. }
  93. public Operation Operation {
  94. get { return operation; }
  95. }
  96. public OperationBinding OperationBinding {
  97. get { return operationBinding; }
  98. }
  99. public Message OutputMessage {
  100. get { return outputMessage; }
  101. }
  102. public Port Port {
  103. get { return port; }
  104. }
  105. public PortType PortType {
  106. get { return portType; }
  107. }
  108. public abstract string ProtocolName {
  109. get;
  110. }
  111. public XmlReflectionImporter ReflectionImporter
  112. {
  113. get
  114. {
  115. if (reflectionImporter == null) {
  116. reflectionImporter = typeInfo.XmlImporter;
  117. if (reflectionImporter == null)
  118. reflectionImporter = new XmlReflectionImporter();
  119. }
  120. return reflectionImporter;
  121. }
  122. }
  123. internal SoapReflectionImporter SoapReflectionImporter
  124. {
  125. get
  126. {
  127. if (soapReflectionImporter == null) {
  128. soapReflectionImporter = typeInfo.SoapImporter;
  129. if (soapReflectionImporter == null)
  130. soapReflectionImporter = new SoapReflectionImporter();
  131. }
  132. return soapReflectionImporter;
  133. }
  134. }
  135. public XmlSchemaExporter SchemaExporter {
  136. get { return schemaExporter; }
  137. }
  138. internal SoapSchemaExporter SoapSchemaExporter {
  139. get { return soapSchemaExporter; }
  140. }
  141. public XmlSchemas Schemas {
  142. get { return serviceReflector.Schemas; }
  143. }
  144. public Service Service {
  145. get { return service; }
  146. }
  147. public ServiceDescription ServiceDescription {
  148. get { return serviceDescription; }
  149. }
  150. public ServiceDescriptionCollection ServiceDescriptions {
  151. get { return serviceReflector.ServiceDescriptions; }
  152. }
  153. public Type ServiceType {
  154. get { return serviceType; }
  155. }
  156. public string ServiceUrl {
  157. get { return serviceUrl; }
  158. }
  159. internal MethodStubInfo MethodStubInfo {
  160. get { return methodStubInfo; }
  161. }
  162. internal TypeStubInfo TypeInfo {
  163. get { return typeInfo; }
  164. }
  165. #endregion // Properties
  166. #region Methods
  167. internal void Reflect (ServiceDescriptionReflector serviceReflector, Type type, string url, XmlSchemaExporter xxporter, SoapSchemaExporter sxporter)
  168. {
  169. portNames = new CodeIdentifiers ();
  170. this.serviceReflector = serviceReflector;
  171. serviceUrl = url;
  172. serviceType = type;
  173. schemaExporter = xxporter;
  174. soapSchemaExporter = sxporter;
  175. typeInfo = TypeStubManager.GetTypeStub (type, ProtocolName);
  176. ServiceDescription desc = ServiceDescriptions [typeInfo.LogicalType.WebServiceNamespace];
  177. if (desc == null)
  178. {
  179. desc = new ServiceDescription ();
  180. desc.TargetNamespace = typeInfo.LogicalType.WebServiceNamespace;
  181. desc.Name = typeInfo.LogicalType.WebServiceName;
  182. ServiceDescriptions.Add (desc);
  183. }
  184. ImportService (desc, typeInfo, url);
  185. }
  186. void ImportService (ServiceDescription desc, TypeStubInfo typeInfo, string url)
  187. {
  188. service = desc.Services [typeInfo.LogicalType.WebServiceName];
  189. if (service == null)
  190. {
  191. service = new Service ();
  192. service.Name = typeInfo.LogicalType.WebServiceName;
  193. service.Documentation = typeInfo.LogicalType.Description;
  194. desc.Services.Add (service);
  195. }
  196. foreach (BindingInfo binfo in typeInfo.Bindings)
  197. ImportBinding (desc, service, typeInfo, url, binfo);
  198. }
  199. void ImportBinding (ServiceDescription desc, Service service, TypeStubInfo typeInfo, string url, BindingInfo binfo)
  200. {
  201. port = new Port ();
  202. port.Name = portNames.AddUnique (binfo.Name, port);
  203. bool bindingFull = true;
  204. if (binfo.Namespace != desc.TargetNamespace)
  205. {
  206. if (binfo.Location == null || binfo.Location == string.Empty)
  207. {
  208. ServiceDescription newDesc = new ServiceDescription();
  209. newDesc.TargetNamespace = binfo.Namespace;
  210. newDesc.Name = binfo.Name;
  211. bindingFull = ImportBindingContent (newDesc, typeInfo, url, binfo);
  212. if (bindingFull) {
  213. int id = ServiceDescriptions.Add (newDesc);
  214. AddImport (desc, binfo.Namespace, GetWsdlUrl (url,id));
  215. }
  216. }
  217. else {
  218. AddImport (desc, binfo.Namespace, binfo.Location);
  219. bindingFull = true;
  220. }
  221. }
  222. else
  223. bindingFull = ImportBindingContent (desc, typeInfo, url, binfo);
  224. if (bindingFull)
  225. {
  226. port.Binding = new XmlQualifiedName (binding.Name, binfo.Namespace);
  227. service.Ports.Add (port);
  228. }
  229. }
  230. bool ImportBindingContent (ServiceDescription desc, TypeStubInfo typeInfo, string url, BindingInfo binfo)
  231. {
  232. serviceDescription = desc;
  233. // Look for an unused name
  234. int n=0;
  235. string name = binfo.Name;
  236. bool found;
  237. do
  238. {
  239. found = false;
  240. foreach (Binding bi in desc.Bindings)
  241. if (bi.Name == name) { found = true; n++; name = binfo.Name+n; break; }
  242. }
  243. while (found);
  244. // Create the binding
  245. binding = new Binding ();
  246. binding.Name = name;
  247. binding.Type = new XmlQualifiedName (binding.Name, binfo.Namespace);
  248. portType = new PortType ();
  249. portType.Name = binding.Name;
  250. BeginClass ();
  251. foreach (MethodStubInfo method in typeInfo.Methods)
  252. {
  253. methodStubInfo = method;
  254. string metBinding = ReflectMethodBinding ();
  255. if (typeInfo.GetBinding (metBinding) != binfo) continue;
  256. operation = new Operation ();
  257. operation.Name = method.OperationName;
  258. operation.Documentation = method.MethodAttribute.Description;
  259. inputMessage = new Message ();
  260. inputMessage.Name = method.Name + ProtocolName + "In";
  261. ServiceDescription.Messages.Add (inputMessage);
  262. outputMessage = new Message ();
  263. outputMessage.Name = method.Name + ProtocolName + "Out";
  264. ServiceDescription.Messages.Add (outputMessage);
  265. OperationInput inOp = new OperationInput ();
  266. if (method.Name != method.OperationName) inOp.Name = method.Name;
  267. Operation.Messages.Add (inOp);
  268. inOp.Message = new XmlQualifiedName (inputMessage.Name, ServiceDescription.TargetNamespace);
  269. OperationOutput outOp = new OperationOutput ();
  270. if (method.Name != method.OperationName) outOp.Name = method.Name;
  271. Operation.Messages.Add (outOp);
  272. outOp.Message = new XmlQualifiedName (outputMessage.Name, ServiceDescription.TargetNamespace);
  273. portType.Operations.Add (operation);
  274. ImportOperationBinding ();
  275. ReflectMethod ();
  276. foreach (SoapExtensionReflector reflector in extensionReflectors)
  277. {
  278. reflector.ReflectionContext = this;
  279. reflector.ReflectMethod ();
  280. }
  281. }
  282. EndClass ();
  283. if (portType.Operations.Count > 0)
  284. {
  285. desc.Bindings.Add (binding);
  286. desc.PortTypes.Add (portType);
  287. return true;
  288. }
  289. else
  290. return false;
  291. }
  292. void ImportOperationBinding ()
  293. {
  294. operationBinding = new OperationBinding ();
  295. operationBinding.Name = methodStubInfo.OperationName;
  296. InputBinding inOp = new InputBinding ();
  297. operationBinding.Input = inOp;
  298. OutputBinding outOp = new OutputBinding ();
  299. operationBinding.Output = outOp;
  300. if (methodStubInfo.OperationName != methodStubInfo.Name)
  301. inOp.Name = outOp.Name = methodStubInfo.Name;
  302. binding.Operations.Add (operationBinding);
  303. }
  304. internal static void AddImport (ServiceDescription desc, string ns, string location)
  305. {
  306. Import im = new Import();
  307. im.Namespace = ns;
  308. im.Location = location;
  309. desc.Imports.Add (im);
  310. }
  311. string GetWsdlUrl (string baseUrl, int id)
  312. {
  313. return baseUrl + "?wsdl=" + id;
  314. }
  315. protected virtual void BeginClass ()
  316. {
  317. }
  318. protected virtual void EndClass ()
  319. {
  320. }
  321. public ServiceDescription GetServiceDescription (string ns)
  322. {
  323. return ServiceDescriptions [ns];
  324. }
  325. protected abstract bool ReflectMethod ();
  326. protected virtual string ReflectMethodBinding ()
  327. {
  328. return null;
  329. }
  330. #endregion
  331. }
  332. }