X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fclass%2FMono.Cecil%2FMono.Cecil%2FBaseAssemblyResolver.cs;h=10ab2c34a868cecfb0569888cf9a8d8e9645e71d;hb=f4df78bd2d1f95d26cf380552f6894721e2baf63;hp=7a4ac1b5c328315452282e0e589947e277e6e523;hpb=84d7e0f62957fdb0451d3ca94a49ea6d74d98e56;p=mono.git diff --git a/mcs/class/Mono.Cecil/Mono.Cecil/BaseAssemblyResolver.cs b/mcs/class/Mono.Cecil/Mono.Cecil/BaseAssemblyResolver.cs index 7a4ac1b5c32..10ab2c34a86 100644 --- a/mcs/class/Mono.Cecil/Mono.Cecil/BaseAssemblyResolver.cs +++ b/mcs/class/Mono.Cecil/Mono.Cecil/BaseAssemblyResolver.cs @@ -4,7 +4,7 @@ // Author: // Jb Evain (jbevain@gmail.com) // -// (C) 2005 Jb Evain +// Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the @@ -26,88 +26,170 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +using Mono.Collections.Generic; + namespace Mono.Cecil { - using System; - using System.Collections; - using System.IO; - using SR = System.Reflection; - using System.Text; + public delegate AssemblyDefinition AssemblyResolveEventHandler (object sender, AssemblyNameReference reference); + + public sealed class AssemblyResolveEventArgs : EventArgs { + + readonly AssemblyNameReference reference; + + public AssemblyNameReference AssemblyReference { + get { return reference; } + } + + public AssemblyResolveEventArgs (AssemblyNameReference reference) + { + this.reference = reference; + } + } + +#if !SILVERLIGHT && !CF + [Serializable] +#endif + public class AssemblyResolutionException : FileNotFoundException { + + readonly AssemblyNameReference reference; + + public AssemblyNameReference AssemblyReference { + get { return reference; } + } + + public AssemblyResolutionException (AssemblyNameReference reference) + : base (string.Format ("Failed to resolve assembly: '{0}'", reference)) + { + this.reference = reference; + } + +#if !SILVERLIGHT && !CF + protected AssemblyResolutionException ( + System.Runtime.Serialization.SerializationInfo info, + System.Runtime.Serialization.StreamingContext context) + : base (info, context) + { + } +#endif + } public abstract class BaseAssemblyResolver : IAssemblyResolver { - ArrayList m_directories; + static readonly bool on_mono = Type.GetType ("Mono.Runtime") != null; + + readonly Collection directories; + +#if !SILVERLIGHT && !CF + Collection gac_paths; +#endif public void AddSearchDirectory (string directory) { - m_directories.Add (directory); + directories.Add (directory); } public void RemoveSearchDirectory (string directory) { - m_directories.Remove (directory); + directories.Remove (directory); } public string [] GetSearchDirectories () { - return (string []) m_directories.ToArray (typeof (string)); + var directories = new string [this.directories.size]; + Array.Copy (this.directories.items, directories, directories.Length); + return directories; } public virtual AssemblyDefinition Resolve (string fullName) { - return Resolve (AssemblyNameReference.Parse (fullName)); + return Resolve (fullName, new ReaderParameters ()); + } + + public virtual AssemblyDefinition Resolve (string fullName, ReaderParameters parameters) + { + if (fullName == null) + throw new ArgumentNullException ("fullName"); + + return Resolve (AssemblyNameReference.Parse (fullName), parameters); + } + + public event AssemblyResolveEventHandler ResolveFailure; + + protected BaseAssemblyResolver () + { + directories = new Collection (2) { ".", "bin" }; } - public BaseAssemblyResolver () + AssemblyDefinition GetAssembly (string file, ReaderParameters parameters) { - m_directories = new ArrayList (); - m_directories.Add ("."); - m_directories.Add ("bin"); + if (parameters.AssemblyResolver == null) + parameters.AssemblyResolver = this; + + return ModuleDefinition.ReadModule (file, parameters).Assembly; } public virtual AssemblyDefinition Resolve (AssemblyNameReference name) { - AssemblyDefinition assembly; - string frameworkdir = Path.GetDirectoryName (typeof (object).Module.FullyQualifiedName); + return Resolve (name, new ReaderParameters ()); + } + + public virtual AssemblyDefinition Resolve (AssemblyNameReference name, ReaderParameters parameters) + { + if (name == null) + throw new ArgumentNullException ("name"); + if (parameters == null) + parameters = new ReaderParameters (); - assembly = SearchDirectory (name, m_directories); + var assembly = SearchDirectory (name, directories, parameters); if (assembly != null) return assembly; +#if !SILVERLIGHT && !CF + var framework_dir = Path.GetDirectoryName (typeof (object).Module.FullyQualifiedName); + if (IsZero (name.Version)) { - assembly = SearchDirectory (name, new string [] {frameworkdir}); + assembly = SearchDirectory (name, new [] { framework_dir }, parameters); if (assembly != null) return assembly; } -#if !CF_1_0 && !CF_2_0 if (name.Name == "mscorlib") { - assembly = GetCorlib (name); + assembly = GetCorlib (name, parameters); if (assembly != null) return assembly; } - assembly = GetAssemblyInGac (name); + assembly = GetAssemblyInGac (name, parameters); if (assembly != null) return assembly; -#endif - assembly = SearchDirectory (name, new string [] {frameworkdir}); + assembly = SearchDirectory (name, new [] { framework_dir }, parameters); if (assembly != null) return assembly; +#endif - throw new FileNotFoundException ("Could not resolve: " + name); - } + if (ResolveFailure != null) { + assembly = ResolveFailure (this, name); + if (assembly != null) + return assembly; + } - static readonly string [] _extentions = new string [] { ".dll", ".exe" }; + throw new AssemblyResolutionException (name); + } - static AssemblyDefinition SearchDirectory (AssemblyNameReference name, IEnumerable directories) + AssemblyDefinition SearchDirectory (AssemblyNameReference name, IEnumerable directories, ReaderParameters parameters) { - foreach (string dir in directories) { - foreach (string ext in _extentions) { - string file = Path.Combine (dir, name.Name + ext); + var extensions = new [] { ".exe", ".dll" }; + foreach (var directory in directories) { + foreach (var extension in extensions) { + string file = Path.Combine (directory, name.Name + extension); if (File.Exists (file)) - return AssemblyFactory.GetAssembly (file); + return GetAssembly (file, parameters); } } @@ -116,100 +198,165 @@ namespace Mono.Cecil { static bool IsZero (Version version) { - return version.Major == 0 && version.Minor == 0 && version.Build == 0 && version.Revision == 0; + return version == null || (version.Major == 0 && version.Minor == 0 && version.Build == 0 && version.Revision == 0); } -#if !CF_1_0 && !CF_2_0 - static AssemblyDefinition GetCorlib (AssemblyNameReference reference) +#if !SILVERLIGHT && !CF + AssemblyDefinition GetCorlib (AssemblyNameReference reference, ReaderParameters parameters) { - SR.AssemblyName corlib = typeof (object).Assembly.GetName (); - if (corlib.Version == reference.Version || IsZero (reference.Version)) - return AssemblyFactory.GetAssembly (typeof (object).Module.FullyQualifiedName); + var version = reference.Version; + var corlib = typeof (object).Assembly.GetName (); - string path = Directory.GetParent ( + if (corlib.Version == version || IsZero (version)) + return GetAssembly (typeof (object).Module.FullyQualifiedName, parameters); + + var path = Directory.GetParent ( Directory.GetParent ( typeof (object).Module.FullyQualifiedName).FullName ).FullName; - if (OnMono ()) { - if (reference.Version.Major == 1) + if (on_mono) { + if (version.Major == 1) path = Path.Combine (path, "1.0"); - else if (reference.Version.Major == 2) { - if (reference.Version.Minor == 1) + else if (version.Major == 2) { + if (version.MajorRevision == 5) path = Path.Combine (path, "2.1"); else path = Path.Combine (path, "2.0"); - } else - throw new NotSupportedException ("Version not supported: " + reference.Version); + } else if (version.Major == 4) + path = Path.Combine (path, "4.0"); + else + throw new NotSupportedException ("Version not supported: " + version); } else { - if (reference.Version.ToString () == "1.0.3300.0") - path = Path.Combine (path, "v1.0.3705"); - else if (reference.Version.ToString () == "1.0.5000.0") - path = Path.Combine (path, "v1.1.4322"); - else if (reference.Version.ToString () == "2.0.0.0") + switch (version.Major) { + case 1: + if (version.MajorRevision == 3300) + path = Path.Combine (path, "v1.0.3705"); + else + path = Path.Combine (path, "v1.0.5000.0"); + break; + case 2: path = Path.Combine (path, "v2.0.50727"); - else if (reference.Version.ToString () == "4.0.0.0") - path = Path.Combine (path, "v4.0.20506"); - else - throw new NotSupportedException ("Version not supported: " + reference.Version); + break; + case 4: + path = Path.Combine (path, "v4.0.30319"); + break; + default: + throw new NotSupportedException ("Version not supported: " + version); + } } - if (File.Exists (Path.Combine (path, "mscorlib.dll"))) - return AssemblyFactory.GetAssembly (Path.Combine (path, "mscorlib.dll")); + var file = Path.Combine (path, "mscorlib.dll"); + if (File.Exists (file)) + return GetAssembly (file, parameters); return null; } - public static bool OnMono () + static Collection GetGacPaths () + { + if (on_mono) + return GetDefaultMonoGacPaths (); + + var paths = new Collection (2); + var windir = Environment.GetEnvironmentVariable ("WINDIR"); + if (windir == null) + return paths; + + paths.Add (Path.Combine (windir, "assembly")); + paths.Add (Path.Combine (windir, Path.Combine ("Microsoft.NET", "assembly"))); + return paths; + } + + static Collection GetDefaultMonoGacPaths () + { + var paths = new Collection (1); + var gac = GetCurrentMonoGac (); + if (gac != null) + paths.Add (gac); + + var gac_paths_env = Environment.GetEnvironmentVariable ("MONO_GAC_PREFIX"); + if (string.IsNullOrEmpty (gac_paths_env)) + return paths; + + var prefixes = gac_paths_env.Split (Path.PathSeparator); + foreach (var prefix in prefixes) { + if (string.IsNullOrEmpty (prefix)) + continue; + + var gac_path = Path.Combine (Path.Combine (Path.Combine (prefix, "lib"), "mono"), "gac"); + if (Directory.Exists (gac_path) && !paths.Contains (gac)) + paths.Add (gac_path); + } + + return paths; + } + + static string GetCurrentMonoGac () { - return typeof (object).Assembly.GetType ("System.MonoType", false) != null; + return Path.Combine ( + Directory.GetParent ( + Path.GetDirectoryName (typeof (object).Module.FullyQualifiedName)).FullName, + "gac"); } - static AssemblyDefinition GetAssemblyInGac (AssemblyNameReference reference) + AssemblyDefinition GetAssemblyInGac (AssemblyNameReference reference, ReaderParameters parameters) { if (reference.PublicKeyToken == null || reference.PublicKeyToken.Length == 0) return null; - string currentGac = GetCurrentGacPath (); - if (OnMono ()) { - string s = GetAssemblyFile (reference, currentGac); - if (File.Exists (s)) - return AssemblyFactory.GetAssembly (s); - } else { - string [] gacs = new string [] {"GAC_MSIL", "GAC_32", "GAC"}; - for (int i = 0; i < gacs.Length; i++) { - string gac = Path.Combine (Directory.GetParent (currentGac).FullName, gacs [i]); - string asm = GetAssemblyFile (reference, gac); - if (Directory.Exists (gac) && File.Exists (asm)) - return AssemblyFactory.GetAssembly (asm); + if (gac_paths == null) + gac_paths = GetGacPaths (); + + if (on_mono) + return GetAssemblyInMonoGac (reference, parameters); + + return GetAssemblyInNetGac (reference, parameters); + } + + AssemblyDefinition GetAssemblyInMonoGac (AssemblyNameReference reference, ReaderParameters parameters) + { + for (int i = 0; i < gac_paths.Count; i++) { + var gac_path = gac_paths [i]; + var file = GetAssemblyFile (reference, string.Empty, gac_path); + if (File.Exists (file)) + return GetAssembly (file, parameters); + } + + return null; + } + + AssemblyDefinition GetAssemblyInNetGac (AssemblyNameReference reference, ReaderParameters parameters) + { + var gacs = new [] { "GAC_MSIL", "GAC_32", "GAC" }; + var prefixes = new [] { string.Empty, "v4.0_" }; + + for (int i = 0; i < 2; i++) { + for (int j = 0; j < gacs.Length; j++) { + var gac = Path.Combine (gac_paths [i], gacs [j]); + var file = GetAssemblyFile (reference, prefixes [i], gac); + if (Directory.Exists (gac) && File.Exists (file)) + return GetAssembly (file, parameters); } } return null; } - static string GetAssemblyFile (AssemblyNameReference reference, string gac) + static string GetAssemblyFile (AssemblyNameReference reference, string prefix, string gac) { - StringBuilder sb = new StringBuilder (); - sb.Append (reference.Version); - sb.Append ("__"); + var gac_folder = new StringBuilder () + .Append (prefix) + .Append (reference.Version) + .Append ("__"); + for (int i = 0; i < reference.PublicKeyToken.Length; i++) - sb.Append (reference.PublicKeyToken [i].ToString ("x2")); + gac_folder.Append (reference.PublicKeyToken [i].ToString ("x2")); return Path.Combine ( Path.Combine ( - Path.Combine (gac, reference.Name), sb.ToString ()), - string.Concat (reference.Name, ".dll")); - } - - static string GetCurrentGacPath () - { - return Directory.GetParent ( - Directory.GetParent ( - Path.GetDirectoryName ( - typeof (Uri).Module.FullyQualifiedName) - ).FullName - ).FullName; + Path.Combine (gac, reference.Name), gac_folder.ToString ()), + reference.Name + ".dll"); } #endif }