* ObjRef.cs: Fixed type check in in ObjRef constructor. The requested class
[mono.git] / mcs / class / corlib / System.Runtime.Remoting / ObjRef.cs
1 //
2 // System.Runtime.Remoting.ObjRef.cs
3 //
4 // Author:
5 //   Miguel de Icaza (miguel@ximian.com)
6 //   Dietmar Maurer (dietmar@ximian.com)
7 //   Lluis Sanchez Gual (lluis@ideary.com)
8 //   Patrik Torstensson
9 //
10 // (C) Ximian, Inc.  http://www.ximian.com
11 //
12
13 //
14 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
15 //
16 // Permission is hereby granted, free of charge, to any person obtaining
17 // a copy of this software and associated documentation files (the
18 // "Software"), to deal in the Software without restriction, including
19 // without limitation the rights to use, copy, modify, merge, publish,
20 // distribute, sublicense, and/or sell copies of the Software, and to
21 // permit persons to whom the Software is furnished to do so, subject to
22 // the following conditions:
23 // 
24 // The above copyright notice and this permission notice shall be
25 // included in all copies or substantial portions of the Software.
26 // 
27 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
28 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
29 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
30 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
31 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
32 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
33 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 //
35
36 using System;
37 using System.Runtime.Serialization;
38 using System.Runtime.Remoting.Channels;
39 using System.Runtime.Remoting.Messaging;
40 using System.Runtime.Remoting.Proxies;
41
42 namespace System.Runtime.Remoting {
43
44         [Serializable]
45         public class ObjRef : IObjectReference, ISerializable 
46         {
47                 IChannelInfo channel_info;
48                 string uri;
49                 IRemotingTypeInfo typeInfo;
50                 IEnvoyInfo envoyInfo;
51                 int flags;
52                 Type _serverType;
53
54                 static int MarshalledObjectRef = 1;
55                 static int WellKnowObjectRef = 2;
56                 
57                 public ObjRef ()
58                 {
59                         // no idea why this needs to be public
60
61                         UpdateChannelInfo();
62                 }
63
64                 internal ObjRef (string typeName, string uri, IChannelInfo cinfo) 
65                 {
66                         this.uri = uri;
67                         channel_info = cinfo;
68                         typeInfo = new TypeInfo (Type.GetType (typeName));
69                 }
70
71                 internal ObjRef (ObjRef o, bool unmarshalAsProxy) {
72                         channel_info = o.channel_info;
73                         uri = o.uri;
74         
75                         typeInfo = o.typeInfo;
76                         envoyInfo = o.envoyInfo;
77                         flags = o.flags;
78                         if (unmarshalAsProxy) flags |= MarshalledObjectRef;
79                 }
80
81                 public ObjRef (MarshalByRefObject mbr, Type type)
82                 {
83                         if (mbr == null)
84                                 throw new ArgumentNullException ("mbr");
85                         
86                         if (type == null)
87                                 throw new ArgumentNullException ("type");
88
89                         // The ObjRef can only be constructed if the given mbr
90                         // has already been marshalled using RemotingServices.Marshall
91
92                         uri = RemotingServices.GetObjectUri(mbr);
93                         typeInfo = new TypeInfo(type);
94
95                         if (!type.IsAssignableFrom (mbr.GetType()))
96                                 throw new RemotingException ("The server object type cannot be cast to the requested type " + type.FullName + ".");
97
98                         UpdateChannelInfo();
99                 }
100
101                 internal ObjRef (Type type, string url, object remoteChannelData)
102                 {
103                         uri = url;
104                         typeInfo = new TypeInfo(type);
105
106                         if (remoteChannelData != null)
107                                 channel_info = new ChannelInfo (remoteChannelData);
108
109                         flags |= WellKnowObjectRef;
110                 }
111
112                 protected ObjRef (SerializationInfo si, StreamingContext sc)
113                 {
114                         SerializationInfoEnumerator en = si.GetEnumerator();
115                         // Info to serialize: uri, objrefFlags, typeInfo, envoyInfo, channelInfo
116
117                         bool marshalledValue = true;
118
119                         while (en.MoveNext ()) {
120                                 switch (en.Name) {
121                                 case "uri":
122                                         uri = (string)en.Value;
123                                         break;
124                                 case "typeInfo":
125                                         typeInfo = (IRemotingTypeInfo)en.Value;
126                                         break;
127                                 case "channelInfo":
128                                         channel_info = (IChannelInfo)en.Value;
129                                         break;
130                                 case "envoyInfo":
131                                         envoyInfo = (IEnvoyInfo)en.Value;
132                                         break;
133                                 case "fIsMarshalled":
134                                         int status;
135                                         Object o = en.Value;
136                                         if (o is string)
137                                                 status = ((IConvertible) o).ToInt32(null);
138                                         else
139                                                 status = (int) o;
140
141                                         if (status == 0)
142                                                 marshalledValue = false;
143                                         break;
144                                 case "objrefFlags":
145                                         flags = Convert.ToInt32 (en.Value);
146                                         break;
147                                 default:
148                                         throw new NotSupportedException ();
149                                 }
150                         }
151                         if (marshalledValue) flags |= MarshalledObjectRef;
152                 }
153
154                 internal bool IsPossibleToCAD () 
155                 {
156                         // we should check if this obj ref belongs to a cross app context.
157
158                         // Return false. If not, serialization of this ObjRef will not work
159                         // on the target AD.
160                         return false;
161                 }
162
163                 internal bool IsReferenceToWellKnow
164                 {
165                         get { return (flags & WellKnowObjectRef) > 0; }
166                 }
167
168                 public virtual IChannelInfo ChannelInfo {
169
170                         get {
171                                 return channel_info;
172                         }
173                         
174                         set {
175                                 channel_info = value;
176                         }
177                 }
178                 
179                 public virtual IEnvoyInfo EnvoyInfo {
180                         get {
181                                 return envoyInfo;
182                         }
183                         set {
184                                 envoyInfo = value;
185                         }
186                 }
187                 
188                 public virtual IRemotingTypeInfo TypeInfo {
189                         get {
190                                 return typeInfo;
191                         }
192                         set {
193                                 typeInfo = value;
194                         }
195                 }
196                 
197                 public virtual string URI {
198                         get {
199                                 return uri;
200                         }
201                         set {
202                                 uri = value;
203                         }
204                 }
205
206                 public virtual void GetObjectData (SerializationInfo si, StreamingContext sc)
207                 {
208                         si.SetType (GetType());
209                         si.AddValue ("uri", uri);
210                         si.AddValue ("typeInfo", typeInfo, typeof (IRemotingTypeInfo));
211                         si.AddValue ("envoyInfo", envoyInfo, typeof (IEnvoyInfo));
212                         si.AddValue ("channelInfo", channel_info, typeof(IChannelInfo));
213                         si.AddValue ("objrefFlags", flags);
214                 }
215
216                 public virtual object GetRealObject (StreamingContext sc)
217                 {
218                         if ((flags & MarshalledObjectRef) > 0)
219                                 return RemotingServices.Unmarshal (this);
220                         else
221                                 return this;
222                 }
223
224                 public bool IsFromThisAppDomain ()
225                 {
226                         Identity identity = RemotingServices.GetIdentityForUri (uri);
227                         if (identity == null) return false;             // URI not registered in this domain
228
229                         return identity.IsFromThisAppDomain;
230                 }
231
232                 public bool IsFromThisProcess ()
233                 {
234                         foreach (object data in channel_info.ChannelData)
235                         {
236                                 if (data is CrossAppDomainData)
237                                 {
238                                         string refProcId = ((CrossAppDomainData)data).ProcessID;
239                                         return (refProcId == RemotingConfiguration.ProcessId);
240                                 }
241                         }
242                         
243                         return true;
244                 }
245
246                 internal void UpdateChannelInfo()
247                 {
248                         channel_info = new ChannelInfo ();
249                 }
250
251                 internal Type ServerType
252                 {
253                         get
254                         {
255                                 if (_serverType == null) _serverType = Type.GetType (typeInfo.TypeName);
256                                 return _serverType;
257                         }
258                 }
259         }
260 }