Merge pull request #4464 from kumpera/backport-4454-2017-02
[mono-project.git] / mcs / tools / cil-strip / Mono.Cecil / BaseAssemblyResolver.cs
blobf661075f73e362d50a25d566da1cd04ececee98a
1 //
2 // BaseAssemblyResolver.cs
3 //
4 // Author:
5 // Jb Evain (jbevain@gmail.com)
6 //
7 // (C) 2005 Jb Evain
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 namespace Mono.Cecil {
31 using System;
32 using System.Collections;
33 using System.IO;
34 using SR = System.Reflection;
35 using System.Text;
37 internal abstract class BaseAssemblyResolver : IAssemblyResolver {
39 ArrayList m_directories;
40 string[] m_monoGacPaths;
42 public void AddSearchDirectory (string directory)
44 m_directories.Add (directory);
47 public void RemoveSearchDirectory (string directory)
49 m_directories.Remove (directory);
52 public string [] GetSearchDirectories ()
54 return (string []) m_directories.ToArray (typeof (string));
57 public virtual AssemblyDefinition Resolve (string fullName)
59 return Resolve (AssemblyNameReference.Parse (fullName));
62 public BaseAssemblyResolver ()
64 m_directories = new ArrayList ();
65 m_directories.Add (".");
66 m_directories.Add ("bin");
69 public virtual AssemblyDefinition Resolve (AssemblyNameReference name)
71 AssemblyDefinition assembly;
72 string frameworkdir = Path.GetDirectoryName (typeof (object).Module.FullyQualifiedName);
74 assembly = SearchDirectory (name, m_directories);
75 if (assembly != null)
76 return assembly;
78 if (IsZero (name.Version)) {
79 assembly = SearchDirectory (name, new string [] {frameworkdir});
80 if (assembly != null)
81 return assembly;
84 #if !CF_1_0 && !CF_2_0 && !NO_SYSTEM_DLL
85 if (name.Name == "mscorlib") {
86 assembly = GetCorlib (name);
87 if (assembly != null)
88 return assembly;
91 assembly = GetAssemblyInGac (name);
92 if (assembly != null)
93 return assembly;
94 #endif
96 assembly = SearchDirectory (name, new string [] {frameworkdir});
97 if (assembly != null)
98 return assembly;
100 throw new FileNotFoundException ("Could not resolve: " + name);
103 static readonly string [] _extentions = new string [] { ".dll", ".exe" };
105 static AssemblyDefinition SearchDirectory (AssemblyNameReference name, IEnumerable directories)
107 foreach (string dir in directories) {
108 foreach (string ext in _extentions) {
109 string file = Path.Combine (dir, name.Name + ext);
110 if (File.Exists (file))
111 return AssemblyFactory.GetAssembly (file);
115 return null;
118 static bool IsZero (Version version)
120 return version.Major == 0 && version.Minor == 0 && version.Build == 0 && version.Revision == 0;
123 #if !CF_1_0 && !CF_2_0 && !NO_SYSTEM_DLL
124 static AssemblyDefinition GetCorlib (AssemblyNameReference reference)
126 SR.AssemblyName corlib = typeof (object).Assembly.GetName ();
127 if (corlib.Version == reference.Version || IsZero (reference.Version))
128 return AssemblyFactory.GetAssembly (typeof (object).Module.FullyQualifiedName);
130 string path = Directory.GetParent (
131 Directory.GetParent (
132 typeof (object).Module.FullyQualifiedName).FullName
133 ).FullName;
135 string runtime_path = null;
136 if (OnMono ()) {
137 if (reference.Version.Major == 1)
138 runtime_path = "1.0";
139 else if (reference.Version.Major == 2) {
140 if (reference.Version.Minor == 1)
141 runtime_path = "2.1";
142 else
143 runtime_path = "2.0";
144 } else if (reference.Version.Major == 4)
145 runtime_path = "4.0";
146 } else {
147 switch (reference.Version.ToString ()) {
148 case "1.0.3300.0":
149 runtime_path = "v1.0.3705";
150 break;
151 case "1.0.5000.0":
152 runtime_path = "v1.1.4322";
153 break;
154 case "2.0.0.0":
155 runtime_path = "v2.0.50727";
156 break;
157 case "4.0.0.0":
158 runtime_path = "v4.0.30319";
159 break;
163 if (runtime_path == null)
164 throw new NotSupportedException ("Version not supported: " + reference.Version);
166 path = Path.Combine (path, runtime_path);
168 if (File.Exists (Path.Combine (path, "mscorlib.dll")))
169 return AssemblyFactory.GetAssembly (Path.Combine (path, "mscorlib.dll"));
171 return null;
174 public static bool OnMono ()
176 return typeof (object).Assembly.GetType ("System.MonoType", false) != null;
179 string[] MonoGacPaths {
180 get {
181 if (m_monoGacPaths == null)
182 m_monoGacPaths = GetDefaultMonoGacPaths ();
183 return m_monoGacPaths;
187 static string[] GetDefaultMonoGacPaths ()
189 ArrayList paths = new ArrayList ();
190 string s = GetCurrentGacPath ();
191 if (s != null)
192 paths.Add (s);
193 string gacPathsEnv = Environment.GetEnvironmentVariable ("MONO_GAC_PREFIX");
194 if (gacPathsEnv != null && gacPathsEnv.Length > 0) {
195 string[] gacPrefixes = gacPathsEnv.Split (Path.PathSeparator);
196 foreach (string gacPrefix in gacPrefixes) {
197 if (gacPrefix != null && gacPrefix.Length > 0) {
198 string gac = Path.Combine (Path.Combine (Path.Combine (gacPrefix, "lib"), "mono"), "gac");
199 if (Directory.Exists (gac) && !paths.Contains (gac))
200 paths.Add (gac);
204 return (string[]) paths.ToArray (typeof (String));
207 AssemblyDefinition GetAssemblyInGac (AssemblyNameReference reference)
209 if (reference.PublicKeyToken == null || reference.PublicKeyToken.Length == 0)
210 return null;
212 if (OnMono ()) {
213 foreach (string gacpath in MonoGacPaths) {
214 string s = GetAssemblyFile (reference, gacpath);
215 if (File.Exists (s))
216 return AssemblyFactory.GetAssembly (s);
218 } else {
219 string currentGac = GetCurrentGacPath ();
220 if (currentGac == null)
221 return null;
223 string [] gacs = new string [] {"GAC_MSIL", "GAC_32", "GAC"};
224 for (int i = 0; i < gacs.Length; i++) {
225 string gac = Path.Combine (Directory.GetParent (currentGac).FullName, gacs [i]);
226 string asm = GetAssemblyFile (reference, gac);
227 if (Directory.Exists (gac) && File.Exists (asm))
228 return AssemblyFactory.GetAssembly (asm);
232 return null;
235 static string GetAssemblyFile (AssemblyNameReference reference, string gac)
237 StringBuilder sb = new StringBuilder ();
238 sb.Append (reference.Version);
239 sb.Append ("__");
240 for (int i = 0; i < reference.PublicKeyToken.Length; i++)
241 sb.Append (reference.PublicKeyToken [i].ToString ("x2"));
243 return Path.Combine (
244 Path.Combine (
245 Path.Combine (gac, reference.Name), sb.ToString ()),
246 string.Concat (reference.Name, ".dll"));
249 static string GetCurrentGacPath ()
251 string file = typeof (Uri).Module.FullyQualifiedName;
252 if (!File.Exists (file))
253 return null;
255 return Directory.GetParent (
256 Directory.GetParent (
257 Path.GetDirectoryName (
258 file)
259 ).FullName
260 ).FullName;
262 #endif