2009-07-11 Michael Barker <mike@middlesoft.co.uk>
[mono.git] / mcs / class / System.ServiceModel / System.ServiceModel / OperationContext.cs
1 //
2 // OperationContext.cs
3 //
4 // Author: Atsushi Enomoto (atsushi@ximian.com)
5 //
6 // Copyright (C) 2005,2007 Novell, Inc (http://www.novell.com)
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining
9 // a copy of this software and associated documentation files (the
10 // "Software"), to deal in the Software without restriction, including
11 // without limitation the rights to use, copy, modify, merge, publish,
12 // distribute, sublicense, and/or sell copies of the Software, and to
13 // permit persons to whom the Software is furnished to do so, subject to
14 // the following conditions:
15 // 
16 // The above copyright notice and this permission notice shall be
17 // included in all copies or substantial portions of the Software.
18 // 
19 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
23 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 //
27 using System;
28 using System.Collections.Generic;
29 using System.Collections.ObjectModel;
30 using System.ServiceModel.Channels;
31 using System.ServiceModel.Dispatcher;
32 using System.ServiceModel.Security;
33 using System.Threading;
34
35 namespace System.ServiceModel
36 {
37         public sealed class OperationContext : IExtensibleObject<OperationContext>
38         {
39                 // generated guid (no special meaning)
40                 const string operation_context_name = "c15795e2-bb44-4cfb-a89c-8529feb170cb";
41                 Message incoming_message;
42
43                 public static OperationContext Current {
44                         get { return Thread.GetData (Thread.GetNamedDataSlot (operation_context_name)) as OperationContext; }
45                         set { Thread.SetData (Thread.GetNamedDataSlot (operation_context_name), value); }
46                 }
47
48 #if !NET_2_1
49                 EndpointDispatcher dispatcher;
50 #endif
51                 IContextChannel channel;
52                 RequestContext request_ctx;
53                 ExtensionCollection<OperationContext> extensions;
54                 MessageHeaders outgoing_headers;
55                 MessageProperties outgoing_properties;
56                 InstanceContext instance_context;
57
58                 public OperationContext (IContextChannel channel)
59                 {
60                         if (channel == null)
61                                 throw new ArgumentNullException ("channel");
62                         this.channel = channel;
63                 }
64
65                 public event EventHandler OperationCompleted;
66
67                 public IContextChannel Channel {
68                         get { return channel; }
69                 }
70
71                 public IExtensionCollection<OperationContext> Extensions {
72                         get {
73                                 if (extensions == null)
74                                         extensions = new ExtensionCollection<OperationContext> (this);
75                                 return extensions;
76                         }
77                 }
78
79
80 #if !NET_2_1
81                 public EndpointDispatcher EndpointDispatcher {
82                         get { return dispatcher; }
83                         set { dispatcher = value; }
84                 }
85                 public bool HasSupportingTokens {
86                         get { return SupportingTokens != null ? SupportingTokens.Count > 0 : false; }
87                 }
88
89                 public ServiceHostBase Host {
90                         get { return dispatcher != null ? dispatcher.ChannelDispatcher.Host : null; }
91                 }
92 #endif
93
94                 public MessageHeaders IncomingMessageHeaders {
95                         get { return incoming_message != null ? incoming_message.Headers : null; }
96                 }
97
98                 public MessageProperties IncomingMessageProperties {
99                         get { return incoming_message != null ? incoming_message.Properties : null; }
100                 }
101
102                 public MessageVersion IncomingMessageVersion {
103                         get { return incoming_message != null ? incoming_message.Version : null; }
104                 }
105
106                 [MonoTODO]
107                 public InstanceContext InstanceContext {
108                         get {                           
109                                 return instance_context;
110                         }
111                         internal set {
112                                 instance_context = value;
113                         }
114                 }
115
116                 [MonoTODO]
117                 public bool IsUserContext {
118                         get { throw new NotImplementedException (); }
119                 }
120
121                 public MessageHeaders OutgoingMessageHeaders {
122                         get {
123                                 if (outgoing_headers == null)
124                                         outgoing_headers = new MessageHeaders (MessageVersion.Default);
125                                 return outgoing_headers;
126                         }
127                 }
128
129                 public MessageProperties OutgoingMessageProperties {
130                         get {
131                                 if (outgoing_properties == null)
132                                         outgoing_properties = new MessageProperties ();
133                                 return outgoing_properties;
134                         }
135                 }
136
137                 public RequestContext RequestContext {
138                         get { return request_ctx; }
139                         set { request_ctx = value; }
140                 }
141
142                 public string SessionId {
143                         get { return Channel.SessionId; }
144                 }
145
146 #if !NET_2_1
147                 public ServiceSecurityContext ServiceSecurityContext {
148                         get { return IncomingMessageProperties != null ? IncomingMessageProperties.Security.ServiceSecurityContext : null; }
149                 }
150
151                 public ICollection<SupportingTokenSpecification> SupportingTokens {
152                         get { return IncomingMessageProperties != null ? IncomingMessageProperties.Security.IncomingSupportingTokens : null; }
153                 }
154
155                 public T GetCallbackChannel<T> ()
156                 {
157                         if (!(channel is IDuplexContextChannel))
158                                 return default (T);
159                         IDuplexContextChannel duplex = (IDuplexContextChannel) channel;
160                         foreach (IChannel ch in duplex.CallbackInstance.IncomingChannels)
161                                 if (typeof (T).IsAssignableFrom (ch.GetType ()))
162                                         return (T) (object) ch;
163                         foreach (IChannel ch in duplex.CallbackInstance.OutgoingChannels)
164                                 if (typeof (T).IsAssignableFrom (ch.GetType ()))
165                                         return (T) (object) ch;
166                         return default (T);
167                 }
168
169                 [MonoTODO]
170                 public void SetTransactionComplete ()
171                 {
172                         throw new NotImplementedException ();
173                 }
174 #endif
175
176                 internal Message IncomingMessage {
177                         get {
178                                 return incoming_message;
179                         }
180                         set {
181                                 incoming_message = value;
182                         }
183                 }
184         }
185 }