* ObjRef.cs: Little optimization.
[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 using System;
14 using System.Runtime.Serialization;
15 using System.Runtime.Remoting.Channels;
16 using System.Runtime.Remoting.Messaging;
17 using System.Runtime.Remoting.Proxies;
18
19 namespace System.Runtime.Remoting {
20
21         [Serializable]
22         public class ObjRef : IObjectReference, ISerializable 
23         {
24                 IChannelInfo channel_info;
25                 string uri;
26                 IRemotingTypeInfo typeInfo;
27                 IEnvoyInfo envoyInfo;
28                 int flags;
29                 Type _serverType;
30
31                 static int MarshalledObjectRef = 1;
32                 static int WellKnowObjectRef = 2;
33                 
34                 public ObjRef ()
35                 {
36                         // no idea why this needs to be public
37
38                         UpdateChannelInfo();
39                 }
40
41                 internal ObjRef (string typeName, string uri, IChannelInfo cinfo) 
42                 {
43                         this.uri = uri;
44                         channel_info = cinfo;
45                         typeInfo = new TypeInfo (Type.GetType (typeName));
46                 }
47
48                 internal ObjRef (ObjRef o, bool unmarshalAsProxy) {
49                         channel_info = o.channel_info;
50                         uri = o.uri;
51         
52                         typeInfo = o.typeInfo;
53                         envoyInfo = o.envoyInfo;
54                         flags = o.flags;
55                         if (unmarshalAsProxy) flags |= MarshalledObjectRef;
56                 }
57
58                 public ObjRef (MarshalByRefObject mbr, Type type)
59                 {
60                         if (mbr == null)
61                                 throw new ArgumentNullException ("mbr");
62                         
63                         if (type == null)
64                                 throw new ArgumentNullException ("type");
65
66                         // The ObjRef can only be constructed if the given mbr
67                         // has already been marshalled using RemotingServices.Marshall
68
69                         uri = RemotingServices.GetObjectUri(mbr);
70                         typeInfo = new TypeInfo(type);
71
72                         if (!typeInfo.CanCastTo(mbr.GetType(), mbr))
73                                 throw new RemotingException ("The server object type cannot be cast to the requested type " + type.FullName + ".");
74
75                         UpdateChannelInfo();
76                 }
77
78                 internal ObjRef (Type type, string url, object remoteChannelData)
79                 {
80                         uri = url;
81                         typeInfo = new TypeInfo(type);
82
83                         if (remoteChannelData != null)
84                                 channel_info = new ChannelInfo (remoteChannelData);
85
86                         flags |= WellKnowObjectRef;
87                 }
88
89                 protected ObjRef (SerializationInfo si, StreamingContext sc)
90                 {
91                         SerializationInfoEnumerator en = si.GetEnumerator();
92                         // Info to serialize: uri, objrefFlags, typeInfo, envoyInfo, channelInfo
93
94                         bool marshalledValue = true;
95
96                         while (en.MoveNext ()) {
97                                 switch (en.Name) {
98                                 case "uri":
99                                         uri = (string)en.Value;
100                                         break;
101                                 case "typeInfo":
102                                         typeInfo = (IRemotingTypeInfo)en.Value;
103                                         break;
104                                 case "channelInfo":
105                                         channel_info = (IChannelInfo)en.Value;
106                                         break;
107                                 case "envoyInfo":
108                                         envoyInfo = (IEnvoyInfo)en.Value;
109                                         break;
110                                 case "fIsMarshalled":
111                                         int status;
112                                         Object o = en.Value;
113                                         if (o is string)
114                                                 status = ((IConvertible) o).ToInt32(null);
115                                         else
116                                                 status = (int) o;
117
118                                         if (status == 0)
119                                                 marshalledValue = false;
120                                         break;
121                                 case "objrefFlags":
122                                         flags = Convert.ToInt32 (en.Value);
123                                         break;
124                                 default:
125                                         throw new NotSupportedException ();
126                                 }
127                         }
128                         if (marshalledValue) flags |= MarshalledObjectRef;
129                 }
130
131                 internal bool IsPossibleToCAD () 
132                 {
133                         // we should check if this obj ref belongs to a cross app context.
134
135                         // Return false. If not, serialization of this ObjRef will not work
136                         // on the target AD.
137                         return false;
138                 }
139
140                 internal bool IsReferenceToWellKnow
141                 {
142                         get { return (flags & WellKnowObjectRef) > 0; }
143                 }
144
145                 public virtual IChannelInfo ChannelInfo {
146
147                         get {
148                                 return channel_info;
149                         }
150                         
151                         set {
152                                 channel_info = value;
153                         }
154                 }
155                 
156                 public virtual IEnvoyInfo EnvoyInfo {
157                         get {
158                                 return envoyInfo;
159                         }
160                         set {
161                                 envoyInfo = value;
162                         }
163                 }
164                 
165                 public virtual IRemotingTypeInfo TypeInfo {
166                         get {
167                                 return typeInfo;
168                         }
169                         set {
170                                 typeInfo = value;
171                         }
172                 }
173                 
174                 public virtual string URI {
175                         get {
176                                 return uri;
177                         }
178                         set {
179                                 uri = value;
180                         }
181                 }
182
183                 public virtual void GetObjectData (SerializationInfo si, StreamingContext sc)
184                 {
185                         si.SetType (GetType());
186                         si.AddValue ("uri", uri);
187                         si.AddValue ("typeInfo", typeInfo, typeof (IRemotingTypeInfo));
188                         si.AddValue ("envoyInfo", envoyInfo, typeof (IEnvoyInfo));
189                         si.AddValue ("channelInfo", channel_info, typeof(IChannelInfo));
190                         si.AddValue ("objrefFlags", flags);
191                 }
192
193                 public virtual object GetRealObject (StreamingContext sc)
194                 {
195                         if ((flags & MarshalledObjectRef) > 0)
196                                 return RemotingServices.Unmarshal (this);
197                         else
198                                 return this;
199                 }
200
201                 public bool IsFromThisAppDomain ()
202                 {
203                         Identity identity = RemotingServices.GetIdentityForUri (uri);
204                         if (identity == null) return false;             // URI not registered in this domain
205
206                         return identity.IsFromThisAppDomain;
207                 }
208
209                 public bool IsFromThisProcess ()
210                 {
211                         foreach (object data in channel_info.ChannelData)
212                         {
213                                 if (data is CrossAppDomainData)
214                                 {
215                                         string refProcId = ((CrossAppDomainData)data).ProcessID;
216                                         return (refProcId == RemotingConfiguration.ProcessId);
217                                 }
218                         }
219                         
220                         return true;
221                 }
222
223                 internal void UpdateChannelInfo()
224                 {
225                         channel_info = new ChannelInfo ();
226                 }
227
228                 internal Type ServerType
229                 {
230                         get
231                         {
232                                 if (_serverType == null) _serverType = Type.GetType (typeInfo.TypeName);
233                                 return _serverType;
234                         }
235                 }
236         }
237 }