// 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; }
// 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 "); }
internal void Put(String name, String value) { nameA.Push(name); valueA.Push(value); }