- // ==++==
- //
- //
- // Copyright (c) 2002 Microsoft Corporation. All rights reserved.
- //
- // The use and distribution terms for this software are contained in the file
- // named license.txt, which can be found in the root of this distribution.
- // By using this software in any fashion, you are agreeing to be bound by the
- // terms of this license.
- //
- // You must not remove this notice, or any other, from this software.
- //
- //
- // ==--==
- //============================================================
- //
- // Class: ObjectReader
- // Purpose: DeSerializes XML in SOAP Format into an an object graph
- //
- // Date: June 10, 1999
- //
- //============================================================
- namespace System.Runtime.Serialization.Formatters.Soap {
- using System;
- using System.IO;
- using System.Reflection;
- using System.Collections;
- using System.Text;
- using System.Runtime.Remoting;
- using System.Runtime.Remoting.Metadata.W3cXsd2001;
- using System.Runtime.Remoting.Messaging;
- using System.Runtime.Serialization;
- using System.Security;
- using System.Security.Permissions;
- using System.Diagnostics;
- using System.Globalization;
- internal sealed class ObjectReader
- {
- // System.Serializer information
- internal ObjectIDGenerator m_idGenerator;
- internal Stream m_stream;
- internal ISurrogateSelector m_surrogates;
- internal StreamingContext m_context;
- internal ObjectManager m_objectManager;
- internal InternalFE formatterEnums;
- internal SerializationBinder m_binder;
- internal SoapHandler soapHandler; //Set from SoapHandler
- // Fake Top object and headers
- internal long topId = 0;
- internal SerStack topStack; // Stack for placing ProcessRecords if the top record cannot be serialized on the first pass.
- internal bool isTopObjectSecondPass = false;
- internal bool isTopObjectResolved = true;
- internal bool isHeaderHandlerCalled = false;
- internal Exception deserializationSecurityException = null;
- internal Object handlerObject = null;
- internal Object topObject;
- internal long soapFaultId;
- internal Header[] headers;
- internal Header[] newheaders;
- internal bool IsFakeTopObject = false;
- internal HeaderHandler handler;
- internal SerObjectInfoInit serObjectInfoInit = null;
- internal IFormatterConverter m_formatterConverter = null;
- // Stack of Object ParseRecords
- internal SerStack stack = new SerStack("ObjectReader Object Stack");
- // ValueType Fixup Stack
- internal SerStack valueFixupStack = new SerStack("ValueType Fixup Stack");
- // Generate Object Id's
- internal Hashtable objectIdTable = new Hashtable(25); // holds the keyId value from the XML input and associated internal Id
- internal long objectIds = 0;
- internal int paramPosition = 0; //Position of parameter if soap top fake record.
- internal int majorVersion = 0;
- internal int minorVersion = 0;
- internal String faultString = null;
- // GetType - eliminate redundant Type.GetType()
- //internal Hashtable typeTable = new Hashtable(10);
- internal static SecurityPermission serializationPermission = new SecurityPermission(SecurityPermissionFlag.SerializationFormatter);
- internal ObjectReader(Stream stream, ISurrogateSelector selector, StreamingContext context, InternalFE formatterEnums, SerializationBinder binder)
- {
- InternalST.Soap( this, "Constructor ISurrogateSelector ",((selector == null)?"null selector ":"selector present"));
- if (stream==null)
- {
- throw new ArgumentNullException("stream", SoapUtil.GetResourceString("ArgumentNull_Stream"));
- }
- m_stream=stream;
- m_surrogates = selector;
- m_context = context;
- m_binder = binder;
- this.formatterEnums = formatterEnums;
- InternalST.Soap( this, "Constructor formatterEnums.FEtopObject ",formatterEnums.FEtopObject);
- if (formatterEnums.FEtopObject != null)
- IsFakeTopObject = true;
- else
- IsFakeTopObject = false;
- m_formatterConverter = new FormatterConverter();
- }
- private ObjectManager GetObjectManager() {
- new SecurityPermission(SecurityPermissionFlag.SerializationFormatter).Assert();
- return new ObjectManager(m_surrogates, m_context);
- }
- // Deserialize the stream into an object graph.
- internal Object Deserialize(HeaderHandler handler, ISerParser serParser)
- {
- InternalST.Soap( this, "Deserialize Entry handler", handler);
- if (serParser == null)
- throw new ArgumentNullException("serParser", String.Format(SoapUtil.GetResourceString("ArgumentNull_WithParamName"), serParser));
- deserializationSecurityException = null;
- try {
- serializationPermission.Demand();
- } catch(Exception e ) {
- deserializationSecurityException = e;
- }
- this.handler = handler;
- isTopObjectSecondPass = false;
- isHeaderHandlerCalled = false;
- if (handler != null)
- IsFakeTopObject = true;
- m_idGenerator = new ObjectIDGenerator();
- m_objectManager = GetObjectManager();
- serObjectInfoInit = new SerObjectInfoInit();
- objectIdTable.Clear();
- objectIds = 0;
- // Will call back to ParseObject, ParseHeader for each object found
- serParser.Run();
- if (handler != null)
- {
- InternalST.Soap( this, "Deserialize Fixup Before Delegate Invoke");
- m_objectManager.DoFixups(); // Fixup for headers
- // Header handler isn't invoked until method name is known from body fake record
- // Except for SoapFault, in which case it is invoked below
- if (handlerObject == null)
- {
- InternalST.Soap( this, "Deserialize Before SoapFault Delegate Invoke ");
- handlerObject = handler(newheaders);
- InternalST.Soap( this, "Deserialize after SoapFault Delegate Invoke");
- }
- // SoapFault creation Create a fake Pr for the handlerObject to use.
- // Create a member for the fake pr with name __fault;
- if ((soapFaultId > 0) && (handlerObject != null))
- {
- InternalST.Soap( this, "Deserialize SoapFault ");
- topStack = new SerStack("Top ParseRecords");
- ParseRecord pr = new ParseRecord();
- pr.PRparseTypeEnum = InternalParseTypeE.Object;
- pr.PRobjectPositionEnum = InternalObjectPositionE.Top;
- pr.PRparseStateEnum = InternalParseStateE.Object;
- pr.PRname = "Response";
- topStack.Push(pr);
- pr = new ParseRecord();
- pr.PRparseTypeEnum = InternalParseTypeE.Member;
- pr.PRobjectPositionEnum = InternalObjectPositionE.Child;
- pr.PRmemberTypeEnum = InternalMemberTypeE.Field;
- pr.PRmemberValueEnum = InternalMemberValueE.Reference;
- pr.PRparseStateEnum = InternalParseStateE.Member;
- pr.PRname = "__fault";
- pr.PRidRef = soapFaultId;
- topStack.Push(pr);
- pr = new ParseRecord();
- pr.PRparseTypeEnum = InternalParseTypeE.ObjectEnd;
- pr.PRobjectPositionEnum = InternalObjectPositionE.Top;
- pr.PRparseStateEnum = InternalParseStateE.Object;
- pr.PRname = "Response";
- topStack.Push(pr);
- isTopObjectResolved = false;
- }
- }
- // Resolve fake top object if necessary
- if (!isTopObjectResolved)
- {
- //resolve top object
- InternalST.Soap( this, "Deserialize TopObject Second Pass");
- isTopObjectSecondPass = true;
- topStack.Reverse();
- // The top of the stack now contains the fake record
- // When it is Parsed, the handler object will be substituted
- // for it in ParseObject.
- int topStackLength = topStack.Count();
- ParseRecord pr = null;
- for (int i=0; i<topStackLength; i++)
- {
- pr = (ParseRecord)topStack.Pop();
- Parse(pr);
- }
- }
- InternalST.Soap( this, "Deserialize Finished Parsing DoFixups");
- m_objectManager.DoFixups();
- if (topObject == null)
- throw new SerializationException(SoapUtil.GetResourceString("Serialization_TopObject"));
- if (topObject is IObjectReference) {
- topObject = ((IObjectReference)topObject).GetRealObject(m_context);
- }
- InternalST.Soap( this, "Deserialize Exit ",topObject);
- m_objectManager.RaiseDeserializationEvent();
- if ((formatterEnums.FEtopObject != null) &
- (topObject is InternalSoapMessage))
- {
- // Convert InternalSoapMessage to SoapMessage
- InternalST.Soap( this, "Deserialize SoapMessage Entry ");
- InternalSoapMessage ismc = (InternalSoapMessage)topObject;
- ISoapMessage smc = (ISoapMessage)formatterEnums.FEtopObject;
- smc.MethodName = ismc.methodName;
- smc.XmlNameSpace = ismc.xmlNameSpace;
- smc.ParamNames = ismc.paramNames;
- smc.ParamValues = ismc.paramValues;
- smc.Headers = headers;
- topObject = smc;
- isTopObjectResolved = true;
- InternalST.Soap( this, "Deserialize SoapMessage Exit topObject ",topObject," method name ",smc.MethodName);
- }
- return topObject;
- }
- internal ReadObjectInfo CreateReadObjectInfo(Type objectType, String assemblyName)
- {
- ReadObjectInfo objectInfo = ReadObjectInfo.Create(objectType, m_surrogates, m_context, m_objectManager, serObjectInfoInit, m_formatterConverter, assemblyName);
- objectInfo.SetVersion(majorVersion, minorVersion);
- return objectInfo;
- }
- internal ReadObjectInfo CreateReadObjectInfo(Type objectType, String[] memberNames, String assemblyName)
- {
- ReadObjectInfo objectInfo = ReadObjectInfo.Create(objectType, memberNames, null, m_surrogates, m_context, m_objectManager, serObjectInfoInit, m_formatterConverter, assemblyName);
- objectInfo.SetVersion(majorVersion, minorVersion);
- return objectInfo;
- }
- internal ReadObjectInfo CreateReadObjectInfo(Type objectType, String[] memberNames, Type[] memberTypes, String assemblyName)
- {
- ReadObjectInfo objectInfo = ReadObjectInfo.Create(objectType, memberNames, memberTypes, m_surrogates, m_context, m_objectManager, serObjectInfoInit, m_formatterConverter, assemblyName);
- objectInfo.SetVersion(majorVersion, minorVersion);
- return objectInfo;
- }
- // Main Parse routine, called by the XML Parse Handlers in XMLParser and also called internally to
- // parse the fake top object.
- internal void Parse(ParseRecord pr)
- {
- InternalST.Soap( this, "Parse Entry");
- stack.Dump();
- pr.Dump();
- switch(pr.PRparseTypeEnum)
- {
- case InternalParseTypeE.SerializedStreamHeader:
- ParseSerializedStreamHeader(pr);
- break;
- case InternalParseTypeE.SerializedStreamHeaderEnd:
- ParseSerializedStreamHeaderEnd(pr);
- break;
- case InternalParseTypeE.Object:
- ParseObject(pr);
- break;
- case InternalParseTypeE.ObjectEnd:
- ParseObjectEnd(pr);
- break;
- case InternalParseTypeE.Member:
- ParseMember(pr);
- break;
- case InternalParseTypeE.MemberEnd:
- ParseMemberEnd(pr);
- break;
- case InternalParseTypeE.Body:
- case InternalParseTypeE.BodyEnd:
- case InternalParseTypeE.Envelope:
- case InternalParseTypeE.EnvelopeEnd:
- break;
- case InternalParseTypeE.Empty:
- default:
- throw new SerializationException(String.Format(SoapUtil.GetResourceString("Serialization_XMLElement"), pr.PRname));
- }
- }
- // Styled ParseError output
- private void ParseError(ParseRecord processing, ParseRecord onStack)
- {
- InternalST.Soap( this, " ParseError ",processing," ",onStack);
- throw new SerializationException(String.Format(SoapUtil.GetResourceString("Serialization_ParseError"),onStack.PRname+" "+((Enum)onStack.PRparseTypeEnum).ToString()+" "+processing.PRname+" "+((Enum)processing.PRparseTypeEnum).ToString()));
- }
- // Parse the SerializedStreamHeader element. This is the first element in the stream if present
- private void ParseSerializedStreamHeader(ParseRecord pr)
- {
- InternalST.Soap( this, "SerializedHeader ",pr);
- stack.Push(pr);
- }
- // Parse the SerializedStreamHeader end element. This is the last element in the stream if present
- private void ParseSerializedStreamHeaderEnd(ParseRecord pr)
- {
- InternalST.Soap( this, "SerializedHeaderEnd ",pr);
- stack.Pop();
- }
- private bool IsRemoting {
- get {
- //return (m_context.State & (StreamingContextStates.Persistence|StreamingContextStates.File|StreamingContextStates.Clone)) == 0;
- return IsFakeTopObject;
- }
- }
- private void CheckSecurity(ParseRecord pr)
- {
- InternalST.SoapAssert(pr!=null, "[BinaryObjectReader.CheckSecurity]pr!=null");
- Type t = pr.PRdtType;
- if (t != null && IsRemoting){
- if (typeof(MarshalByRefObject).IsAssignableFrom(t))
- throw new ArgumentException(String.Format(SoapUtil.GetResourceString("Serialization_MBRAsMBV"), t.FullName));
- }
- //If we passed the security check, they can do whatever they'd like,
- //so we'll just short-circuit this.
- if (deserializationSecurityException==null) {
- return;
- }
- // BaseTypes and Array of basetypes allowed
- if (t != null)
- {
- if (t.IsPrimitive || t == Converter.typeofString)
- return;
- if (typeof(Enum).IsAssignableFrom(t))
- return;
- if (t.IsArray)
- {
- Type type = t.GetElementType();
- if (type.IsPrimitive || type == Converter.typeofString)
- return;
- }
- }
- throw deserializationSecurityException;
- }
- // New object encountered in stream
- private void ParseObject(ParseRecord pr)
- {
- InternalST.Soap( this, "ParseObject Entry ");
- if (pr.PRobjectPositionEnum == InternalObjectPositionE.Top)
- topId = pr.PRobjectId;
- if (pr.PRparseTypeEnum == InternalParseTypeE.Object)
- {
- InternalST.Soap( this, "ParseObject Push "+pr.PRname);
- stack.Push(pr); // Nested objects member names are already on stack
- }
- if (pr.PRobjectTypeEnum == InternalObjectTypeE.Array)
- {
- ParseArray(pr);
- InternalST.Soap( this, "ParseObject Exit, ParseArray ");
- return;
- }
- if ((pr.PRdtType == null) && !IsFakeTopObject)
- throw new SerializationException(String.Format(SoapUtil.GetResourceString("Serialization_TopObjectInstantiate"),pr.PRname));
- if (pr.PRobjectPositionEnum == InternalObjectPositionE.Top && IsFakeTopObject && pr.PRdtType != Converter.typeofSoapFault)
- {
- // Soap fake top object
- if (handler != null)
- {
- // Handler object will supply real top object
- InternalST.Soap( this, "ParseObject FakeTopObject with handlerObject ");
- // Now know the method name, can call header handler
- //Create header for method name
- if (!isHeaderHandlerCalled)
- {
- newheaders = null;
- isHeaderHandlerCalled = true;
- if (headers == null)
- {
- newheaders = new Header[1];
- }
- else
- {
- newheaders = new Header[headers.Length+1];
- Array.Copy(headers, 0, newheaders, 1, headers.Length);
- }
- Header methodNameHeader = new Header("__methodName", pr.PRname, false, pr.PRnameXmlKey);
- newheaders[0] = methodNameHeader;
- InternalST.Soap( this, "Deserialize Before Delegate Invoke ");
- handlerObject = handler(newheaders);
- InternalST.Soap( this, "Deserialize after Delegate Invoke");
- InternalST.Soap( this, "Deserialize delgate object ",((handlerObject == null)?"null":handlerObject));
- }
- if (isHeaderHandlerCalled)
- {
- // Handler object has supplied the real object for the fake object
- // which is on top of the stack
- pr.PRnewObj = handlerObject;
- pr.PRdtType = handlerObject.GetType();
- CheckSecurity(pr);
- if (pr.PRnewObj is IFieldInfo)
- {
- IFieldInfo fi = (IFieldInfo)pr.PRnewObj;
- if ((fi.FieldTypes != null) && (fi.FieldTypes.Length > 0))
- {
- pr.PRobjectInfo = CreateReadObjectInfo(pr.PRdtType, fi.FieldNames, fi.FieldTypes, pr.PRassemblyName);
- }
- }
- }
- else
- {
- // Handler object has not yet been asked for the real object
- // Stack the parse record until the second pass
- isTopObjectResolved = false;
- topStack = new SerStack("Top ParseRecords");
- InternalST.Soap( this, "ParseObject Handler Push "+pr.PRname);
- topStack.Push(pr.Copy());
- return;
- }
- }
- else if (formatterEnums.FEtopObject != null)
- {
- // SoapMessage will be used as the real object
- InternalST.Soap( this, "ParseObject FakeTopObject with SoapMessage ");
- if (isTopObjectSecondPass)
- {
- // This creates a the SoapMessage object as the real object, at this point it is an unitialized object.
- pr.PRnewObj = new InternalSoapMessage();
- pr.PRdtType = typeof(InternalSoapMessage);
- CheckSecurity(pr);
- if (formatterEnums.FEtopObject != null)
- {
- ISoapMessage soapMessage = (ISoapMessage)formatterEnums.FEtopObject;
- pr.PRobjectInfo = CreateReadObjectInfo(pr.PRdtType, soapMessage.ParamNames, soapMessage.ParamTypes, pr.PRassemblyName);
- }
- }
- else
- {
- // Stack the parse record until the second pass
- isTopObjectResolved = false;
- topStack = new SerStack("Top ParseRecords");
- topStack.Push(pr.Copy());
- return;
- }
- }
- }
- else if (pr.PRdtType == Converter.typeofString)
- {
- // String as a top level object
- if (pr.PRvalue != null)
- {
- pr.PRnewObj = pr.PRvalue;
- if (pr.PRobjectPositionEnum == InternalObjectPositionE.Top)
- {
- InternalST.Soap( this, "ParseObject String as top level, Top Object Resolved");
- isTopObjectResolved = true;
- topObject = pr.PRnewObj;
- //stack.Pop();
- return;
- }
- else
- {
- InternalST.Soap( this, "ParseObject String as an object");
- stack.Pop();
- RegisterObject(pr.PRnewObj, pr, (ParseRecord)stack.Peek());
- return;
- }
- }
- else
- {
- // xml Doesn't have the value until later
- return;
- }
- }
- else
- {
- if (pr.PRdtType == null)
- {
- ParseRecord objectPr = (ParseRecord)stack.Peek();
- if (objectPr.PRdtType == Converter.typeofSoapFault)
- {
- InternalST.Soap( this, "ParseObject unknown SoapFault detail");
- throw new ServerException(String.Format(SoapUtil.GetResourceString("Serialization_SoapFault"),faultString));
- }
- throw new SerializationException(String.Format(SoapUtil.GetResourceString("Serialization_TypeElement"),pr.PRname));
- }
- pr.PRnewObj = FormatterServices.GetUninitializedObject(pr.PRdtType);
- CheckSecurity(pr);
- }
- if (pr.PRnewObj == null)
- throw new SerializationException(String.Format(SoapUtil.GetResourceString("Serialization_TopObjectInstantiate"),pr.PRdtType));
- long genId = pr.PRobjectId;
- if (genId < 1)
- pr.PRobjectId = GetId("GenId-"+objectIds);
- if (IsFakeTopObject && pr.PRobjectPositionEnum == InternalObjectPositionE.Top)
- {
- InternalST.Soap( this, "ParseObject fake Top object resolved ",pr.PRnewObj);
- isTopObjectResolved = true;
- topObject = pr.PRnewObj;
- }
- if (pr.PRobjectInfo == null)
- pr.PRobjectInfo = CreateReadObjectInfo(pr.PRdtType, pr.PRassemblyName);
- pr.PRobjectInfo.obj = pr.PRnewObj;
- if (IsFakeTopObject && pr.PRobjectPositionEnum == InternalObjectPositionE.Top)
- {
- InternalST.Soap( this, "ParseObject AddValue to fake object ",pr.PRobjectInfo.obj);
- // Add the methodName to top object, either InternalSoapMessage or object returned by handler
- pr.PRobjectInfo.AddValue("__methodName", pr.PRname);
- pr.PRobjectInfo.AddValue("__keyToNamespaceTable", soapHandler.keyToNamespaceTable);
- pr.PRobjectInfo.AddValue("__paramNameList", pr.PRobjectInfo.SetFakeObject());
- if (formatterEnums.FEtopObject != null)
- pr.PRobjectInfo.AddValue("__xmlNameSpace", pr.PRxmlNameSpace);
- }
- InternalST.Soap( this, "ParseObject Exit ");
- }
- private bool IsWhiteSpace(String value)
- {
- for (int i=0; i<value.Length; i++)
- {
- if (value[i] == ' ' || value[i] == '/n' || value[i] == '/r')
- continue;
- else
- return false;
- }
- return true;
- }
- // End of object encountered in stream
- private void ParseObjectEnd(ParseRecord pr)
- {
- InternalST.Soap( this, "ParseObjectEnd Entry ",pr.Trace());
- ParseRecord objectPr = (ParseRecord)stack.Peek();
- if (objectPr == null)
- objectPr = pr;
- //BCLDebug.Assert(objectPr != null, "[System.Runtime.Serialization.Formatters.ParseObjectEnd]objectPr != null");
- InternalST.Soap( this, "ParseObjectEnd objectPr ",objectPr.Trace());
- if (objectPr.PRobjectPositionEnum == InternalObjectPositionE.Top)
- {
- InternalST.Soap( this, "ParseObjectEnd Top Object dtType ",objectPr.PRdtType);
- if (objectPr.PRdtType == Converter.typeofString)
- {
- InternalST.Soap( this, "ParseObjectEnd Top String");
- if (objectPr.PRvalue == null)
- objectPr.PRvalue = String.Empty; // Not a null object, but an empty string
- objectPr.PRnewObj = objectPr.PRvalue;
- CheckSecurity(objectPr);
- isTopObjectResolved = true;
- topObject = objectPr.PRnewObj;
- return;
- }
- else if (objectPr.PRdtType != null && objectPr.PRvalue != null && !IsWhiteSpace(objectPr.PRvalue) && (objectPr.PRdtType.IsPrimitive || objectPr.PRdtType == Converter.typeofTimeSpan))
- {
- // When an xsd type is transmitted as a top level string <xsd:int>111</xsd:int>
- objectPr.PRnewObj = Converter.FromString(objectPr.PRvalue, Converter.ToCode(objectPr.PRdtType));
- CheckSecurity(objectPr);
- isTopObjectResolved = true;
- topObject = objectPr.PRnewObj;
- return;
- }
- else if ((!isTopObjectResolved) && (objectPr.PRdtType != Converter.typeofSoapFault))
- {
- InternalST.Soap( this, "ParseObjectEnd Top but not String");
- // Need to keep top record on object stack until finished building top stack
- topStack.Push(pr.Copy());
- // Note this is PRparseRecordId and not objectId
- if (objectPr.PRparseRecordId == pr.PRparseRecordId)
- {
- // This handles the case of top stack containing nested objects and
- // referenced objects. If nested objects the objects are not placed
- // on stack, only topstack. If referenced objects they are placed on
- // stack and need to be popped.
- stack.Pop();
- }
- return;
- }
- }
- stack.Pop();
- ParseRecord parentPr = (ParseRecord)stack.Peek();
- if (objectPr.PRobjectTypeEnum == InternalObjectTypeE.Array)
- {
- if (objectPr.PRobjectPositionEnum == InternalObjectPositionE.Top)
- {
- InternalST.Soap( this, "ParseObjectEnd Top Object (Array) Resolved");
- isTopObjectResolved = true;
- topObject = objectPr.PRnewObj;
- }
- InternalST.Soap( this, "ParseArray RegisterObject ",objectPr.PRobjectId," ",objectPr.PRnewObj.GetType());
- RegisterObject(objectPr.PRnewObj, objectPr, parentPr);
- return;
- }
- if (objectPr.PRobjectInfo != null)
- {
- objectPr.PRobjectInfo.PopulateObjectMembers();
- }
- if (objectPr.PRnewObj == null)
- {
- if (objectPr.PRdtType == Converter.typeofString)
- {
- InternalST.Soap( this, "ParseObjectEnd String ");
- if (objectPr.PRvalue == null)
- objectPr.PRvalue = String.Empty; // Not a null object, but an empty string
- objectPr.PRnewObj = objectPr.PRvalue;
- CheckSecurity(objectPr);
- }
- else
- throw new SerializationException(String.Format(SoapUtil.GetResourceString("Serialization_ObjectMissing"),pr.PRname));
- }
- // Registration is after object is populated
- if (!objectPr.PRisRegistered && objectPr.PRobjectId > 0)
- {
- InternalST.Soap( this, "ParseObjectEnd Register Object ",objectPr.PRobjectId," ",objectPr.PRnewObj.GetType());
- RegisterObject(objectPr.PRnewObj, objectPr, parentPr);
- }
- if (objectPr.PRisValueTypeFixup)
- {
- InternalST.Soap( this, "ParseObjectEnd ValueTypeFixup ",objectPr.PRnewObj.GetType());
- ValueFixup fixup = (ValueFixup)valueFixupStack.Pop(); //Value fixup
- fixup.Fixup(objectPr, parentPr); // Value fixup
- }
- if (objectPr.PRobjectPositionEnum == InternalObjectPositionE.Top)
- {
- InternalST.Soap( this, "ParseObjectEnd Top Object Resolved ",objectPr.PRnewObj.GetType());
- isTopObjectResolved = true;
- topObject = objectPr.PRnewObj;
- }
- if (objectPr.PRnewObj is SoapFault)
- soapFaultId = objectPr.PRobjectId;
- if (objectPr.PRobjectInfo != null)
- {
- if (objectPr.PRobjectInfo.bfake && !objectPr.PRobjectInfo.bSoapFault)
- objectPr.PRobjectInfo.AddValue("__fault", null); // need this because SerializationObjectInfo throws an exception if a name being referenced is missing
- objectPr.PRobjectInfo.ObjectEnd();
- }
- InternalST.Soap( this, "ParseObjectEnd Exit ",objectPr.PRnewObj," id: ",objectPr.PRobjectId);
- }
- // Array object encountered in stream
- private void ParseArray(ParseRecord pr)
- {
- InternalST.Soap( this, "ParseArray Entry");
- pr.Dump();
- long genId = pr.PRobjectId;
- if (genId < 1)
- pr.PRobjectId = GetId("GenId-"+objectIds);
- if ((pr.PRarrayElementType != null) && (pr.PRarrayElementType.IsEnum))
- pr.PRisEnum = true;
- if (pr.PRarrayTypeEnum == InternalArrayTypeE.Base64)
- {
- if (pr.PRvalue == null)
- {
- pr.PRnewObj = new Byte[0];
- CheckSecurity(pr);
- }
- else
- {
- // Used for arrays of Base64 and also for a parameter of Base64
- InternalST.Soap( this, "ParseArray bin.base64 ",pr.PRvalue.Length," ",pr.PRvalue);
- if (pr.PRdtType == Converter.typeofSoapBase64Binary)
- {
- // Parameter - Case where the return type is a SoapENC:base64 but the parameter type is xsd:base64Binary
- pr.PRnewObj = SoapBase64Binary.Parse(pr.PRvalue);
- CheckSecurity(pr);
- }
- else
- {
- // ByteArray
- if (pr.PRvalue.Length > 0)
- {
- pr.PRnewObj = Convert.FromBase64String(FilterBin64(pr.PRvalue));
- CheckSecurity(pr);
- }
- else
- {
- pr.PRnewObj = new Byte[0];
- CheckSecurity(pr);
- }
- }
- }
- if (stack.Peek() == pr)
- {
- InternalST.Soap( this, "ParseArray, bin.base64 has been stacked");
- stack.Pop();
- }
- if (pr.PRobjectPositionEnum == InternalObjectPositionE.Top)
- {
- InternalST.Soap( this, "ParseArray, bin.base64 Top Object");
- topObject = pr.PRnewObj;
- isTopObjectResolved = true;
- }
- ParseRecord parentPr = (ParseRecord)stack.Peek();
- // Base64 can be registered at this point because it is populated
- InternalST.Soap( this, "ParseArray RegisterObject ",pr.PRobjectId," ",pr.PRnewObj.GetType());
- RegisterObject(pr.PRnewObj, pr, parentPr);
- }
- else if ((pr.PRnewObj != null) && Converter.IsWriteAsByteArray(pr.PRarrayElementTypeCode))
- {
- // Primtive typed Array has already been read
- if (pr.PRobjectPositionEnum == InternalObjectPositionE.Top)
- {
- topObject = pr.PRnewObj;
- isTopObjectResolved = true;
- }
- ParseRecord parentPr = (ParseRecord)stack.Peek();
- // Primitive typed array can be registered at this point because it is populated
- InternalST.Soap( this, "ParseArray RegisterObject ",pr.PRobjectId," ",pr.PRnewObj.GetType());
- RegisterObject(pr.PRnewObj, pr, parentPr);
- }
- else if ((pr.PRarrayTypeEnum == InternalArrayTypeE.Jagged) || (pr.PRarrayTypeEnum == InternalArrayTypeE.Single))
- {
- // Multidimensional jagged array or single array
- InternalST.Soap( this, "ParseArray Before Jagged,Simple create ",pr.PRarrayElementType," ",(pr.PRrank >0?pr.PRlengthA[0].ToString():"0"));
- if ((pr.PRlowerBoundA == null) || (pr.PRlowerBoundA[0] == 0))
- {
- pr.PRnewObj = Array.CreateInstance(pr.PRarrayElementType, (pr.PRrank>0?pr.PRlengthA[0]:0));
- pr.PRisLowerBound = false;
- }
- else
- {
- pr.PRnewObj = Array.CreateInstance(pr.PRarrayElementType, pr.PRlengthA, pr.PRlowerBoundA);
- pr.PRisLowerBound = true;
- }
- if (pr.PRarrayTypeEnum == InternalArrayTypeE.Single)
- {
- if (!pr.PRisLowerBound && (Converter.IsWriteAsByteArray(pr.PRarrayElementTypeCode)))
- {
- pr.PRprimitiveArray = new PrimitiveArray(pr.PRarrayElementTypeCode, (Array)pr.PRnewObj);
- }
- else if (!pr.PRarrayElementType.IsValueType)
- pr.PRobjectA = (Object[])pr.PRnewObj;
- }
- CheckSecurity(pr);
- InternalST.Soap( this, "ParseArray Jagged,Simple Array ",pr.PRnewObj.GetType());
- // For binary, headers comes in as an array of header objects
- if (pr.PRobjectPositionEnum == InternalObjectPositionE.Headers)
- {
- InternalST.Soap( this, "ParseArray header array");
- headers = (Header[])pr.PRnewObj;
- }
- pr.PRindexMap = new int[1];
- }
- else if (pr.PRarrayTypeEnum == InternalArrayTypeE.Rectangular)
- {
- // Rectangle array
- pr.PRisLowerBound = false;
- if (pr.PRlowerBoundA != null)
- {
- for (int i=0; i<pr.PRrank; i++)
- {
- if (pr.PRlowerBoundA[i] != 0)
- pr.PRisLowerBound = true;
- }
- }
- if (!pr.PRisLowerBound)
- pr.PRnewObj = Array.CreateInstance(pr.PRarrayElementType, pr.PRlengthA);
- else
- pr.PRnewObj = Array.CreateInstance(pr.PRarrayElementType, pr.PRlengthA, pr.PRlowerBoundA);
- CheckSecurity(pr);
- InternalST.Soap( this, "ParseArray Rectangle Array ",pr.PRnewObj.GetType()," lower Bound ",pr.PRisLowerBound);
- // Calculate number of items
- int sum = 1;
- for (int i=0; i<pr.PRrank; i++)
- {
- sum = sum*pr.PRlengthA[i];
- }
- pr.PRindexMap = new int[pr.PRrank];
- pr.PRrectangularMap = new int[pr.PRrank];
- pr.PRlinearlength = sum;
- }
- else
- throw new SerializationException(String.Format(SoapUtil.GetResourceString("Serialization_ArrayType"),((Enum)pr.PRarrayTypeEnum).ToString()));
- InternalST.Soap( this, "ParseArray Exit");
- }
- // Builds a map for each item in an incoming rectangle array. The map specifies where the item is placed in the output Array Object
- private void NextRectangleMap(ParseRecord pr)
- {
- // For each invocation, calculate the next rectangular array position
- // example
- // indexMap 0 [0,0,0]
- // indexMap 1 [0,0,1]
- // indexMap 2 [0,0,2]
- // indexMap 3 [0,0,3]
- // indexMap 4 [0,1,0]
- for (int irank = pr.PRrank-1; irank>-1; irank--)
- {
- // Find the current or lower dimension which can be incremented.
- if (pr.PRrectangularMap[irank] < pr.PRlengthA[irank]-1)
- {
- // The current dimension is at maximum. Increase the next lower dimension by 1
- pr.PRrectangularMap[irank]++;
- if (irank < pr.PRrank-1)
- {
- // The current dimension and higher dimensions are zeroed.
- for (int i = irank+1; i<pr.PRrank; i++)
- pr.PRrectangularMap[i] = 0;
- }
- Array.Copy(pr.PRrectangularMap, pr.PRindexMap, pr.PRrank);
- break;
- }
- }
- }
- // Array object item encountered in stream
- private void ParseArrayMember(ParseRecord pr)
- {
- InternalST.Soap( this, "ParseArrayMember Entry");
- ParseRecord objectPr = (ParseRecord)stack.Peek();
- // Set up for inserting value into correct array position
- if (objectPr.PRarrayTypeEnum == InternalArrayTypeE.Rectangular)
- {
- if (objectPr.PRmemberIndex > 0)
- NextRectangleMap(objectPr); // Rectangle array, calculate position in array
- if (objectPr.PRisLowerBound)
- {
- for (int i=0; i<objectPr.PRrank; i++)
- {
- if (objectPr.PRpositionA == null)
- objectPr.PRindexMap[i] = objectPr.PRrectangularMap[i] + objectPr.PRlowerBoundA[i];
- else
- objectPr.PRindexMap[i] = objectPr.PRpositionA[i];
- }
- }
- }
- else
- {
- if (!objectPr.PRisLowerBound)
- {
- if (objectPr.PRpositionA == null)
- objectPr.PRindexMap[0] = objectPr.PRmemberIndex; // Zero based array
- else
- objectPr.PRindexMap[0] = objectPr.PRpositionA[0]; // item position specified in SOAP stream
- }
- else
- objectPr.PRindexMap[0] = objectPr.PRlowerBoundA[0]+objectPr.PRmemberIndex; // Lower Bound based array
- }
- IndexTraceMessage("ParseArrayMember isLowerBound "+objectPr.PRisLowerBound+" indexMap ", objectPr.PRindexMap);
- // Set Array element according to type of element
- if (pr.PRmemberValueEnum == InternalMemberValueE.Reference)
- {
- // Object Reference
- // See if object has already been instantiated
- Object refObj = m_objectManager.GetObject(pr.PRidRef);
- if (refObj == null)
- {
- // Object not instantiated
- // Array fixup manager
- IndexTraceMessage("ParseArrayMember Record Fixup "+objectPr.PRnewObj.GetType(), objectPr.PRindexMap);
- int[] fixupIndex = new int[objectPr.PRrank];
- Array.Copy(objectPr.PRindexMap, 0, fixupIndex, 0, objectPr.PRrank);
- InternalST.Soap( this, "ParseArrayMember RecordArrayElementFixup objectId ",objectPr.PRobjectId," idRef ",pr.PRidRef);
- m_objectManager.RecordArrayElementFixup(objectPr.PRobjectId, fixupIndex, pr.PRidRef);
- }
- else
- {
- IndexTraceMessage("ParseArrayMember SetValue ObjectReference "+objectPr.PRnewObj.GetType()+" "+refObj, objectPr.PRindexMap);
- if (objectPr.PRobjectA != null)
- objectPr.PRobjectA[objectPr.PRindexMap[0]] = refObj;
- else
- ((Array)objectPr.PRnewObj).SetValue(refObj, objectPr.PRindexMap); // Object has been instantiated
- }
- }
- else if (pr.PRmemberValueEnum == InternalMemberValueE.Nested)
- {
- //Set up dtType for ParseObject
- InternalST.Soap( this, "ParseArrayMember Nested ");
- if (pr.PRdtType == null)
- {
- pr.PRdtType = objectPr.PRarrayElementType;
- }
- ParseObject(pr);
- InternalST.Soap( "ParseArrayMember Push object "+pr.PRname);
- stack.Push(pr);
- if ((objectPr.PRarrayElementType.IsValueType) && (pr.PRarrayElementTypeCode == InternalPrimitiveTypeE.Invalid))
- {
- InternalST.Soap( "ParseArrayMember ValueType ObjectPr ",objectPr.PRnewObj," index ",objectPr.PRmemberIndex);
- pr.PRisValueTypeFixup = true; //Valuefixup
- valueFixupStack.Push(new ValueFixup((Array)objectPr.PRnewObj, objectPr.PRindexMap)); //valuefixup
- RegisterObject(pr.PRnewObj, pr, objectPr);
- }
- else
- {
- InternalST.Soap( "ParseArrayMember SetValue Nested, memberIndex ",objectPr.PRmemberIndex);
- IndexTraceMessage("ParseArrayMember SetValue Nested ContainerObject "+objectPr.PRnewObj.GetType()+" "+objectPr.PRnewObj+" item Object "+pr.PRnewObj+" index ", objectPr.PRindexMap);
- stack.Dump();
- InternalST.Soap( "ParseArrayMember SetValue Nested ContainerObject objectPr ",objectPr.Trace());
- InternalST.Soap( "ParseArrayMember SetValue Nested ContainerObject pr ",pr.Trace());
- if (objectPr.PRobjectA != null)
- objectPr.PRobjectA[objectPr.PRindexMap[0]] = pr.PRnewObj;
- else
- ((Array)objectPr.PRnewObj).SetValue(pr.PRnewObj, objectPr.PRindexMap);
- }
- }
- else if (pr.PRmemberValueEnum == InternalMemberValueE.InlineValue)
- {
- if (objectPr.PRarrayElementType == Converter.typeofString)
- {
- // String
- ParseString(pr, objectPr);
- IndexTraceMessage("ParseArrayMember SetValue String "+objectPr.PRnewObj.GetType()+" "+pr.PRvalue, objectPr.PRindexMap);
- if (objectPr.PRobjectA != null)
- objectPr.PRobjectA[objectPr.PRindexMap[0]] = (Object)pr.PRvalue;
- else
- ((Array)objectPr.PRnewObj).SetValue((Object)pr.PRvalue, objectPr.PRindexMap);
- }
- else if (objectPr.PRisEnum)
- {
- // Soap sends Enums as strings
- Object var = Enum.Parse(objectPr.PRarrayElementType, pr.PRvalue);
- if (objectPr.PRobjectA != null)
- objectPr.PRobjectA[objectPr.PRindexMap[0]] = (Enum)var;
- else
- ((Array)objectPr.PRnewObj).SetValue((Enum)var, objectPr.PRindexMap);
- InternalST.Soap( this, "ParseArrayMember Enum 1");
- }
- else if (objectPr.PRisArrayVariant)
- {
- // Array of type object
- if (pr.PRdtType == null && pr.PRkeyDt == null)
- throw new SerializationException(SoapUtil.GetResourceString("Serialization_ArrayTypeObject"));
- Object var = null;
- if (pr.PRdtType == Converter.typeofString)
- {
- ParseString(pr, objectPr);
- var = pr.PRvalue;
- }
- else if (pr.PRdtType.IsEnum)
- {
- // Soap sends Enums as strings
- var = Enum.Parse(pr.PRdtType, pr.PRvalue);
- InternalST.Soap( this, "ParseArrayMember Enum 2");
- }
- else if (pr.PRdtTypeCode == InternalPrimitiveTypeE.Invalid)
- {
- // Not nested and invalid, so it is an empty object
- var = FormatterServices.GetUninitializedObject(pr.PRdtType);
- }
- else
- {
- if (pr.PRvarValue != null)
- var = pr.PRvarValue;
- else
- var = Converter.FromString(pr.PRvalue, pr.PRdtTypeCode);
- }
- IndexTraceMessage("ParseArrayMember SetValue variant or Object "+objectPr.PRnewObj.GetType()+" var "+var+" indexMap ", objectPr.PRindexMap);
- if (objectPr.PRobjectA != null)
- objectPr.PRobjectA[objectPr.PRindexMap[0]] = var;
- else
- ((Array)objectPr.PRnewObj).SetValue(var, objectPr.PRindexMap); // Primitive type
- }
- else
- {
- // Primitive type
- if (objectPr.PRprimitiveArray != null)
- {
- // Fast path for Soap primitive arrays. Binary was handled in the BinaryParser
- objectPr.PRprimitiveArray.SetValue(pr.PRvalue, objectPr.PRindexMap[0]);
- }
- else
- {
- Object var = null;
- if (pr.PRvarValue != null)
- var = pr.PRvarValue;
- else
- var = Converter.FromString(pr.PRvalue, objectPr.PRarrayElementTypeCode);
- if (objectPr.PRarrayElementTypeCode == InternalPrimitiveTypeE.QName)
- {
- InternalST.Soap( this, "ParseArrayMember Primitive QName");
- SoapQName soapQName = (SoapQName)var;
- if (soapQName.Key.Length == 0)
- soapQName.Namespace = (String)soapHandler.keyToNamespaceTable["xmlns"];
- else
- soapQName.Namespace = (String)soapHandler.keyToNamespaceTable["xmlns"+":"+soapQName.Key];
- }
- InternalST.Soap( this, "ParseArrayMember SetValue Primitive pr.PRvalue "+var," elementTypeCode ",((Enum)objectPr.PRdtTypeCode).ToString());
- IndexTraceMessage("ParseArrayMember SetValue Primitive "+objectPr.PRnewObj.GetType()+" var: "+var+" varType "+var.GetType(), objectPr.PRindexMap);
- if (objectPr.PRobjectA != null)
- objectPr.PRobjectA[objectPr.PRindexMap[0]] = var;
- else
- ((Array)objectPr.PRnewObj).SetValue(var, objectPr.PRindexMap); // Primitive type
- InternalST.Soap( this, "ParseArrayMember SetValue Primitive after");
- }
- }
- }
- else if (pr.PRmemberValueEnum == InternalMemberValueE.Null)
- {
- InternalST.Soap( "ParseArrayMember Null item ",pr.PRmemberIndex);
- }
- else
- ParseError(pr, objectPr);
- InternalST.Soap( "ParseArrayMember increment memberIndex ",objectPr.PRmemberIndex," ",objectPr.Trace());
- objectPr.PRmemberIndex++;
- InternalST.Soap( "ParseArrayMember Exit");
- }
- private void ParseArrayMemberEnd(ParseRecord pr)
- {
- InternalST.Soap( this, "ParseArrayMemberEnd");
- // If this is a nested array object, then pop the stack
- if (pr.PRmemberValueEnum == InternalMemberValueE.Nested)
- {
- ParseObjectEnd(pr);
- }
- }
- // Object member encountered in stream
- private void ParseMember(ParseRecord pr)
- {
- InternalST.Soap( this, "ParseMember Entry ");
- ParseRecord objectPr = (ParseRecord)stack.Peek();
- String objName = null;
- if (objectPr != null)
- objName = objectPr.PRname;
- InternalST.Soap( this, "ParseMember ",objectPr.PRobjectId," ",pr.PRname);
- InternalST.Soap( this, "ParseMember objectPr ",objectPr.Trace());
- InternalST.Soap( this, "ParseMember pr ",pr.Trace());
- if (objectPr.PRdtType == Converter.typeofSoapFault && pr.PRname.ToLower(CultureInfo.InvariantCulture) == "faultstring")
- faultString = pr.PRvalue; // Save fault string in case rest of SoapFault cannot be parsed
- if ((objectPr.PRobjectPositionEnum == InternalObjectPositionE.Top) && !isTopObjectResolved)
- {
- InternalST.Soap( this, "ParseMember Top not resolved");
- if (pr.PRdtType == Converter.typeofString)
- {
- ParseString(pr, objectPr);
- }
- topStack.Push(pr.Copy());
- return;
- }
- switch(pr.PRmemberTypeEnum)
- {
- case InternalMemberTypeE.Item:
- ParseArrayMember(pr);
- return;
- case InternalMemberTypeE.Field:
- break;
- }
- if (objectPr.PRobjectInfo != null)
- objectPr.PRobjectInfo.AddMemberSeen();
- bool bParams = (IsFakeTopObject &
- objectPr.PRobjectPositionEnum == InternalObjectPositionE.Top &&
- objectPr.PRobjectInfo != null && objectPr.PRdtType != Converter.typeofSoapFault);
- if ((pr.PRdtType == null) && objectPr.PRobjectInfo.isTyped)
- {
- InternalST.Soap( this, "ParseMember pr.PRdtType null and not isSi");
- if (bParams)
- {
- // Get type of parameters
- InternalST.Soap( this, "ParseMember pr.PRdtType Get Param Type position "+paramPosition+" name "+pr.PRname);
- pr.PRdtType = objectPr.PRobjectInfo.GetType(paramPosition++);
- InternalST.Soap( this, "ParseMember pr.PRdtType Get Param Type Type "+pr.PRdtType);
- }
- else
- pr.PRdtType = objectPr.PRobjectInfo.GetType(pr.PRname);
- if (pr.PRdtType == null)
- throw new SerializationException(String.Format(SoapUtil.GetResourceString("Serialization_TypeResolved"), objectPr.PRnewObj+" "+pr.PRname));
- pr.PRdtTypeCode = Converter.ToCode(pr.PRdtType);
- }
- else
- {
- if (bParams)
- {
- paramPosition++;
- }
- }
- if (pr.PRmemberValueEnum == InternalMemberValueE.Null)
- {
- // Value is Null
- InternalST.Soap( this, "ParseMember null member: ",pr.PRname);
- InternalST.Soap( this, "AddValue 1");
- objectPr.PRobjectInfo.AddValue(pr.PRname, null);
- }
- else if (pr.PRmemberValueEnum == InternalMemberValueE.Nested)
- {
- InternalST.Soap( this, "ParseMember Nested Type member: ",pr.PRname," objectPr.PRnewObj ",objectPr.PRnewObj);
- ParseObject(pr);
- InternalST.Soap( "ParseMember Push object "+pr.PRname);
- stack.Push(pr);
- InternalST.Soap( this, "AddValue 2 ",pr.PRnewObj," is value type ",pr.PRnewObj.GetType().IsValueType);
- if ((pr.PRobjectInfo != null) && (pr.PRobjectInfo.objectType.IsValueType))
- {
- InternalST.Soap( "ParseMember ValueType ObjectPr ",objectPr.PRnewObj," memberName ",pr.PRname," nested object ",pr.PRnewObj);
- if (IsFakeTopObject)
- objectPr.PRobjectInfo.AddParamName(pr.PRname);
- pr.PRisValueTypeFixup = true; //Valuefixup
- valueFixupStack.Push(new ValueFixup(objectPr.PRnewObj, pr.PRname, objectPr.PRobjectInfo));//valuefixup
- }
- else
- {
- InternalST.Soap( this, "AddValue 2A ");
- objectPr.PRobjectInfo.AddValue(pr.PRname, pr.PRnewObj);
- }
- }
- else if (pr.PRmemberValueEnum == InternalMemberValueE.Reference)
- {
- InternalST.Soap( this, "ParseMember Reference Type member: ",pr.PRname);
- // See if object has already been instantiated
- Object refObj = m_objectManager.GetObject(pr.PRidRef);
- if (refObj == null)
- {
- InternalST.Soap( this, "ParseMember RecordFixup: ",pr.PRname);
- InternalST.Soap( this, "AddValue 3");
- objectPr.PRobjectInfo.AddValue(pr.PRname, null);
- objectPr.PRobjectInfo.RecordFixup(objectPr.PRobjectId, pr.PRname, pr.PRidRef); // Object not instantiated
- }
- else
- {
- InternalST.Soap( this, "ParseMember Referenced Object Known ",pr.PRname," ",refObj);
- InternalST.Soap( this, "AddValue 5");
- objectPr.PRobjectInfo.AddValue(pr.PRname, refObj);
- }
- }
- else if (pr.PRmemberValueEnum == InternalMemberValueE.InlineValue)
- {
- // Primitive type or String
- InternalST.Soap( this, "ParseMember primitive or String member: ",pr.PRname);
- if (pr.PRdtType == Converter.typeofString)
- {
- ParseString(pr, objectPr);
- InternalST.Soap( this, "AddValue 6");
- objectPr.PRobjectInfo.AddValue(pr.PRname, pr.PRvalue);
- }
- else if (pr.PRdtTypeCode == InternalPrimitiveTypeE.Invalid)
- {
- // The member field was an object put the value is Inline either bin.Base64 or invalid
- if (pr.PRarrayTypeEnum == InternalArrayTypeE.Base64)
- {
- InternalST.Soap( this, "AddValue 7");
- objectPr.PRobjectInfo.AddValue(pr.PRname, Convert.FromBase64String(FilterBin64(pr.PRvalue)));
- }
- else if (pr.PRdtType == Converter.typeofObject && pr.PRvalue != null)
- {
- if (objectPr != null && objectPr.PRdtType == Converter.typeofHeader)
- {
- // assume the type is a string for a header
- pr.PRdtType = Converter.typeofString;
- ParseString(pr, objectPr);
- InternalST.Soap( this, "AddValue 6");
- objectPr.PRobjectInfo.AddValue(pr.PRname, pr.PRvalue);
- }
- else
- throw new SerializationException(String.Format(SoapUtil.GetResourceString("Serialization_TypeMissing"), pr.PRname));
- }
- else
- {
- InternalST.Soap( this, "Object Class with no memberInfo data Member "+pr.PRname+" type "+pr.PRdtType);
- if (pr.PRdtType != null && pr.PRdtType.IsEnum)
- {
- // Soap sends Enums as strings
- Object obj = Enum.Parse(pr.PRdtType, pr.PRvalue);
- InternalST.Soap( this, "AddValue 8");
- objectPr.PRobjectInfo.AddValue(pr.PRname, obj);
- }
- else if (pr.PRdtType != null && pr.PRdtType == Converter.typeofTypeArray)
- {
- // Soap sends MethodSignature as an array of types
- InternalST.Soap( this, "AddValue 8A");
- objectPr.PRobjectInfo.AddValue(pr.PRname, pr.PRvarValue);
- }
- else
- {
- if ((!pr.PRisRegistered) && (pr.PRobjectId > 0))
- {
- if (pr.PRvalue == null)
- pr.PRvalue = ""; //can't register null value, this must be a string so set to empty string.
- InternalST.Soap( this, "ParseMember RegisterObject ",pr.PRvalue," ",pr.PRobjectId);
- RegisterObject(pr.PRvalue, pr, objectPr);
- }
- // Object Class with no memberInfo data
- if (pr.PRdtType == Converter.typeofSystemVoid)
- {
- InternalST.Soap( this, "AddValue 9");
- objectPr.PRobjectInfo.AddValue(pr.PRname, pr.PRdtType);
- }
- else if (objectPr.PRobjectInfo.isSi)
- {
- // ISerializable are added as strings, the conversion to type is done by the
- // ISerializable object
- InternalST.Soap( this, "AddValue 10");
- objectPr.PRobjectInfo.AddValue(pr.PRname, pr.PRvalue);
- }
- }
- }
- }
- else
- {
- Object var = null;
- if (pr.PRvarValue != null)
- var = pr.PRvarValue;
- else
- var = Converter.FromString(pr.PRvalue, pr.PRdtTypeCode);
- // Not a string, convert the value
- InternalST.Soap( this, "ParseMember Converting primitive and storing");
- stack.Dump();
- InternalST.Soap( this, "ParseMember pr "+pr.Trace());
- InternalST.Soap( this, "ParseMember objectPr ",objectPr.Trace());
- InternalST.Soap( this, "AddValue 11");
- if (pr.PRdtTypeCode == InternalPrimitiveTypeE.QName && var != null)
- {
- SoapQName soapQName = (SoapQName)var;
- if (soapQName.Key != null)
- {
- if (soapQName.Key.Length == 0)
- soapQName.Namespace = (String)soapHandler.keyToNamespaceTable["xmlns"];
- else
- soapQName.Namespace = (String)soapHandler.keyToNamespaceTable["xmlns"+":"+soapQName.Key];
- }
- }
- objectPr.PRobjectInfo.AddValue(pr.PRname, var);
- }
- }
- else
- ParseError(pr, objectPr);
- }
- // Object member end encountered in stream
- private void ParseMemberEnd(ParseRecord pr)
- {
- InternalST.Soap( this, "ParseMemberEnd");
- switch(pr.PRmemberTypeEnum)
- {
- case InternalMemberTypeE.Item:
- ParseArrayMemberEnd(pr);
- return;
- case InternalMemberTypeE.Field:
- if (pr.PRmemberValueEnum == InternalMemberValueE.Nested)
- ParseObjectEnd(pr);
- break;
- default:
- if (pr.PRmemberValueEnum == InternalMemberValueE.Nested)
- ParseObjectEnd(pr);
- else
- ParseError(pr, (ParseRecord)stack.Peek());
- break;
- }
- }
- // Processes a string object by getting an internal ID for it and registering it with the objectManager
- private void ParseString(ParseRecord pr, ParseRecord parentPr)
- {
- InternalST.Soap( this, "ParseString Entry ",pr.PRobjectId," ",pr.PRvalue," ",pr.PRisRegistered);
- // If there is a string and it wasn't marked as a null object, then it is an empty string
- if (pr.PRvalue == null)
- pr.PRvalue = "";
- // Process String class
- if ((!pr.PRisRegistered) && (pr.PRobjectId > 0))
- {
- InternalST.Soap( this, "ParseString RegisterObject ",pr.PRvalue," ",pr.PRobjectId);
- // String is treated as an object if it has an id
- //m_objectManager.RegisterObject(pr.PRvalue, pr.PRobjectId);
- RegisterObject(pr.PRvalue, pr, parentPr);
- }
- }
- private void RegisterObject(Object obj, ParseRecord pr, ParseRecord objectPr)
- {
- if (!pr.PRisRegistered)
- {
- pr.PRisRegistered = true;
- SerializationInfo si = null;
- long parentId = 0;
- MemberInfo memberInfo = null;
- int[] indexMap = null;
- if (objectPr != null)
- {
- indexMap = objectPr.PRindexMap;
- parentId = objectPr.PRobjectId;
- if (objectPr.PRobjectInfo != null)
- {
- if (!objectPr.PRobjectInfo.isSi)
- {
- // ParentId is only used if there is a memberInfo
- InternalST.Soap( this, "RegisterObject GetMemberInfo parent ",objectPr.PRobjectInfo.objectType," name looking for ", pr.PRname," field obj "+obj);
- memberInfo = objectPr.PRobjectInfo.GetMemberInfo(pr.PRname);
- }
- }
- }
- if (pr.PRobjectInfo != null)
- {
- // SerializationInfo is always needed for ISerialization
- si = pr.PRobjectInfo.si;
- }
- InternalST.Soap( this, "RegisterObject 0bj ",obj," objectId ",pr.PRobjectId," si ", si," parentId ",parentId," memberInfo ",memberInfo, " indexMap "+indexMap);
- m_objectManager.RegisterObject(obj, pr.PRobjectId, si, parentId, memberInfo, indexMap);
- }
- }
- internal void SetVersion(int major, int minor)
- {
- // Don't do version checking if property is set to Simple
- if (formatterEnums.FEassemblyFormat != FormatterAssemblyStyle.Simple)
- {
- this.majorVersion = major;
- this.minorVersion = minor;
- }
- }
- // Assigns an internal ID associated with the xml id attribute
- String inKeyId = null;
- long outKeyId = 0;
- internal long GetId(String keyId)
- {
- if (keyId == null)
- throw new ArgumentNullException("keyId", String.Format(SoapUtil.GetResourceString("ArgumentNull_WithParamName"), "keyId"));
- if (keyId != inKeyId)
- {
- inKeyId = keyId;
- String idString = null;
- InternalST.Soap( this, "GetId Entry ",keyId);
- if (keyId[0] == '#')
- idString = keyId.Substring(1);
- else
- idString = keyId;
- Object idObj = objectIdTable[idString];
- if (idObj == null)
- {
- outKeyId = ++objectIds;
- objectIdTable[idString] = outKeyId;
- InternalST.Soap( this, "GetId Exit new ID ",outKeyId);
- }
- else
- {
- InternalST.Soap( this, "GetId Exit oldId ",(Int64)idObj);
- outKeyId = (Int64)idObj;
- }
- }
- InternalST.Soap( this, "GetId in id ",keyId, " out id ", outKeyId);
- return outKeyId;
- }
- // Assigns an internal ID associated with the binary id number
- long inId = 0;
- long outId = 0;
- internal long GetId(long objectId)
- {
- if (inId != objectId)
- {
- inId = objectId;
- Object idObj = null;
- if (objectId > 0)
- idObj = objectIdTable[objectId];
- if (idObj == null)
- {
- outId = ++objectIds;
- objectIdTable[objectId] = outId;
- InternalST.Soap( this, "GetId Exit new ID ",outId);
- }
- else
- {
- InternalST.Soap( this, "GetId Exit oldId ",(Int64)idObj);
- outId = (Int64)idObj;
- }
- }
- return outId;
- }
- // Trace which includes a single dimensional int array
- [Conditional("SER_LOGGING")]
- private void IndexTraceMessage(String message, int[] index)
- {
- StringBuilder sb = new StringBuilder(10);
- sb.Append("[");
- for (int i=0; i<index.Length; i++)
- {
- sb.Append(index[i]);
- if (i != index.Length -1)
- sb.Append(",");
- }
- sb.Append("]");
- InternalST.Soap( this, message," ",sb.ToString());
- }
- internal Assembly LoadAssemblyFromString(String assemblyString)
- {
- Assembly assm = null;
- if(formatterEnums.FEassemblyFormat == FormatterAssemblyStyle.Simple) {
- assm = Assembly.LoadWithPartialName(assemblyString);
- }
- else {
- try
- {
- assm = Assembly.Load(assemblyString);
- }
- catch (Exception)
- {
- }
- }
- return assm;
- }
- internal Type Bind(String assemblyString, String typeString)
- {
- Type type = null;
- if (m_binder != null)
- type = m_binder.BindToType(assemblyString, typeString);
- return type;
- }
- internal class TypeNAssembly
- {
- public Type type;
- public String assemblyName;
- }
- NameCache typeCache = new NameCache();
- internal Type FastBindToType(String assemblyName, String typeName)
- {
- Type type = null;
- TypeNAssembly entry = (TypeNAssembly)typeCache.GetCachedValue(typeName);
- if (entry == null || entry.assemblyName != assemblyName)
- {
- Assembly assm = LoadAssemblyFromString(assemblyName);
- if (assm == null)
- return null;
- type = FormatterServices.GetTypeFromAssembly(assm, typeName);
- if (type == null)
- return null;
- entry = new TypeNAssembly();
- entry.type = type;
- entry.assemblyName = assemblyName;
- typeCache.SetCachedValue(entry);
- }
- return entry.type;
- }
- /*
- static Hashtable typeNames = new Hashtable();
- static int s_numEntries = 0;
- private const int MAX_CACHE_ENTRIES = 128; // No data gathered to arrive at this number !
- internal Type FastBindToType(String assemblyName, String typeName)
- {
- TypeNAssembly match = (TypeNAssembly)typeNames[typeName];
- if (match == null)
- {
- match = new TypeNAssembly();
- Assembly assm = null;
- try
- {
- assm = Assembly.Load(assemblyName);
- }
- catch (Exception)
- {
- return null;
- }
- if (assm == null)
- return null;
- match.type = FormatterServices.GetTypeFromAssembly(assm, typeName);
- if (match.type == null)
- return null;
- match.assemblyName = assemblyName;
- lock (typeNames)
- {
- if (s_numEntries == MAX_CACHE_ENTRIES)
- {
- typeNames.Clear();
- s_numEntries = 0;
- }
- typeNames[typeName] = match;
- s_numEntries ++;
- }
- return match.type;
- }
- if (match.assemblyName.Equals(assemblyName))
- return match.type;
- // So if same type name occurs in 2 assemblies, the second guy loses
- return null;
- }
- */
- StringBuilder sbf = new StringBuilder();
- internal String FilterBin64(String value)
- {
- sbf.Length = 0;
- for (int i=0; i<value.Length; i++)
- {
- if (!(value[i] == ' '|| value[i] == '/n' || value[i] == '/r'))
- sbf.Append(value[i]);
- }
- return sbf.ToString();
- }
- }
- }
ObjectReader
最新推荐文章于 2023-10-23 18:00:44 发布