* HttpSimpleProtocolReflector.cs, ProtocolReflector.cs:
[mono.git] / mcs / class / System.Web.Services / System.Web.Services.Description / ProtocolReflector.cs
1 // 
2 // System.Web.Services.Description.ProtocolReflector.cs
3 //
4 // Author:
5 //   Tim Coleman (tim@timcoleman.com)
6 //   Lluis Sanchez Gual (lluis@ximian.com)
7 //
8 // Copyright (C) Tim Coleman, 2002
9 //
10
11 using System.Web.Services;
12 using System.Web.Services.Protocols;
13 using System.Xml.Serialization;
14 using System.Xml;
15 using System.Xml.Schema;
16 using System.Collections;
17
18 namespace System.Web.Services.Description {
19         public abstract class ProtocolReflector {
20
21                 #region Fields
22
23                 Binding binding;
24                 string defaultNamespace;
25                 MessageCollection headerMessages;
26                 Message inputMessage;
27                 LogicalMethodInfo[] methods;
28                 Operation operation;
29                 OperationBinding operationBinding;
30                 Message outputMessage;          
31                 Port port;
32                 PortType portType;
33                 string protocolName;
34                 XmlSchemaExporter schemaExporter;
35                 Service service;
36                 ServiceDescription serviceDescription;
37                 Type serviceType;
38                 string serviceUrl;
39                 SoapSchemaExporter soapSchemaExporter;
40                 MethodStubInfo methodStubInfo;
41                 TypeStubInfo typeInfo;
42                 ArrayList extensionReflectors;
43                 ServiceDescriptionReflector serviceReflector;
44
45                 XmlReflectionImporter reflectionImporter;
46                 SoapReflectionImporter soapReflectionImporter;
47                 
48                 #endregion // Fields
49
50                 #region Constructors
51         
52                 protected ProtocolReflector ()
53                 {
54                         defaultNamespace = WebServiceAttribute.DefaultNamespace;
55                         extensionReflectors = ExtensionManager.BuildExtensionReflectors ();
56                 }
57                 
58                 #endregion // Constructors
59
60                 #region Properties
61
62                 public Binding Binding {
63                         get { return binding; }
64                 }
65
66                 public string DefaultNamespace {
67                         get { return defaultNamespace; }
68                 }
69
70                 public MessageCollection HeaderMessages {
71                         get { return headerMessages; }  // TODO: set
72                 }
73
74                 public Message InputMessage {
75                         get { return inputMessage; }
76                 }
77
78                 public LogicalMethodInfo Method {
79                         get { return methodStubInfo.MethodInfo; }
80                 }
81
82                 public WebMethodAttribute MethodAttribute {
83                         get { return methodStubInfo.MethodAttribute; }
84                 }
85
86                 public LogicalMethodInfo[] Methods {
87                         get { return typeInfo.LogicalType.LogicalMethods; }
88                 }
89         
90                 public Operation Operation {
91                         get { return operation; }
92                 }
93
94                 public OperationBinding OperationBinding {
95                         get { return operationBinding; }
96                 }
97
98                 public Message OutputMessage {
99                         get { return outputMessage; }
100                 }
101
102                 public Port Port {
103                         get { return port; }
104                 }
105
106                 public PortType PortType {
107                         get { return portType; }
108                 }
109
110                 public abstract string ProtocolName {
111                         get; 
112                 }
113
114                 public XmlReflectionImporter ReflectionImporter 
115                 {
116                         get
117                         {
118                                 if (reflectionImporter == null) {
119                                         reflectionImporter = typeInfo.XmlImporter;
120                                         if (reflectionImporter == null)
121                                                 reflectionImporter = new XmlReflectionImporter();
122                                 }
123                                 return reflectionImporter;
124                         }
125                 }
126
127                 internal SoapReflectionImporter SoapReflectionImporter 
128                 {
129                         get
130                         {
131                                 if (soapReflectionImporter == null) {
132                                         soapReflectionImporter = typeInfo.SoapImporter;
133                                         if (soapReflectionImporter == null)
134                                                 soapReflectionImporter = new SoapReflectionImporter();
135                                 }
136                                 return soapReflectionImporter;
137                         }
138                 }
139
140                 public XmlSchemaExporter SchemaExporter {
141                         get { return schemaExporter; }
142                 }
143
144                 public SoapSchemaExporter SoapSchemaExporter {
145                         get { return soapSchemaExporter; }
146                 }
147
148                 public XmlSchemas Schemas {
149                         get { return serviceReflector.Schemas; }
150                 }
151
152                 public Service Service {
153                         get { return service; }
154                 }
155
156                 public ServiceDescription ServiceDescription {
157                         get { return serviceDescription; }
158                 }
159
160                 public ServiceDescriptionCollection ServiceDescriptions {
161                         get { return serviceReflector.ServiceDescriptions; }
162                 }
163
164                 public Type ServiceType {
165                         get { return serviceType; }
166                 }
167
168                 public string ServiceUrl {
169                         get { return serviceUrl; }
170                 }
171                 
172                 internal MethodStubInfo MethodStubInfo {
173                         get { return methodStubInfo; }
174                 }
175                 
176                 internal TypeStubInfo TypeInfo {
177                         get { return typeInfo; }
178                 }
179
180
181                 #endregion // Properties
182
183                 #region Methods
184                 
185                 internal void Reflect (ServiceDescriptionReflector serviceReflector, Type type, string url, XmlSchemaExporter xxporter, SoapSchemaExporter sxporter)
186                 {
187                         this.serviceReflector = serviceReflector;
188                         serviceUrl = url;
189                         serviceType = type;
190                         
191                         schemaExporter = xxporter;
192                         soapSchemaExporter = sxporter;
193                         
194                         typeInfo = TypeStubManager.GetTypeStub (type, ProtocolName);
195                         
196                         ServiceDescription desc = ServiceDescriptions [typeInfo.LogicalType.WebServiceNamespace];
197                         
198                         if (desc == null)
199                         {
200                                 desc = new ServiceDescription ();
201                                 desc.TargetNamespace = typeInfo.LogicalType.WebServiceNamespace;
202                                 desc.Name = typeInfo.LogicalType.WebServiceName;
203                                 ServiceDescriptions.Add (desc);
204                         }
205                         
206                         ImportService (desc, typeInfo, url);                    
207                 }
208
209                 void ImportService (ServiceDescription desc, TypeStubInfo typeInfo, string url)
210                 {
211                         service = desc.Services [typeInfo.LogicalType.WebServiceName];
212                         if (service == null)
213                         {
214                                 service = new Service ();
215                                 service.Name = typeInfo.LogicalType.WebServiceName;
216                                 service.Documentation = typeInfo.LogicalType.Description;
217                                 desc.Services.Add (service);
218                         }
219                         
220                         foreach (BindingInfo binfo in typeInfo.Bindings)
221                                 ImportBinding (desc, service, typeInfo, url, binfo);
222                 }
223                 
224                 void ImportBinding (ServiceDescription desc, Service service, TypeStubInfo typeInfo, string url, BindingInfo binfo)
225                 {
226                         port = new Port ();
227                         port.Name = binfo.Name;
228                         port.Binding = new XmlQualifiedName (binfo.Name, binfo.Namespace);
229                         service.Ports.Add (port);
230
231                         if (binfo.Namespace != desc.TargetNamespace)
232                         {
233                                 if (binfo.Location == null || binfo.Location == string.Empty)
234                                 {
235                                         ServiceDescription newDesc = new ServiceDescription();
236                                         newDesc.TargetNamespace = binfo.Namespace;
237                                         int id = ServiceDescriptions.Add (newDesc);
238                                         AddImport (desc, binfo.Namespace, GetWsdlUrl (url,id));
239                                         ImportBindingContent (newDesc, typeInfo, url, binfo);
240                                 }
241                                 else
242                                         AddImport (desc, binfo.Namespace, binfo.Location);
243                         }
244                         else
245                                 ImportBindingContent (desc, typeInfo, url, binfo);
246                 }
247
248                 void ImportBindingContent (ServiceDescription desc, TypeStubInfo typeInfo, string url, BindingInfo binfo)
249                 {
250                         serviceDescription = desc;
251                         binding = new Binding ();
252                         binding.Name = binfo.Name;
253                         binding.Type = new XmlQualifiedName (binfo.Name, binfo.Namespace);
254                         desc.Bindings.Add (binding);
255                         
256                         portType = new PortType ();
257                         portType.Name = binding.Name;
258                         desc.PortTypes.Add (portType);
259
260                         BeginClass ();
261                         
262                         foreach (MethodStubInfo method in typeInfo.Methods)
263                         {
264                                 methodStubInfo = method;
265                                 
266                                 string metBinding = ReflectMethodBinding ();
267                                 if (metBinding != null && (metBinding != binding.Name)) continue;
268                                 
269                                 operation = new Operation ();
270                                 operation.Name = method.OperationName;
271                                 operation.Documentation = method.MethodAttribute.Description;
272                                 
273                                 inputMessage = new Message ();
274                                 inputMessage.Name = method.Name + ProtocolName + "In";
275                                 ServiceDescription.Messages.Add (inputMessage);
276                                 
277                                 outputMessage = new Message ();
278                                 outputMessage.Name = method.Name + ProtocolName + "Out";
279                                 ServiceDescription.Messages.Add (outputMessage);
280
281                                 OperationInput inOp = new OperationInput ();
282                                 if (method.Name != method.OperationName) inOp.Name = method.Name;
283                                 Operation.Messages.Add (inOp);
284                                 inOp.Message = new XmlQualifiedName (inputMessage.Name, ServiceDescription.TargetNamespace);
285                                 
286                                 OperationOutput outOp = new OperationOutput ();
287                                 if (method.Name != method.OperationName) outOp.Name = method.Name;
288                                 Operation.Messages.Add (outOp);
289                                 outOp.Message = new XmlQualifiedName (outputMessage.Name, ServiceDescription.TargetNamespace);
290                         
291                                 portType.Operations.Add (operation);
292                                 ImportOperationBinding ();
293                                 
294                                 ReflectMethod ();
295                                 
296                                 foreach (SoapExtensionReflector reflector in extensionReflectors)
297                                 {
298                                         reflector.ReflectionContext = this;
299                                         reflector.ReflectMethod ();
300                                 }
301                         }
302
303                         EndClass ();
304                 }
305
306                 void ImportOperationBinding ()
307                 {
308                         operationBinding = new OperationBinding ();
309                         operationBinding.Name = methodStubInfo.OperationName;
310                         
311                         InputBinding inOp = new InputBinding ();
312                         operationBinding.Input = inOp;
313                         
314                         OutputBinding outOp = new OutputBinding ();
315                         operationBinding.Output = outOp;
316                         
317                         if (methodStubInfo.OperationName != methodStubInfo.Name)
318                                 inOp.Name = outOp.Name = methodStubInfo.Name;
319                         
320                         binding.Operations.Add (operationBinding);
321                 }
322                 
323                 internal static void AddImport (ServiceDescription desc, string ns, string location)
324                 {
325                         Import im = new Import();
326                         im.Namespace = ns;
327                         im.Location = location;
328                         desc.Imports.Add (im);
329                 }
330                 
331                 string GetWsdlUrl (string baseUrl, int id)
332                 {
333                         return baseUrl + "?wsdl=" + id;
334                 }
335                 
336                 protected virtual void BeginClass ()
337                 {
338                 }
339
340                 protected virtual void EndClass ()
341                 {
342                 }
343
344                 public ServiceDescription GetServiceDescription (string ns)
345                 {
346                         return ServiceDescriptions [ns];
347                 }
348
349                 protected abstract bool ReflectMethod ();
350
351                 protected virtual string ReflectMethodBinding ()
352                 {
353                         return null;
354                 }
355
356                 #endregion
357         }
358 }