The Labs \ Source Viewer \ SSCLI \ System.Runtime.Serialization.Formatters.Soap \ SoapParser

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. //============================================================
  16. //
  17. // Class: SoapParser
  18. // Purpose: XML Handlers for System.XML parser
  19. //
  20. // Date: June 10, 1999
  21. //
  22. //============================================================
  23. namespace System.Runtime.Serialization.Formatters.Soap
  24. {
  25.     using System;
  26.     using System.Runtime.Serialization.Formatters;
  27.     using System.Xml;
  28.     using System.IO;
  29.     using System.Globalization;
  30.     using System.Collections;
  31.     using System.Reflection;
  32.     using System.Runtime.Serialization;
  33.     using System.Text;
  34.     using System.Runtime.Remoting;
  35.     using System.Runtime.Remoting.Messaging;
  36.     using System.Runtime.Remoting.Metadata;
  37.    
  38.    
  39.     internal sealed class SoapParser : ISerParser
  40.     {
  41.         internal XmlTextReader xmlReader;
  42.         internal SoapHandler soapHandler;
  43.         internal ObjectReader objectReader;
  44.         internal bool bStop = false;
  45.         int depth = 0;
  46.         bool bDebug = false;
  47.         TextReader textReader = null;
  48.        
  49.         internal SoapParser(Stream stream)
  50.         {
  51.             InternalST.Soap(this, "Constructor");
  52.             TraceStream(stream);
  53.             if (bDebug)
  54.                 xmlReader = new XmlTextReader(textReader);
  55.             else
  56.                 xmlReader = new XmlTextReader(stream);
  57.             xmlReader.XmlResolver = null;
  58.             xmlReader.ProhibitDtd = true;
  59.             soapHandler = new SoapHandler(this);
  60.         }
  61.        
  62.        
  63.         // Trace when checked builds
  64.         [System.Diagnostics.Conditional("_LOGGING")]
  65.         private void TraceStream(Stream stream)
  66.         {
  67.             bDebug = true;
  68.             TextReader tempReader = new StreamReader(stream);
  69.             string strbuffer = tempReader.ReadToEnd();
  70.             InternalST.InfoSoap("******************** Begin Deserialized Stream Buffer *******************");
  71.             InternalST.InfoSoap(strbuffer);
  72.             InternalST.InfoSoap("******************** End Deserialized Stream Buffer *******************");
  73.             textReader = new StringReader(strbuffer);
  74.         }
  75.        
  76.        
  77.         internal void Init(ObjectReader objectReader)
  78.         {
  79.             InternalST.Soap(this, "Init");
  80.             this.objectReader = objectReader;
  81.             soapHandler.Init(objectReader);
  82.             bStop = false;
  83.             depth = 0;
  84.             xmlReader.ResetState();
  85.         }
  86.        
  87.         // Start parsing the input
  88.         public void Run()
  89.         {
  90.             InternalST.Soap(this, "Run");
  91.             try {
  92.                 soapHandler.Start(xmlReader);
  93.                 ParseXml();
  94.             }
  95.             catch (EndOfStreamException) {
  96.             }
  97.         }
  98.        
  99.         internal void Stop()
  100.         {
  101.             InternalST.Soap(this, "Stop");
  102.             bStop = true;
  103.         }
  104.        
  105.        
  106.         private void ParseXml()
  107.         {
  108.             InternalST.Soap(this, "ParseXml");
  109.             while (!bStop && xmlReader.Read()) {
  110.                 if (depth < xmlReader.Depth) {
  111.                     soapHandler.StartChildren();
  112.                     depth = xmlReader.Depth;
  113.                 }
  114.                 else if (depth > xmlReader.Depth) {
  115.                     soapHandler.FinishChildren(xmlReader.Prefix, xmlReader.LocalName, xmlReader.NamespaceURI);
  116.                     depth = xmlReader.Depth;
  117.                 }
  118.                
  119.                 switch (xmlReader.NodeType) {
  120.                     case (XmlNodeType.None):
  121.                         break;
  122.                     case (XmlNodeType.Element):
  123.                         Dump("Node Element", xmlReader);
  124.                         soapHandler.StartElement(xmlReader.Prefix, xmlReader.LocalName, xmlReader.NamespaceURI);
  125.                         int attributeCount = xmlReader.AttributeCount;
  126.                         while (xmlReader.MoveToNextAttribute()) {
  127.                             soapHandler.Attribute(xmlReader.Prefix, xmlReader.LocalName, xmlReader.NamespaceURI, xmlReader.Value);
  128.                         }
  129.                         xmlReader.MoveToElement();
  130.                         if (xmlReader.IsEmptyElement)
  131.                             soapHandler.EndElement(xmlReader.Prefix, xmlReader.LocalName, xmlReader.NamespaceURI);
  132.                         break;
  133.                     case XmlNodeType.EndElement:
  134.                         Dump("Node EndElement", xmlReader);
  135.                         soapHandler.EndElement(xmlReader.Prefix, xmlReader.LocalName, xmlReader.NamespaceURI);
  136.                         break;
  137.                     case (XmlNodeType.Text):
  138.                         Dump("Node Text", xmlReader);
  139.                         soapHandler.Text(xmlReader.Value);
  140.                         break;
  141.                     case (XmlNodeType.SignificantWhitespace):
  142.                         Dump("Node SignificantWhitespace", xmlReader);
  143.                         soapHandler.Text(xmlReader.Value);
  144.                         break;
  145.                     case (XmlNodeType.Whitespace):
  146.                         Dump("Node Whitespace", xmlReader);
  147.                         soapHandler.Text(xmlReader.Value);
  148.                         break;
  149.                     case (XmlNodeType.Entity):
  150.                         Dump("Node Entity", xmlReader);
  151.                         break;
  152.                     case (XmlNodeType.CDATA):
  153.                         Dump("Node CDATA", xmlReader);
  154.                         soapHandler.Text(xmlReader.Value);
  155.                         break;
  156.                     case (XmlNodeType.Comment):
  157.                         Dump("Node Comment", xmlReader);
  158.                         soapHandler.Comment(xmlReader.Value);
  159.                         break;
  160.                     case (XmlNodeType.EntityReference):
  161.                         Dump("Node EntityReference", xmlReader);
  162.                         break;
  163.                     case (XmlNodeType.ProcessingInstruction):
  164.                         Dump("Node ProcessingInstruction", xmlReader);
  165.                         break;
  166.                     case (XmlNodeType.Document):
  167.                         Dump("Node Document", xmlReader);
  168.                         break;
  169.                     case (XmlNodeType.DocumentType):
  170.                         Dump("Node DocumentType", xmlReader);
  171.                         break;
  172.                     case (XmlNodeType.DocumentFragment):
  173.                         Dump("Node DocumentFragment", xmlReader);
  174.                         break;
  175.                     case (XmlNodeType.Notation):
  176.                         Dump("Node Notation", xmlReader);
  177.                         break;
  178.                     case (XmlNodeType.EndEntity):
  179.                         Dump("Node EndEntity", xmlReader);
  180.                         break;
  181.                     default:
  182.                         Dump("Node Default", xmlReader);
  183.                         break;
  184.                 }
  185.                
  186.             }
  187.         }
  188.        
  189.         [System.Diagnostics.Conditional("SER_LOGGING")]
  190.         private static void Dump(string name, XmlReader xmlReader)
  191.         {
  192.             InternalST.Soap("========== " + name + " ============");
  193.             InternalST.Soap("Prefix : " + xmlReader.Prefix);
  194.             InternalST.Soap("Name : " + xmlReader.Name);
  195.             InternalST.Soap("LocalName : " + xmlReader.LocalName);
  196.             InternalST.Soap("Namespace : " + xmlReader.NamespaceURI);
  197.             InternalST.Soap("Depth : " + xmlReader.Depth);
  198.             InternalST.Soap("Value : [" + xmlReader.Value + "]");
  199.             InternalST.Soap("IsDefault : " + xmlReader.IsDefault);
  200.             InternalST.Soap("XmlSpace : " + xmlReader.XmlSpace);
  201.             InternalST.Soap("XmlLang : " + xmlReader.XmlLang);
  202.             InternalST.Soap("QuoteChar : " + xmlReader.QuoteChar);
  203.             InternalST.Soap("================================\n");
  204.         }
  205.        
  206.     }
  207.    
  208.     // Sets the handler which contains the callbacks for the parser
  209.     internal sealed class SoapHandler
  210.     {
  211.         SerStack stack = new SerStack("SoapParser Stack");
  212.        
  213.         XmlTextReader xmlTextReader = null;
  214.         SoapParser soapParser = null;
  215.        
  216.        
  217.         // Current text
  218.         string textValue = "";
  219.        
  220.         // XML Formatter
  221.         ObjectReader objectReader;
  222.         internal Hashtable keyToNamespaceTable;
  223.         //needed for xsd QName type
  224.         // Current state
  225.         InternalParseStateE currentState;
  226.         bool isEnvelope = false;
  227.         bool isBody = false;
  228.         bool isTopFound = false;
  229.         HeaderStateEnum headerState = HeaderStateEnum.None;
  230.        
  231.         // Attribute holder
  232.         SerStack attributeValues = new SerStack("AttributePrefix");
  233.        
  234.         SerStack prPool = new SerStack("prPool");
  235.        
  236.         // XML Key to AssemblyId table
  237.         // Key of SOAP has an AssemblyId of -1
  238.         // Key of urt has an AssemblyId of -2
  239.         Hashtable assemKeyToAssemblyTable = null;
  240.         Hashtable assemKeyToNameSpaceTable = null;
  241.         Hashtable assemKeyToInteropAssemblyTable = null;
  242.         Hashtable nameSpaceToKey = null;
  243.         // Used to assign a key to default xml namespaces
  244.         string soapKey = "SOAP-ENC";
  245.         //xml key for soap, should be SOAP
  246.         string urtKey = "urt";
  247.         //xml key for urt, should be urt
  248.         string soapEnvKey = "SOAP-ENV";
  249.         //xml key for SOAPRENV, initial value, might change
  250.         string xsiKey = "xsi";
  251.         //xml key for xsi, initial value, might change
  252.         string xsdKey = "xsd";
  253.         //xml key for xsd, initial value, might change
  254.         int nextPrefix = 0;
  255.         // Used to generate a prefix if necessary
  256.         internal SoapHandler(SoapParser soapParser)
  257.         {
  258.             this.soapParser = soapParser;
  259.         }
  260.        
  261.         internal void Init(ObjectReader objectReader)
  262.         {
  263.             this.objectReader = objectReader;
  264.             objectReader.soapHandler = this;
  265.             isEnvelope = false;
  266.             isBody = false;
  267.             isTopFound = false;
  268.             attributeValues.Clear();
  269.             assemKeyToAssemblyTable = new Hashtable(10);
  270.             assemKeyToAssemblyTable[urtKey] = new SoapAssemblyInfo(SoapUtil.urtAssemblyString, SoapUtil.urtAssembly);
  271.             assemKeyToNameSpaceTable = new Hashtable(10);
  272.             assemKeyToInteropAssemblyTable = new Hashtable(10);
  273.             nameSpaceToKey = new Hashtable(5);
  274.             keyToNamespaceTable = new Hashtable(10);
  275.            
  276.         }
  277.        
  278.         private string NextPrefix()
  279.         {
  280.             nextPrefix++;
  281.             return "_P" + nextPrefix;
  282.            
  283.         }
  284.        
  285.         internal class AttributeValueEntry
  286.         {
  287.             internal string prefix;
  288.             internal string key;
  289.             internal string value;
  290.             internal string urn;
  291.            
  292.             internal AttributeValueEntry(string prefix, string key, string value, string urn)
  293.             {
  294.                 this.prefix = prefix;
  295.                 this.key = key;
  296.                 this.value = value;
  297.                 this.urn = urn;
  298.             }
  299.         }
  300.        
  301.         private ParseRecord GetPr()
  302.         {
  303.             ParseRecord pr = null;
  304.            
  305.             if (!prPool.IsEmpty()) {
  306.                 pr = (ParseRecord)prPool.Pop();
  307.                 pr.Init();
  308.             }
  309.             else
  310.                 pr = new ParseRecord();
  311.            
  312.             return pr;
  313.         }
  314.        
  315.         private void PutPr(ParseRecord pr)
  316.         {
  317.             prPool.Push(pr);
  318.         }
  319.        
  320.         // Creates a trace string
  321.         private static string SerTraceString(string handler, ParseRecord pr, string value, InternalParseStateE currentState, HeaderStateEnum headerState)
  322.         {
  323.             string valueString = "";
  324.             if (value != null)
  325.                 valueString = value;
  326.            
  327.             string prString = "";
  328.             if (pr != null)
  329.                 prString = ((Enum)pr.PRparseStateEnum).ToString();
  330.            
  331.             return handler + " - " + valueString + ", State " + ((Enum)currentState).ToString() + ", PushState " + prString;
  332.         }
  333.        
  334.         #if _DEBUG
  335.         private static string SerTraceString(string handler, ParseRecord pr, string value, string prefix, string urn, InternalParseStateE currentState, HeaderStateEnum headerState)
  336.         {
  337.             string valueString = "";
  338.             if (value != null)
  339.                 valueString = value;
  340.            
  341.             string prString = "";
  342.             if (pr != null)
  343.                 prString = ((Enum)pr.PRparseStateEnum).ToString();
  344.            
  345.             return handler + " - name " + valueString + ", prefix " + prefix + ", urn " + urn + ", CuurentState " + ((Enum)currentState).ToString() + ", HeaderState " + ((Enum)headerState).ToString() + ", PushState " + prString;
  346.         }
  347.         #endif
  348.        
  349.        
  350.         // Formats the error message and throws a SerializationException
  351.         private void MarshalError(string handler, ParseRecord pr, string value, InternalParseStateE currentState)
  352.         {
  353.             string traceString = SerTraceString(handler, pr, value, currentState, headerState);
  354.             #if _DEBUG
  355.             InternalST.Soap(this, "MarshalError,", traceString);
  356.             #endif
  357.             throw new SerializationException(String.Format(CultureInfo.CurrentCulture, SoapUtil.GetResourceString("Serialization_Syntax"), traceString));
  358.         }
  359.        
  360.         // Called at the beginning of parsing
  361.         internal void Start(XmlTextReader p)
  362.         {
  363.             InternalST.Soap(this, "Start ");
  364.             currentState = InternalParseStateE.Object;
  365.             xmlTextReader = p;
  366.         }
  367.        
  368.         // Called at the begining of an element
  369.         internal void StartElement(string prefix, string name, string urn)
  370.         {
  371.             #if _DEBUG
  372.             InternalST.Soap(this, SerTraceString("StartElement Begin ", (ParseRecord)stack.Peek(), name, prefix, urn, currentState, headerState));
  373.             #endif
  374.             string actualName = NameFilter(name);
  375.             string actualPrefix = prefix;
  376.            
  377.             ParseRecord pr = null;
  378.            
  379.             if (!((urn == null) || (urn.Length == 0)) && ((prefix == null) || (prefix.Length == 0))) {
  380.                 // Need to assign a prefix to the urn
  381.                 if (nameSpaceToKey.ContainsKey(urn))
  382.                     actualPrefix = (string)nameSpaceToKey[urn];
  383.                 else {
  384.                     actualPrefix = NextPrefix();
  385.                     nameSpaceToKey[urn] = actualPrefix;
  386.                 }
  387.                 InternalST.Soap(this, "StartElement Begin null urn assigned prefix ", actualPrefix);
  388.             }
  389.            
  390.            
  391.             switch (currentState) {
  392.                 case InternalParseStateE.Object:
  393.                     pr = GetPr();
  394.                     pr.PRname = actualName;
  395.                     pr.PRnameXmlKey = actualPrefix;
  396.                     pr.PRxmlNameSpace = urn;
  397.                     pr.PRparseStateEnum = InternalParseStateE.Object;
  398.                    
  399.                     if ((String.Compare(name, "Array", StringComparison.OrdinalIgnoreCase) == 0) && actualPrefix.Equals(soapKey))
  400.                         pr.PRparseTypeEnum = InternalParseTypeE.Object;
  401.                     else if (((String.Compare(name, "anyType", StringComparison.OrdinalIgnoreCase) == 0) || (String.Compare(name, "ur-type", StringComparison.OrdinalIgnoreCase) == 0)) && actualPrefix.Equals(xsdKey)) {
  402.                         pr.PRname = "System.Object";
  403.                         pr.PRnameXmlKey = urtKey;
  404.                         pr.PRxmlNameSpace = urn;
  405.                         pr.PRparseTypeEnum = InternalParseTypeE.Object;
  406.                     }
  407.                     else if (String.Compare(urn, "http://schemas.xmlsoap.org/soap/envelope/", StringComparison.OrdinalIgnoreCase) == 0) {
  408.                         if (String.Compare(name, "Envelope", StringComparison.OrdinalIgnoreCase) == 0) {
  409.                             if (isEnvelope)
  410.                                 throw new SerializationException(String.Format(CultureInfo.CurrentCulture, SoapUtil.GetResourceString("Serialization_Parser_Envelope"), prefix + ":" + name));
  411.                            
  412.                             isEnvelope = true;
  413.                             pr.PRparseTypeEnum = InternalParseTypeE.Envelope;
  414.                         }
  415.                         else if (String.Compare(name, "Body", StringComparison.OrdinalIgnoreCase) == 0) {
  416.                             if (!isEnvelope)
  417.                                 throw new SerializationException(SoapUtil.GetResourceString("Serialization_Parser_BodyChild"));
  418.                            
  419.                             if (isBody)
  420.                                 throw new SerializationException(SoapUtil.GetResourceString("Serialization_Parser_BodyOnce"));
  421.                            
  422.                             isBody = true;
  423.                             headerState = HeaderStateEnum.None;
  424.                             isTopFound = false;
  425.                             pr.PRparseTypeEnum = InternalParseTypeE.Body;
  426.                         }
  427.                         else if (String.Compare(name, "Header", StringComparison.OrdinalIgnoreCase) == 0) {
  428.                             if (!isEnvelope)
  429.                                 throw new SerializationException(SoapUtil.GetResourceString("Serialization_Parser_Header"));
  430.                            
  431.                             pr.PRparseTypeEnum = InternalParseTypeE.Headers;
  432.                             headerState = HeaderStateEnum.FirstHeaderRecord;
  433.                         }
  434.                         else
  435.                             pr.PRparseTypeEnum = InternalParseTypeE.Object;
  436.                         //SoapFault has an envelope key
  437.                     }
  438.                     else {
  439.                         pr.PRparseTypeEnum = InternalParseTypeE.Object;
  440.                     }
  441.                    
  442.                     stack.Push(pr);
  443.                     break;
  444.                 case InternalParseStateE.Member:
  445.                    
  446.                     pr = GetPr();
  447.                    
  448.                     // Members of Top object records cannot be reused because of the need to resolving fake element
  449.                     ParseRecord objectPr = (ParseRecord)stack.Peek();
  450.                     pr.PRname = actualName;
  451.                     pr.PRnameXmlKey = actualPrefix;
  452.                     pr.PRxmlNameSpace = urn;
  453.                     pr.PRparseTypeEnum = InternalParseTypeE.Member;
  454.                     pr.PRparseStateEnum = InternalParseStateE.Member;
  455.                     stack.Push(pr);
  456.                     break;
  457.                 case InternalParseStateE.MemberChild:
  458.                    
  459.                     objectPr = (ParseRecord)stack.PeekPeek();
  460.                     pr = (ParseRecord)stack.Peek();
  461.                     pr.PRmemberValueEnum = InternalMemberValueE.Nested;
  462.                     ProcessAttributes(pr, objectPr);
  463.                     switch (headerState) {
  464.                         case HeaderStateEnum.None:
  465.                         case HeaderStateEnum.TopLevelObject:
  466.                             InternalST.Soap(this, "ObjectReader.Parse 1");
  467.                             objectReader.Parse(pr);
  468.                             pr.PRisParsed = true;
  469.                             break;
  470.                         case HeaderStateEnum.HeaderRecord:
  471.                         case HeaderStateEnum.NestedObject:
  472.                             ProcessHeaderMember(pr);
  473.                             break;
  474.                     }
  475.                    
  476.                     ParseRecord nestPr = GetPr();
  477.                     nestPr.PRparseTypeEnum = InternalParseTypeE.Member;
  478.                     nestPr.PRparseStateEnum = InternalParseStateE.Member;
  479.                     nestPr.PRname = actualName;
  480.                     nestPr.PRnameXmlKey = actualPrefix;
  481.                     pr.PRxmlNameSpace = urn;
  482.                     currentState = InternalParseStateE.Member;
  483.                     stack.Push(nestPr);
  484.                     break;
  485.                 default:
  486.                    
  487.                     MarshalError("StartElement", (ParseRecord)stack.Peek(), actualName, currentState);
  488.                     break;
  489.             }
  490.            
  491.             #if _DEBUG
  492.             InternalST.Soap(this, SerTraceString("StartElement End ", (ParseRecord)stack.Peek(), name, currentState, headerState));
  493.             #endif
  494.         }
  495.        
  496.        
  497.         // Called at the end of an element
  498.         internal void EndElement(string prefix, string name, string urn)
  499.         {
  500.             #if _DEBUG
  501.             InternalST.Soap(this, SerTraceString("EndElement Begin ", (ParseRecord)stack.Peek(), name, prefix, urn, currentState, headerState));
  502.             #endif
  503.            
  504.             string actualName = NameFilter(name);
  505.            
  506.             ParseRecord objectPr = null;
  507.             ParseRecord pr = null;
  508.            
  509.             switch (currentState) {
  510.                 case InternalParseStateE.Object:
  511.                     pr = (ParseRecord)stack.Pop();
  512.                     if (pr.PRparseTypeEnum == InternalParseTypeE.Envelope)
  513.                         pr.PRparseTypeEnum = InternalParseTypeE.EnvelopeEnd;
  514.                     else if (pr.PRparseTypeEnum == InternalParseTypeE.Body)
  515.                         pr.PRparseTypeEnum = InternalParseTypeE.BodyEnd;
  516.                     else if (pr.PRparseTypeEnum == InternalParseTypeE.Headers) {
  517.                         pr.PRparseTypeEnum = InternalParseTypeE.HeadersEnd;
  518.                         headerState = HeaderStateEnum.HeaderRecord;
  519.                     }
  520.                     else if (pr.PRarrayTypeEnum != InternalArrayTypeE.Base64) {
  521.                         // A Base64 array object treated special by ObjectReader. It is completely processed when
  522.                         // pr.PRparseTypeEnum == InternalParseTypeE.Object, an ObjectEnd is not needed to complete parsing
  523.                        
  524.                         // For an element like <element />, the check was not made for top
  525.                         objectPr = (ParseRecord)stack.Peek();
  526.                         InternalST.Soap(this, "SoapParser.EndElement TopFound " + isTopFound + " objectPr.parseTypeEnum " + (objectPr == null ? "null" : ((Enum)objectPr.PRparseTypeEnum).ToString()));
  527.                         if (!isTopFound && (objectPr != null) && (objectPr.PRparseTypeEnum == InternalParseTypeE.Body)) {
  528.                             pr.PRobjectPositionEnum = InternalObjectPositionE.Top;
  529.                             isTopFound = true;
  530.                             InternalST.Soap(this, "SoapParser.EndElement change position to top");
  531.                         }
  532.                        
  533.                         if (!pr.PRisParsed) {
  534.                             InternalST.Soap(this, "SoapParser.EndElement Object hasn't been parsed");
  535.                             if (!pr.PRisProcessAttributes && !(pr.PRobjectPositionEnum == InternalObjectPositionE.Top && objectReader.IsFakeTopObject))
  536.                                 ProcessAttributes(pr, objectPr);
  537.                             objectReader.Parse(pr);
  538.                             pr.PRisParsed = true;
  539.                         }
  540.                         pr.PRparseTypeEnum = InternalParseTypeE.ObjectEnd;
  541.                     }
  542.                    
  543.                     switch (headerState) {
  544.                         case HeaderStateEnum.None:
  545.                         case HeaderStateEnum.TopLevelObject:
  546.                             InternalST.Soap(this, "SoapParser.EndElement Parse EndObject");
  547.                             objectReader.Parse(pr);
  548.                             break;
  549.                         case HeaderStateEnum.HeaderRecord:
  550.                         case HeaderStateEnum.NestedObject:
  551.                             InternalST.Soap(this, "SoapParser.EndElement ProcessHeaderEnd");
  552.                             ProcessHeaderEnd(pr);
  553.                             break;
  554.                     }
  555.                    
  556.                     if (pr.PRparseTypeEnum == InternalParseTypeE.EnvelopeEnd) {
  557.                         // End of document
  558.                         soapParser.Stop();
  559.                     }
  560.                    
  561.                     PutPr(pr);
  562.                     break;
  563.                 case InternalParseStateE.Member:
  564.                    
  565.                     pr = (ParseRecord)stack.Peek();
  566.                     objectPr = (ParseRecord)stack.PeekPeek();
  567.                     ProcessAttributes(pr, objectPr);
  568.                    
  569.                     // Check if there are any XmlAttribute records, if there are, process them
  570.                     if (xmlAttributeList != null)
  571.                         InternalST.Soap(this, "XmlAttribute check count ", xmlAttributeList.Count);
  572.                     else
  573.                         InternalST.Soap(this, "XmlAttribute null");
  574.                    
  575.                     if ((xmlAttributeList != null) && (xmlAttributeList.Count > 0)) {
  576.                         InternalST.Soap(this, "xmlAttribute list count ", xmlAttributeList.Count);
  577.                         for (int i = 0; i < xmlAttributeList.Count; i++) {
  578.                             InternalST.Soap(this, "ObjectReader.Parse 7");
  579.                             objectReader.Parse((ParseRecord)xmlAttributeList[i]);
  580.                         }
  581.                         xmlAttributeList.Clear();
  582.                     }
  583.                    
  584.                     pr = (ParseRecord)stack.Pop();
  585.                     if ((headerState == HeaderStateEnum.TopLevelObject) && (pr.PRarrayTypeEnum == InternalArrayTypeE.Base64)) {
  586.                         // A Base64 array object treated specially by ObjectReader. It is completely processed when
  587.                         // pr.PRparseTypeEnum == InternalParseTypeE.Object, an ObjectEnd is not needed to complete parsing
  588.                         InternalST.Soap(this, "ObjectReader.Parse 3");
  589.                         objectReader.Parse(pr);
  590.                         pr.PRisParsed = true;
  591.                     }
  592.                     else if (pr.PRmemberValueEnum != InternalMemberValueE.Nested) {
  593.                         if ((pr.PRobjectTypeEnum == InternalObjectTypeE.Array) && (pr.PRmemberValueEnum != InternalMemberValueE.Null)) {
  594.                             // Empty array
  595.                             pr.PRmemberValueEnum = InternalMemberValueE.Nested;
  596.                             InternalST.Soap(this, "ObjectReader.Parse 4");
  597.                             objectReader.Parse(pr);
  598.                             pr.PRisParsed = true;
  599.                            
  600.                             pr.PRparseTypeEnum = InternalParseTypeE.MemberEnd;
  601.                         }
  602.                         else if (pr.PRidRef > 0)
  603.                             pr.PRmemberValueEnum = InternalMemberValueE.Reference;
  604.                         else if (pr.PRmemberValueEnum != InternalMemberValueE.Null)
  605.                             pr.PRmemberValueEnum = InternalMemberValueE.InlineValue;
  606.                        
  607.                         switch (headerState) {
  608.                             case HeaderStateEnum.None:
  609.                             case HeaderStateEnum.TopLevelObject:
  610.                                 InternalST.Soap(this, "ObjectReader.Parse 5");
  611.                                 if (pr.PRparseTypeEnum == InternalParseTypeE.Object) {
  612.                                     // Empty object in header case
  613.                                     if (!pr.PRisParsed)
  614.                                         objectReader.Parse(pr);
  615.                                     pr.PRparseTypeEnum = InternalParseTypeE.ObjectEnd;
  616.                                 }
  617.                                 objectReader.Parse(pr);
  618.                                 pr.PRisParsed = true;
  619.                                 break;
  620.                             case HeaderStateEnum.HeaderRecord:
  621.                             case HeaderStateEnum.NestedObject:
  622.                                 ProcessHeaderMember(pr);
  623.                                 break;
  624.                         }
  625.                     }
  626.                     else {
  627.                         // Nested member already parsed, need end to finish nested object
  628.                         pr.PRparseTypeEnum = InternalParseTypeE.MemberEnd;
  629.                         switch (headerState) {
  630.                             case HeaderStateEnum.None:
  631.                             case HeaderStateEnum.TopLevelObject:
  632.                                 InternalST.Soap(this, "ObjectReader.Parse 6");
  633.                                 objectReader.Parse(pr);
  634.                                 pr.PRisParsed = true;
  635.                                 break;
  636.                             case HeaderStateEnum.HeaderRecord:
  637.                             case HeaderStateEnum.NestedObject:
  638.                                 ProcessHeaderMemberEnd(pr);
  639.                                 break;
  640.                         }
  641.                     }
  642.                     PutPr(pr);
  643.                     break;
  644.                 case InternalParseStateE.MemberChild:
  645.                    
  646.                     pr = (ParseRecord)stack.Peek();
  647.                     if (pr.PRmemberValueEnum != InternalMemberValueE.Null)
  648.                         MarshalError("EndElement", (ParseRecord)stack.Peek(), actualName, currentState);
  649.                     break;
  650.                 default:
  651.                    
  652.                     MarshalError("EndElement", (ParseRecord)stack.Peek(), actualName, currentState);
  653.                     break;
  654.             }
  655.             #if _DEBUG
  656.             InternalST.Soap(this, SerTraceString("EndElement End ", (ParseRecord)stack.Peek(), name, currentState, headerState));
  657.             #endif
  658.         }
  659.        
  660.         // Called at the start of processing child nodes for an element
  661.         internal void StartChildren()
  662.         {
  663.             #if _DEBUG
  664.             InternalST.Soap(this, SerTraceString("StartChildren Begin ", (ParseRecord)stack.Peek(), null, currentState, headerState));
  665.             #endif
  666.             ParseRecord pr = null;
  667.            
  668.             switch (currentState) {
  669.                 case InternalParseStateE.Object:
  670.                     InternalST.Soap(this, "StartChildren Object");
  671.                     pr = (ParseRecord)stack.Peek();
  672.                     ParseRecord objectPr = (ParseRecord)stack.PeekPeek();
  673.                     ProcessAttributes(pr, objectPr);
  674.                     if (pr.PRarrayTypeEnum != InternalArrayTypeE.Base64) {
  675.                         if (!((pr.PRparseTypeEnum == InternalParseTypeE.Envelope) || (pr.PRparseTypeEnum == InternalParseTypeE.Body))) {
  676.                             currentState = InternalParseStateE.Member;
  677.                            
  678.                         }
  679.                        
  680.                         switch (headerState) {
  681.                             case HeaderStateEnum.None:
  682.                             case HeaderStateEnum.TopLevelObject:
  683.                                 InternalST.Soap(this, "ObjectReader.Parse 8");
  684.                                 InternalST.Soap(this, "SoapParser.StartChildren TopFound " + isTopFound + " objectPr.parseTypeEnum " + (objectPr == null ? "null" : ((Enum)objectPr.PRparseTypeEnum).ToString()));
  685.                                 if (!isTopFound && (objectPr != null) && (objectPr.PRparseTypeEnum == InternalParseTypeE.Body)) {
  686.                                     pr.PRobjectPositionEnum = InternalObjectPositionE.Top;
  687.                                     isTopFound = true;
  688.                                     InternalST.Soap(this, "SoapParser.StartChildren change position to top");
  689.                                 }
  690.                                 objectReader.Parse(pr);
  691.                                 pr.PRisParsed = true;
  692.                                 break;
  693.                             case HeaderStateEnum.HeaderRecord:
  694.                             case HeaderStateEnum.NestedObject:
  695.                             case HeaderStateEnum.FirstHeaderRecord:
  696.                                 ProcessHeader(pr);
  697.                                 break;
  698.                         }
  699.                     }
  700.                     break;
  701.                 case InternalParseStateE.Member:
  702.                    
  703.                     InternalST.Soap(this, "StartChildren Member");
  704.                     pr = (ParseRecord)stack.Peek();
  705.                     currentState = InternalParseStateE.MemberChild;
  706.                     break;
  707.                 case InternalParseStateE.MemberChild:
  708.                 default:
  709.                    
  710.                     MarshalError("StartChildren", (ParseRecord)stack.Peek(), null, currentState);
  711.                     break;
  712.             }
  713.            
  714.             #if _DEBUG
  715.             InternalST.Soap(this, "StartChildren 10");
  716.             InternalST.Soap(this, SerTraceString("StartChildren End ", (ParseRecord)stack.Peek(), null, currentState, headerState));
  717.             #endif
  718.         }
  719.        
  720.         // Called at the end of process the child nodes for an element
  721.         internal void FinishChildren(string prefix, string name, string urn)
  722.         {
  723.             #if _DEBUG
  724.             InternalST.Soap(this, SerTraceString("FinishChildren Begin ", (ParseRecord)stack.Peek(), name, prefix, urn, currentState, headerState));
  725.             #endif
  726.             ParseRecord pr = null;
  727.            
  728.             switch (currentState) {
  729.                 case InternalParseStateE.Member:
  730.                     pr = (ParseRecord)stack.Peek();
  731.                     currentState = pr.PRparseStateEnum;
  732.                     // For an object which has a value such as top level System.String
  733.                     pr.PRvalue = textValue;
  734.                     textValue = "";
  735.                     break;
  736.                 case InternalParseStateE.MemberChild:
  737.                    
  738.                     pr = (ParseRecord)stack.Peek();
  739.                     currentState = pr.PRparseStateEnum;
  740.                    
  741.                     ParseRecord objectPr = (ParseRecord)stack.PeekPeek();
  742.                     pr.PRvalue = textValue;
  743.                     // Non-primitive type need to filter
  744.                     textValue = "";
  745.                    
  746.                     break;
  747.                 case InternalParseStateE.Object:
  748.                    
  749.                     pr = (ParseRecord)stack.Peek();
  750.                     if (pr.PRarrayTypeEnum == InternalArrayTypeE.Base64) {
  751.                         pr.PRvalue = textValue;
  752.                         textValue = "";
  753.                     }
  754.                     // Only occur for top object, returning to SerializedStreamHeader object
  755.                     break;
  756.                 default:
  757.                    
  758.                     MarshalError("FinishChildren", (ParseRecord)stack.Peek(), name, currentState);
  759.                     break;
  760.             }
  761.            
  762.             #if _DEBUG
  763.             InternalST.Soap(this, SerTraceString("FinishChildren End ", (ParseRecord)stack.Peek(), name, currentState, headerState));
  764.             #endif
  765.         }
  766.        
  767.         // Called at when an attribute is finished
  768.         internal void Attribute(string prefix, string name, string urn, string value)
  769.         {
  770.             #if _DEBUG
  771.             InternalST.Soap(this, SerTraceString("Attribute Begin ", (ParseRecord)stack.Peek(), name, prefix, urn, currentState, headerState));
  772.             InternalST.Soap(this, "Attribute prefix ", prefix, ", Name ", name, ", urn ", urn, ",value " + value);
  773.             #endif
  774.             switch (currentState) {
  775.                 case InternalParseStateE.Object:
  776.                 case InternalParseStateE.Member:
  777.                    
  778.                     ParseRecord pr = (ParseRecord)stack.Peek();
  779.                    
  780.                     string actualName = name;
  781.                     if (!((urn == null) || (urn.Length == 0)) && ((prefix == null) || (prefix.Length == 0))) {
  782.                         // Default namespaces, assign a name to reference urn
  783.                         if (nameSpaceToKey.ContainsKey(urn))
  784.                             actualName = (string)nameSpaceToKey[urn];
  785.                         else {
  786.                             actualName = NextPrefix();
  787.                             nameSpaceToKey[urn] = actualName;
  788.                         }
  789.                         InternalST.Soap(this, "EndAttribute null urn assigned Name ", actualName);
  790.                     }
  791.                    
  792.                     if (!((prefix == null) || (actualName == null) || (value == null) || (urn == null))) {
  793.                         // Xml parser returns an end attribute without a begin attribute for xmlns="" (which is a cancellation of a default namespace)
  794.                         // In this case want to avoid the push
  795.                         attributeValues.Push(new AttributeValueEntry(prefix, actualName, value, urn));
  796.                     }
  797.                     break;
  798.                 case InternalParseStateE.MemberChild:
  799.                 default:
  800.                     MarshalError("EndAttribute, Unknown State ", (ParseRecord)stack.Peek(), name, currentState);
  801.                     break;
  802.             }
  803.            
  804.             #if _DEBUG
  805.             InternalST.Soap(this, SerTraceString("EndAttribute End ", (ParseRecord)stack.Peek(), name, currentState, headerState));
  806.             #endif
  807.         }
  808.        
  809.        
  810.         // Called at when a text element is encountered
  811.         internal void Text(string text)
  812.         {
  813.             InternalST.Soap(this, "Text ", text);
  814.             textValue = text;
  815.         }
  816.        
  817.         // Called at when a Comment is encountered (not used)
  818.         internal void Comment(string body)
  819.         {
  820.             InternalST.Soap(this, "Comment ", body);
  821.         }
  822.        
  823.        
  824.         // Process the attributes placed into the ParseRecord
  825.         StringBuilder sburi = new StringBuilder(50);
  826.         private void ProcessAttributes(ParseRecord pr, ParseRecord objectPr)
  827.         {
  828.             InternalST.Soap(this, "ProcessAttributes Entry ", pr.Trace(), " headerState ", ((Enum)headerState).ToString());
  829.             string keyPosition = null;
  830.             string keyOffset = null;
  831.             string keyMustUnderstand = null;
  832.            
  833.             pr.PRisProcessAttributes = true;
  834.            
  835.             string SoapKeyUrl = "http://schemas.xmlsoap.org/soap/encoding/";
  836.             int SoapKeyUrlLength = SoapKeyUrl.Length;
  837.             string UrtKeyUrl = "http://schemas.microsoft.com/clr/id";
  838.             int UrtKeyUrlLength = UrtKeyUrl.Length;
  839.             string SoapEnvKeyUrl = "http://schemas.xmlsoap.org/soap/envelope/";
  840.             int SoapEnvKeyUrlLength = SoapEnvKeyUrl.Length;
  841.             string XSIKey2001 = "http://www.w3.org/2001/XMLSchema-instance";
  842.             int XSIKey2001Length = XSIKey2001.Length;
  843.             string XSIKey2000 = "http://www.w3.org/2000/10/XMLSchema-instance";
  844.             int XSIKey2000Length = XSIKey2000.Length;
  845.             string XSIKey1999 = "http://www.w3.org/1999/XMLSchema-instance";
  846.             int XSIKey1999Length = XSIKey1999.Length;
  847.            
  848.             string XSDKey1999 = "http://www.w3.org/1999/XMLSchema";
  849.             int XSDKey1999Length = XSDKey1999.Length;
  850.             string XSDKey2000 = "http://www.w3.org/2000/10/XMLSchema";
  851.             int XSDKey2000Length = XSDKey2000.Length;
  852.             string XSDKey2001 = "http://www.w3.org/2001/XMLSchema";
  853.             int XSDKey2001Length = XSDKey2001.Length;
  854.             string clrNS = "http://schemas.microsoft.com/soap/encoding/clr/1.0";
  855.             int clrNSLength = clrNS.Length;
  856.            
  857.             for (int i = 0; i < attributeValues.Count(); i++) {
  858.                 AttributeValueEntry attributeValueEntry = (AttributeValueEntry)attributeValues.GetItem(i);
  859.                 string prefix = attributeValueEntry.prefix;
  860.                 string key = attributeValueEntry.key;
  861.                 if ((key == null) || (key.Length == 0))
  862.                     key = pr.PRnameXmlKey;
  863.                 //case where there is a default key
  864.                 string value = attributeValueEntry.value;
  865.                 bool prefixMatchesXmlns = false;
  866.                 string urn = attributeValueEntry.urn;
  867.                 InternalST.Soap(this, "ProcessAttributes attribute prefix ", prefix, " key ", key, " value ", value, " urn ", urn);
  868.                
  869.                 int keyLength = key.Length;
  870.                 int valueLength = value.Length;
  871.                 // table need for QName xsd types
  872.                 if (key == null || keyLength == 0)
  873.                     keyToNamespaceTable[prefix] = value;
  874.                 else
  875.                     keyToNamespaceTable[prefix + ":" + key] = value;
  876.                
  877.                 if (keyLength == 2 && String.Compare(key, "id", StringComparison.OrdinalIgnoreCase) == 0)
  878.                     pr.PRobjectId = objectReader.GetId(value);
  879.                 else if (keyLength == 8 && String.Compare(key, "position", StringComparison.OrdinalIgnoreCase) == 0)
  880.                     keyPosition = value;
  881.                 else if (keyLength == 6 && String.Compare(key, "offset", StringComparison.OrdinalIgnoreCase) == 0)
  882.                     keyOffset = value;
  883.                 else if (keyLength == 14 && String.Compare(key, "MustUnderstand", StringComparison.OrdinalIgnoreCase) == 0)
  884.                     keyMustUnderstand = value;
  885.                 else if (keyLength == 4 && String.Compare(key, "null", StringComparison.OrdinalIgnoreCase) == 0) {
  886.                     pr.PRmemberValueEnum = InternalMemberValueE.Null;
  887.                     pr.PRvalue = null;
  888.                 }
  889.                 else if (keyLength == 4 && String.Compare(key, "root", StringComparison.OrdinalIgnoreCase) == 0) {
  890.                     if (value.Equals("1"))
  891.                         pr.PRisHeaderRoot = true;
  892.                 }
  893.                 else if (keyLength == 4 && String.Compare(key, "href", StringComparison.OrdinalIgnoreCase) == 0)
  894.                     pr.PRidRef = objectReader.GetId(value);
  895.                 else if (keyLength == 4 && String.Compare(key, "type", StringComparison.OrdinalIgnoreCase) == 0) {
  896.                     string currentPRtypeXmlKey = pr.PRtypeXmlKey;
  897.                     string currentPRkeyDt = pr.PRkeyDt;
  898.                     Type currentPRdtType = pr.PRdtType;
  899.                    
  900.                     string typeValue = value;
  901.                     int index = value.IndexOf(":");
  902.                     if (index > 0) {
  903.                         pr.PRtypeXmlKey = value.Substring(0, index);
  904.                         typeValue = value.Substring(++index);
  905.                     }
  906.                     else {
  907.                         pr.PRtypeXmlKey = prefix;
  908.                     }
  909.                    
  910.                     if (String.Compare(typeValue, "anyType", StringComparison.OrdinalIgnoreCase) == 0 || String.Compare(typeValue, "ur-type", StringComparison.OrdinalIgnoreCase) == 0) {
  911.                         pr.PRkeyDt = "System.Object";
  912.                         pr.PRdtType = SoapUtil.typeofObject;
  913.                         pr.PRtypeXmlKey = urtKey;
  914.                     }
  915.                    
  916.                     //Don't need to process xsi:type="SOAP-ENC:Array"
  917.                     if (pr.PRtypeXmlKey == soapKey && typeValue == "Array") {
  918.                         // Array values already found,use these value rather then the xsi:type values
  919.                         pr.PRtypeXmlKey = currentPRtypeXmlKey;
  920.                         pr.PRkeyDt = currentPRkeyDt;
  921.                         pr.PRdtType = currentPRdtType;
  922.                         InternalST.Soap(this, "ProcessAttributes, xsi:type='SOAP-ENC:Array' pr.PRtypeXmlKey ", pr.PRtypeXmlKey, " pr.PRkeyDt " + pr.PRkeyDt);
  923.                     }
  924.                     else {
  925.                         pr.PRkeyDt = typeValue;
  926.                         InternalST.Soap(this, "ProcessAttributes, not xsi:type='SOAP-ENC:Array' pr.PRtypeXmlKey ", pr.PRtypeXmlKey, " pr.PRkeyDt " + pr.PRkeyDt);
  927.                     }
  928.                 }
  929.                 else if (keyLength == 9 && String.Compare(key, "arraytype", StringComparison.OrdinalIgnoreCase) == 0) {
  930.                     string typeValue = value;
  931.                     int index = value.IndexOf(":");
  932.                     if (index > 0) {
  933.                         pr.PRtypeXmlKey = value.Substring(0, index);
  934.                         pr.PRkeyDt = typeValue = value.Substring(++index);
  935.                     }
  936.                    
  937.                     if (typeValue.StartsWith("ur_type[", StringComparison.Ordinal)) {
  938.                         pr.PRkeyDt = "System.Object" + typeValue.Substring(6);
  939.                         pr.PRtypeXmlKey = urtKey;
  940.                     }
  941.                 }
  942.                 else if (SoapServices.IsClrTypeNamespace(value)) {
  943.                     if (!assemKeyToAssemblyTable.ContainsKey(key)) {
  944.                         string typeNamespace = null;
  945.                         string assemblyName = null;
  946.                         SoapServices.DecodeXmlNamespaceForClrTypeNamespace(value, out typeNamespace, out assemblyName);
  947.                         if (assemblyName == null) {
  948.                             assemKeyToAssemblyTable[key] = new SoapAssemblyInfo(SoapUtil.urtAssemblyString, SoapUtil.urtAssembly);
  949.                             assemKeyToNameSpaceTable[key] = typeNamespace;
  950.                         }
  951.                         else {
  952.                             assemKeyToAssemblyTable[key] = new SoapAssemblyInfo(assemblyName);
  953.                             if (typeNamespace != null)
  954.                                 assemKeyToNameSpaceTable[key] = typeNamespace;
  955.                         }
  956.                        
  957.                     }
  958.                 }
  959.                 else if ((prefixMatchesXmlns = prefix.Equals("xmlns")) && (valueLength == SoapKeyUrlLength && String.Compare(value, SoapKeyUrl, StringComparison.OrdinalIgnoreCase) == 0)) {
  960.                     soapKey = key;
  961.                 }
  962.                 else if (prefixMatchesXmlns && (valueLength == UrtKeyUrlLength && String.Compare(value, UrtKeyUrl, StringComparison.OrdinalIgnoreCase) == 0)) {
  963.                     urtKey = key;
  964.                     assemKeyToAssemblyTable[urtKey] = new SoapAssemblyInfo(SoapUtil.urtAssemblyString, SoapUtil.urtAssembly);
  965.                 }
  966.                 else if (prefixMatchesXmlns && (valueLength == SoapEnvKeyUrlLength && String.Compare(value, SoapEnvKeyUrl, StringComparison.OrdinalIgnoreCase) == 0)) {
  967.                     soapEnvKey = key;
  968.                 }
  969.                 else if (key == "encodingStyle") {
  970.                     /*
  971.                     String[] split = value.Split(' ');
  972.                     foreach (String s in split)
  973.                     {
  974.                         if (s == "http://schemas.microsoft.com/soap/encoding/clr/1.0")
  975.                         {
  976.                             objectReader.SetVersion(1,0);
  977.                             break;
  978.                         }
  979.                     }
  980.                     */                   
  981.                 }
  982.                 else if (prefixMatchesXmlns && ((valueLength == XSIKey2001Length && String.Compare(value, XSIKey2001, StringComparison.OrdinalIgnoreCase) == 0) || (valueLength == XSIKey1999Length && String.Compare(value, XSIKey1999, StringComparison.OrdinalIgnoreCase) == 0) || (valueLength == XSIKey2000Length && String.Compare(value, XSIKey2000, StringComparison.OrdinalIgnoreCase) == 0))) {
  983.                     xsiKey = key;
  984.                 }
  985.                 else if (prefixMatchesXmlns && ((valueLength == XSDKey2001Length && String.Compare(value, XSDKey2001, StringComparison.OrdinalIgnoreCase) == 0)) || (valueLength == XSDKey1999Length && String.Compare(value, XSDKey1999, StringComparison.OrdinalIgnoreCase) == 0) || (valueLength == XSDKey2000Length && String.Compare(value, XSDKey2000, StringComparison.OrdinalIgnoreCase) == 0)) {
  986.                     xsdKey = key;
  987.                 }
  988.                 else if (prefixMatchesXmlns && (valueLength == clrNSLength && String.Compare(value, clrNS, StringComparison.OrdinalIgnoreCase) == 0)) {
  989.                     objectReader.SetVersion(1, 0);
  990.                 }
  991.                 else {
  992.                     //String lowerCaseValue = value.ToLower();
  993.                     if (prefixMatchesXmlns) {
  994.                         // Assume it is an interop namespace
  995.                         assemKeyToInteropAssemblyTable[key] = value;
  996.                         InternalST.Soap(this, "ProcessAttributes, InteropType key " + key + " value ", value);
  997.                     }
  998.                     else if (String.Compare(prefix, soapKey, StringComparison.OrdinalIgnoreCase) == 0) {
  999.                         InternalST.Soap(this, "ProcessAttributes, Not processed key ", prefix, ":", key, " = ", value);
  1000.                     }
  1001.                     else {
  1002.                         // See if it is a XmlAttribute
  1003.                         InternalST.Soap(this, "ProcessAttributes, XmlAttribute prefix ", prefix, " key ", key, " value ", value, " urn ", urn, " hashtable ",
  1004.                         assemKeyToInteropAssemblyTable[prefix]);
  1005.                        
  1006.                         if ((assemKeyToInteropAssemblyTable.ContainsKey(prefix)) && ((string)assemKeyToInteropAssemblyTable[prefix]).Equals(urn)) {
  1007.                             ProcessXmlAttribute(prefix, key, value, objectPr);
  1008.                         }
  1009.                         else {
  1010.                             InternalST.Soap(this, "ProcessAttributes, Not processed prefix ", prefix, " key ", key, " value ", value, " urn ", urn);
  1011.                         }
  1012.                     }
  1013.                 }
  1014.             }
  1015.            
  1016.             attributeValues.Clear();
  1017.            
  1018.             // reset the header state
  1019.             // If no headers then headerState is None
  1020.             //
  1021.             // if parent is a header section then these are top level objects
  1022.             // within the header section. If the object has a root set
  1023.             // then it is a header record, if not then it is a toplevel object
  1024.             // in the header section which is not a header record.
  1025.             //
  1026.             // if the parent is not a header section and is a header root
  1027.             // then this is a nested object within a header record. All
  1028.             // subsequent object will be nested until another header
  1029.             // root is encountered
  1030.             //
  1031.             // The first header record is considered a root record
  1032.             if (headerState != HeaderStateEnum.None) {
  1033.                 if (objectPr.PRparseTypeEnum == InternalParseTypeE.Headers) {
  1034.                     if (pr.PRisHeaderRoot || (headerState == HeaderStateEnum.FirstHeaderRecord)) {
  1035.                         headerState = HeaderStateEnum.HeaderRecord;
  1036.                     }
  1037.                     else {
  1038.                         headerState = HeaderStateEnum.TopLevelObject;
  1039.                         currentState = InternalParseStateE.Object;
  1040.                         pr.PRobjectTypeEnum = InternalObjectTypeE.Object;
  1041.                         pr.PRparseTypeEnum = InternalParseTypeE.Object;
  1042.                         pr.PRparseStateEnum = InternalParseStateE.Object;
  1043.                         pr.PRmemberTypeEnum = InternalMemberTypeE.Empty;
  1044.                         pr.PRmemberValueEnum = InternalMemberValueE.Empty;
  1045.                     }
  1046.                 }
  1047.                 else if (objectPr.PRisHeaderRoot)
  1048.                     headerState = HeaderStateEnum.NestedObject;
  1049.             }
  1050.            
  1051.             InternalST.Soap(this, "ProcessAttributes, headerState ", ((Enum)headerState).ToString());
  1052.            
  1053.            
  1054.             if (!isTopFound && (objectPr != null) && (objectPr.PRparseTypeEnum == InternalParseTypeE.Body)) {
  1055.                 pr.PRobjectPositionEnum = InternalObjectPositionE.Top;
  1056.                 isTopFound = true;
  1057.             }
  1058.             else if (pr.PRobjectPositionEnum != InternalObjectPositionE.Top)
  1059.                 pr.PRobjectPositionEnum = InternalObjectPositionE.Child;
  1060.            
  1061.            
  1062.             // Don't process type for envelop, topSoapElement unless it has a key of soapEnvKey (SOAP-ENV). Fault
  1063.             // is the only top record which currently falls into this category.
  1064.             if (!((pr.PRparseTypeEnum == InternalParseTypeE.Envelope) || (pr.PRparseTypeEnum == InternalParseTypeE.Body) || (pr.PRparseTypeEnum == InternalParseTypeE.Headers) || (pr.PRobjectPositionEnum == InternalObjectPositionE.Top && objectReader.IsFakeTopObject && !pr.PRnameXmlKey.Equals(soapEnvKey)))) {
  1065.                 InternalST.Soap(this, "ProcessAttributes before Process Type ", ((Enum)pr.PRparseTypeEnum).ToString());
  1066.                 ProcessType(pr, objectPr);
  1067.             }
  1068.            
  1069.             if (keyPosition != null) {
  1070.                 int outRank;
  1071.                 string outDimSignature;
  1072.                 InternalArrayTypeE outArrayTypeEnum;
  1073.                 pr.PRpositionA = ParseArrayDimensions(keyPosition, out outRank, out outDimSignature, out outArrayTypeEnum);
  1074.             }
  1075.            
  1076.             if (keyOffset != null) {
  1077.                 int outRank;
  1078.                 string outDimSignature;
  1079.                 InternalArrayTypeE outArrayTypeEnum;
  1080.                 pr.PRlowerBoundA = ParseArrayDimensions(keyOffset, out outRank, out outDimSignature, out outArrayTypeEnum);
  1081.             }
  1082.            
  1083.             if (keyMustUnderstand != null)
  1084.                 if (keyMustUnderstand.Equals("1"))
  1085.                     pr.PRisMustUnderstand = true;
  1086.                 else if (keyMustUnderstand.Equals("0"))
  1087.                     pr.PRisMustUnderstand = false;
  1088.                 else
  1089.                     throw new SerializationException(String.Format(CultureInfo.CurrentCulture, SoapUtil.GetResourceString("Serialization_MustUnderstand"), keyMustUnderstand));
  1090.            
  1091.             if (pr.PRparseTypeEnum == InternalParseTypeE.Member) {
  1092.                 // Process Member
  1093.                
  1094.                 InternalST.Soap(this, "ProcessAttributes Member ");
  1095.                 stack.Dump();
  1096.                
  1097.                 if (objectPr.PRparseTypeEnum == InternalParseTypeE.Headers)
  1098.                     pr.PRmemberTypeEnum = InternalMemberTypeE.Header;
  1099.                 else if (objectPr.PRobjectTypeEnum == InternalObjectTypeE.Array)
  1100.                     pr.PRmemberTypeEnum = InternalMemberTypeE.Item;
  1101.                 else
  1102.                     pr.PRmemberTypeEnum = InternalMemberTypeE.Field;
  1103.             }
  1104.         }
  1105.        
  1106.        
  1107.         // Create a URT type from the XML dt type
  1108.         private void ProcessType(ParseRecord pr, ParseRecord objectPr)
  1109.         {
  1110.             InternalST.Soap(this, "ProcessType nameXmlKey ", pr.PRnameXmlKey, " typeXmlKey ", pr.PRtypeXmlKey);
  1111.             pr.Dump();
  1112.             if (pr.PRdtType != null)
  1113.                 return;
  1114.             if ((pr.PRnameXmlKey.Equals(soapEnvKey)) && (String.Compare(pr.PRname, "Fault", StringComparison.OrdinalIgnoreCase) == 0)) {
  1115.                 // Fault object
  1116.                 InternalST.Soap(this, "ProcessType SoapFault");
  1117.                 pr.PRdtType = SoapUtil.typeofSoapFault;
  1118.                 pr.PRparseTypeEnum = InternalParseTypeE.Object;
  1119.             }
  1120.             else if (pr.PRname != null) {
  1121.                 InternalST.Soap(this, "ProcessType Attribute 1");
  1122.                
  1123.                 string interopAssemblyNameString = null;
  1124.                
  1125.                 // determine interop assembly string if there is a namespace
  1126.                 if ((pr.PRnameXmlKey != null) && (pr.PRnameXmlKey.Length > 0)) {
  1127.                     interopAssemblyNameString = (string)assemKeyToInteropAssemblyTable[pr.PRnameXmlKey];
  1128.                     InternalST.Soap(this, "ProcessType Attribute 2 " + interopAssemblyNameString);
  1129.                 }
  1130.                
  1131.                 // look for interop data
  1132.                 Type type = null;
  1133.                 string name = null;
  1134.                
  1135.                 if (objectPr != null) {
  1136.                     if (pr.PRisXmlAttribute) {
  1137.                         // These should processed after containing element
  1138.                         // is processed.
  1139.                         SoapServices.GetInteropFieldTypeAndNameFromXmlAttribute(objectPr.PRdtType, pr.PRname, interopAssemblyNameString, out type, out name);
  1140.                         InternalST.Soap(this, "ProcessType Attribute 3 type " + type + " name " + name);
  1141.                     }
  1142.                     else {
  1143.                         SoapServices.GetInteropFieldTypeAndNameFromXmlElement(objectPr.PRdtType, pr.PRname, interopAssemblyNameString, out type, out name);
  1144.                         InternalST.Soap(this, "ProcessType Attribute 4 type objectPr.PRdtType ", objectPr.PRdtType, " pr.PRname ", pr.PRname, " interopAssemblyNameString ", interopAssemblyNameString, " type ", type, " name ",
  1145.                         name);
  1146.                     }
  1147.                 }
  1148.                
  1149.                 if (type != null) {
  1150.                     pr.PRdtType = type;
  1151.                     pr.PRname = name;
  1152.                     pr.PRdtTypeCode = Converter.SoapToCode(pr.PRdtType);
  1153.                     InternalST.Soap(this, "ProcessType Attribute 5 typeCode " + ((Enum)pr.PRdtTypeCode));
  1154.                 }
  1155.                 else {
  1156.                     if (interopAssemblyNameString != null)
  1157.                         pr.PRdtType = objectReader.Bind(interopAssemblyNameString, pr.PRname);
  1158.                     // try to get type from SerializationBinder
  1159.                     if (pr.PRdtType == null) {
  1160.                         pr.PRdtType = SoapServices.GetInteropTypeFromXmlElement(pr.PRname, interopAssemblyNameString);
  1161.                     }
  1162.                    
  1163.                     // Array item where the element name gives the element type
  1164.                     if (pr.PRkeyDt == null && pr.PRnameXmlKey != null && pr.PRnameXmlKey.Length > 0 && objectPr.PRobjectTypeEnum == InternalObjectTypeE.Array && objectPr.PRarrayElementType == Converter.typeofObject) {
  1165.                         pr.PRdtType = ProcessGetType(pr.PRname, pr.PRnameXmlKey, out pr.PRassemblyName);
  1166.                         pr.PRdtTypeCode = Converter.SoapToCode(pr.PRdtType);
  1167.                     }
  1168.                    
  1169.                     InternalST.Soap(this, "ProcessType Attribute 6 type pr.PRname ", pr.PRname, " interopAssemblyNameString ", interopAssemblyNameString, " pr.PRdtType ", pr.PRdtType);
  1170.                 }
  1171.                
  1172.             }
  1173.            
  1174.             if (pr.PRdtType != null)
  1175.                 return;
  1176.            
  1177.             if ((pr.PRtypeXmlKey != null) && (pr.PRtypeXmlKey.Length > 0) && (pr.PRkeyDt != null) && (pr.PRkeyDt.Length > 0) && (assemKeyToInteropAssemblyTable.ContainsKey(pr.PRtypeXmlKey))) {
  1178.                 InternalST.Soap(this, "ProcessType Attribute 7 ");
  1179.                 // Interop type get from dtType
  1180.                 int index = pr.PRkeyDt.IndexOf("[");
  1181.                 if (index > 0) {
  1182.                     ProcessArray(pr, index, true);
  1183.                 }
  1184.                 else {
  1185.                     string assemblyString = (string)assemKeyToInteropAssemblyTable[pr.PRtypeXmlKey];
  1186.                     pr.PRdtType = objectReader.Bind(assemblyString, pr.PRkeyDt);
  1187.                     // try to get type from SerializationBinder
  1188.                     if (pr.PRdtType == null) {
  1189.                         pr.PRdtType = SoapServices.GetInteropTypeFromXmlType(pr.PRkeyDt, assemblyString);
  1190.                         if (pr.PRdtType == null)
  1191.                             throw new SerializationException(String.Format(CultureInfo.CurrentCulture, SoapUtil.GetResourceString("Serialization_TypeElement"), pr.PRname + " " + pr.PRkeyDt));
  1192.                     }
  1193.                     InternalST.Soap(this, "ProcessType Attribute 8 type pr.PRkeyDt ", pr.PRkeyDt, " pr.PRdtType ", pr.PRdtType);
  1194.                     if (pr.PRdtType == null) {
  1195.                         throw new SerializationException(String.Format(CultureInfo.CurrentCulture, SoapUtil.GetResourceString("Serialization_TypeElement"), pr.PRname + " " + pr.PRkeyDt + ", " + assemblyString));
  1196.                     }
  1197.                 }
  1198.             }
  1199.             else if (pr.PRkeyDt != null) {
  1200.                 if (String.Compare(pr.PRkeyDt, "Base64", StringComparison.OrdinalIgnoreCase) == 0) {
  1201.                     pr.PRobjectTypeEnum = InternalObjectTypeE.Array;
  1202.                     pr.PRarrayTypeEnum = InternalArrayTypeE.Base64;
  1203.                 }
  1204.                 else if (String.Compare(pr.PRkeyDt, "String", StringComparison.OrdinalIgnoreCase) == 0) {
  1205.                     pr.PRdtType = SoapUtil.typeofString;
  1206.                 }
  1207.                 else if (String.Compare(pr.PRkeyDt, "methodSignature", StringComparison.OrdinalIgnoreCase) == 0) {
  1208.                     // MethodSignature needs to be expanded to an array of types
  1209.                     InternalST.Soap(this, "ProcessType methodSignature ", pr.PRvalue);
  1210.                     try {
  1211.                         pr.PRdtType = typeof(System.Type[]);
  1212.                         char[] c = {' ', ':'};
  1213.                         string[] typesStr = null;
  1214.                         if (pr.PRvalue != null)
  1215.                             typesStr = pr.PRvalue.Split(c);
  1216.                         Type[] types = null;
  1217.                         if ((typesStr == null) || (typesStr.Length == 1 && typesStr[0].Length == 0)) {
  1218.                             // Method signature with no parameters
  1219.                             types = new Type[0];
  1220.                         }
  1221.                         else {
  1222.                             types = new Type[typesStr.Length / 2];
  1223.                             //throw new SerializationException(String.Format(SoapUtil.GetResourceString("Serialization_MethodSignature"),pr.PRvalue));
  1224.                            
  1225.                             for (int i = 0; i < typesStr.Length; i += 2) {
  1226.                                 string prefix = typesStr[i];
  1227.                                 string typeString = typesStr[i + 1];
  1228.                                 types[i / 2] = ProcessGetType(typeString, prefix, out pr.PRassemblyName);
  1229.                                 InternalST.Soap(this, "ProcessType methodSignature type string ", i + " " + " prefix " + prefix + " typestring " + typeString + " type " + types[i / 2]);
  1230.                                 //Temp
  1231.                             }
  1232.                         }
  1233.                         pr.PRvarValue = types;
  1234.                     }
  1235.                     catch {
  1236.                         throw new SerializationException(String.Format(CultureInfo.CurrentCulture, SoapUtil.GetResourceString("Serialization_MethodSignature"), pr.PRvalue));
  1237.                     }
  1238.                 }
  1239.                 else {
  1240.                     pr.PRdtTypeCode = Converter.ToCode(pr.PRkeyDt);
  1241.                     if (pr.PRdtTypeCode != InternalPrimitiveTypeE.Invalid) {
  1242.                         pr.PRdtType = Converter.SoapToType(pr.PRdtTypeCode);
  1243.                     }
  1244.                     else {
  1245.                         // Find out if it is an array
  1246.                         int index = pr.PRkeyDt.IndexOf("[");
  1247.                         if (index > 0) {
  1248.                             // Array
  1249.                             ProcessArray(pr, index, false);
  1250.                         }
  1251.                         else {
  1252.                             // Object
  1253.                             pr.PRobjectTypeEnum = InternalObjectTypeE.Object;
  1254.                             pr.PRdtType = ProcessGetType(pr.PRkeyDt, pr.PRtypeXmlKey, out pr.PRassemblyName);
  1255.                             if ((pr.PRdtType == null) && (pr.PRobjectPositionEnum != InternalObjectPositionE.Top))
  1256.                                 throw new SerializationException(String.Format(CultureInfo.CurrentCulture, SoapUtil.GetResourceString("Serialization_TypeElement"), pr.PRname + " " + pr.PRkeyDt));
  1257.                         }
  1258.                     }
  1259.                     InternalST.Soap(this, "ProcessType Attribute 9 type " + pr.PRdtType);
  1260.                 }
  1261.             }
  1262.             else {
  1263.                 if ((pr.PRparseTypeEnum == InternalParseTypeE.Object) && (!(objectReader.IsFakeTopObject && (pr.PRobjectPositionEnum == InternalObjectPositionE.Top)))) {
  1264.                     if (String.Compare(pr.PRname, "Array", StringComparison.OrdinalIgnoreCase) == 0)
  1265.                         pr.PRdtType = ProcessGetType(pr.PRkeyDt, pr.PRtypeXmlKey, out pr.PRassemblyName);
  1266.                     else {
  1267.                         pr.PRdtType = ProcessGetType(pr.PRname, pr.PRnameXmlKey, out pr.PRassemblyName);
  1268.                     }
  1269.                     InternalST.Soap(this, "ProcessType Attribute 10 type " + pr.PRdtType);
  1270.                 }
  1271.                
  1272.             }
  1273.         }
  1274.        
  1275.         private Type ProcessGetType(string value, string xmlKey, out string assemblyString)
  1276.         {
  1277.             InternalST.Soap(this, "ProcessGetType Entry xmlKey ", xmlKey, " value ", value);
  1278.             Type type = null;
  1279.             string typeValue = null;
  1280.             assemblyString = null;
  1281.            
  1282.             // If there is an attribute which matches a preloaded type, then return the preloaded type
  1283.             string httpstring = (string)keyToNamespaceTable["xmlns:" + xmlKey];
  1284.             if (httpstring != null) {
  1285.                 type = GetInteropType(value, httpstring);
  1286.                 if (type != null)
  1287.                     return type;
  1288.             }
  1289.            
  1290.            
  1291.             if ((String.Compare(value, "anyType", StringComparison.OrdinalIgnoreCase) == 0 || String.Compare(value, "ur-type", StringComparison.OrdinalIgnoreCase) == 0) && (xmlKey.Equals(xsdKey)))
  1292.                 type = SoapUtil.typeofObject;
  1293.             else if ((xmlKey.Equals(xsdKey)) || (xmlKey.Equals(soapKey))) {
  1294.                 if (String.Compare(value, "string", StringComparison.OrdinalIgnoreCase) == 0) {
  1295.                     type = SoapUtil.typeofString;
  1296.                 }
  1297.                 else {
  1298.                     InternalPrimitiveTypeE code = Converter.ToCode(value);
  1299.                     if (code == InternalPrimitiveTypeE.Invalid)
  1300.                         throw new SerializationException(String.Format(CultureInfo.CurrentCulture, SoapUtil.GetResourceString("Serialization_Parser_xsd"), value));
  1301.                    
  1302.                     type = Converter.SoapToType(code);
  1303.                 }
  1304.             }
  1305.             else {
  1306.                 if (xmlKey == null)
  1307.                     throw new SerializationException(String.Format(CultureInfo.CurrentCulture, SoapUtil.GetResourceString("Serialization_Parser_xml"), value));
  1308.                
  1309.                 string nameSpace = (string)assemKeyToNameSpaceTable[xmlKey];
  1310.                 typeValue = null;
  1311.                 if (nameSpace == null || nameSpace.Length == 0)
  1312.                     typeValue = value;
  1313.                 else
  1314.                     typeValue = nameSpace + "." + value;
  1315.                
  1316.                 SoapAssemblyInfo assemblyInfo = (SoapAssemblyInfo)assemKeyToAssemblyTable[xmlKey];
  1317.                 if (assemblyInfo == null)
  1318.                     throw new SerializationException(String.Format(CultureInfo.CurrentCulture, SoapUtil.GetResourceString("Serialization_Parser_xmlAssembly"), xmlKey + " " + value));
  1319.                
  1320.                 assemblyString = assemblyInfo.assemblyString;
  1321.                 if (assemblyString != null) {
  1322.                     // See if a SerializationBinder was defined to resolve this type
  1323.                     type = objectReader.Bind(assemblyString, typeValue);
  1324.                     if (type == null)
  1325.                         type = objectReader.FastBindToType(assemblyString, typeValue);
  1326.                 }
  1327.                
  1328.                 if (type == null) {
  1329.                     Assembly assembly = null;
  1330.                     try {
  1331.                         assembly = assemblyInfo.GetAssembly(objectReader);
  1332.                     }
  1333.                     catch {
  1334.                     }
  1335.                    
  1336.                     if (assembly == null)
  1337.                         throw new SerializationException(String.Format(CultureInfo.CurrentCulture, SoapUtil.GetResourceString("Serialization_Parser_xmlAssembly"), xmlKey + ":" + httpstring + " " + value));
  1338.                     else
  1339.                         type = FormatterServices.GetTypeFromAssembly(assembly, typeValue);
  1340.                 }
  1341.             }
  1342.             if (type == null)
  1343.                 throw new SerializationException(String.Format(CultureInfo.CurrentCulture, SoapUtil.GetResourceString("Serialization_Parser_xmlType"), xmlKey + " " + typeValue + " " + assemblyString));
  1344.             InternalST.Soap(this, "ProcessGetType Exit ", type);
  1345.             return type;
  1346.         }
  1347.        
  1348.         private Type GetInteropType(string value, string httpstring)
  1349.         {
  1350.             // For the case where the client dll has a different name from the server dll
  1351.             // The assembly name returned in soap won't match the assembly name in the client dll.
  1352.             // so the custom attributes are needed to map from the Soap assembly name to the client assembly
  1353.             // This map can only work if the client type was preloaded.
  1354.             Type type = SoapServices.GetInteropTypeFromXmlType(value, httpstring);
  1355.             if (type == null) {
  1356.                 // try simple assembly name
  1357.                 int index = httpstring.IndexOf("%2C");
  1358.                 if (index > 0) {
  1359.                     string simpleAssem = httpstring.Substring(0, index);
  1360.                     type = SoapServices.GetInteropTypeFromXmlType(value, simpleAssem);
  1361.                 }
  1362.             }
  1363.             return type;
  1364.         }
  1365.        
  1366.        
  1367.         // Determine the Array information from the dt attribute
  1368.         private void ProcessArray(ParseRecord pr, int firstIndex, bool IsInterop)
  1369.         {
  1370.             InternalST.Soap(this, "ProcessArray Enter ", firstIndex, " ", pr.PRkeyDt);
  1371.             string dimString = null;
  1372.             string xmlKey = pr.PRtypeXmlKey;
  1373.             InternalPrimitiveTypeE primitiveArrayTypeCode = InternalPrimitiveTypeE.Invalid;
  1374.             pr.PRobjectTypeEnum = InternalObjectTypeE.Array;
  1375.             pr.PRmemberTypeEnum = InternalMemberTypeE.Item;
  1376.             // Need this set in case this it is a nested empty array
  1377.             pr.PRprimitiveArrayTypeString = pr.PRkeyDt.Substring(0, firstIndex);
  1378.             dimString = pr.PRkeyDt.Substring(firstIndex);
  1379.             if (IsInterop) {
  1380.                 string assemblyString = (string)assemKeyToInteropAssemblyTable[pr.PRtypeXmlKey];
  1381.                 pr.PRarrayElementType = objectReader.Bind(assemblyString, pr.PRprimitiveArrayTypeString);
  1382.                 // try to get type from SerializationBinder
  1383.                 if (pr.PRarrayElementType == null)
  1384.                     pr.PRarrayElementType = SoapServices.GetInteropTypeFromXmlType(pr.PRprimitiveArrayTypeString, assemblyString);
  1385.                 if (pr.PRarrayElementType == null)
  1386.                     pr.PRarrayElementType = SoapServices.GetInteropTypeFromXmlElement(pr.PRprimitiveArrayTypeString, assemblyString);
  1387.                 if (pr.PRarrayElementType == null)
  1388.                     throw new SerializationException(String.Format(CultureInfo.CurrentCulture, SoapUtil.GetResourceString("Serialization_TypeElement"), pr.PRname + " " + pr.PRkeyDt));
  1389.                 pr.PRprimitiveArrayTypeString = pr.PRarrayElementType.FullName;
  1390.             }
  1391.             else {
  1392.                 primitiveArrayTypeCode = Converter.ToCode(pr.PRprimitiveArrayTypeString);
  1393.                 if (primitiveArrayTypeCode != InternalPrimitiveTypeE.Invalid) {
  1394.                     pr.PRprimitiveArrayTypeString = Converter.SoapToComType(primitiveArrayTypeCode);
  1395.                     xmlKey = urtKey;
  1396.                 }
  1397.                 else if (String.Compare(pr.PRprimitiveArrayTypeString, "string", StringComparison.Ordinal) == 0) {
  1398.                     pr.PRprimitiveArrayTypeString = "System.String";
  1399.                     xmlKey = urtKey;
  1400.                 }
  1401.                 else if (String.Compare(pr.PRprimitiveArrayTypeString, "anyType", StringComparison.Ordinal) == 0 || String.Compare(pr.PRprimitiveArrayTypeString, "ur-type", StringComparison.Ordinal) == 0) {
  1402.                     pr.PRprimitiveArrayTypeString = "System.Object";
  1403.                     xmlKey = urtKey;
  1404.                 }
  1405.             }
  1406.            
  1407.             int beginIndex = firstIndex;
  1408.             int endIndex = pr.PRkeyDt.IndexOf(']', beginIndex + 1);
  1409.             if (endIndex < 1)
  1410.                 throw new SerializationException(String.Format(CultureInfo.CurrentCulture, SoapUtil.GetResourceString("Serialization_ArrayDimensions"), pr.PRkeyDt));
  1411.            
  1412.             int outRank = 0;
  1413.             int[] outDimensions = null;
  1414.             string outDimSignature = null;
  1415.             InternalArrayTypeE outArrayTypeEnum = InternalArrayTypeE.Empty;
  1416.             int numBrackets = 0;
  1417.            
  1418.             StringBuilder elementSig = new StringBuilder(10);
  1419.            
  1420.             while (true) {
  1421.                 numBrackets++;
  1422.                 outDimensions = ParseArrayDimensions(pr.PRkeyDt.Substring(beginIndex, endIndex - beginIndex + 1), out outRank, out outDimSignature, out outArrayTypeEnum);
  1423.                 if (endIndex + 1 == pr.PRkeyDt.Length)
  1424.                     break;
  1425.                 elementSig.Append(outDimSignature);
  1426.                 // Don't want last dimension in element sig
  1427.                 beginIndex = endIndex + 1;
  1428.                 endIndex = pr.PRkeyDt.IndexOf(']', beginIndex);
  1429.             }
  1430.            
  1431.             pr.PRlengthA = outDimensions;
  1432.             pr.PRrank = outRank;
  1433.            
  1434.            
  1435.             if (numBrackets == 1) {
  1436.                 pr.PRarrayElementTypeCode = primitiveArrayTypeCode;
  1437.                 pr.PRarrayTypeEnum = outArrayTypeEnum;
  1438.                 pr.PRarrayElementTypeString = pr.PRprimitiveArrayTypeString;
  1439.             }
  1440.             else {
  1441.                 pr.PRarrayElementTypeCode = InternalPrimitiveTypeE.Invalid;
  1442.                 pr.PRarrayTypeEnum = InternalArrayTypeE.Rectangular;
  1443.                 pr.PRarrayElementTypeString = pr.PRprimitiveArrayTypeString + elementSig.ToString();
  1444.                
  1445.             }
  1446.            
  1447.             InternalST.Soap(this, "ProcessArray GetType ", pr.PRarrayElementType);
  1448.             if (!IsInterop || numBrackets > 1) {
  1449.                 pr.PRarrayElementType = ProcessGetType(pr.PRarrayElementTypeString, xmlKey, out pr.PRassemblyName);
  1450.                 if (pr.PRarrayElementType == null)
  1451.                     throw new SerializationException(String.Format(CultureInfo.CurrentCulture, SoapUtil.GetResourceString("Serialization_ArrayType"), pr.PRarrayElementType));
  1452.                
  1453.                 if ((pr.PRarrayElementType == SoapUtil.typeofObject)) {
  1454.                     pr.PRisArrayVariant = true;
  1455.                     xmlKey = urtKey;
  1456.                 }
  1457.             }
  1458.            
  1459.             InternalST.Soap(this, "ProcessArray Exit");
  1460.         }
  1461.        
  1462.         // Parse an array dimension bracket
  1463.         private int[] ParseArrayDimensions(string dimString, out int rank, out string dimSignature, out InternalArrayTypeE arrayTypeEnum)
  1464.         {
  1465.             InternalST.Soap(this, "ProcessArrayDimensions Enter ", dimString);
  1466.             char[] dimArray = dimString.ToCharArray();
  1467.            
  1468.             int paramCount = 0;
  1469.             int commaCount = 0;
  1470.             int rankCount = 0;
  1471.             int[] dim = new int[dimArray.Length];
  1472.            
  1473.            
  1474.             StringBuilder sb = new StringBuilder(10);
  1475.             StringBuilder sigSb = new StringBuilder(10);
  1476.            
  1477.             for (int i = 0; i < dimArray.Length; i++) {
  1478.                 if (dimArray[i] == '[') {
  1479.                     paramCount++;
  1480.                     sigSb.Append(dimArray[i]);
  1481.                 }
  1482.                 else if (dimArray[i] == ']') {
  1483.                     if (sb.Length > 0) {
  1484.                         dim[rankCount++] = Int32.Parse(sb.ToString(), CultureInfo.InvariantCulture);
  1485.                         sb.Length = 0;
  1486.                     }
  1487.                     sigSb.Append(dimArray[i]);
  1488.                 }
  1489.                 else if (dimArray[i] == ',') {
  1490.                     commaCount++;
  1491.                     if (sb.Length > 0) {
  1492.                         dim[rankCount++] = Int32.Parse(sb.ToString(), CultureInfo.InvariantCulture);
  1493.                         sb.Length = 0;
  1494.                     }
  1495.                     sigSb.Append(dimArray[i]);
  1496.                 }
  1497.                 else if ((dimArray[i] == '-') || (Char.IsDigit(dimArray[i]))) {
  1498.                     sb.Append(dimArray[i]);
  1499.                 }
  1500.                 else
  1501.                     throw new SerializationException(String.Format(CultureInfo.CurrentCulture, SoapUtil.GetResourceString("Serialization_ArrayDimensions"), dimString));
  1502.             }
  1503.            
  1504.             rank = rankCount;
  1505.             dimSignature = sigSb.ToString();
  1506.             int[] dimA = new int[rank];
  1507.             for (int i = 0; i < rank; i++) {
  1508.                 dimA[i] = dim[i];
  1509.             }
  1510.            
  1511.             InternalArrayTypeE outEnum = InternalArrayTypeE.Empty;
  1512.            
  1513.             if (commaCount > 0)
  1514.                 outEnum = InternalArrayTypeE.Rectangular;
  1515.             else
  1516.                 outEnum = InternalArrayTypeE.Single;
  1517.            
  1518.             arrayTypeEnum = outEnum;
  1519.            
  1520.             InternalST.Soap(this, "ProcessArrayDimensions Exit rank ", rank, " dimSignature ", sigSb.ToString(), " arrayTypeEnum ", ((Enum)outEnum).ToString());
  1521.            
  1522.             return dimA;
  1523.         }
  1524.        
  1525.         StringBuilder stringBuffer = new StringBuilder(120);
  1526.        
  1527.         // Filter an element name for $ and leading digit
  1528.        
  1529.         NameCache nameCache = new NameCache();
  1530.         private string NameFilter(string name)
  1531.         {
  1532.             string value = nameCache.GetCachedValue(name) as string;
  1533.             if (value == null) {
  1534.                 value = System.Xml.XmlConvert.DecodeName(name);
  1535.                 nameCache.SetCachedValue(value);
  1536.             }
  1537.             return value;
  1538.         }
  1539.        
  1540.         ArrayList xmlAttributeList = null;
  1541.        
  1542.         private void ProcessXmlAttribute(string prefix, string key, string value, ParseRecord objectPr)
  1543.         {
  1544.             InternalST.Soap(this, "ProcessXmlAttribute prefix ", prefix, " key ", key, " value ", value);
  1545.             if (xmlAttributeList == null)
  1546.                 xmlAttributeList = new ArrayList(10);
  1547.             ParseRecord pr = GetPr();
  1548.             pr.PRparseTypeEnum = InternalParseTypeE.Member;
  1549.             pr.PRmemberTypeEnum = InternalMemberTypeE.Field;
  1550.             pr.PRmemberValueEnum = InternalMemberValueE.InlineValue;
  1551.             pr.PRname = key;
  1552.             pr.PRvalue = value;
  1553.             pr.PRnameXmlKey = prefix;
  1554.             pr.PRisXmlAttribute = true;
  1555.            
  1556.             ProcessType(pr, objectPr);
  1557.            
  1558.             xmlAttributeList.Add(pr);
  1559.         }
  1560.        
  1561.         ArrayList headerList = null;
  1562.         int headerArrayLength;
  1563.        
  1564.         private void ProcessHeader(ParseRecord pr)
  1565.         {
  1566.             InternalST.Soap(this, "ProcessHeader ");
  1567.             pr.Dump();
  1568.            
  1569.             if (headerList == null)
  1570.                 headerList = new ArrayList(10);
  1571.             ParseRecord headerPr = GetPr();
  1572.             headerPr.PRparseTypeEnum = InternalParseTypeE.Object;
  1573.             headerPr.PRobjectTypeEnum = InternalObjectTypeE.Array;
  1574.             headerPr.PRobjectPositionEnum = InternalObjectPositionE.Headers;
  1575.             headerPr.PRarrayTypeEnum = InternalArrayTypeE.Single;
  1576.             headerPr.PRarrayElementType = typeof(System.Runtime.Remoting.Messaging.Header);
  1577.             headerPr.PRisArrayVariant = false;
  1578.             headerPr.PRarrayElementTypeCode = InternalPrimitiveTypeE.Invalid;
  1579.             headerPr.PRrank = 1;
  1580.             headerPr.PRlengthA = new int[1];
  1581.             headerList.Add(headerPr);
  1582.         }
  1583.        
  1584.         private void ProcessHeaderMember(ParseRecord pr)
  1585.         {
  1586.             ParseRecord headerPr;
  1587.            
  1588.             InternalST.Soap(this, "ProcessHeaderMember HeaderState ", ((Enum)headerState).ToString());
  1589.             pr.Dump();
  1590.            
  1591.             if (headerState == HeaderStateEnum.NestedObject) {
  1592.                 // Nested object in Header member
  1593.                 ParseRecord newPr = pr.Copy();
  1594.                 headerList.Add(newPr);
  1595.                 return;
  1596.             }
  1597.            
  1598.             // Item record
  1599.             headerPr = GetPr();
  1600.             headerPr.PRparseTypeEnum = InternalParseTypeE.Member;
  1601.             headerPr.PRmemberTypeEnum = InternalMemberTypeE.Item;
  1602.             headerPr.PRmemberValueEnum = InternalMemberValueE.Nested;
  1603.             headerPr.PRisHeaderRoot = true;
  1604.             headerArrayLength++;
  1605.             headerList.Add(headerPr);
  1606.            
  1607.             // Name field
  1608.             headerPr = GetPr();
  1609.             headerPr.PRparseTypeEnum = InternalParseTypeE.Member;
  1610.             headerPr.PRmemberTypeEnum = InternalMemberTypeE.Field;
  1611.             headerPr.PRmemberValueEnum = InternalMemberValueE.InlineValue;
  1612.             headerPr.PRisHeaderRoot = true;
  1613.             headerPr.PRname = "Name";
  1614.             headerPr.PRvalue = pr.PRname;
  1615.             headerPr.PRdtType = SoapUtil.typeofString;
  1616.             headerPr.PRdtTypeCode = InternalPrimitiveTypeE.Invalid;
  1617.             headerList.Add(headerPr);
  1618.            
  1619.             // Namespace field
  1620.             headerPr = GetPr();
  1621.             headerPr.PRparseTypeEnum = InternalParseTypeE.Member;
  1622.             headerPr.PRmemberTypeEnum = InternalMemberTypeE.Field;
  1623.             headerPr.PRmemberValueEnum = InternalMemberValueE.InlineValue;
  1624.             headerPr.PRisHeaderRoot = true;
  1625.             headerPr.PRname = "HeaderNamespace";
  1626.             headerPr.PRvalue = pr.PRxmlNameSpace;
  1627.             headerPr.PRdtType = SoapUtil.typeofString;
  1628.             headerPr.PRdtTypeCode = InternalPrimitiveTypeE.Invalid;
  1629.             headerList.Add(headerPr);
  1630.            
  1631.             // MustUnderstand Field
  1632.             headerPr = GetPr();
  1633.             headerPr.PRparseTypeEnum = InternalParseTypeE.Member;
  1634.             headerPr.PRmemberTypeEnum = InternalMemberTypeE.Field;
  1635.             headerPr.PRmemberValueEnum = InternalMemberValueE.InlineValue;
  1636.             headerPr.PRisHeaderRoot = true;
  1637.             headerPr.PRname = "MustUnderstand";
  1638.             if (pr.PRisMustUnderstand)
  1639.                 headerPr.PRvarValue = true;
  1640.             else
  1641.                 headerPr.PRvarValue = false;
  1642.             headerPr.PRdtType = SoapUtil.typeofBoolean;
  1643.             headerPr.PRdtTypeCode = InternalPrimitiveTypeE.Boolean;
  1644.             headerList.Add(headerPr);
  1645.            
  1646.             // Value field
  1647.             headerPr = GetPr();
  1648.             headerPr.PRparseTypeEnum = InternalParseTypeE.Member;
  1649.             headerPr.PRmemberTypeEnum = InternalMemberTypeE.Field;
  1650.             headerPr.PRmemberValueEnum = pr.PRmemberValueEnum;
  1651.             headerPr.PRisHeaderRoot = true;
  1652.             headerPr.PRname = "Value";
  1653.             switch (pr.PRmemberValueEnum) {
  1654.                 case InternalMemberValueE.Null:
  1655.                     headerList.Add(headerPr);
  1656.                     ProcessHeaderMemberEnd(pr);
  1657.                     break;
  1658.                 case InternalMemberValueE.Reference:
  1659.                     headerPr.PRidRef = pr.PRidRef;
  1660.                     headerList.Add(headerPr);
  1661.                     ProcessHeaderMemberEnd(pr);
  1662.                     break;
  1663.                 case InternalMemberValueE.Nested:
  1664.                     headerPr.PRdtType = pr.PRdtType;
  1665.                     headerPr.PRdtTypeCode = pr.PRdtTypeCode;
  1666.                     headerPr.PRkeyDt = pr.PRkeyDt;
  1667.                     headerList.Add(headerPr);
  1668.                     // ProcessHeaderMemberEnd will be called from the parse loop
  1669.                     break;
  1670.                 case InternalMemberValueE.InlineValue:
  1671.                    
  1672.                     headerPr.PRvalue = pr.PRvalue;
  1673.                     headerPr.PRvarValue = pr.PRvarValue;
  1674.                     headerPr.PRdtType = pr.PRdtType;
  1675.                     headerPr.PRdtTypeCode = pr.PRdtTypeCode;
  1676.                     headerPr.PRkeyDt = pr.PRkeyDt;
  1677.                     headerList.Add(headerPr);
  1678.                     ProcessHeaderMemberEnd(pr);
  1679.                     break;
  1680.             }
  1681.         }
  1682.        
  1683.         private void ProcessHeaderMemberEnd(ParseRecord pr)
  1684.         {
  1685.             ParseRecord headerPr = null;
  1686.            
  1687.             InternalST.Soap(this, "ProcessHeaderMemberEnd HeaderState ", ((Enum)headerState).ToString());
  1688.             pr.Dump();
  1689.            
  1690.             if (headerState == HeaderStateEnum.NestedObject) {
  1691.                 ParseRecord newPr = pr.Copy();
  1692.                 headerList.Add(newPr);
  1693.             }
  1694.             else {
  1695.                 // Member End
  1696.                 headerPr = GetPr();
  1697.                 headerPr.PRparseTypeEnum = InternalParseTypeE.MemberEnd;
  1698.                 headerPr.PRmemberTypeEnum = InternalMemberTypeE.Field;
  1699.                 headerPr.PRmemberValueEnum = pr.PRmemberValueEnum;
  1700.                 headerPr.PRisHeaderRoot = true;
  1701.                 headerList.Add(headerPr);
  1702.                
  1703.                 // Item End
  1704.                 headerPr = GetPr();
  1705.                 headerPr.PRparseTypeEnum = InternalParseTypeE.MemberEnd;
  1706.                 headerPr.PRmemberTypeEnum = InternalMemberTypeE.Item;
  1707.                 headerPr.PRmemberValueEnum = InternalMemberValueE.Nested;
  1708.                 headerPr.PRisHeaderRoot = true;
  1709.                 headerList.Add(headerPr);
  1710.             }
  1711.         }
  1712.        
  1713.        
  1714.         private void ProcessHeaderEnd(ParseRecord pr)
  1715.         {
  1716.             InternalST.Soap(this, "ProcessHeaderEnd ");
  1717.             pr.Dump();
  1718.            
  1719.             if (headerList == null)
  1720.                 return;
  1721.             // Empty header array
  1722.            
  1723.             // Object End
  1724.             ParseRecord headerPr = GetPr();
  1725.             headerPr.PRparseTypeEnum = InternalParseTypeE.ObjectEnd;
  1726.             headerPr.PRobjectTypeEnum = InternalObjectTypeE.Array;
  1727.             headerList.Add(headerPr);
  1728.            
  1729.             headerPr = (ParseRecord)headerList[0];
  1730.             headerPr = (ParseRecord)headerList[0];
  1731.             headerPr.PRlengthA[0] = headerArrayLength;
  1732.             headerPr.PRobjectPositionEnum = InternalObjectPositionE.Headers;
  1733.            
  1734.             for (int i = 0; i < headerList.Count; i++) {
  1735.                 InternalST.Soap(this, "Parse Header Record ", i);
  1736.                 InternalST.Soap(this, "ObjectReader.Parse 9");
  1737.                 objectReader.Parse((ParseRecord)headerList[i]);
  1738.             }
  1739.            
  1740.             for (int i = 0; i < headerList.Count; i++)
  1741.                 PutPr((ParseRecord)headerList[i]);
  1742.         }
  1743.        
  1744.         [Serializable()]
  1745.         enum HeaderStateEnum
  1746.         {
  1747.             None = 0,
  1748.             FirstHeaderRecord = 1,
  1749.             HeaderRecord = 2,
  1750.             NestedObject = 3,
  1751.             TopLevelObject = 4
  1752.         }
  1753.     }
  1754. }

Developer Fusion