The Labs \ Source Viewer \ SSCLI \ Microsoft.JScript \ VsaReference

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. namespace Microsoft.JScript
  16. {
  17.    
  18.     using Microsoft.JScript.Vsa;
  19.     using System;
  20.     using System.Globalization;
  21.     using System.IO;
  22.     using System.Reflection;
  23.     using Microsoft.Vsa;
  24.    
  25.     class VsaReference : VsaItem, IVsaReferenceItem
  26.     {
  27.        
  28.         private string assemblyName;
  29.         private Assembly assembly;
  30.         bool loadFailed;
  31.        
  32.         internal VsaReference(VsaEngine engine, string itemName) : base(engine, itemName, VsaItemType.Reference, VsaItemFlag.None)
  33.         {
  34.             this.assemblyName = itemName;
  35.             // default to item name
  36.             this.assembly = null;
  37.             this.loadFailed = false;
  38.         }
  39.        
  40.         public string AssemblyName {
  41.             get {
  42.                 if (this.engine == null)
  43.                     throw new VsaException(VsaError.EngineClosed);
  44.                 return this.assemblyName;
  45.             }
  46.            
  47.             set {
  48.                 if (this.engine == null)
  49.                     throw new VsaException(VsaError.EngineClosed);
  50.                 this.assemblyName = value;
  51.                 this.isDirty = true;
  52.                 this.engine.IsDirty = true;
  53.             }
  54.         }
  55.        
  56.         internal Assembly Assembly {
  57.             get {
  58.                 if (this.engine == null)
  59.                     throw new VsaException(VsaError.EngineClosed);
  60.                 return this.assembly;
  61.             }
  62.         }
  63.        
  64.         internal Type GetType(string typeName)
  65.         {
  66.             if (this.assembly == null) {
  67.                 if (!loadFailed) {
  68.                     try {
  69.                         this.Load();
  70.                     }
  71.                     catch {
  72.                         loadFailed = true;
  73.                     }
  74.                 }
  75.                 if (this.assembly == null)
  76.                     return null;
  77.             }
  78.             Type result = this.assembly.GetType(typeName, false);
  79.             if (result != null && (!result.IsPublic || CustomAttribute.IsDefined(result, typeof(System.Runtime.CompilerServices.RequiredAttributeAttribute), true)))
  80.                 result = null;
  81.             //Suppress the type if it is not public or if it is a funky C++ type.
  82.             return result;
  83.         }
  84.        
  85.         internal override void Compile()
  86.         {
  87.             Compile(true);
  88.         }
  89.        
  90.         internal bool Compile(bool throwOnFileNotFound)
  91.         {
  92.             try {
  93.                 string assemblyFileName = Path.GetFileName(this.assemblyName);
  94.                 string alternateName = assemblyFileName + ".dll";
  95.                 if (String.Compare(assemblyFileName, "mscorlib.dll", StringComparison.OrdinalIgnoreCase) == 0 || String.Compare(alternateName, "mscorlib.dll", StringComparison.OrdinalIgnoreCase) == 0)
  96.                     this.assembly = typeof(object).Assembly;
  97.                 if (String.Compare(assemblyFileName, "microsoft.jscript.dll", StringComparison.OrdinalIgnoreCase) == 0 || String.Compare(alternateName, "microsoft.jscript.dll", StringComparison.OrdinalIgnoreCase) == 0) {
  98.                     this.assembly = engine.JScriptModule.Assembly;
  99.                 }
  100.                 else if (String.Compare(assemblyFileName, "microsoft.vsa.dll", StringComparison.OrdinalIgnoreCase) == 0 || String.Compare(alternateName, "microsoft.vsa.dll", StringComparison.OrdinalIgnoreCase) == 0) {
  101.                     this.assembly = engine.VsaModule.Assembly;
  102.                 }
  103.                 else if (this.engine.ReferenceLoaderAPI != LoaderAPI.ReflectionOnlyLoadFrom) {
  104.                     if (String.Compare(assemblyFileName, "system.dll", StringComparison.OrdinalIgnoreCase) == 0 || String.Compare(alternateName, "system.dll", StringComparison.OrdinalIgnoreCase) == 0)
  105.                         this.assembly = typeof(System.Text.RegularExpressions.Regex).Module.Assembly;
  106.                 }
  107.                
  108.                 if (this.assembly == null) {
  109.                     string path = this.engine.FindAssembly(this.assemblyName);
  110.                     // if not found, look for the file with ".dll" appended to the assembly name
  111.                     if (path == null) {
  112.                         // check for duplicates before we add the ".dll" part
  113.                         alternateName = this.assemblyName + ".dll";
  114.                         bool fDuplicate = false;
  115.                         foreach (object item in this.engine.Items) {
  116.                             if (item is VsaReference && String.Compare(((VsaReference)item).AssemblyName, alternateName, StringComparison.OrdinalIgnoreCase) == 0) {
  117.                                 fDuplicate = true;
  118.                                 break;
  119.                             }
  120.                         }
  121.                         if (!fDuplicate) {
  122.                             path = this.engine.FindAssembly(alternateName);
  123.                             if (path != null)
  124.                                 this.assemblyName = alternateName;
  125.                         }
  126.                     }
  127.                     if (path == null) {
  128.                         if (throwOnFileNotFound)
  129.                             throw new VsaException(VsaError.AssemblyExpected, this.assemblyName, new System.IO.FileNotFoundException());
  130.                         else
  131.                             return false;
  132.                     }
  133.                     switch (this.engine.ReferenceLoaderAPI) {
  134.                         case LoaderAPI.LoadFrom:
  135.                             this.assembly = Assembly.LoadFrom(path);
  136.                             break;
  137.                         case LoaderAPI.LoadFile:
  138.                             this.assembly = Assembly.LoadFile(path);
  139.                             break;
  140.                         case LoaderAPI.ReflectionOnlyLoadFrom:
  141.                             this.assembly = Assembly.ReflectionOnlyLoadFrom(path);
  142.                             break;
  143.                     }
  144.                    
  145.                     // Warn if building a machine specfic assembly and the referenced assembly is machine
  146.                     // specific but does not match.
  147.                     CheckCompatibility();
  148.                 }
  149.             }
  150.             catch (VsaException) {
  151.                 throw;
  152.             }
  153.             catch (System.BadImageFormatException e) {
  154.                 throw new VsaException(VsaError.AssemblyExpected, this.assemblyName, e);
  155.             }
  156.             catch (System.IO.FileNotFoundException e) {
  157.                 if (throwOnFileNotFound)
  158.                     throw new VsaException(VsaError.AssemblyExpected, this.assemblyName, e);
  159.                 else
  160.                     return false;
  161.             }
  162.             catch (System.IO.FileLoadException e) {
  163.                 throw new VsaException(VsaError.AssemblyExpected, this.assemblyName, e);
  164.             }
  165.             catch (System.ArgumentException e) {
  166.                 throw new VsaException(VsaError.AssemblyExpected, this.assemblyName, e);
  167.             }
  168.             catch (Exception e) {
  169.                 throw new VsaException(VsaError.InternalCompilerError, e.ToString(), e);
  170.             }
  171.             catch {
  172.                 throw new VsaException(VsaError.InternalCompilerError);
  173.             }
  174.             if (this.assembly == null) {
  175.                 if (throwOnFileNotFound)
  176.                     throw new VsaException(VsaError.AssemblyExpected, this.assemblyName);
  177.                 else
  178.                     return false;
  179.             }
  180.             return true;
  181.         }
  182.        
  183.        
  184.         // This method is called at runtime. When this is called this.assemblyName is the
  185.         // actual assembly name ( eg., mscorlib ) rather than the file name ( eg., mscorlib.dll)
  186.         private void Load()
  187.         {
  188.             try {
  189.                 if (String.Compare(this.assemblyName, "mscorlib", StringComparison.OrdinalIgnoreCase) == 0)
  190.                     this.assembly = typeof(object).Module.Assembly;
  191.                 else if (String.Compare(this.assemblyName, "Microsoft.JScript", StringComparison.OrdinalIgnoreCase) == 0)
  192.                     this.assembly = typeof(VsaEngine).Module.Assembly;
  193.                 else if (String.Compare(this.assemblyName, "Microsoft.Vsa", StringComparison.OrdinalIgnoreCase) == 0)
  194.                     this.assembly = typeof(IVsaEngine).Module.Assembly;
  195.                 else if (String.Compare(this.assemblyName, "System", StringComparison.OrdinalIgnoreCase) == 0)
  196.                     this.assembly = typeof(System.Text.RegularExpressions.Regex).Module.Assembly;
  197.                 else {
  198.                     this.assembly = Assembly.Load(this.assemblyName);
  199.                 }
  200.             }
  201.             catch (System.BadImageFormatException e) {
  202.                 throw new VsaException(VsaError.AssemblyExpected, this.assemblyName, e);
  203.             }
  204.             catch (System.IO.FileNotFoundException e) {
  205.                 throw new VsaException(VsaError.AssemblyExpected, this.assemblyName, e);
  206.             }
  207.             catch (System.ArgumentException e) {
  208.                 throw new VsaException(VsaError.AssemblyExpected, this.assemblyName, e);
  209.             }
  210.             catch (Exception e) {
  211.                 throw new VsaException(VsaError.InternalCompilerError, e.ToString(), e);
  212.             }
  213.             catch {
  214.                 throw new VsaException(VsaError.InternalCompilerError);
  215.             }
  216.             if (this.assembly == null) {
  217.                 throw new VsaException(VsaError.AssemblyExpected, this.assemblyName);
  218.             }
  219.         }
  220.        
  221.         private void CheckCompatibility()
  222.         {
  223.             // If reference is agnostic, then compatible
  224.             PortableExecutableKinds RefPEKindFlags;
  225.             ImageFileMachine RefPEMachineArchitecture;
  226.             this.assembly.ManifestModule.GetPEKind(out RefPEKindFlags, out RefPEMachineArchitecture);
  227.            
  228.             if (RefPEMachineArchitecture == ImageFileMachine.I386 && PortableExecutableKinds.ILOnly == (RefPEKindFlags & (PortableExecutableKinds.ILOnly | PortableExecutableKinds.Required32Bit))) {
  229.                 return;
  230.             }
  231.            
  232.             // Warn if building an agnostic assembly, but referenced assembly is not.
  233.             PortableExecutableKinds PEKindFlags = engine.PEKindFlags;
  234.             ImageFileMachine PEMachineArchitecture = engine.PEMachineArchitecture;
  235.             if (PEMachineArchitecture == ImageFileMachine.I386 && PortableExecutableKinds.ILOnly == (PEKindFlags & (PortableExecutableKinds.ILOnly | PortableExecutableKinds.Required32Bit))) {
  236.                 // We are agnostic, but the reference is not. Do not emit a warning - this is a very common
  237.                 // case. Many of the system libraries are platform specific.
  238.                 return;
  239.             }
  240.            
  241.             // Warning if architectures don't match.
  242.             if (RefPEMachineArchitecture != PEMachineArchitecture) {
  243.                 JScriptException e = new JScriptException(JSError.IncompatibleAssemblyReference);
  244.                 e.value = this.assemblyName;
  245.                 this.engine.OnCompilerError(e);
  246.             }
  247.         }
  248.     }
  249. }

Developer Fusion