Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / whidbey / NetFXspW7 / ndp / fx / src / XmlUtils / System / Xml / Xsl / Xslt / Scripts.cs / 1 / Scripts.cs
//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// [....]
// http://devdiv/Documents/Whidbey/CLR/CurrentSpecs/BCL/CodeDom%20Activation.doc
//-----------------------------------------------------------------------------
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Configuration;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.Threading;
using System.Xml.Xsl.IlGen;
using System.Xml.Xsl.Runtime;
using System.Security.Permissions;
namespace System.Xml.Xsl.Xslt {
using Res = System.Xml.Utils.Res;
internal class ScriptClass {
public string ns;
public CompilerInfo compilerInfo;
public StringCollection refAssemblies = new StringCollection();
public StringCollection nsImports = new StringCollection();
public StringCollection scriptFiles = new StringCollection();
public CodeTypeDeclaration typeDecl;
public bool refAssembliesByHref = false;
// These three fields are used to report a compile error when its position is outside
// of all user code snippets in the generated temporary file
public string endFileName;
public int endLine;
public int endPos;
public ScriptClass(string ns, CompilerInfo compilerInfo) {
this.ns = ns;
this.compilerInfo = compilerInfo;
this.typeDecl = new CodeTypeDeclaration(GenerateUniqueClassName());
}
private static long scriptClassCounter = 0;
private static string GenerateUniqueClassName() {
return "Script" + Interlocked.Increment(ref scriptClassCounter);
}
public void AddScriptBlock(string source, string uriString, int lineNumber, int endLine, int endPos) {
CodeSnippetTypeMember scriptSnippet = new CodeSnippetTypeMember(source);
string fileName = SourceLineInfo.GetFileName(uriString);
if (lineNumber > 0) {
scriptSnippet.LinePragma = new CodeLinePragma(fileName, lineNumber);
scriptFiles.Add(fileName);
}
typeDecl.Members.Add(scriptSnippet);
this.endFileName = fileName;
this.endLine = endLine;
this.endPos = endPos;
}
public CompilerError CreateCompileExceptionError(Exception e) {
string errorText = XslTransformException.CreateMessage(/*[XT_041]*/Res.Xslt_ScriptCompileException, e.Message);
return new CompilerError(this.endFileName, this.endLine, this.endPos, /*errorNumber:*/string.Empty, errorText);
}
}
internal class Scripts {
private const string ScriptClassesNamespace = "System.Xml.Xsl.CompiledQuery";
private Compiler compiler;
private List scriptClasses = new List();
private Dictionary nsToType = new Dictionary();
private XmlExtensionFunctionTable extFuncs = new XmlExtensionFunctionTable();
public Scripts(Compiler compiler) {
this.compiler = compiler;
}
public Dictionary ScriptClasses {
get { return nsToType; }
}
public XmlExtensionFunction ResolveFunction(string name, string ns, int numArgs, IErrorHelper errorHelper) {
Type type;
if (nsToType.TryGetValue(ns, out type)) {
try {
return extFuncs.Bind(name, ns, numArgs, type, XmlQueryRuntime.EarlyBoundFlags);
}
catch (XslTransformException e) {
errorHelper.ReportError(e.Message);
}
}
return null;
}
public ScriptClass GetScriptClass(string ns, string language, IErrorHelper errorHelper) {
CompilerInfo compilerInfo;
try {
compilerInfo = CodeDomProvider.GetCompilerInfo(language);
Debug.Assert(compilerInfo != null);
}
catch (ConfigurationException) {
// There is no CodeDom provider defined for this language
errorHelper.ReportError(/*[XT_010]*/Res.Xslt_ScriptInvalidLanguage, language);
return null;
}
foreach (ScriptClass scriptClass in scriptClasses) {
if (ns == scriptClass.ns) {
// Use object comparison because CompilerInfo.Equals may throw
if (compilerInfo != scriptClass.compilerInfo) {
errorHelper.ReportError(/*[XT_011]*/Res.Xslt_ScriptMixedLanguages, ns);
return null;
}
return scriptClass;
}
}
ScriptClass newScriptClass = new ScriptClass(ns, compilerInfo);
newScriptClass.typeDecl.TypeAttributes = TypeAttributes.Public;
scriptClasses.Add(newScriptClass);
return newScriptClass;
}
//------------------------------------------------
// Compilation
//------------------------------------------------
public void CompileScripts() {
List scriptsForLang = new List();
for (int i = 0; i < scriptClasses.Count; i++) {
// If the script is already compiled, skip it
if (scriptClasses[i] == null)
continue;
// Group together scripts with the same CompilerInfo
CompilerInfo compilerInfo = scriptClasses[i].compilerInfo;
scriptsForLang.Clear();
for (int j = i; j < scriptClasses.Count; j++) {
// Use object comparison because CompilerInfo.Equals may throw
if (scriptClasses[j] != null && scriptClasses[j].compilerInfo == compilerInfo) {
scriptsForLang.Add(scriptClasses[j]);
scriptClasses[j] = null;
}
}
Assembly assembly = CompileAssembly(scriptsForLang);
if (assembly != null) {
foreach (ScriptClass script in scriptsForLang) {
Type clrType = assembly.GetType(ScriptClassesNamespace + Type.Delimiter + script.typeDecl.Name);
if (clrType != null) {
nsToType.Add(script.ns, clrType);
}
}
}
}
}
// Namespaces we always import when compiling
private static readonly string[] defaultNamespaces = new string[] {
"System",
"System.Collections",
"System.Text",
"System.Text.RegularExpressions",
"System.Xml",
"System.Xml.Xsl",
"System.Xml.XPath",
};
[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
private Assembly CompileAssembly(List scriptsForLang) {
TempFileCollection allTempFiles = compiler.CompilerResults.TempFiles;
CompilerErrorCollection allErrors = compiler.CompilerResults.Errors;
ScriptClass lastScript = scriptsForLang[scriptsForLang.Count - 1];
CodeDomProvider provider;
bool isVB = false;
try {
provider = lastScript.compilerInfo.CreateProvider();
}
catch (ConfigurationException e) {
// The CodeDom provider type could not be located, or some error in machine.config
allErrors.Add(lastScript.CreateCompileExceptionError(e));
return null;
}
#if !FEATURE_PAL // visualbasic
isVB = provider is Microsoft.VisualBasic.VBCodeProvider;
#endif // !FEATURE_PAL
CodeCompileUnit[] codeUnits = new CodeCompileUnit[scriptsForLang.Count];
CompilerParameters compilParams = lastScript.compilerInfo.CreateDefaultCompilerParameters();
//
compilParams.ReferencedAssemblies.Add(typeof(System.Xml.Res).Assembly.Location);
compilParams.ReferencedAssemblies.Add("System.dll");
if (isVB) {
compilParams.ReferencedAssemblies.Add("Microsoft.VisualBasic.dll");
}
bool refAssembliesByHref = false;
for (int idx = 0; idx < scriptsForLang.Count; idx++) {
ScriptClass script = scriptsForLang[idx];
CodeNamespace scriptNs = new CodeNamespace(ScriptClassesNamespace);
// Add imported namespaces
foreach (string ns in defaultNamespaces) {
scriptNs.Imports.Add(new CodeNamespaceImport(ns));
}
if (isVB) {
scriptNs.Imports.Add(new CodeNamespaceImport("Microsoft.VisualBasic"));
}
foreach (string ns in script.nsImports) {
scriptNs.Imports.Add(new CodeNamespaceImport(ns));
}
scriptNs.Types.Add(script.typeDecl);
CodeCompileUnit unit = new CodeCompileUnit(); {
unit.Namespaces.Add(scriptNs);
if (isVB) {
// This settings have sense for Visual Basic only. In future releases we may allow to specify
// them explicitly in the msxsl:script element.
unit.UserData["AllowLateBound"] = true; // Allow variables to be declared untyped
unit.UserData["RequireVariableDeclaration"] = false; // Allow variables to be undeclared
}
// Put SecurityTransparentAttribute on the first CodeCompileUnit only
if (idx == 0) {
unit.AssemblyCustomAttributes.Add(new CodeAttributeDeclaration("System.Security.SecurityTransparentAttribute"));
}
}
codeUnits[idx] = unit;
foreach (string name in script.refAssemblies) {
compilParams.ReferencedAssemblies.Add(name);
}
refAssembliesByHref |= script.refAssembliesByHref;
}
XsltSettings settings = compiler.Settings;
compilParams.WarningLevel = settings.WarningLevel >= 0 ? settings.WarningLevel : compilParams.WarningLevel;
compilParams.TreatWarningsAsErrors = settings.TreatWarningsAsErrors;
compilParams.IncludeDebugInformation = compiler.IsDebug;
string asmPath = compiler.ScriptAssemblyPath;
if (asmPath != null && scriptsForLang.Count < scriptClasses.Count) {
asmPath = Path.ChangeExtension(asmPath, "." + GetLanguageName(lastScript.compilerInfo) + Path.GetExtension(asmPath));
}
compilParams.OutputAssembly = asmPath;
string tempDir = (settings.TempFiles != null) ? settings.TempFiles.TempDir : null;
compilParams.TempFiles = new TempFileCollection(tempDir);
// We need only .dll and .pdb, but there is no way to specify that
bool keepFiles = ((compiler.IsDebug && asmPath == null) || XmlILTrace.IsEnabled) && !settings.CheckOnly;
compilParams.TempFiles.KeepFiles = keepFiles;
// If GenerateInMemory == true, then CodeDom loads the compiled assembly using Assembly.Load(byte[])
// instead of Assembly.Load(AssemblyName). That means the assembly will be loaded in the anonymous
// context (http://blogs.msdn.com/[....]/archive/2003/05/29/57143.aspx), and its dependencies can only
// be loaded from the Load context or using AssemblyResolve event. However we want to use the LoadFrom
// context to preload all dependencies specified by , so we turn off
// GenerateInMemory here.
compilParams.GenerateInMemory = (asmPath == null && !compiler.IsDebug && !refAssembliesByHref) || settings.CheckOnly;
CompilerResults results;
try {
results = provider.CompileAssemblyFromDom(compilParams, codeUnits);
}
catch (ExternalException e) {
// Compiler might have created temporary files
results = new CompilerResults(compilParams.TempFiles);
results.Errors.Add(lastScript.CreateCompileExceptionError(e));
}
if (!settings.CheckOnly) {
foreach (string fileName in results.TempFiles) {
allTempFiles.AddFile(fileName, allTempFiles.KeepFiles);
}
}
foreach (CompilerError error in results.Errors) {
FixErrorPosition(error, scriptsForLang);
}
allErrors.AddRange(results.Errors);
return results.Errors.HasErrors ? null : results.CompiledAssembly;
}
private int assemblyCounter = 0;
private string GetLanguageName(CompilerInfo compilerInfo) {
Regex alphaNumeric = new Regex("^[0-9a-zA-Z]+$");
foreach (string name in compilerInfo.GetLanguages()) {
if (alphaNumeric.IsMatch(name))
return name;
}
return "script" + (++assemblyCounter).ToString(CultureInfo.InvariantCulture);
}
#if !FEATURE_CASE_SENSITIVE_FILESYSTEM
private static readonly StringComparison fileNameComparison = StringComparison.OrdinalIgnoreCase;
#else
private static readonly StringComparison fileNameComparison = StringComparison.Ordinal;
#endif
// The position of a compile error may be outside of all user code snippets (for example, in case of
// unclosed '{'). In that case filename would be the name of the temporary file, and not the name
// of the stylesheet file. Exposing the path of the temporary file is considered to be a security issue,
// so here we check that filename is amongst user files.
private static void FixErrorPosition(CompilerError error, List scriptsForLang) {
string fileName = error.FileName;
foreach (ScriptClass script in scriptsForLang) {
foreach (string scriptFile in script.scriptFiles) {
// We assume that CodeDom provider returns absolute paths (VSWhidbey 289665).
// Note that casing may be different.
if (fileName.Equals(scriptFile, fileNameComparison)) {
// The error position is within one of user stylesheets, its filename may be reported
error.FileName = scriptFile;
return;
}
}
}
// Error is outside user code snippeets, we should hide filename for security reasons.
// Return filename and position of the end of the last script block for the given class.
int idx, scriptNumber;
ScriptClass errScript = scriptsForLang[scriptsForLang.Count - 1];
// Normally temporary source files are named according to the scheme ".
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- Types.cs
- ToolStripItemClickedEventArgs.cs
- XmlILModule.cs
- TextEditorTables.cs
- _KerberosClient.cs
- DockPattern.cs
- FilterElement.cs
- MethodSignatureGenerator.cs
- ControlUtil.cs
- ComContractElementCollection.cs
- Win32KeyboardDevice.cs
- MexNamedPipeBindingCollectionElement.cs
- TypeLibConverter.cs
- CultureTableRecord.cs
- Help.cs
- TreeNodeBindingDepthConverter.cs
- ModulesEntry.cs
- HandlerFactoryCache.cs
- XmlRawWriter.cs
- ipaddressinformationcollection.cs
- PropertyChangedEventArgs.cs
- GenerateScriptTypeAttribute.cs
- FunctionNode.cs
- WaitForChangedResult.cs
- ToolStripArrowRenderEventArgs.cs
- Decoder.cs
- xml.cs
- ObjectConverter.cs
- TextTreeText.cs
- SQLSingleStorage.cs
- WorkflowView.cs
- COM2EnumConverter.cs
- CodeCommentStatementCollection.cs
- PackWebResponse.cs
- ChtmlSelectionListAdapter.cs
- NumberSubstitution.cs
- DataFormat.cs
- SoapExtension.cs
- Stack.cs
- ComplexBindingPropertiesAttribute.cs
- SHA384Managed.cs
- RangeContentEnumerator.cs
- ToolStripDropDownButton.cs
- DependencyPropertyDescriptor.cs
- AudioDeviceOut.cs
- PlatformNotSupportedException.cs
- ActivityXRefConverter.cs
- ContentDisposition.cs
- ErrorEventArgs.cs
- LayoutTableCell.cs
- XmlSchemaAnnotated.cs
- StatusBarDrawItemEvent.cs
- recordstatefactory.cs
- ObjectSpanRewriter.cs
- PolicyStatement.cs
- XmlDataSourceNodeDescriptor.cs
- TlsnegoTokenProvider.cs
- LiteralControl.cs
- CloudCollection.cs
- BuildTopDownAttribute.cs
- AssemblyCollection.cs
- SHA512CryptoServiceProvider.cs
- ClassValidator.cs
- XmlSchemaRedefine.cs
- DesignerGenericWebPart.cs
- FieldAccessException.cs
- CompilerInfo.cs
- TimeSpanOrInfiniteConverter.cs
- BrowserCapabilitiesFactoryBase.cs
- AuthenticationModuleElement.cs
- HatchBrush.cs
- SiteMapPath.cs
- StyleCollectionEditor.cs
- AssemblySettingAttributes.cs
- _NegotiateClient.cs
- ServerTooBusyException.cs
- ECDiffieHellman.cs
- EntitySqlQueryState.cs
- RayMeshGeometry3DHitTestResult.cs
- BStrWrapper.cs
- ToolBarButtonClickEvent.cs
- ReadOnlyDataSourceView.cs
- EncoderExceptionFallback.cs
- StreamGeometry.cs
- BaseCollection.cs
- Highlights.cs
- RewritingProcessor.cs
- XNodeNavigator.cs
- RawMouseInputReport.cs
- ToolboxItemCollection.cs
- MetadataArtifactLoaderResource.cs
- SerialPinChanges.cs
- WebPartConnectionsCancelEventArgs.cs
- Base64Stream.cs
- EventLevel.cs
- TextEncodedRawTextWriter.cs
- HotSpotCollection.cs
- WebPartZoneCollection.cs
- MobileTemplatedControlDesigner.cs
- IpcPort.cs