1 //
2 // InstanceContext.cs
3 //
4 // Author:
5 //	Atsushi Enomoto <atsushi@ximian.com>
6 //
7 // Copyright (C) 2005-2006 Novell, Inc.  http://www.novell.com
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28 using System;
29 using System.Threading;
30 using System.Collections.Generic;
31 using System.ServiceModel.Channels;
32 using System.ServiceModel.Dispatcher;
33 
34 namespace System.ServiceModel
35 {
36 	public sealed class InstanceContext : CommunicationObject,
37 		IExtensibleObject<InstanceContext>
38 	{
39 		ServiceHostBase host;
40 		object implementation;
41 		int manual_flow_limit;
42 		InstanceManager instance_manager;
43 		bool is_user_instance_provider;
44 		bool is_user_context_provider;
45 		ExtensionCollection<InstanceContext> _extensions;
46 
47 		static InstanceContextIdleCallback idle_callback = new InstanceContextIdleCallback(NotifyIdle);
48 
InstanceContext(object implementation)49 		public InstanceContext (object implementation)
50 			: this (null, implementation)
51 		{
52 		}
53 
InstanceContext(ServiceHostBase host)54 		public InstanceContext (ServiceHostBase host)
55 			: this (host, null)
56 		{
57 		}
58 
InstanceContext(ServiceHostBase host, object implementation)59 		public InstanceContext (ServiceHostBase host, object implementation)
60 			: this (host, implementation, true)
61 		{
62 		}
63 
InstanceContext(ServiceHostBase host, object implementation, bool userContextProvider)64 		internal InstanceContext (ServiceHostBase host, object implementation, bool userContextProvider)
65 		{
66 			this.host = host;
67 			this.implementation = implementation;
68 			is_user_context_provider = userContextProvider;
69 		}
70 
71 		internal bool IsUserProvidedInstance {
72 			get {
73 				return is_user_instance_provider;
74 			}
75 		}
76 
77 		internal bool IsUserProvidedContext {
78 			get { return is_user_context_provider; }
79 		}
80 
81 		internal InstanceManager InstanceManager {
82 			get { return instance_manager; }
83 			set { instance_manager = value; }
84 		}
85 
86 		protected internal override TimeSpan DefaultCloseTimeout {
87 			get { return host.DefaultCloseTimeout; }
88 		}
89 
90 		protected internal override TimeSpan DefaultOpenTimeout {
91 			get { return host.DefaultOpenTimeout; }
92 		}
93 
94 		public IExtensionCollection<InstanceContext> Extensions {
95 			get {
96 				if (_extensions == null)
97 					_extensions = new ExtensionCollection<InstanceContext> (this);
98 				return _extensions;
99 			}
100 		}
101 
102 		public ServiceHostBase Host {
103 			get { return host; }
104 		}
105 
106 		public ICollection<IChannel> IncomingChannels {
107 			get { throw new NotImplementedException (); }
108 		}
109 
110 		public int ManualFlowControlLimit {
111 			get { return manual_flow_limit; }
112 			set { manual_flow_limit = value; }
113 		}
114 
115 		public ICollection<IChannel> OutgoingChannels {
116 			get { throw new NotImplementedException (); }
117 		}
118 
GetServiceInstance()119 		public object GetServiceInstance ()
120 		{
121 			return GetServiceInstance (null);
122 		}
123 
GetServiceInstance(Message message)124 		public object GetServiceInstance (Message message)
125 		{
126 			if (implementation == null && instance_manager != null) {
127 				implementation = instance_manager.GetServiceInstance (this, message, ref is_user_instance_provider);
128 			}
129 			return implementation;
130 		}
131 
IncrementManualFlowControlLimit(int incrementBy)132 		public int IncrementManualFlowControlLimit (int incrementBy)
133 		{
134 			throw new NotImplementedException ();
135 		}
136 
CloseIfIdle()137 		internal void CloseIfIdle () {
138 			if (instance_manager.InstanceContextProvider != null && !IsUserProvidedContext) {
139 				if (!instance_manager.InstanceContextProvider.IsIdle (this)) {
140 					instance_manager.InstanceContextProvider.NotifyIdle (IdleCallback, this);
141 				}
142 				else {
143 					if (State != CommunicationState.Closed)
144 						Close ();
145 				}
146 			}
147 		}
148 
NotifyIdle(InstanceContext ctx)149 		static void NotifyIdle (InstanceContext ctx) {
150 			ctx.CloseIfIdle ();
151 		}
152 
153 		internal InstanceContextIdleCallback IdleCallback {
154 			get {
155 				return idle_callback;
156 			}
157 		}
158 
ReleaseServiceInstance()159 		public void ReleaseServiceInstance ()
160 		{
161 			instance_manager.ReleaseServiceInstance (this, implementation);
162 			// This does NOT dispose the instance implementation. See DispatrchRuntimeTest.TestInstanceBehavior2 (which never reports "Dispose").
163 			implementation = null;
164 		}
165 
DisposeInstance()166 		void DisposeInstance ()
167 		{
168 			var disp = implementation as IDisposable;
169 			if (disp != null)
170 				disp.Dispose ();
171 			implementation = null;
172 		}
173 
OnAbort()174 		protected override void OnAbort ()
175 		{
176 			DisposeInstance ();
177 		}
178 
OnFaulted()179 		protected override void OnFaulted ()
180 		{
181 			DisposeInstance ();
182 			base.OnFaulted ();
183 		}
184 
OnClosed()185 		protected override void OnClosed ()
186 		{
187 			DisposeInstance ();
188 			base.OnClosed ();
189 		}
190 
191 		[MonoTODO]
OnOpened()192 		protected override void OnOpened ()
193 		{
194 			base.OnOpened ();
195 		}
196 
OnOpening()197 		protected override void OnOpening ()
198 		{
199 			base.OnOpening ();
200 			if (instance_manager != null)
201 				instance_manager.Initialize (this);
202 		}
203 
204 		Action<TimeSpan> open_delegate, close_delegate;
205 
OnBeginOpen( TimeSpan timeout, AsyncCallback callback, object state)206 		protected override IAsyncResult OnBeginOpen (
207 			TimeSpan timeout, AsyncCallback callback, object state)
208 		{
209 			if (open_delegate == null)
210 				open_delegate = new Action<TimeSpan> (OnOpen);
211 			return open_delegate.BeginInvoke (timeout, callback, state);
212 		}
213 
OnEndOpen(IAsyncResult result)214 		protected override void OnEndOpen (IAsyncResult result)
215 		{
216 			open_delegate.EndInvoke (result);
217 		}
218 
OnOpen(TimeSpan timeout)219 		protected override void OnOpen (TimeSpan timeout)
220 		{
221 		}
222 
OnBeginClose( TimeSpan timeout, AsyncCallback callback, object state)223 		protected override IAsyncResult OnBeginClose (
224 			TimeSpan timeout, AsyncCallback callback, object state)
225 		{
226 			if (close_delegate == null)
227 				close_delegate = new Action<TimeSpan> (OnClose);
228 			return close_delegate.BeginInvoke (timeout, callback, state);
229 		}
230 
OnEndClose(IAsyncResult result)231 		protected override void OnEndClose (IAsyncResult result)
232 		{
233 			close_delegate.EndInvoke (result);
234 		}
235 
OnClose(TimeSpan timeout)236 		protected override void OnClose (TimeSpan timeout)
237 		{
238 		}
239 
240 		[MonoTODO]
241 		public SynchronizationContext SynchronizationContext {
242 			get { throw new NotImplementedException (); }
243 			set { throw new NotImplementedException (); }
244 		}
245 	}
246 }
247