TARGET_J2EE/JVM fixes
[mono.git] / mcs / class / corlib / System.Runtime.Remoting.Messaging / CADMessages.cs
old mode 100755 (executable)
new mode 100644 (file)
index 88a2441..ee14562
@@ -7,6 +7,29 @@
 // (C) Patrik Torstensson
 //
 
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
 using System;
 using System.Collections;
 using System.IO;
@@ -27,15 +50,30 @@ namespace System.Runtime.Remoting.Messaging {
        }
        
        internal class CADObjRef {
-               public ObjRef objref;
+               ObjRef objref;
+               public int SourceDomain;
 
-               public CADObjRef (ObjRef o) {
-                       this.objref = o;
+               public CADObjRef (ObjRef o, int sourceDomain) {
+                       objref = o;
+                       SourceDomain = sourceDomain;
+               }
+               
+               public string TypeName {
+                       get { return objref.TypeInfo.TypeName; }
+               }
+               
+               public string URI {
+                       get { return objref.URI; }
                }
        }
 
        internal class CADMessageBase {
 
+               protected object [] _args;
+               protected byte [] _serializedArgs = null;
+               protected int _propertyCount = 0;
+               protected CADArgHolder _callContext;
+               
                // Helper to marshal properties
                internal static int MarshalProperties (IDictionary dict, ref ArrayList args) {
                        IDictionary serDict = dict;
@@ -82,34 +120,36 @@ namespace System.Runtime.Remoting.Messaging {
                        if (objType.IsPrimitive || objType == typeof(void))
                                return true;
                        
+                       if (objType.IsArray && objType.GetElementType().IsPrimitive && ((Array)obj).Rank == 1)
+                               return true;
+                               
+                       if (obj is string || obj is DateTime || obj is TimeSpan)
+                               return true;
+                               
                        return false;
                }
 
                // Checks an argument if it's possible to pass without marshalling and
                // if not it will be added to arguments to be serialized
-               protected static object MarshalArgument (object arg, ref ArrayList args) {
+               protected object MarshalArgument (object arg, ref ArrayList args) {
                        if (null == arg)
                                return null;
 
                        if (IsPossibleToIgnoreMarshal (arg))
                                return arg;
 
-/*                     FIXME
-                       IsPossibleToCAD always return false.
-                       Avoid unneeded marshalling until IsPossibleToCAD is fixed
-                       
                        MarshalByRefObject mbr = arg as MarshalByRefObject;
-                       if (null != mbr) {
-                               if (!RemotingServices.IsTransparentProxy(mbr) || RemotingServices.GetRealProxy(mbr) is RemotingProxy) {
+                       if (null != mbr)
+                       {
+                               if (RemotingServices.IsTransparentProxy(mbr)) {
+                                       // We don't deal with this case yet
+                               }
+                               else {
                                        ObjRef objRef = RemotingServices.Marshal(mbr);
-                                       
-                                       // we should check if we can move this..
-                                       if (objRef.IsPossibleToCAD ()) {
-                                               return new CADObjRef(new ObjRef(objRef, true));
-                                       }
+                                       return new CADObjRef(objRef, System.Threading.Thread.GetDomainID());
                                }
                        }
-*/
+
                        if (null == args)
                                args = new ArrayList();
                        
@@ -119,7 +159,9 @@ namespace System.Runtime.Remoting.Messaging {
                        return new CADArgHolder(args.Count - 1);
                }
 
-               protected static object UnmarshalArgument (object arg, ArrayList args) {
+               protected object UnmarshalArgument (object arg, ArrayList args) {
+                       if (arg == null) return null;
+                       
                        // Check if argument is an holder (then we know that it's a serialized argument)
                        CADArgHolder holder = arg as CADArgHolder;
                        if (null != holder) {
@@ -128,14 +170,71 @@ namespace System.Runtime.Remoting.Messaging {
 
                        CADObjRef objref = arg as CADObjRef;
                        if (null != objref) {
-                               return objref.objref.GetRealObject (new StreamingContext (StreamingContextStates.Other));
+                               string typeName = string.Copy (objref.TypeName);
+                               string uri = string.Copy (objref.URI);
+                               int domid = objref.SourceDomain;
+                               
+                               ChannelInfo cinfo = new ChannelInfo (new CrossAppDomainData (domid));
+                               ObjRef localRef = new ObjRef (typeName, uri, cinfo);
+                               return RemotingServices.Unmarshal (localRef);
+                       }
+                       
+                       if (arg is Array)
+                       {
+                               Array argb = (Array)arg;
+                               Array argn;
+                               
+                               // We can't use Array.CreateInstance (arg.GetType().GetElementType()) because
+                               // GetElementType() returns a type from the source domain.
+                               
+                               switch (Type.GetTypeCode (arg.GetType().GetElementType()))
+                               {
+                                       case TypeCode.Boolean: argn = new bool [argb.Length]; break;
+                                       case TypeCode.Byte: argn = new Byte [argb.Length]; break;
+                                       case TypeCode.Char: argn = new Char [argb.Length]; break;
+                                       case TypeCode.Decimal: argn = new Decimal [argb.Length]; break;
+                                       case TypeCode.Double: argn = new Double [argb.Length]; break;
+                                       case TypeCode.Int16: argn = new Int16 [argb.Length]; break;
+                                       case TypeCode.Int32: argn = new Int32 [argb.Length]; break;
+                                       case TypeCode.Int64: argn = new Int64 [argb.Length]; break;
+                                       case TypeCode.SByte: argn = new SByte [argb.Length]; break;
+                                       case TypeCode.Single: argn = new Single [argb.Length]; break;
+                                       case TypeCode.UInt16: argn = new UInt16 [argb.Length]; break;
+                                       case TypeCode.UInt32: argn = new UInt32 [argb.Length]; break;
+                                       case TypeCode.UInt64: argn = new UInt64 [argb.Length]; break;
+                                       default: throw new NotSupportedException ();
+                               }
+                               
+                               argb.CopyTo (argn, 0);
+                               return argn;
                        }
 
-                       // otherwise the argument is ok just to return
-                       return arg;
+                       switch (Type.GetTypeCode (arg.GetType()))
+                       {
+                               case TypeCode.Boolean: return (bool)arg;
+                               case TypeCode.Byte: return (byte)arg;
+                               case TypeCode.Char: return (char)arg;
+                               case TypeCode.Decimal: return (decimal)arg;
+                               case TypeCode.Double: return (double)arg;
+                               case TypeCode.Int16: return (Int16)arg;
+                               case TypeCode.Int32: return (Int32)arg;
+                               case TypeCode.Int64: return (Int64)arg;
+                               case TypeCode.SByte: return (SByte)arg;
+                               case TypeCode.Single: return (Single)arg;
+                               case TypeCode.UInt16: return (UInt16)arg;
+                               case TypeCode.UInt32: return (UInt32)arg;
+                               case TypeCode.UInt64: return (UInt64)arg;
+                               case TypeCode.String: return string.Copy ((string) arg);
+                               case TypeCode.DateTime: return new DateTime (((DateTime)arg).Ticks);
+                               default:
+                                       if (arg is TimeSpan) return new TimeSpan (((TimeSpan)arg).Ticks);
+                                       break;
+                       }       
+
+                       throw new NotSupportedException ("Parameter of type " + arg.GetType () + " cannot be unmarshalled");
                }
 
-               internal static object [] MarshalArguments (object [] arguments, ref ArrayList args) {
+               internal object [] MarshalArguments (object [] arguments, ref ArrayList args) {
                        object [] marshalledArgs = new object [arguments.Length];
 
                        int total = arguments.Length;
@@ -145,7 +244,7 @@ namespace System.Runtime.Remoting.Messaging {
                        return marshalledArgs;
                }
 
-               internal static object [] UnmarshalArguments (object [] arguments, ArrayList args) {
+               internal object [] UnmarshalArguments (object [] arguments, ArrayList args) {
                        object [] unmarshalledArgs = new object [arguments.Length];
 
                        int total = arguments.Length;
@@ -154,40 +253,40 @@ namespace System.Runtime.Remoting.Messaging {
 
                        return unmarshalledArgs;
                }
+               
+               protected void SaveLogicalCallContext (IMethodMessage msg, ref ArrayList serializeList)
+               {
+                       if (msg.LogicalCallContext != null && msg.LogicalCallContext.HasInfo) 
+                       {
+                               if (serializeList == null)
+                                       serializeList = new ArrayList();
+
+                               _callContext = new CADArgHolder (serializeList.Count);
+                               serializeList.Add (msg.LogicalCallContext);
+                       }
+               }
+               
+               internal LogicalCallContext GetLogicalCallContext (ArrayList args) 
+               {
+                       if (null == _callContext)
+                               return null;
+
+                       return (LogicalCallContext) args [_callContext.index];
+               }
        }
 
        // Used when passing a IMethodCallMessage between appdomains
        internal class CADMethodCallMessage : CADMessageBase {
                string _uri;
-               string _methodName;
-               string _typeName;
-               object [] _args;
-
-               byte [] _serializedArgs = null;
-
-               CADArgHolder _methodSignature;
-               CADArgHolder _callContext;
-
-               int _propertyCount = 0;
-
-               internal string TypeName {
-                       get {
-                               return _typeName;
-                       }
-               }
-
+               
+               internal RuntimeMethodHandle MethodHandle;
+               
                internal string Uri {
                        get {
                                return _uri;
                        }
                }
 
-               internal string MethodName {
-                       get {
-                               return _methodName;
-                       }
-               }
-
                static internal CADMethodCallMessage Create (IMessage callMsg) {
                        IMethodCallMessage msg = callMsg as IMethodCallMessage;
                        if (null == msg)
@@ -196,11 +295,9 @@ namespace System.Runtime.Remoting.Messaging {
                        return new CADMethodCallMessage (msg);
                }
 
-               // todo
                internal CADMethodCallMessage (IMethodCallMessage callMsg) {
-                       _methodName = callMsg.MethodName;
-                       _typeName = callMsg.TypeName;
                        _uri = callMsg.Uri;
+                       MethodHandle = callMsg.MethodBase.MethodHandle;
 
                        ArrayList serializeList = null; 
                        
@@ -208,19 +305,13 @@ namespace System.Runtime.Remoting.Messaging {
 
                        _args = MarshalArguments ( callMsg.Args, ref serializeList);
 
-                       // check if we need to save method signature
-                       if (RemotingServices.IsMethodOverloaded (callMsg)) {
-                               if (null == serializeList)
-                                       serializeList = new ArrayList();
-
-                               _methodSignature = new CADArgHolder (serializeList.Count);
-                               serializeList.Add(callMsg.MethodSignature);
-                       }
-
-                       // todo: save callcontext
+                       // Save callcontext
+                       SaveLogicalCallContext (callMsg, ref serializeList);
+                       
+                       // Serialize message data if needed
 
                        if (null != serializeList) {
-                               MemoryStream stm = CADSerializer.SerializeObject (serializeList);
+                               MemoryStream stm = CADSerializer.SerializeObject (serializeList.ToArray());
                                _serializedArgs = stm.GetBuffer();
                        }
                }
@@ -229,7 +320,8 @@ namespace System.Runtime.Remoting.Messaging {
                        ArrayList ret = null;
 
                        if (null != _serializedArgs) {
-                               ret = (ArrayList) CADSerializer.DeserializeObject (new MemoryStream (_serializedArgs));
+                               object[] oret = (object[]) CADSerializer.DeserializeObject (new MemoryStream (_serializedArgs));
+                               ret = new ArrayList (oret);
                                _serializedArgs = null;
                        }
 
@@ -239,13 +331,6 @@ namespace System.Runtime.Remoting.Messaging {
                internal object [] GetArgs (ArrayList args) {
                        return UnmarshalArguments (_args, args);
                }
-                       
-               internal object [] GetMethodSignature (ArrayList args) {
-                       if (null == _methodSignature)
-                               return null;
-
-                       return (object []) args [_methodSignature.index];
-               }
 
                internal int PropertiesCount {
                        get {
@@ -256,15 +341,8 @@ namespace System.Runtime.Remoting.Messaging {
        
        // Used when passing a IMethodReturnMessage between appdomains
        internal class CADMethodReturnMessage : CADMessageBase {
-               object [] _args;
                object _returnValue;
-
-               byte [] _serializedArgs = null;
-
                CADArgHolder _exception = null;
-               CADArgHolder _callContext;
-
-               int _propertyCount = 0;
 
                static internal CADMethodReturnMessage Create (IMessage callMsg) {
                        IMethodReturnMessage msg = callMsg as IMethodReturnMessage;
@@ -290,10 +368,11 @@ namespace System.Runtime.Remoting.Messaging {
                                serializeList.Add(retMsg.Exception);
                        }
 
-                       // todo: save callcontext
+                       // Save callcontext
+                       SaveLogicalCallContext (retMsg, ref serializeList);
 
                        if (null != serializeList) {
-                               MemoryStream stm = CADSerializer.SerializeObject (serializeList);
+                               MemoryStream stm = CADSerializer.SerializeObject (serializeList.ToArray());
                                _serializedArgs = stm.GetBuffer();
                        }
                }
@@ -302,7 +381,8 @@ namespace System.Runtime.Remoting.Messaging {
                        ArrayList ret = null;
 
                        if (null != _serializedArgs) {
-                               ret = (ArrayList) CADSerializer.DeserializeObject (new MemoryStream (_serializedArgs));
+                               object[] oret = (object[]) CADSerializer.DeserializeObject (new MemoryStream (_serializedArgs));
+                               ret = new ArrayList (oret);
                                _serializedArgs = null;
                        }