The Labs \ Source Viewer \ SSCLI \ System.Xml.Xsl.XsltOld \ Sort

  1. //------------------------------------------------------------------------------
  2. // <copyright file="Compiler.cs" company="Microsoft">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. //------------------------------------------------------------------------------
  15. namespace System.Xml.Xsl.XsltOld
  16. {
  17.     using Res = System.Xml.Utils.Res;
  18.     using System;
  19.     using System.Diagnostics;
  20.     using System.Globalization;
  21.     using System.Xml;
  22.     using System.Xml.XPath;
  23.     using System.Xml.Xsl.Runtime;
  24.     using MS.Internal.Xml.XPath;
  25.     using System.Xml.Xsl.XsltOld.Debugger;
  26.     using System.Text;
  27.     using System.Collections;
  28.     using System.Collections.Generic;
  29.     using System.Collections.Specialized;
  30.     using System.IO;
  31.     using System.CodeDom;
  32.     using System.CodeDom.Compiler;
  33.     using System.Reflection;
  34.     using System.Security;
  35.     using System.Security.Policy;
  36.     using System.Security.Permissions;
  37.    
  38.     internal class Sort
  39.     {
  40.         internal int select;
  41.         internal string lang;
  42.         internal XmlDataType dataType;
  43.         internal XmlSortOrder order;
  44.         internal XmlCaseOrder caseOrder;
  45.        
  46.         public Sort(int sortkey, string xmllang, XmlDataType datatype, XmlSortOrder xmlorder, XmlCaseOrder xmlcaseorder)
  47.         {
  48.             select = sortkey;
  49.             lang = xmllang;
  50.             dataType = datatype;
  51.             order = xmlorder;
  52.             caseOrder = xmlcaseorder;
  53.         }
  54.     }
  55.    
  56.     internal enum ScriptingLanguage
  57.     {
  58.         JScript,
  59.         CSharp
  60.     }
  61.    
  62.     internal class Compiler
  63.     {
  64.         internal const int InvalidQueryKey = -1;
  65.        
  66.         internal const double RootPriority = 0.5;
  67.        
  68.         // cached StringBuilder for AVT parseing
  69.         internal StringBuilder AvtStringBuilder = new StringBuilder();
  70.        
  71.         private int stylesheetid;
  72.         // Root stylesheet has id=0. We are using this in CompileImports to compile BuiltIns
  73.         private InputScope rootScope;
  74.        
  75.         //
  76.         // Object members
  77.         private XmlResolver xmlResolver;
  78.        
  79.         //
  80.         // Template being currently compiled
  81.         private TemplateBaseAction currentTemplate;
  82.         private XmlQualifiedName currentMode;
  83.         private Hashtable globalNamespaceAliasTable;
  84.        
  85.         //
  86.         // Current import stack
  87.         private Stack stylesheets;
  88.        
  89.         private HybridDictionary documentURIs = new HybridDictionary();
  90.        
  91.         // import/include documents, who is here has its URI in this.documentURIs
  92.         private NavigatorInput input;
  93.        
  94.         // Atom table & InputScopeManager - cached top of the this.input stack
  95.         private Keywords atoms;
  96.         private InputScopeManager scopeManager;
  97.        
  98.         //
  99.         // Compiled stylesheet state
  100.         internal Stylesheet stylesheet;
  101.         internal Stylesheet rootStylesheet;
  102.         private RootAction rootAction;
  103.         private List<TheQuery> queryStore;
  104.         private QueryBuilder queryBuilder = new QueryBuilder();
  105.         private int rtfCount = 0;
  106.        
  107.         // Used to load Built In templates
  108.         public bool AllowBuiltInMode;
  109.         public static XmlQualifiedName BuiltInMode = new XmlQualifiedName("*", string.Empty);
  110.        
  111.         internal Keywords Atoms {
  112.             get {
  113.                 Debug.Assert(this.atoms != null);
  114.                 return this.atoms;
  115.             }
  116.         }
  117.        
  118.         internal int Stylesheetid {
  119.             get { return this.stylesheetid; }
  120.             set { this.stylesheetid = value; }
  121.         }
  122.        
  123.         internal NavigatorInput Document {
  124.             get { return this.input; }
  125.         }
  126.        
  127.         internal NavigatorInput Input {
  128.             get { return this.input; }
  129.         }
  130.        
  131.         internal bool Advance()
  132.         {
  133.             Debug.Assert(Document != null);
  134.             return Document.Advance();
  135.         }
  136.        
  137.         internal bool Recurse()
  138.         {
  139.             Debug.Assert(Document != null);
  140.             return Document.Recurse();
  141.         }
  142.        
  143.         internal bool ToParent()
  144.         {
  145.             Debug.Assert(Document != null);
  146.             return Document.ToParent();
  147.         }
  148.        
  149.         internal Stylesheet CompiledStylesheet {
  150.             get { return this.stylesheet; }
  151.         }
  152.        
  153.         internal RootAction RootAction {
  154.             get { return this.rootAction; }
  155.             set {
  156.                 Debug.Assert(this.rootAction == null);
  157.                 this.rootAction = value;
  158.                 Debug.Assert(this.currentTemplate == null);
  159.                 this.currentTemplate = this.rootAction;
  160.             }
  161.         }
  162.        
  163.         internal List<TheQuery> QueryStore {
  164.             get { return this.queryStore; }
  165.         }
  166.        
  167.         public virtual IXsltDebugger Debugger {
  168.             get { return null; }
  169.         }
  170.        
  171.         internal string GetUnicRtfId()
  172.         {
  173.             this.rtfCount++;
  174.             return this.rtfCount.ToString(CultureInfo.InvariantCulture);
  175.         }
  176.        
  177.         //
  178.         // The World of Compile
  179.         //
  180.         internal void Compile(NavigatorInput input, XmlResolver xmlResolver, Evidence evidence)
  181.         {
  182.             Debug.Assert(input != null);
  183.             Debug.Assert(xmlResolver != null);
  184.             // Debug.Assert(evidence != null); -- default evidence is null now
  185.             Debug.Assert(this.input == null && this.atoms == null);
  186.             this.xmlResolver = xmlResolver;
  187.            
  188.             PushInputDocument(input);
  189.             this.rootScope = this.scopeManager.PushScope();
  190.             this.queryStore = new List<TheQuery>();
  191.            
  192.             try {
  193.                 this.rootStylesheet = new Stylesheet();
  194.                 PushStylesheet(this.rootStylesheet);
  195.                
  196.                 Debug.Assert(this.input != null && this.atoms != null);
  197.                
  198.                 try {
  199.                     this.CreateRootAction();
  200.                 }
  201.                 catch (XsltCompileException) {
  202.                     throw;
  203.                 }
  204.                 catch (Exception e) {
  205.                     throw new XsltCompileException(e, this.Input.BaseURI, this.Input.LineNumber, this.Input.LinePosition);
  206.                 }
  207.                
  208.                 this.stylesheet.ProcessTemplates();
  209.                 this.rootAction.PorcessAttributeSets(this.rootStylesheet);
  210.                 this.stylesheet.SortWhiteSpace();
  211.                 CompileScript(evidence);
  212.                 if (evidence != null) {
  213.                     this.rootAction.permissions = SecurityManager.ResolvePolicy(evidence);
  214.                 }
  215.                
  216.                 if (this.globalNamespaceAliasTable != null) {
  217.                     this.stylesheet.ReplaceNamespaceAlias(this);
  218.                     this.rootAction.ReplaceNamespaceAlias(this);
  219.                 }
  220.             }
  221.             finally {
  222.                 PopInputDocument();
  223.             }
  224.            
  225.             Debug.Assert(this.rootAction != null);
  226.             Debug.Assert(this.stylesheet != null);
  227.             Debug.Assert(this.queryStore != null);
  228.             Debug.Assert(this.input == null && this.atoms == null);
  229.         }
  230.        
  231.         //
  232.         // Input scope compiler's support
  233.         //
  234.        
  235.         internal bool ForwardCompatibility {
  236.             get { return this.scopeManager.CurrentScope.ForwardCompatibility; }
  237.             set { this.scopeManager.CurrentScope.ForwardCompatibility = value; }
  238.         }
  239.        
  240.         internal bool CanHaveApplyImports {
  241.             get { return this.scopeManager.CurrentScope.CanHaveApplyImports; }
  242.             set { this.scopeManager.CurrentScope.CanHaveApplyImports = value; }
  243.         }
  244.        
  245.         internal void InsertExtensionNamespace(string value)
  246.         {
  247.             string[] nsList = ResolvePrefixes(value);
  248.             if (nsList != null) {
  249.                 scopeManager.InsertExtensionNamespaces(nsList);
  250.             }
  251.         }
  252.        
  253.         internal void InsertExcludedNamespace(string value)
  254.         {
  255.             string[] nsList = ResolvePrefixes(value);
  256.             if (nsList != null) {
  257.                 scopeManager.InsertExcludedNamespaces(nsList);
  258.             }
  259.         }
  260.        
  261.         internal void InsertExtensionNamespace()
  262.         {
  263.             InsertExtensionNamespace(Input.Navigator.GetAttribute(Input.Atoms.ExtensionElementPrefixes, Input.Atoms.XsltNamespace));
  264.         }
  265.        
  266.         internal void InsertExcludedNamespace()
  267.         {
  268.             InsertExcludedNamespace(Input.Navigator.GetAttribute(Input.Atoms.ExcludeResultPrefixes, Input.Atoms.XsltNamespace));
  269.         }
  270.        
  271.         internal bool IsExtensionNamespace(string nspace)
  272.         {
  273.             return this.scopeManager.IsExtensionNamespace(nspace);
  274.         }
  275.        
  276.         internal bool IsExcludedNamespace(string nspace)
  277.         {
  278.             return this.scopeManager.IsExcludedNamespace(nspace);
  279.         }
  280.        
  281.         internal void PushLiteralScope()
  282.         {
  283.             PushNamespaceScope();
  284.             string value = Input.Navigator.GetAttribute(Atoms.Version, Atoms.XsltNamespace);
  285.             if (value.Length != 0) {
  286.                 ForwardCompatibility = (value != Keywords.s_Version10);
  287.             }
  288.         }
  289.        
  290.         internal void PushNamespaceScope()
  291.         {
  292.             this.scopeManager.PushScope();
  293.             NavigatorInput input = Input;
  294.            
  295.             if (input.MoveToFirstNamespace()) {
  296.                 do {
  297.                     this.scopeManager.PushNamespace(input.LocalName, input.Value);
  298.                 }
  299.                 while (input.MoveToNextNamespace());
  300.                 input.ToParent();
  301.             }
  302.         }
  303.        
  304.         protected InputScopeManager ScopeManager {
  305.             get { return this.scopeManager; }
  306.         }
  307.        
  308.         internal virtual void PopScope()
  309.         {
  310.             this.currentTemplate.ReleaseVariableSlots(this.scopeManager.CurrentScope.GetVeriablesCount());
  311.             this.scopeManager.PopScope();
  312.         }
  313.        
  314.         internal InputScopeManager CloneScopeManager()
  315.         {
  316.             return this.scopeManager.Clone();
  317.         }
  318.        
  319.         //
  320.         // Variable support
  321.         //
  322.        
  323.         internal int InsertVariable(VariableAction variable)
  324.         {
  325.             InputScope varScope;
  326.             if (variable.IsGlobal) {
  327.                 Debug.Assert(this.rootAction != null);
  328.                 varScope = this.rootScope;
  329.             }
  330.             else {
  331.                 Debug.Assert(this.currentTemplate != null);
  332.                 Debug.Assert(variable.VarType == VariableType.LocalVariable || variable.VarType == VariableType.LocalParameter || variable.VarType == VariableType.WithParameter);
  333.                 varScope = this.scopeManager.VariableScope;
  334.             }
  335.            
  336.             VariableAction oldVar = varScope.ResolveVariable(variable.Name);
  337.             if (oldVar != null) {
  338.                 // Other variable with this name is visible in this scope
  339.                 if (oldVar.IsGlobal) {
  340.                     if (variable.IsGlobal) {
  341.                         // Global Vars replace each other base on import presidens odred
  342.                         if (variable.Stylesheetid == oldVar.Stylesheetid) {
  343.                             // Both vars are in the same stylesheet
  344.                             throw XsltException.Create(Res.Xslt_DupVarName, variable.NameStr);
  345.                         }
  346.                         else if (variable.Stylesheetid < oldVar.Stylesheetid) {
  347.                             // newly defined var is more importent
  348.                             varScope.InsertVariable(variable);
  349.                             return oldVar.VarKey;
  350.                         }
  351.                         else {
  352.                             // we egnore new variable
  353.                             return InvalidQueryKey;
  354.                             // We didn't add this var, so doesn't matter what VarKey we return;
  355.                         }
  356.                     }
  357.                     else {
  358.                         // local variable can shadow global
  359.                     }
  360.                 }
  361.                 else {
  362.                     // Local variable never can be "shadowed"
  363.                     throw XsltException.Create(Res.Xslt_DupVarName, variable.NameStr);
  364.                 }
  365.             }
  366.            
  367.             varScope.InsertVariable(variable);
  368.             return this.currentTemplate.AllocateVariableSlot();
  369.         }
  370.        
  371.         internal void AddNamespaceAlias(string StylesheetURI, NamespaceInfo AliasInfo)
  372.         {
  373.             if (this.globalNamespaceAliasTable == null) {
  374.                 this.globalNamespaceAliasTable = new Hashtable();
  375.             }
  376.             NamespaceInfo duplicate = this.globalNamespaceAliasTable[StylesheetURI] as NamespaceInfo;
  377.             if (duplicate == null || AliasInfo.stylesheetId <= duplicate.stylesheetId) {
  378.                 this.globalNamespaceAliasTable[StylesheetURI] = AliasInfo;
  379.             }
  380.         }
  381.        
  382.         internal bool IsNamespaceAlias(string StylesheetURI)
  383.         {
  384.             if (this.globalNamespaceAliasTable == null) {
  385.                 return false;
  386.             }
  387.             return this.globalNamespaceAliasTable.Contains(StylesheetURI);
  388.         }
  389.        
  390.         internal NamespaceInfo FindNamespaceAlias(string StylesheetURI)
  391.         {
  392.             if (this.globalNamespaceAliasTable != null) {
  393.                 return (NamespaceInfo)this.globalNamespaceAliasTable[StylesheetURI];
  394.             }
  395.             return null;
  396.         }
  397.        
  398.         internal string ResolveXmlNamespace(string prefix)
  399.         {
  400.             return this.scopeManager.ResolveXmlNamespace(prefix);
  401.         }
  402.        
  403.         internal string ResolveXPathNamespace(string prefix)
  404.         {
  405.             return this.scopeManager.ResolveXPathNamespace(prefix);
  406.         }
  407.        
  408.         internal string DefaultNamespace {
  409.             get { return this.scopeManager.DefaultNamespace; }
  410.         }
  411.        
  412.         internal void InsertKey(XmlQualifiedName name, int MatchKey, int UseKey)
  413.         {
  414.             this.rootAction.InsertKey(name, MatchKey, UseKey);
  415.         }
  416.        
  417.         internal void AddDecimalFormat(XmlQualifiedName name, DecimalFormat formatinfo)
  418.         {
  419.             this.rootAction.AddDecimalFormat(name, formatinfo);
  420.         }
  421.        
  422.         //
  423.         // Attribute parsing support
  424.         //
  425.        
  426.         // This function is for processing optional attributes only. In case of error
  427.         // the value is ignored iff forwards-compatible mode is on.
  428.         private string[] ResolvePrefixes(string tokens)
  429.         {
  430.             if (tokens == null || tokens.Length == 0) {
  431.                 return null;
  432.             }
  433.             string[] nsList = XmlConvert.SplitString(tokens);
  434.            
  435.             try {
  436.                 for (int idx = 0; idx < nsList.Length; idx++) {
  437.                     string prefix = nsList[idx];
  438.                     nsList[idx] = scopeManager.ResolveXmlNamespace(prefix == Keywords.s_HashDefault ? string.Empty : prefix);
  439.                 }
  440.             }
  441.             catch (XsltException) {
  442.                 // The only exception here might be Res.Xslt_InvalidPrefix
  443.                 if (!ForwardCompatibility) {
  444.                     // Rethrow the exception if we're not in forwards-compatible mode
  445.                     throw;
  446.                 }
  447.                 // Ignore the whole list in forwards-compatible mode
  448.                 return null;
  449.             }
  450.             return nsList;
  451.         }
  452.        
  453.         internal bool GetYesNo(string value)
  454.         {
  455.             Debug.Assert(value != null);
  456.             Debug.Assert((object)value == (object)Input.Value);
  457.             // this is always true. Why we passing value to this function.
  458.             // if (value == null)
  459.             // return false; // in XSLT it happens that default value was always false;
  460.             if (value.Equals(Atoms.Yes)) {
  461.                 return true;
  462.             }
  463.             if (value.Equals(Atoms.No)) {
  464.                 return false;
  465.             }
  466.             throw XsltException.Create(Res.Xslt_InvalidAttrValue, Input.LocalName, value);
  467.         }
  468.        
  469.         internal string GetSingleAttribute(string attributeAtom)
  470.         {
  471.             NavigatorInput input = Input;
  472.             string element = input.LocalName;
  473.             string value = null;
  474.            
  475.             if (input.MoveToFirstAttribute()) {
  476.                 do {
  477.                     string nspace = input.NamespaceURI;
  478.                     string name = input.LocalName;
  479.                    
  480.                     if (!Keywords.Equals(nspace, Atoms.Empty))
  481.                         continue;
  482.                    
  483.                     if (Keywords.Equals(name, attributeAtom)) {
  484.                         value = input.Value;
  485.                     }
  486.                     else {
  487.                         if (!this.ForwardCompatibility) {
  488.                             throw XsltException.Create(Res.Xslt_InvalidAttribute, name, element);
  489.                         }
  490.                     }
  491.                 }
  492.                 while (input.MoveToNextAttribute());
  493.                 input.ToParent();
  494.             }
  495.            
  496.             if (value == null) {
  497.                 throw XsltException.Create(Res.Xslt_MissingAttribute, attributeAtom);
  498.             }
  499.             return value;
  500.         }
  501.        
  502.         internal XmlQualifiedName CreateXPathQName(string qname)
  503.         {
  504.             string prefix;
  505.             string local;
  506.             PrefixQName.ParseQualifiedName(qname, out prefix, out local);
  507.            
  508.             return new XmlQualifiedName(local, this.scopeManager.ResolveXPathNamespace(prefix));
  509.         }
  510.        
  511.         internal XmlQualifiedName CreateXmlQName(string qname)
  512.         {
  513.             string prefix;
  514.             string local;
  515.             PrefixQName.ParseQualifiedName(qname, out prefix, out local);
  516.            
  517.             return new XmlQualifiedName(local, this.scopeManager.ResolveXmlNamespace(prefix));
  518.         }
  519.        
  520.         //
  521.         // Input documents management
  522.         //
  523.        
  524.         static internal XPathDocument LoadDocument(XmlTextReaderImpl reader)
  525.         {
  526.             reader.EntityHandling = EntityHandling.ExpandEntities;
  527.             reader.XmlValidatingReaderCompatibilityMode = true;
  528.             try {
  529.                 return new XPathDocument(reader, XmlSpace.Preserve);
  530.             }
  531.             finally {
  532.                 reader.Close();
  533.             }
  534.         }
  535.        
  536.         private void AddDocumentURI(string href)
  537.         {
  538.             Debug.Assert(!this.documentURIs.Contains(href), "Circular references must be checked while processing xsl:include and xsl:import");
  539.             this.documentURIs.Add(href, null);
  540.         }
  541.        
  542.         private void RemoveDocumentURI(string href)
  543.         {
  544.             Debug.Assert(this.documentURIs.Contains(href), "Attempt to remove href that was not added");
  545.             this.documentURIs.Remove(href);
  546.         }
  547.        
  548.         internal bool IsCircularReference(string href)
  549.         {
  550.             return this.documentURIs.Contains(href);
  551.         }
  552.        
  553.         internal Uri ResolveUri(string relativeUri)
  554.         {
  555.             Debug.Assert(this.xmlResolver != null);
  556.             string baseUri = this.Input.BaseURI;
  557.             Uri uri = this.xmlResolver.ResolveUri((baseUri.Length != 0) ? this.xmlResolver.ResolveUri(null, baseUri) : null, relativeUri);
  558.             if (uri == null) {
  559.                 throw XsltException.Create(Res.Xslt_CantResolve, relativeUri);
  560.             }
  561.             return uri;
  562.         }
  563.        
  564.         internal NavigatorInput ResolveDocument(Uri absoluteUri)
  565.         {
  566.             Debug.Assert(this.xmlResolver != null);
  567.             object input = this.xmlResolver.GetEntity(absoluteUri, null, null);
  568.             string resolved = absoluteUri.ToString();
  569.            
  570.             if (input is Stream) {
  571.                 XmlTextReaderImpl tr = new XmlTextReaderImpl(resolved, (Stream)input);
  572.                 {
  573.                     tr.XmlResolver = this.xmlResolver;
  574.                 }
  575.                 // reader is closed by Compiler.LoadDocument()
  576.                 return new NavigatorInput(Compiler.LoadDocument(tr).CreateNavigator(), resolved, rootScope);
  577.             }
  578.             else if (input is XPathNavigator) {
  579.                 return new NavigatorInput((XPathNavigator)input, resolved, rootScope);
  580.             }
  581.             else {
  582.                 throw XsltException.Create(Res.Xslt_CantResolve, resolved);
  583.             }
  584.         }
  585.        
  586.         internal void PushInputDocument(NavigatorInput newInput)
  587.         {
  588.             Debug.Assert(newInput != null);
  589.             string inputUri = newInput.Href;
  590.            
  591.             AddDocumentURI(inputUri);
  592.            
  593.             newInput.Next = this.input;
  594.             this.input = newInput;
  595.             this.atoms = this.input.Atoms;
  596.             this.scopeManager = this.input.InputScopeManager;
  597.         }
  598.        
  599.         internal void PopInputDocument()
  600.         {
  601.             Debug.Assert(this.input != null);
  602.             Debug.Assert(this.input.Atoms == this.atoms);
  603.            
  604.             NavigatorInput lastInput = this.input;
  605.            
  606.             this.input = lastInput.Next;
  607.             lastInput.Next = null;
  608.            
  609.             if (this.input != null) {
  610.                 this.atoms = this.input.Atoms;
  611.                 this.scopeManager = this.input.InputScopeManager;
  612.             }
  613.             else {
  614.                 this.atoms = null;
  615.                 this.scopeManager = null;
  616.             }
  617.            
  618.             RemoveDocumentURI(lastInput.Href);
  619.             lastInput.Close();
  620.         }
  621.        
  622.         //
  623.         // Stylesheet management
  624.         //
  625.        
  626.         internal void PushStylesheet(Stylesheet stylesheet)
  627.         {
  628.             if (this.stylesheets == null) {
  629.                 this.stylesheets = new Stack();
  630.             }
  631.             Debug.Assert(this.stylesheets != null);
  632.            
  633.             this.stylesheets.Push(stylesheet);
  634.             this.stylesheet = stylesheet;
  635.         }
  636.        
  637.         internal Stylesheet PopStylesheet()
  638.         {
  639.             Debug.Assert(this.stylesheet == this.stylesheets.Peek());
  640.             Stylesheet stylesheet = (Stylesheet)this.stylesheets.Pop();
  641.             this.stylesheet = (Stylesheet)this.stylesheets.Peek();
  642.             return stylesheet;
  643.         }
  644.        
  645.         //
  646.         // Attribute-Set management
  647.         //
  648.        
  649.         internal void AddAttributeSet(AttributeSetAction attributeSet)
  650.         {
  651.             Debug.Assert(this.stylesheet == this.stylesheets.Peek());
  652.             this.stylesheet.AddAttributeSet(attributeSet);
  653.         }
  654.        
  655.         //
  656.         // Template management
  657.         //
  658.        
  659.         internal void AddTemplate(TemplateAction template)
  660.         {
  661.             Debug.Assert(this.stylesheet == this.stylesheets.Peek());
  662.             this.stylesheet.AddTemplate(template);
  663.         }
  664.        
  665.         internal void BeginTemplate(TemplateAction template)
  666.         {
  667.             Debug.Assert(this.currentTemplate != null);
  668.             this.currentTemplate = template;
  669.             this.currentMode = template.Mode;
  670.             this.CanHaveApplyImports = template.MatchKey != Compiler.InvalidQueryKey;
  671.         }
  672.        
  673.         internal void EndTemplate()
  674.         {
  675.             Debug.Assert(this.currentTemplate != null);
  676.             this.currentTemplate = this.rootAction;
  677.         }
  678.        
  679.         internal XmlQualifiedName CurrentMode {
  680.             get { return this.currentMode; }
  681.         }
  682.        
  683.         //
  684.         // Query management
  685.         //
  686.         internal int AddQuery(string xpathQuery)
  687.         {
  688.                 /*allowVars:*/                /*allowKey*/            return AddQuery(xpathQuery, true, true, false);
  689.         }
  690.        
  691.         internal int AddQuery(string xpathQuery, bool allowVar, bool allowKey, bool isPattern)
  692.         {
  693.             Debug.Assert(this.queryStore != null);
  694.            
  695.             CompiledXpathExpr expr;
  696.             try {
  697.                 expr = new CompiledXpathExpr((isPattern ? this.queryBuilder.BuildPatternQuery(xpathQuery, allowVar, allowKey) : this.queryBuilder.Build(xpathQuery, allowVar, allowKey)), xpathQuery, false);
  698.             }
  699.             catch (XPathException e) {
  700.                 if (!ForwardCompatibility) {
  701.                     throw XsltException.Create(Res.Xslt_InvalidXPath, new string[] {xpathQuery}, e);
  702.                 }
  703.                 expr = new ErrorXPathExpression(xpathQuery, this.Input.BaseURI, this.Input.LineNumber, this.Input.LinePosition);
  704.             }
  705.             this.queryStore.Add(new TheQuery(expr, this.scopeManager));
  706.             return this.queryStore.Count - 1;
  707.         }
  708.        
  709.         internal int AddStringQuery(string xpathQuery)
  710.         {
  711.             string modifiedQuery = XmlCharType.Instance.IsOnlyWhitespace(xpathQuery) ? xpathQuery : "string(" + xpathQuery + ")";
  712.             return AddQuery(modifiedQuery);
  713.         }
  714.        
  715.         internal int AddBooleanQuery(string xpathQuery)
  716.         {
  717.             string modifiedQuery = XmlCharType.Instance.IsOnlyWhitespace(xpathQuery) ? xpathQuery : "boolean(" + xpathQuery + ")";
  718.             return AddQuery(modifiedQuery);
  719.         }
  720.        
  721.         //
  722.         // Script support
  723.         //
  724.         Hashtable[] _typeDeclsByLang = new Hashtable[] {new Hashtable(), new Hashtable(), new Hashtable()};
  725.         ArrayList scriptFiles = new ArrayList();
  726.         // Namespaces we always import when compiling
  727.         private static string[] _defaultNamespaces = new string[] {"System", "System.Collections", "System.Text", "System.Text.RegularExpressions", "System.Xml", "System.Xml.Xsl", "System.Xml.XPath"};
  728.        
  729.         private static int scriptClassCounter = 0;
  730.         private static string GenerateUniqueClassName()
  731.         {
  732.             return "ScriptClass_" + (++scriptClassCounter);
  733.         }
  734.        
  735.         internal void AddScript(string source, ScriptingLanguage lang, string ns, string fileName, int lineNumber)
  736.         {
  737.             ValidateExtensionNamespace(ns);
  738.            
  739.             for (ScriptingLanguage langTmp = ScriptingLanguage.JScript; langTmp <= ScriptingLanguage.CSharp; langTmp++) {
  740.                 Hashtable typeDecls = _typeDeclsByLang[(int)langTmp];
  741.                 if (lang == langTmp) {
  742.                     CodeTypeDeclaration scriptClass = (CodeTypeDeclaration)typeDecls[ns];
  743.                     if (scriptClass == null) {
  744.                         scriptClass = new CodeTypeDeclaration(GenerateUniqueClassName());
  745.                         scriptClass.TypeAttributes = TypeAttributes.Public;
  746.                         typeDecls.Add(ns, scriptClass);
  747.                     }
  748.                     CodeSnippetTypeMember scriptSnippet = new CodeSnippetTypeMember(source);
  749.                     if (lineNumber > 0) {
  750.                         scriptSnippet.LinePragma = new CodeLinePragma(fileName, lineNumber);
  751.                         scriptFiles.Add(fileName);
  752.                     }
  753.                     scriptClass.Members.Add(scriptSnippet);
  754.                 }
  755.                 else if (typeDecls.Contains(ns)) {
  756.                     throw XsltException.Create(Res.Xslt_ScriptMixedLanguages, ns);
  757.                 }
  758.             }
  759.         }
  760.        
  761.         private static void ValidateExtensionNamespace(string nsUri)
  762.         {
  763.             if (nsUri.Length == 0 || nsUri == Keywords.s_XsltNamespace) {
  764.                 throw XsltException.Create(Res.Xslt_InvalidExtensionNamespace);
  765.             }
  766.             XmlConvert.ToUri(nsUri);
  767.         }
  768.        
  769.         private void FixCompilerError(CompilerError e)
  770.         {
  771.             foreach (string scriptFile in this.scriptFiles) {
  772.                 if (e.FileName == scriptFile) {
  773.                     return;
  774.                     // Yes! this error is in our code sippet.
  775.                 }
  776.             }
  777.             e.FileName = string.Empty;
  778.         }
  779.        
  780.         CodeDomProvider ChooseCodeDomProvider(ScriptingLanguage lang)
  781.         {
  782.                 /*CSharp | default */            return (lang == ScriptingLanguage.JScript ? (CodeDomProvider)Activator.CreateInstance(Type.GetType("Microsoft.JScript.JScriptCodeProvider, " + AssemblyRef.MicrosoftJScript), BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.CreateInstance, null, null, null) : (CodeDomProvider)new Microsoft.CSharp.CSharpCodeProvider());
  783.         }
  784.        
  785.         private void CompileScript(Evidence evidence)
  786.         {
  787.             for (ScriptingLanguage lang = ScriptingLanguage.JScript; lang <= ScriptingLanguage.CSharp; lang++) {
  788.                 int idx = (int)lang;
  789.                 if (_typeDeclsByLang[idx].Count > 0) {
  790.                     CompileAssembly(lang, _typeDeclsByLang[idx], lang.ToString(), evidence);
  791.                 }
  792.             }
  793.         }
  794.        
  795.         [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
  796.         private void CompileAssembly(ScriptingLanguage lang, Hashtable typeDecls, string nsName, Evidence evidence)
  797.         {
  798.             nsName = "Microsoft.Xslt.CompiledScripts." + nsName;
  799.             CodeNamespace msXslt = new CodeNamespace(nsName);
  800.            
  801.             // Add all the default namespaces
  802.             foreach (string ns in _defaultNamespaces) {
  803.                 msXslt.Imports.Add(new CodeNamespaceImport(ns));
  804.             }
  805.            
  806.            
  807.             foreach (CodeTypeDeclaration scriptClass in typeDecls.Values) {
  808.                 msXslt.Types.Add(scriptClass);
  809.             }
  810.            
  811.             CodeCompileUnit unit = new CodeCompileUnit();
  812.             {
  813.                 unit.Namespaces.Add(msXslt);
  814.                 unit.UserData["AllowLateBound"] = true;
  815.                 // Allow variables to be undeclared
  816.                 unit.UserData["RequireVariableDeclaration"] = false;
  817.                 // Allow variables to be declared untyped
  818.             }
  819.             CompilerParameters compilParams = new CompilerParameters();
  820.             {
  821.                 try {
  822.                     new SecurityPermission(SecurityPermissionFlag.ControlEvidence).Assert();
  823.                     try {
  824.                         compilParams.GenerateInMemory = true;
  825.                         compilParams.Evidence = evidence;
  826.                         compilParams.ReferencedAssemblies.Add(typeof(XPathNavigator).Module.FullyQualifiedName);
  827.                         compilParams.ReferencedAssemblies.Add("system.dll");
  828.                     }
  829.                     finally {
  830.                         CodeAccessPermission.RevertAssert();
  831.                     }
  832.                 }
  833.                 catch {
  834.                     throw;
  835.                 }
  836.             }
  837.            
  838.             CompilerResults results = ChooseCodeDomProvider(lang).CompileAssemblyFromDom(compilParams, unit);
  839.             if (results.Errors.HasErrors) {
  840.                 StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture);
  841.                 foreach (CompilerError e in results.Errors) {
  842.                     FixCompilerError(e);
  843.                     stringWriter.WriteLine(e.ToString());
  844.                 }
  845.                 throw XsltException.Create(Res.Xslt_ScriptCompileErrors, stringWriter.ToString());
  846.             }
  847.             Assembly assembly = results.CompiledAssembly;
  848.             foreach (DictionaryEntry entry in typeDecls) {
  849.                 string ns = (string)entry.Key;
  850.                 CodeTypeDeclaration scriptClass = (CodeTypeDeclaration)entry.Value;
  851.                 this.stylesheet.ScriptObjectTypes.Add(ns, assembly.GetType(nsName + "." + scriptClass.Name));
  852.             }
  853.         }
  854.        
  855.         public string GetNsAlias(ref string prefix)
  856.         {
  857.             Debug.Assert(Keywords.Equals(this.input.LocalName, this.input.Atoms.StylesheetPrefix) || Keywords.Equals(this.input.LocalName, this.input.Atoms.ResultPrefix));
  858.             if (Keywords.Compare(this.input.Atoms.HashDefault, prefix)) {
  859.                 prefix = string.Empty;
  860.                 return this.DefaultNamespace;
  861.             }
  862.             else {
  863.                 if (!PrefixQName.ValidatePrefix(prefix)) {
  864.                     throw XsltException.Create(Res.Xslt_InvalidAttrValue, this.input.LocalName, prefix);
  865.                 }
  866.                 return this.ResolveXPathNamespace(prefix);
  867.             }
  868.         }
  869.        
  870.         // AVT's compilation.
  871.         // CompileAvt() returns ArrayList of TextEvent & AvtEvent
  872.        
  873.         private static void getTextLex(string avt, ref int start, StringBuilder lex)
  874.         {
  875.             Debug.Assert(avt.Length != start, "Empty string not supposed here");
  876.             Debug.Assert(lex.Length == 0, "Builder shoud to be reset here");
  877.             int avtLength = avt.Length;
  878.             int i;
  879.             for (i = start; i < avtLength; i++) {
  880.                 char ch = avt[i];
  881.                 if (ch == '{') {
  882.                     if (i + 1 < avtLength && avt[i + 1] == '{') {
  883.                         // "{{"
  884.                         i++;
  885.                     }
  886.                     else {
  887.                         break;
  888.                     }
  889.                 }
  890.                 else if (ch == '}') {
  891.                     if (i + 1 < avtLength && avt[i + 1] == '}') {
  892.                         // "}}"
  893.                         i++;
  894.                     }
  895.                     else {
  896.                         throw XsltException.Create(Res.Xslt_SingleRightAvt, avt);
  897.                     }
  898.                 }
  899.                 lex.Append(ch);
  900.             }
  901.             start = i;
  902.         }
  903.        
  904.         private static void getXPathLex(string avt, ref int start, StringBuilder lex)
  905.         {
  906.             // AVT parser states
  907.             const int InExp = 0;
  908.             // Inside AVT expression
  909.             const int InLiteralA = 1;
  910.             // Inside literal in expression, apostrophe delimited
  911.             const int InLiteralQ = 2;
  912.             // Inside literal in expression, quote delimited
  913.             Debug.Assert(avt.Length != start, "Empty string not supposed here");
  914.             Debug.Assert(lex.Length == 0, "Builder shoud to be reset here");
  915.             Debug.Assert(avt[start] == '{', "We calling getXPathLex() only after we realy meet {");
  916.             int avtLength = avt.Length;
  917.             int state = InExp;
  918.             for (int i = start + 1; i < avtLength; i++) {
  919.                 char ch = avt[i];
  920.                 switch (state) {
  921.                     case InExp:
  922.                         switch (ch) {
  923.                             case '{':
  924.                                 throw XsltException.Create(Res.Xslt_NestedAvt, avt);
  925.                                 break;
  926.                             case '}':
  927.                                 i++;
  928.                                 // include '}'
  929.                                 if (i == start + 2) {
  930.                                     // empty XPathExpresion
  931.                                     throw XsltException.Create(Res.Xslt_EmptyAvtExpr, avt);
  932.                                 }
  933.                                 lex.Append(avt, start + 1, i - start - 2);
  934.                                 // avt without {}
  935.                                 start = i;
  936.                                 return;
  937.                             case '\'':
  938.                                 state = InLiteralA;
  939.                                 break;
  940.                             case '"':
  941.                                 state = InLiteralQ;
  942.                                 break;
  943.                         }
  944.                         break;
  945.                     case InLiteralA:
  946.                         if (ch == '\'') {
  947.                             state = InExp;
  948.                         }
  949.                         break;
  950.                     case InLiteralQ:
  951.                         if (ch == '"') {
  952.                             state = InExp;
  953.                         }
  954.                         break;
  955.                 }
  956.             }
  957.            
  958.             // if we meet end of string before } we have an error
  959.             throw XsltException.Create(state == InExp ? Res.Xslt_OpenBracesAvt : Res.Xslt_OpenLiteralAvt, avt);
  960.         }
  961.        
  962.         private static bool GetNextAvtLex(string avt, ref int start, StringBuilder lex, out bool isAvt)
  963.         {
  964.             Debug.Assert(start <= avt.Length);
  965.             #if DEBUG
  966.             int saveStart = start;
  967.             #endif
  968.             isAvt = false;
  969.             if (start == avt.Length) {
  970.                 return false;
  971.             }
  972.             lex.Length = 0;
  973.             getTextLex(avt, ref start, lex);
  974.             if (lex.Length == 0) {
  975.                 isAvt = true;
  976.                 getXPathLex(avt, ref start, lex);
  977.             }
  978.             #if DEBUG
  979.             Debug.Assert(saveStart < start, "We have to read something. Otherwise it's dead loop.");
  980.             #endif
  981.             return true;
  982.         }
  983.        
  984.         internal ArrayList CompileAvt(string avtText, out bool constant)
  985.         {
  986.             Debug.Assert(avtText != null);
  987.             ArrayList list = new ArrayList();
  988.            
  989.             constant = true;
  990.             /* Parse input.Value as AVT */ {
  991.                 int pos = 0;
  992.                 bool isAvt;
  993.                 while (GetNextAvtLex(avtText, ref pos, this.AvtStringBuilder, out isAvt)) {
  994.                     string lex = this.AvtStringBuilder.ToString();
  995.                     if (isAvt) {
  996.                         list.Add(new AvtEvent(this.AddStringQuery(lex)));
  997.                         constant = false;
  998.                     }
  999.                     else {
  1000.                         list.Add(new TextEvent(lex));
  1001.                     }
  1002.                 }
  1003.             }
  1004.             Debug.Assert(!constant || list.Count <= 1, "We can't have more then 1 text event if now {avt} found");
  1005.             return list;
  1006.         }
  1007.        
  1008.         internal ArrayList CompileAvt(string avtText)
  1009.         {
  1010.             bool constant;
  1011.             return CompileAvt(avtText, out constant);
  1012.         }
  1013.        
  1014.         // Compiler is a class factory for some actions:
  1015.         // CompilerDbg override all this methods:
  1016.        
  1017.         public virtual ApplyImportsAction CreateApplyImportsAction()
  1018.         {
  1019.             ApplyImportsAction action = new ApplyImportsAction();
  1020.             action.Compile(this);
  1021.             return action;
  1022.         }
  1023.        
  1024.         public virtual ApplyTemplatesAction CreateApplyTemplatesAction()
  1025.         {
  1026.             ApplyTemplatesAction action = new ApplyTemplatesAction();
  1027.             action.Compile(this);
  1028.             return action;
  1029.         }
  1030.        
  1031.         public virtual AttributeAction CreateAttributeAction()
  1032.         {
  1033.             AttributeAction action = new AttributeAction();
  1034.             action.Compile(this);
  1035.             return action;
  1036.         }
  1037.        
  1038.         public virtual AttributeSetAction CreateAttributeSetAction()
  1039.         {
  1040.             AttributeSetAction action = new AttributeSetAction();
  1041.             action.Compile(this);
  1042.             return action;
  1043.         }
  1044.        
  1045.         public virtual CallTemplateAction CreateCallTemplateAction()
  1046.         {
  1047.             CallTemplateAction action = new CallTemplateAction();
  1048.             action.Compile(this);
  1049.             return action;
  1050.         }
  1051.        
  1052.         public virtual ChooseAction CreateChooseAction()
  1053.         {
  1054.             //!!! don't need to be here
  1055.             ChooseAction action = new ChooseAction();
  1056.             action.Compile(this);
  1057.             return action;
  1058.         }
  1059.        
  1060.         public virtual CommentAction CreateCommentAction()
  1061.         {
  1062.             CommentAction action = new CommentAction();
  1063.             action.Compile(this);
  1064.             return action;
  1065.         }
  1066.        
  1067.         public virtual CopyAction CreateCopyAction()
  1068.         {
  1069.             CopyAction action = new CopyAction();
  1070.             action.Compile(this);
  1071.             return action;
  1072.         }
  1073.        
  1074.         public virtual CopyOfAction CreateCopyOfAction()
  1075.         {
  1076.             CopyOfAction action = new CopyOfAction();
  1077.             action.Compile(this);
  1078.             return action;
  1079.         }
  1080.        
  1081.         public virtual ElementAction CreateElementAction()
  1082.         {
  1083.             ElementAction action = new ElementAction();
  1084.             action.Compile(this);
  1085.             return action;
  1086.         }
  1087.        
  1088.         public virtual ForEachAction CreateForEachAction()
  1089.         {
  1090.             ForEachAction action = new ForEachAction();
  1091.             action.Compile(this);
  1092.             return action;
  1093.         }
  1094.        
  1095.         public virtual IfAction CreateIfAction(IfAction.ConditionType type)
  1096.         {
  1097.             IfAction action = new IfAction(type);
  1098.             action.Compile(this);
  1099.             return action;
  1100.         }
  1101.        
  1102.         public virtual MessageAction CreateMessageAction()
  1103.         {
  1104.             MessageAction action = new MessageAction();
  1105.             action.Compile(this);
  1106.             return action;
  1107.         }
  1108.        
  1109.         public virtual NewInstructionAction CreateNewInstructionAction()
  1110.         {
  1111.             NewInstructionAction action = new NewInstructionAction();
  1112.             action.Compile(this);
  1113.             return action;
  1114.         }
  1115.        
  1116.         public virtual NumberAction CreateNumberAction()
  1117.         {
  1118.             NumberAction action = new NumberAction();
  1119.             action.Compile(this);
  1120.             return action;
  1121.         }
  1122.        
  1123.         public virtual ProcessingInstructionAction CreateProcessingInstructionAction()
  1124.         {
  1125.             ProcessingInstructionAction action = new ProcessingInstructionAction();
  1126.             action.Compile(this);
  1127.             return action;
  1128.         }
  1129.        
  1130.         public virtual void CreateRootAction()
  1131.         {
  1132.             this.RootAction = new RootAction();
  1133.             this.RootAction.Compile(this);
  1134.         }
  1135.        
  1136.         public virtual SortAction CreateSortAction()
  1137.         {
  1138.             SortAction action = new SortAction();
  1139.             action.Compile(this);
  1140.             return action;
  1141.         }
  1142.        
  1143.         public virtual TemplateAction CreateTemplateAction()
  1144.         {
  1145.             TemplateAction action = new TemplateAction();
  1146.             action.Compile(this);
  1147.             return action;
  1148.         }
  1149.        
  1150.         public virtual TemplateAction CreateSingleTemplateAction()
  1151.         {
  1152.             TemplateAction action = new TemplateAction();
  1153.             action.CompileSingle(this);
  1154.             return action;
  1155.         }
  1156.        
  1157.         public virtual TextAction CreateTextAction()
  1158.         {
  1159.             TextAction action = new TextAction();
  1160.             action.Compile(this);
  1161.             return action;
  1162.         }
  1163.        
  1164.         public virtual UseAttributeSetsAction CreateUseAttributeSetsAction()
  1165.         {
  1166.             UseAttributeSetsAction action = new UseAttributeSetsAction();
  1167.             action.Compile(this);
  1168.             return action;
  1169.         }
  1170.        
  1171.         public virtual ValueOfAction CreateValueOfAction()
  1172.         {
  1173.             ValueOfAction action = new ValueOfAction();
  1174.             action.Compile(this);
  1175.             return action;
  1176.         }
  1177.        
  1178.         public virtual VariableAction CreateVariableAction(VariableType type)
  1179.         {
  1180.             VariableAction action = new VariableAction(type);
  1181.             action.Compile(this);
  1182.             if (action.VarKey != InvalidQueryKey) {
  1183.                 return action;
  1184.             }
  1185.             else {
  1186.                 return null;
  1187.             }
  1188.         }
  1189.        
  1190.         public virtual WithParamAction CreateWithParamAction()
  1191.         {
  1192.             WithParamAction action = new WithParamAction();
  1193.             action.Compile(this);
  1194.             return action;
  1195.         }
  1196.        
  1197.         // Compiler is a class factory for some events:
  1198.         // CompilerDbg override all this methods:
  1199.        
  1200.         public virtual BeginEvent CreateBeginEvent()
  1201.         {
  1202.             return new BeginEvent(this);
  1203.         }
  1204.        
  1205.         public virtual TextEvent CreateTextEvent()
  1206.         {
  1207.             return new TextEvent(this);
  1208.         }
  1209.        
  1210.         public XsltException UnexpectedKeyword()
  1211.         {
  1212.             XPathNavigator nav = this.Input.Navigator.Clone();
  1213.             string thisName = nav.Name;
  1214.             nav.MoveToParent();
  1215.             string parentName = nav.Name;
  1216.             return XsltException.Create(Res.Xslt_UnexpectedKeyword, thisName, parentName);
  1217.         }
  1218.        
  1219.         internal class ErrorXPathExpression : CompiledXpathExpr
  1220.         {
  1221.             private string baseUri;
  1222.             private int lineNumber, linePosition;
  1223.             public ErrorXPathExpression(string expression, string baseUri, int lineNumber, int linePosition) : base(null, expression, false)
  1224.             {
  1225.                 this.baseUri = baseUri;
  1226.                 this.lineNumber = lineNumber;
  1227.                 this.linePosition = linePosition;
  1228.             }
  1229.            
  1230.             public override XPathExpression Clone()
  1231.             {
  1232.                 return this;
  1233.             }
  1234.             public override void CheckErrors()
  1235.             {
  1236.                 throw new XsltException(Res.Xslt_InvalidXPath, new string[] {Expression}, baseUri, linePosition, lineNumber, null);
  1237.             }
  1238.         }
  1239.     }
  1240. }

Developer Fusion