The Labs \ Source Viewer \ SSCLI \ System.Xml.Serialization \ Compiler

  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. // <owner current="true" primary="true">ElenaK</owner>
  15. //------------------------------------------------------------------------------
  16. namespace System.Xml.Serialization
  17. {
  18.     using System.Reflection;
  19.     using System.Reflection.Emit;
  20.     using System.Collections;
  21.     using System.IO;
  22.     using System;
  23.     using System.Text;
  24.     using System.ComponentModel;
  25.     using System.CodeDom.Compiler;
  26.     using System.Security;
  27.     using System.Security.Permissions;
  28.     using System.Diagnostics;
  29.     using System.Security.Principal;
  30.     using System.Security.Policy;
  31.     using System.Threading;
  32.     using System.Xml.Serialization.Configuration;
  33.     using System.Globalization;
  34.    
  35.     internal class Compiler
  36.     {
  37.         bool debugEnabled = DiagnosticsSwitches.KeepTempFiles.Enabled;
  38.         Hashtable imports = new Hashtable();
  39.         StringWriter writer = new StringWriter(CultureInfo.InvariantCulture);
  40.        
  41.         protected string[] Imports {
  42.             get {
  43.                 string[] array = new string[imports.Values.Count];
  44.                 imports.Values.CopyTo(array, 0);
  45.                 return array;
  46.             }
  47.         }
  48.        
  49.         internal void AddImport(Type type, Hashtable types)
  50.         {
  51.             if (type == null)
  52.                 return;
  53.             if (TypeScope.IsKnownType(type))
  54.                 return;
  55.             if (types[type] != null)
  56.                 return;
  57.             types[type] = type;
  58.             Type baseType = type.BaseType;
  59.             if (baseType != null)
  60.                 AddImport(baseType, types);
  61.            
  62.             Type declaringType = type.DeclaringType;
  63.             if (declaringType != null)
  64.                 AddImport(declaringType, types);
  65.            
  66.             foreach (Type intf in type.GetInterfaces())
  67.                 AddImport(intf, types);
  68.            
  69.             ConstructorInfo[] ctors = type.GetConstructors();
  70.             for (int i = 0; i < ctors.Length; i++) {
  71.                 ParameterInfo[] parms = ctors[i].GetParameters();
  72.                 for (int j = 0; j < parms.Length; j++) {
  73.                     AddImport(parms[j].ParameterType, types);
  74.                 }
  75.             }
  76.            
  77.             if (type.IsGenericType) {
  78.                 Type[] arguments = type.GetGenericArguments();
  79.                 for (int i = 0; i < arguments.Length; i++) {
  80.                     AddImport(arguments[i], types);
  81.                 }
  82.             }
  83.            
  84.             TempAssembly.FileIOPermission.Assert();
  85.             Module module = type.Module;
  86.             Assembly assembly = module.Assembly;
  87.             if (DynamicAssemblies.IsTypeDynamic(type)) {
  88.                 DynamicAssemblies.Add(assembly);
  89.                 return;
  90.             }
  91.             imports[assembly] = assembly.Location;
  92.         }
  93.        
  94.         internal void AddImport(Assembly assembly)
  95.         {
  96.             TempAssembly.FileIOPermission.Assert();
  97.             imports[assembly] = assembly.Location;
  98.         }
  99.        
  100.         internal TextWriter Source {
  101.             get { return writer; }
  102.         }
  103.        
  104.         internal void Close()
  105.         {
  106.         }
  107.        
  108.         static internal string GetTempAssemblyPath(string baseDir, Assembly assembly, string defaultNamespace)
  109.         {
  110.             if (assembly.Location == null || assembly.Location.Length == 0) {
  111.                 throw new InvalidOperationException(Res.GetString(Res.XmlPregenAssemblyDynamic, assembly.Location));
  112.             }
  113.            
  114.             PermissionSet perms = new PermissionSet(PermissionState.None);
  115.             perms.AddPermission(new FileIOPermission(PermissionState.Unrestricted));
  116.             perms.AddPermission(new EnvironmentPermission(PermissionState.Unrestricted));
  117.             perms.Assert();
  118.            
  119.             try {
  120.                 if (baseDir != null && baseDir.Length > 0) {
  121.                     // check that the dirsctory exists
  122.                     if (!Directory.Exists(baseDir)) {
  123.                         throw new UnauthorizedAccessException(Res.GetString(Res.XmlPregenMissingDirectory, baseDir));
  124.                     }
  125.                 }
  126.                 else {
  127.                     baseDir = Path.GetTempPath();
  128.                     // check that the dirsctory exists
  129.                     if (!Directory.Exists(baseDir)) {
  130.                         throw new UnauthorizedAccessException(Res.GetString(Res.XmlPregenMissingTempDirectory));
  131.                     }
  132.                 }
  133.                 if (baseDir.EndsWith("\\", StringComparison.Ordinal))
  134.                     baseDir += GetTempAssemblyName(assembly.GetName(), defaultNamespace);
  135.                 else
  136.                     baseDir += "\\" + GetTempAssemblyName(assembly.GetName(), defaultNamespace);
  137.             }
  138.             finally {
  139.                 CodeAccessPermission.RevertAssert();
  140.             }
  141.             return baseDir + ".dll";
  142.         }
  143.        
  144.         static internal string GetTempAssemblyName(AssemblyName parent, string ns)
  145.         {
  146.             return parent.Name + ".XmlSerializers" + (ns == null || ns.Length == 0 ? "" : "." + ns.GetHashCode());
  147.         }
  148.        
  149.         internal Assembly Compile(Assembly parent, string ns, CompilerParameters parameters, Evidence evidence)
  150.         {
  151.             CodeDomProvider codeProvider = new Microsoft.CSharp.CSharpCodeProvider();
  152.             parameters.ReferencedAssemblies.AddRange(Imports);
  153.            
  154.             if (debugEnabled) {
  155.                 parameters.GenerateInMemory = false;
  156.                 parameters.IncludeDebugInformation = true;
  157.                 parameters.TempFiles.KeepFiles = true;
  158.             }
  159.             PermissionSet perms = new PermissionSet(PermissionState.None);
  160.             perms.AddPermission(TempAssembly.FileIOPermission);
  161.             perms.AddPermission(new EnvironmentPermission(PermissionState.Unrestricted));
  162.             perms.AddPermission(new SecurityPermission(SecurityPermissionFlag.UnmanagedCode));
  163.             perms.AddPermission(new SecurityPermission(SecurityPermissionFlag.ControlEvidence));
  164.             perms.Assert();
  165.            
  166.             if (parent != null && (parameters.OutputAssembly == null || parameters.OutputAssembly.Length == 0)) {
  167.                 string assemblyName = AssemblyNameFromOptions(parameters.CompilerOptions);
  168.                 if (assemblyName == null)
  169.                     assemblyName = GetTempAssemblyPath(parameters.TempFiles.TempDir, parent, ns);
  170.                 parameters.OutputAssembly = assemblyName;
  171.             }
  172.            
  173.             if (parameters.CompilerOptions == null || parameters.CompilerOptions.Length == 0)
  174.                 parameters.CompilerOptions = "/nostdlib";
  175.             else
  176.                 parameters.CompilerOptions += " /nostdlib";
  177.            
  178.             parameters.CompilerOptions += " /D:_DYNAMIC_XMLSERIALIZER_COMPILATION";
  179.             parameters.Evidence = evidence;
  180.             CompilerResults results = null;
  181.             Assembly assembly = null;
  182.             try {
  183.                 results = codeProvider.CompileAssemblyFromSource(parameters, writer.ToString());
  184.                 // check the output for errors or a certain level-1 warning (1595)
  185.                 if (results.Errors.Count > 0) {
  186.                     StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture);
  187.                     stringWriter.WriteLine(Res.GetString(Res.XmlCompilerError, results.NativeCompilerReturnValue.ToString(CultureInfo.InvariantCulture)));
  188.                     bool foundOne = false;
  189.                     foreach (CompilerError e in results.Errors) {
  190.                         // clear filename. This makes ToString() print just error number and message.
  191.                         e.FileName = "";
  192.                         if (!e.IsWarning || e.ErrorNumber == "CS1595") {
  193.                             foundOne = true;
  194.                             stringWriter.WriteLine(e.ToString());
  195.                         }
  196.                     }
  197.                     if (foundOne) {
  198.                         throw new InvalidOperationException(stringWriter.ToString());
  199.                     }
  200.                 }
  201.                 assembly = results.CompiledAssembly;
  202.             }
  203.             catch (UnauthorizedAccessException) {
  204.                 // try to get the user token
  205.                 string user = GetCurrentUser();
  206.                 if (user == null || user.Length == 0) {
  207.                     throw new UnauthorizedAccessException(Res.GetString(Res.XmlSerializerAccessDenied));
  208.                 }
  209.                 else {
  210.                     throw new UnauthorizedAccessException(Res.GetString(Res.XmlIdentityAccessDenied, user));
  211.                 }
  212.             }
  213.             catch (FileLoadException fle) {
  214.                 throw new InvalidOperationException(Res.GetString(Res.XmlSerializerCompileFailed), fle);
  215.             }
  216.             finally {
  217.                 CodeAccessPermission.RevertAssert();
  218.             }
  219.             // somehow we got here without generating an assembly
  220.             if (assembly == null)
  221.                 throw new InvalidOperationException(Res.GetString(Res.XmlInternalError));
  222.            
  223.             return assembly;
  224.         }
  225.        
  226.         static string AssemblyNameFromOptions(string options)
  227.         {
  228.             if (options == null || options.Length == 0)
  229.                 return null;
  230.            
  231.             string outName = null;
  232.             string[] flags = options.ToLower(CultureInfo.InvariantCulture).Split(null);
  233.             for (int i = 0; i < flags.Length; i++) {
  234.                 string val = flags[i].Trim();
  235.                 if (val.StartsWith("/out:", StringComparison.Ordinal)) {
  236.                     outName = val.Substring(5);
  237.                 }
  238.             }
  239.             return outName;
  240.         }
  241.        
  242.         static internal string GetCurrentUser()
  243.         {
  244.             return "";
  245.         }
  246.     }
  247. }

Developer Fusion