2010-02-03 Jonathan Pobst <monkey@jpobst.com>
[mono.git] / mcs / class / System.Runtime.Remoting / System.Runtime.Remoting.Channels / SoapMessageFormatter.cs
index 2d85709cf822ef650907d82845cd03e1cf7b8200..85c71a1c0264c558a0a260a5e401901f2db11e94 100644 (file)
@@ -6,6 +6,27 @@
 //\r
 //\r
 \r
+//\r
+// Permission is hereby granted, free of charge, to any person obtaining\r
+// a copy of this software and associated documentation files (the\r
+// "Software"), to deal in the Software without restriction, including\r
+// without limitation the rights to use, copy, modify, merge, publish,\r
+// distribute, sublicense, and/or sell copies of the Software, and to\r
+// permit persons to whom the Software is furnished to do so, subject to\r
+// the following conditions:\r
+// \r
+// The above copyright notice and this permission notice shall be\r
+// included in all copies or substantial portions of the Software.\r
+// \r
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\r
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\r
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+//\r
+\r
 using System;\r
 using System.Collections;\r
 using System.Reflection;\r
@@ -53,6 +74,34 @@ namespace System.Runtime.Remoting.Channels {
                        if (sf != null) {\r
                                if(_serverFaultExceptionField != null)\r
                                        e = (Exception) _serverFaultExceptionField.GetValue(sf);\r
+#if TARGET_JVM                         \r
+                               if (e == null && sf.ExceptionType != null)\r
+                               {\r
+                                       try\r
+                                       {\r
+                                               Type te = Type.GetType(sf.ExceptionType);\r
+                                               if (te != null)\r
+                                               {\r
+                                                       ConstructorInfo ce = te.GetConstructor(\r
+                                                               BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.CreateInstance,\r
+                                                               null, new Type[] {typeof(string)}, null);\r
+\r
+                                                       if (ce != null)\r
+                                                       {\r
+                                                               e = (Exception) ce.Invoke(new object[] {sf.ExceptionMessage});\r
+                                                       }\r
+                                                       else\r
+                                                       {\r
+                                                               e = (Exception) Activator.CreateInstance(te);\r
+                                                       }\r
+                                               }\r
+                                       }\r
+                                       catch\r
+                                       {\r
+                                               e = null;\r
+                                       }\r
+                               }\r
+#endif\r
                        }\r
                        if (e == null)\r
                                e = new RemotingException (fault.FaultString);\r
@@ -78,7 +127,7 @@ namespace System.Runtime.Remoting.Channels {
                        }\r
                        else {\r
                                object rtnObject = null;\r
-                               RemMessageType messageType;\r
+                               //RemMessageType messageType;\r
                                \r
                                // Get the output of the function if it is not *void*\r
                                if(_methodCallInfo.ReturnType != typeof(void)){\r
@@ -128,13 +177,12 @@ namespace System.Runtime.Remoting.Channels {
                        \r
                        requestHeaders = new TransportHeaders();\r
                        SoapMessage soapMsg = new SoapMessage();\r
-                       string uri = mcm.Uri;\r
 \r
                        GetInfoFromMethodCallMessage(mcm);\r
 \r
                        // Format the SoapMessage that will be used to create the RPC\r
                        soapMsg.MethodName = mcm.MethodName;\r
-                       int count = mcm.ArgCount;\r
+                       //int count = mcm.ArgCount;\r
                        ArrayList paramNames = new ArrayList(_methodCallParameters.Length);\r
                        ArrayList paramTypes = new ArrayList(_methodCallParameters.Length);\r
                        ArrayList paramValues = new ArrayList(_methodCallParameters.Length);\r
@@ -174,9 +222,18 @@ namespace System.Runtime.Remoting.Channels {
                        headersList.Add(new Header("__Uri", uri));\r
                        headersList.Add(new Header("__MethodName", soapMessage.MethodName));\r
                        string typeNamespace, assemblyName;\r
-                       bool b = SoapServices.DecodeXmlNamespaceForClrTypeNamespace(soapMessage.XmlNameSpace, out typeNamespace, out assemblyName);\r
 \r
-                       _serverType = RemotingServices.GetServerTypeForUri(uri);\r
+                       if (!SoapServices.DecodeXmlNamespaceForClrTypeNamespace(soapMessage.XmlNameSpace, out typeNamespace, out assemblyName))\r
+                               throw new RemotingException ("Could not decode SoapMessage");\r
+\r
+                       // Note that we don't need to validate the type in\r
+                       // this place because MethodCall will do it anyway.\r
+\r
+                       if (assemblyName == null) // corlib\r
+                               _serverType = Type.GetType (typeNamespace, true);\r
+                       else\r
+                               _serverType = Type.GetType (typeNamespace + ", " + assemblyName, true);\r
+\r
                        headersList.Add(new Header("__TypeName", _serverType.FullName, false));\r
                        \r
                        if (soapMessage.Headers != null) {\r
@@ -188,34 +245,37 @@ namespace System.Runtime.Remoting.Channels {
                        }\r
                        \r
                        _xmlNamespace = soapMessage.XmlNameSpace;\r
-                       RemMessageType messageType;\r
+                       //RemMessageType messageType;\r
                        \r
                        BindingFlags bflags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;\r
                        \r
                        if (signature == null)\r
                                _methodCallInfo = _serverType.GetMethod(soapMessage.MethodName, bflags); \r
                        else\r
-                               _methodCallInfo = _serverType.GetMethod(soapMessage.MethodName, bflags, null, signature, null); \r
+                               _methodCallInfo = _serverType.GetMethod(soapMessage.MethodName, bflags, null, signature, null);\r
+                               \r
+                       if (_methodCallInfo == null && (soapMessage.MethodName == "FieldSetter" || soapMessage.MethodName == "FieldGetter"))\r
+                               _methodCallInfo = typeof(object).GetMethod (soapMessage.MethodName, bflags);\r
 \r
                        // the *out* parameters aren't serialized\r
                        // have to add them here\r
                        _methodCallParameters = _methodCallInfo.GetParameters();\r
                        object[] args = new object[_methodCallParameters.Length];\r
-                       \r
-                       foreach(ParameterInfo paramInfo in _methodCallParameters)\r
+                       int sn = 0;\r
+                       for (int n=0; n<_methodCallParameters.Length; n++)\r
                        {\r
+                               ParameterInfo paramInfo = _methodCallParameters [n];\r
                                Type paramType = (paramInfo.ParameterType.IsByRef ? paramInfo.ParameterType.GetElementType() : paramInfo.ParameterType);\r
 \r
                                if (paramInfo.IsOut && paramInfo.ParameterType.IsByRef) {\r
-                                       args [paramInfo.Position] = GetNullValue (paramType);\r
+                                       args [n] = GetNullValue (paramType);\r
                                }\r
                                else{\r
-                                       int index = Array.IndexOf(soapMessage.ParamNames, paramInfo.Name);\r
-                                       if(soapMessage.ParamValues[index] is IConvertible) \r
-                                               soapMessage.ParamValues[index] = Convert.ChangeType(\r
-                                                               soapMessage.ParamValues[index],\r
-                                                               paramType);\r
-                                       args [paramInfo.Position] = soapMessage.ParamValues[index];\r
+                                       object val = soapMessage.ParamValues[sn++];\r
+                                       if(val is IConvertible) \r
+                                               args [n] = Convert.ChangeType (val, paramType);\r
+                                       else\r
+                                               args [n] = val;\r
                                }\r
                        }\r
                        \r
@@ -246,10 +306,16 @@ namespace System.Runtime.Remoting.Channels {
                                ArrayList paramValues = new ArrayList();\r
                                ArrayList paramTypes = new ArrayList();\r
                                soapMessage.MethodName = mrm.MethodName+"Response";\r
-                               if(mrm.ReturnValue != null && mrm.ReturnValue.GetType() != typeof(void)) {\r
+                               \r
+                               Type retType = ((MethodInfo)mrm.MethodBase).ReturnType;\r
+                               \r
+                               if(retType != typeof(void)) {\r
                                        paramNames.Add("return");\r
                                        paramValues.Add(mrm.ReturnValue);\r
-                                       paramTypes.Add(mrm.ReturnValue.GetType());\r
+                                       if (mrm.ReturnValue != null)\r
+                                               paramTypes.Add(mrm.ReturnValue.GetType());\r
+                                       else\r
+                                               paramTypes.Add(retType);\r
                                }\r
                                \r
                                for(int i = 0; i < mrm.OutArgCount; i++){\r
@@ -266,7 +332,7 @@ namespace System.Runtime.Remoting.Channels {
                        }\r
                        else {\r
                                // an Exception was thrown while executing the function\r
-                               responseHeaders["__HttpStatusCode"] = "400";\r
+                               responseHeaders["__HttpStatusCode"] = "500";\r
                                responseHeaders["__HttpReasonPhrase"] = "Bad Request";\r
                                // fill the transport headers\r
                                responseHeaders["Content-Type"] = "text/xml; charset=\"utf-8\"";\r
@@ -323,17 +389,9 @@ namespace System.Runtime.Remoting.Channels {
                        return sf;\r
                }\r
 \r
-               internal void GetInfoFromMethodCallMessage(IMethodCallMessage mcm) {\r
+               internal void GetInfoFromMethodCallMessage (IMethodMessage mcm) {\r
                        _serverType = Type.GetType(mcm.TypeName, true);\r
-                       \r
-                       if (mcm.MethodSignature != null) \r
-                               _methodCallInfo = _serverType.GetMethod(mcm.MethodName, \r
-                                                                                                               BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, \r
-                                                                                                               null, (Type []) mcm.MethodSignature, null);\r
-                       else\r
-                               _methodCallInfo = _serverType.GetMethod(mcm.MethodName, \r
-                                                                                                               BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);\r
-\r
+                       _methodCallInfo = RemotingServices.GetMethodBaseFromMethodMessage (mcm) as MethodInfo;\r
                        _methodCallParameters = _methodCallInfo.GetParameters();\r
                }       \r
                \r
@@ -373,6 +431,12 @@ namespace System.Runtime.Remoting.Channels {
                \r
                object GetNullValue (Type paramType)\r
                {\r
+#if TARGET_JVM                 \r
+                       if (paramType.IsEnum)\r
+                       {\r
+                               return Activator.CreateInstance(paramType);\r
+                       }\r
+#endif\r
                        switch (Type.GetTypeCode (paramType))\r
                        {\r
                                case TypeCode.Boolean: return false;\r
@@ -388,8 +452,15 @@ namespace System.Runtime.Remoting.Channels {
                                case TypeCode.UInt16: return (ushort)0;\r
                                case TypeCode.UInt32: return (uint)0;\r
                                case TypeCode.UInt64: return (ulong)0;\r
-                               default: return null;\r
+                               default: \r
+#if TARGET_JVM                 \r
+                                       if (paramType.IsValueType)\r
+                                       {\r
+                                               return Activator.CreateInstance(paramType);\r
+                                       }\r
+#endif                                 \r
+                                       return null;\r
                        }\r
                }\r
        }\r
-}
+}\r