2006-12-12 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / class / System.Web.Services / System.Web.Services.Protocols / SoapMessage.cs
1 // 
2 // System.Web.Services.Protocols.SoapMessage.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 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 // 
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31
32 using HeaderInfo = System.Web.Services.Protocols.SoapHeaderMapping;
33
34 using System.ComponentModel;
35 using System.IO;
36 using System.Web.Services;
37
38 namespace System.Web.Services.Protocols {
39         public abstract class SoapMessage {
40
41                 #region Fields
42
43                 string content_type = "text/xml";
44                 string content_encoding;
45                 SoapException exception = null;
46                 SoapHeaderCollection headers;
47                 SoapMessageStage stage;
48                 Stream stream;
49                 object[] inParameters;
50                 object[] outParameters;
51                 
52 #if NET_2_0
53                 SoapProtocolVersion soapVersion;
54 #endif
55
56                 #endregion // Fields
57
58                 #region Constructors
59
60                 internal SoapMessage ()
61                 {
62                         headers = new SoapHeaderCollection ();
63                 }
64
65                 internal SoapMessage (Stream stream, SoapException exception)
66                 {
67                         this.exception = exception;
68                         this.stream = stream;
69                         headers = new SoapHeaderCollection ();
70                 }
71
72                 #endregion
73
74                 #region Properties
75
76                 internal object[] InParameters 
77                 {
78                         get { return inParameters; }
79                         set { inParameters = value; }
80                 }
81
82                 internal object[] OutParameters 
83                 {
84                         get { return outParameters; }
85                         set { outParameters = value; }
86                 }
87
88                 public abstract string Action 
89                 {
90                         get;
91                 }
92
93                 public string ContentType {
94                         get { return content_type; }
95                         set { content_type = value; }
96                 }
97
98                 public SoapException Exception {
99                         get { return exception; }
100 #if NET_2_0
101                         set { exception = value; }
102 #endif
103                 }
104
105                 public SoapHeaderCollection Headers {
106                         get { return headers; }
107                 }
108
109                 public abstract LogicalMethodInfo MethodInfo {
110                         get;
111                 }
112
113                 public abstract bool OneWay {
114                         get;
115                 }
116
117                 public SoapMessageStage Stage {
118                         get { return stage; }
119                 }
120
121                 internal void SetStage (SoapMessageStage stage)
122                 {
123                         this.stage = stage;
124                 }
125                 
126                 public Stream Stream {
127                         get {
128                                 return stream;
129                         }
130                 }
131
132                 public abstract string Url {
133                         get;
134                 }
135                 
136 #if NET_1_1
137                 public string ContentEncoding
138                 {
139                         get { return content_encoding; }
140                         set { content_encoding = value; }
141                 }
142 #else
143                 internal string ContentEncoding
144                 {
145                         get { return content_encoding; }
146                         set { content_encoding = value; }
147                 }
148 #endif
149
150 #if NET_2_0
151                 [System.Runtime.InteropServices.ComVisible(false)]
152                 [DefaultValue (SoapProtocolVersion.Default)]
153                 public virtual SoapProtocolVersion SoapVersion {
154                         get { return soapVersion; }
155                 }
156 #endif
157  
158                 internal Stream InternalStream 
159                 { 
160                         // for getter use public stream property
161                         set {
162                                 stream = value;
163                         }
164                 }
165
166                 #endregion Properties
167
168                 #region Methods
169
170                 protected abstract void EnsureInStage ();
171                 protected abstract void EnsureOutStage ();
172
173                 protected void EnsureStage (SoapMessageStage stage) 
174                 {
175                         if ((((int) stage) & ((int) Stage)) == 0)
176                                 throw new InvalidOperationException ("The current SoapMessageStage is not the asserted stage or stages.");
177                 }
178
179                 public object GetInParameterValue (int index) 
180                 {
181                         return inParameters [index];
182                 }
183
184                 public object GetOutParameterValue (int index) 
185                 {
186                         if (MethodInfo.IsVoid) return outParameters [index];
187                         else return outParameters [index + 1];
188                 }
189
190                 public object GetReturnValue ()
191                 {
192                         if (!MethodInfo.IsVoid && exception == null) return outParameters [0];
193                         else return null;
194                 }
195
196                 internal void SetHeaders (SoapHeaderCollection headers)
197                 {
198                         this.headers = headers;
199                 }
200
201                 internal void SetException (SoapException ex)
202                 {
203                         exception = ex;
204                 }
205
206                 internal void CollectHeaders (object target, HeaderInfo[] headers, SoapHeaderDirection direction)
207                 {
208                         Headers.Clear ();
209                         foreach (HeaderInfo hi in headers) 
210                         {
211                                 if ((hi.Direction & direction) != 0 && !hi.Custom) 
212                                 {
213                                         SoapHeader headerVal = hi.GetHeaderValue (target) as SoapHeader;
214                                         if (headerVal != null)
215                                                 Headers.Add (headerVal);
216                                 }
217                         }
218                 }
219
220                 internal void UpdateHeaderValues (object target, HeaderInfo[] headersInfo)
221                 {
222                         foreach (SoapHeader header in Headers)
223                         {
224                                 HeaderInfo hinfo = FindHeader (headersInfo, header.GetType ());
225                                 if (hinfo != null) {
226                                         hinfo.SetHeaderValue (target, header);
227                                         header.DidUnderstand = !hinfo.Custom;
228                                 }
229                         }
230                 }
231
232                 HeaderInfo FindHeader (HeaderInfo[] headersInfo, Type headerType)
233                 {
234                         HeaderInfo unknownHeaderInfo = null;
235                 
236                         foreach (HeaderInfo headerInfo in headersInfo) {
237                                 if (headerInfo.HeaderType == headerType)
238                                         return headerInfo;
239                                 else if (headerInfo.Custom) 
240                                         unknownHeaderInfo = headerInfo;
241                         }
242                         return unknownHeaderInfo;
243                 }
244
245                 #endregion // Methods
246         }
247 }