2004-12-08 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mcs / class / corlib / System.Runtime.Serialization.Formatters.Binary / BinaryFormatter.cs
index e63faf878b61cb31ae4519c4eff7edad8c3913ce..50f0f6688911293f05a57beccbdade058f40ed97 100755 (executable)
@@ -2,10 +2,33 @@
 //
 // Author:
 //     Dick Porter (dick@ximian.com)
-//  Lluis Sanchez Gual (lsg@ctv.es)
+//  Lluis Sanchez Gual (lluis@ideary.com)
 //
 // (C) 2002 Ximian, Inc.  http://www.ximian.com
 
+//
+// 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.Runtime.Serialization.Formatters;
 using System.Runtime.Serialization;
 using System.Reflection;
@@ -14,13 +37,18 @@ using System.IO;
 using System.Runtime.Remoting.Messaging;
 
 namespace System.Runtime.Serialization.Formatters.Binary {
+
        public sealed class BinaryFormatter : IRemotingFormatter, IFormatter 
        {
-               private FormatterAssemblyStyle assembly_format;
+               private FormatterAssemblyStyle assembly_format = FormatterAssemblyStyle.Full;
                private SerializationBinder binder;
                private StreamingContext context;
                private ISurrogateSelector surrogate_selector;
-               private FormatterTypeStyle type_format;
+               private FormatterTypeStyle type_format;                 // TODO: Do something with this
+               
+#if NET_1_1
+               private TypeFilterLevel filter_level;
+#endif
                
                public BinaryFormatter()
                {
@@ -84,36 +112,59 @@ namespace System.Runtime.Serialization.Formatters.Binary {
                        }
                }
 
+#if NET_1_1
+               [System.Runtime.InteropServices.ComVisible (false)]
+               public TypeFilterLevel FilterLevel 
+               {
+                       get { return filter_level; }
+                       set { filter_level = value; }
+               }
+#endif
+
                public object Deserialize(Stream serializationStream)
                {
-                       if(serializationStream==null) {
+                       return Deserialize (serializationStream, null);
+               }
+
+               public object Deserialize(Stream serializationStream, HeaderHandler handler) 
+               {
+                       if(serializationStream==null) \r
+                       {
                                throw new ArgumentNullException("serializationStream is null");
                        }
                        if(serializationStream.CanSeek &&
-                          serializationStream.Length==0) {
+                               serializationStream.Length==0) \r
+                       {
                                throw new SerializationException("serializationStream supports seeking, but its length is 0");
                        }
 
-                       ObjectReader serializer = new ObjectReader (surrogate_selector, context);
                        BinaryReader reader = new BinaryReader (serializationStream);
-                       return serializer.ReadObjectGraph (reader);
-               }
 
-               [MonoTODO]
-               public object Deserialize(Stream serializationStream, HeaderHandler handler) 
-               {
-                       if(serializationStream==null) {
-                               throw new ArgumentNullException("serializationStream is null");
+                       bool hasHeader;
+                       ReadBinaryHeader (reader, out hasHeader);
+
+                       // Messages are read using a special static method, which does not use ObjectReader
+                       // if it is not needed. This saves time and memory.
+
+                       BinaryElement elem = (BinaryElement) reader.PeekChar();
+
+                       if (elem == BinaryElement.MethodCall) {
+                               return MessageFormatter.ReadMethodCall (reader, hasHeader, handler, this);
                        }
-                       if(serializationStream.CanSeek &&
-                          serializationStream.Length==0) {
-                               throw new SerializationException("serializationStream supports seeking, but its length is 0");
+                       else if (elem == BinaryElement.MethodResponse) {
+                               return MessageFormatter.ReadMethodResponse (reader, hasHeader, handler, null, this);
+                       }
+                       else {
+                               ObjectReader serializer = new ObjectReader (this);
+
+                               object result;
+                               Header[] headers;
+                               serializer.ReadObjectGraph (reader, hasHeader, out result, out headers);
+                               if (handler != null) handler(headers);
+                               return result;
                        }
-                       
-                       return(null);
                }
                
-               [MonoTODO]
                public object DeserializeMethodResponse(Stream serializationStream, HeaderHandler handler, IMethodCallMessage methodCallmessage)
                {
                        if(serializationStream==null) {
@@ -123,31 +174,73 @@ namespace System.Runtime.Serialization.Formatters.Binary {
                           serializationStream.Length==0) {
                                throw new SerializationException("serializationStream supports seeking, but its length is 0");
                        }
-                       
-                       return(null);
+
+                       BinaryReader reader = new BinaryReader (serializationStream);
+
+                       bool hasHeader;
+                       ReadBinaryHeader (reader, out hasHeader);
+                       return MessageFormatter.ReadMethodResponse (reader, hasHeader, handler, methodCallmessage, this);
                }
 
                public void Serialize(Stream serializationStream, object graph)
+               {
+                       Serialize (serializationStream, graph, null);
+               }
+
+               public void Serialize(Stream serializationStream, object graph, Header[] headers)
                {
                        if(serializationStream==null) {
                                throw new ArgumentNullException("serializationStream is null");
                        }
 
-                       ObjectWriter serializer = new ObjectWriter (surrogate_selector, context);
                        BinaryWriter writer = new BinaryWriter (serializationStream);
-                       serializer.WriteObjectGraph (writer, graph);
+                       WriteBinaryHeader (writer, headers!=null);\r
+\r
+                       if (graph is IMethodCallMessage) {\r
+                               MessageFormatter.WriteMethodCall (writer, graph, headers, surrogate_selector, context, assembly_format);\r
+                       }\r
+                       else if (graph is IMethodReturnMessage)  {\r
+                               MessageFormatter.WriteMethodResponse (writer, graph, headers, surrogate_selector, context, assembly_format);\r
+                       }\r
+                       else {\r
+                               ObjectWriter serializer = new ObjectWriter (surrogate_selector, context, assembly_format);
+                               serializer.WriteObjectGraph (writer, graph, headers);
+                       }
                        writer.Flush();
                }
-
+\r
                [MonoTODO]
-               public void Serialize(Stream serializationStream, object graph, Header[] headers)
+               [System.Runtime.InteropServices.ComVisible (false)]
+               public object UnsafeDeserialize(Stream serializationStream, HeaderHandler handler) 
                {
-                       if(serializationStream==null) {
-                               throw new ArgumentNullException("serializationStream is null");
-                       }
-
-                       // fixme: what about headers?
-                       Serialize (serializationStream, graph);                 
+                       throw new NotImplementedException ();
+               }
+               
+               [MonoTODO]
+               [System.Runtime.InteropServices.ComVisible (false)]
+               public object UnsafeDeserializeMethodResponse(Stream serializationStream, HeaderHandler handler, IMethodCallMessage methodCallmessage)
+               {
+                       throw new NotImplementedException ();
                }
+               
+               private void WriteBinaryHeader (BinaryWriter writer, bool hasHeaders)\r
+               {\r
+                       writer.Write ((byte)BinaryElement.Header);\r
+                       writer.Write ((int)1);\r
+                       if (hasHeaders) writer.Write ((int)2);\r
+                       else writer.Write ((int)-1);\r
+                       writer.Write ((int)1);\r
+                       writer.Write ((int)0);\r
+               }\r
+\r
+               private void ReadBinaryHeader (BinaryReader reader, out bool hasHeaders)\r
+               {\r
+                       reader.ReadByte();\r
+                       reader.ReadInt32();\r
+                       int val = reader.ReadInt32();\r
+                       hasHeaders = (val==2);\r
+                       reader.ReadInt32();\r
+                       reader.ReadInt32();\r
+               }\r
        }
 }