2005-01-31 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mcs / class / corlib / System.Runtime.Remoting.Contexts / CrossContextChannel.cs
1 //
2 // System.Runtime.Remoting.Contexts.CrossContextChannel.cs
3 //
4 // Author: Lluis Sanchez Gual (lluis@ideary.com)
5 //
6 // (C) 2002, Lluis Sanchez Gual
7 //
8
9 //
10 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
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 \r
32 using System;\r
33 using System.Threading;\r
34 using System.Runtime.Remoting.Messaging;\r
35 using System.Runtime.Remoting.Activation;\r
36 using System.Runtime.Remoting.Channels;\r
37 \r
38 namespace System.Runtime.Remoting.Contexts\r
39 {\r
40         internal class CrossContextChannel: IMessageSink\r
41         {\r
42                 public IMessage SyncProcessMessage (IMessage msg)
43                 {
44                         ServerIdentity identity = (ServerIdentity) RemotingServices.GetMessageTargetIdentity (msg);
45
46                         Context oldContext = null;
47                         IMessage response;
48
49                         if (Threading.Thread.CurrentContext != identity.Context)
50                                 oldContext = Context.SwitchToContext (identity.Context);
51
52                         try
53                         {
54                                 Context.NotifyGlobalDynamicSinks (true, msg, false, false);
55                                 Thread.CurrentContext.NotifyDynamicSinks (true, msg, false, false);
56
57                                 response = identity.Context.GetServerContextSinkChain().SyncProcessMessage (msg);
58
59                                 Context.NotifyGlobalDynamicSinks (false, msg, false, false);
60                                 Thread.CurrentContext.NotifyDynamicSinks (false, msg, false, false);
61                         }
62                         catch (Exception ex)
63                         {
64                                 response = new ReturnMessage (ex, (IMethodCallMessage)msg);
65                         }
66                         finally
67                         {
68                                 if (oldContext != null)
69                                         Context.SwitchToContext (oldContext);
70                         }
71                         
72                         return response;
73                 }
74
75                 public IMessageCtrl AsyncProcessMessage (IMessage msg, IMessageSink replySink)
76                 {
77                         ServerIdentity identity = (ServerIdentity) RemotingServices.GetMessageTargetIdentity (msg);
78                         
79                         Context oldContext = null;
80                         if (Threading.Thread.CurrentContext != identity.Context)
81                                 oldContext = Context.SwitchToContext (identity.Context);
82
83                         try
84                         {
85                                 Context.NotifyGlobalDynamicSinks (true, msg, false, true);
86                                 Thread.CurrentContext.NotifyDynamicSinks (true, msg, false, false);
87                                 if (replySink != null) replySink = new ContextRestoreSink (replySink, oldContext, msg);
88
89                                 IMessageCtrl res = identity.AsyncObjectProcessMessage (msg, replySink);
90
91                                 if (replySink == null)
92                                 {
93                                         Context.NotifyGlobalDynamicSinks (false, msg, false, false);
94                                         Thread.CurrentContext.NotifyDynamicSinks (false, msg, false, false);
95                                 }
96
97                                 return res;
98                         }
99                         catch (Exception ex)
100                         {
101                                 if (replySink != null)
102                                         replySink.SyncProcessMessage (new ReturnMessage (ex, (IMethodCallMessage)msg));
103                                 return null;
104                         }
105                         finally
106                         {
107                                 if (oldContext != null)
108                                         Context.SwitchToContext (oldContext);
109                         }
110                 }
111
112                 public IMessageSink NextSink 
113                 { 
114                         get { return null; }
115                 }\r
116 \r
117                 class ContextRestoreSink: IMessageSink\r
118                 {\r
119                         IMessageSink _next;\r
120                         Context _context;\r
121                         IMessage _call;\r
122 \r
123                         public ContextRestoreSink (IMessageSink next, Context context, IMessage call)\r
124                         {\r
125                                 _next = next;\r
126                                 _context = context;\r
127                                 _call = call;\r
128                         }\r
129 \r
130                         public IMessage SyncProcessMessage (IMessage msg)
131                         {
132                                 try
133                                 {
134                                         Context.NotifyGlobalDynamicSinks (false, msg, false, false);
135                                         Thread.CurrentContext.NotifyDynamicSinks (false, msg, false, false);
136                                         return _next.SyncProcessMessage (msg);
137                                 }
138                                 catch (Exception ex)
139                                 {
140                                         return new ReturnMessage (ex, (IMethodCallMessage)_call);
141                                 }
142                                 finally
143                                 {
144                                         if (_context != null)
145                                                 Context.SwitchToContext (_context);
146                                 }               \r
147                         }
148
149                         public IMessageCtrl AsyncProcessMessage (IMessage msg, IMessageSink replySink)
150                         {
151                                 throw new NotSupportedException();      // Not needed
152                         }
153
154                         public IMessageSink NextSink 
155                         { 
156                                 get { return _next; }
157                         }               \r
158                 }\r
159 \r
160         }\r
161 }\r