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 		[ThreadStatic]
40 		static OperationContext current;
41 
42 		public static OperationContext Current {
43 			get { return current; }
44 			set { current = value; }
45 		}
46 
47 		Message incoming_message;
48 #if !MOBILE && !XAMMAC_4_5
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 
OperationContext(IContextChannel channel)58 		public OperationContext (IContextChannel channel)
59 			: this (channel, true)
60 		{
61 		}
62 
OperationContext(IContextChannel channel, bool isUserContext)63 		internal OperationContext (IContextChannel channel, bool isUserContext)
64 		{
65 			if (channel == null)
66 				throw new ArgumentNullException ("channel");
67 			this.channel = channel;
68 			IsUserContext = isUserContext;
69 		}
70 
71 		public event EventHandler OperationCompleted;
72 
73 		public IContextChannel Channel {
74 			get { return channel; }
75 		}
76 
77 		public IExtensionCollection<OperationContext> Extensions {
78 			get {
79 				if (extensions == null)
80 					extensions = new ExtensionCollection<OperationContext> (this);
81 				return extensions;
82 			}
83 		}
84 
85 
86 #if !MOBILE && !XAMMAC_4_5
87 		public EndpointDispatcher EndpointDispatcher {
88 			get { return dispatcher; }
89 			set { dispatcher = value; }
90 		}
91 		public bool HasSupportingTokens {
92 			get { return SupportingTokens != null ? SupportingTokens.Count > 0 : false; }
93 		}
94 
95 		public ServiceHostBase Host {
96 			get { return dispatcher != null ? dispatcher.ChannelDispatcher.Host : null; }
97 		}
98 #endif
99 
100 		public MessageHeaders IncomingMessageHeaders {
101 			get { return incoming_message != null ? incoming_message.Headers : null; }
102 		}
103 
104 		public MessageProperties IncomingMessageProperties {
105 			get { return incoming_message != null ? incoming_message.Properties : null; }
106 		}
107 
108 		public MessageVersion IncomingMessageVersion {
109 			get { return incoming_message != null ? incoming_message.Version : null; }
110 		}
111 
112 		[MonoTODO]
113 		public InstanceContext InstanceContext {
114 			get {
115 				return instance_context;
116 			}
117 			internal set {
118 				instance_context = value;
119 			}
120 		}
121 
122 		public bool IsUserContext { get; private set; }
123 
124 		public MessageHeaders OutgoingMessageHeaders {
125 			get {
126 				if (outgoing_headers == null)
127 					outgoing_headers = new MessageHeaders (channel.GetProperty<MessageVersion> () ?? MessageVersion.Default);
128 				return outgoing_headers;
129 			}
130 		}
131 
132 		public MessageProperties OutgoingMessageProperties {
133 			get {
134 				if (outgoing_properties == null)
135 					outgoing_properties = new MessageProperties ();
136 				return outgoing_properties;
137 			}
138 		}
139 
140 		public RequestContext RequestContext {
141 			get { return request_ctx; }
142 			set { request_ctx = value; }
143 		}
144 
145 		public string SessionId {
146 			get { return Channel.SessionId; }
147 		}
148 
149 #if !MOBILE
150 		public ServiceSecurityContext ServiceSecurityContext {
151 			get { return IncomingMessageProperties != null ? IncomingMessageProperties.Security.ServiceSecurityContext : null; }
152 		}
153 
154 		public ICollection<SupportingTokenSpecification> SupportingTokens {
155 			get { return IncomingMessageProperties != null ? IncomingMessageProperties.Security.IncomingSupportingTokens : null; }
156 		}
157 
GetCallbackChannel()158 		public T GetCallbackChannel<T> ()
159 		{
160 			// It is correct; OperationContext.Channel and OperationContext.GetCallbackChannel<T>() returns the same instance on .NET. (at least as far as I tested.)
161 			return (T) (object) channel;
162 		}
163 
164 		[MonoTODO]
SetTransactionComplete()165 		public void SetTransactionComplete ()
166 		{
167 			throw new NotImplementedException ();
168 		}
169 #endif
170 
171 		internal Message IncomingMessage {
172 			get {
173 				return incoming_message;
174 			}
175 			set {
176 				incoming_message = value;
177 			}
178 		}
179 	}
180 }
181