SoapParser

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