// // AssemblyResolver.cs // // Author: // Marek Sieradzki (marek.sieradzki@gmail.com) // // (C) 2006 Marek Sieradzki // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #if NET_2_0 using System; using System.Collections.Generic; using System.IO; using System.Reflection; using System.Security; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; namespace Microsoft.Build.Tasks { internal class AssemblyResolver { // name -> (version -> assemblypath) Dictionary > gac; Dictionary > hint_path_assemblies; Dictionary hint_paths; public AssemblyResolver () { gac = new Dictionary > (); hint_path_assemblies = new Dictionary > (); hint_paths = new Dictionary (); GatherGacAssemblies (); } string GetGacPath () { // NOTE: code from mcs/tools/gacutil/driver.cs PropertyInfo gac = typeof (System.Environment).GetProperty ("GacPath", BindingFlags.Static | BindingFlags.NonPublic); if (gac == null) return null; MethodInfo get_gac = gac.GetGetMethod (true); return (string) get_gac.Invoke (null, null); } void GatherGacAssemblies () { string gac_path = GetGacPath (); if (gac_path == null) throw new InvalidOperationException ("XBuild must be run on Mono runtime"); Version version; DirectoryInfo version_info, assembly_info; foreach (string assembly_name in Directory.GetDirectories (gac_path)) { assembly_info = new DirectoryInfo (assembly_name); foreach (string version_token in Directory.GetDirectories (assembly_name)) { foreach (string file in Directory.GetFiles (version_token, "*.dll")) { version_info = new DirectoryInfo (version_token); version = new Version (version_info.Name.Split ( new char [] {'_'}, StringSplitOptions.RemoveEmptyEntries) [0]); if (!gac.ContainsKey (assembly_info.Name)) gac.Add (assembly_info.Name, new Dictionary ()); gac [assembly_info.Name].Add (version, file); } } } } void GatherHintPathAssemblies (string hintPath) { if (hint_paths.ContainsKey (hintPath)) return; Assembly a; AssemblyName name; try { foreach (string assembly_name in Directory.GetFiles (Path.GetDirectoryName (hintPath))) { try { a = Assembly.ReflectionOnlyLoadFrom (assembly_name); name = new AssemblyName (a.FullName); if (!hint_path_assemblies.ContainsKey (name.Name)) hint_path_assemblies [name.Name] = new Dictionary (); hint_path_assemblies [name.Name] [name.Version] = assembly_name; hint_paths [hintPath] = null; } catch { } } } catch { } } public string ResolveAssemblyReference (ITaskItem reference) { AssemblyName name = null; string resolved = null; try { name = new AssemblyName (reference.ItemSpec); } catch { return null; } if (reference.GetMetadata ("HintPath") != String.Empty) resolved = ResolveHintPathReference (name, reference.GetMetadata ("HintPath")); if (resolved == null) resolved = ResolveGacReference (name); return resolved; } string ResolveGacReference (AssemblyName name) { return ResolveGenericReference (name, gac); } string ResolveHintPathReference (AssemblyName name, string hintpath) { if (hintpath != String.Empty) GatherHintPathAssemblies (hintpath); return ResolveGenericReference (name, hint_path_assemblies); } string ResolveGenericReference (AssemblyName name, Dictionary > dic) { // FIXME: deal with SpecificVersion=False if (!dic.ContainsKey (name.Name)) return null; if (name.Version != null) { if (!dic [name.Name].ContainsKey (name.Version)) return null; else return dic [name.Name] [name.Version]; } Version [] versions = new Version [dic [name.Name].Keys.Count]; dic [name.Name].Keys.CopyTo (versions, 0); Array.Sort (versions, (IComparer ) null); Version highest = versions [versions.Length - 1]; return dic [name.Name] [highest]; } } } #endif