7
// Copyright (C) 2007 Novell, Inc (http://www.novell.com)
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.
31
using System.Collections;
33
using System.Reflection;
34
using Mono.Addins.Description;
35
using Mono.Addins.Serialization;
36
using System.Collections.Generic;
38
namespace Mono.Addins.Database
43
static string monoVersion;
45
public static bool IsWindows {
46
get { return Path.DirectorySeparatorChar == '\\'; }
49
public static bool IsMono {
52
isMono = Type.GetType ("Mono.Runtime") != null ? 1 : -1;
57
public static string MonoVersion {
59
if (monoVersion == null) {
61
throw new InvalidOperationException ();
62
MethodInfo mi = Type.GetType ("Mono.Runtime").GetMethod ("GetDisplayName", BindingFlags.NonPublic|BindingFlags.Static);
64
monoVersion = (string) mi.Invoke (null, null);
66
monoVersion = string.Empty;
72
public static void CheckWrittableFloder (string path)
74
string testFile = null;
77
testFile = Path.Combine (path, new Random ().Next ().ToString ());
79
} while (File.Exists (testFile) && n < 100);
81
throw new InvalidOperationException ("Could not create file in directory: " + path);
83
StreamWriter w = new StreamWriter (testFile);
85
File.Delete (testFile);
88
public static void AddDependencies (AddinDescription desc, AddinScanResult scanResult)
90
// Not implemented in AddinScanResult to avoid making AddinDescription remotable
91
foreach (ModuleDescription mod in desc.AllModules) {
92
foreach (Dependency dep in mod.Dependencies) {
93
AddinDependency adep = dep as AddinDependency;
94
if (adep == null) continue;
95
string depid = Addin.GetFullId (desc.Namespace, adep.AddinId, adep.Version);
96
scanResult.AddAddinToUpdateRelations (depid);
101
public static Assembly LoadAssemblyForReflection (string fileName)
103
/* if (!gotLoadMethod) {
104
reflectionOnlyLoadFrom = typeof(Assembly).GetMethod ("ReflectionOnlyLoadFrom");
105
gotLoadMethod = true;
106
LoadAssemblyForReflection (typeof(Util).Assembly.Location);
109
if (reflectionOnlyLoadFrom != null)
110
return (Assembly) reflectionOnlyLoadFrom.Invoke (null, new string [] { fileName });
112
*/ return Assembly.LoadFile (fileName);
115
public static string NormalizePath (string path)
117
if (path.Length > 2 && path [0] == '[') {
118
int i = path.IndexOf (']', 1);
121
string fname = path.Substring (1, i - 1);
122
Environment.SpecialFolder sf = (Environment.SpecialFolder) Enum.Parse (typeof(Environment.SpecialFolder), fname, true);
123
path = Environment.GetFolderPath (sf) + path.Substring (i + 1);
130
return path.Replace ('/','\\');
132
return path.Replace ('\\','/');
135
// A private hash calculation method is used to be able to get consistent
136
// results across different .NET versions and implementations.
137
public static int GetStringHashCode (string s)
141
for (; n < s.Length - 1; n+=2) {
142
h = unchecked ((h << 5) - h + s[n]);
143
h = unchecked ((h << 5) - h + s[n+1]);
146
h = unchecked ((h << 5) - h + s[n]);
150
public static string GetGacPath (string fullName)
152
string[] parts = fullName.Split (',');
153
if (parts.Length != 4) return null;
154
string name = parts[0].Trim ();
156
int i = parts[1].IndexOf ('=');
157
string version = i != -1 ? parts[1].Substring (i+1).Trim () : parts[1].Trim ();
159
i = parts[2].IndexOf ('=');
160
string culture = i != -1 ? parts[2].Substring (i+1).Trim () : parts[2].Trim ();
161
if (culture == "neutral") culture = "";
163
i = parts[3].IndexOf ('=');
164
string token = i != -1 ? parts[3].Substring (i+1).Trim () : parts[3].Trim ();
166
string versionDirName = version + "_" + culture + "_" + token;
169
string gacDir = typeof(Uri).Assembly.Location;
170
gacDir = Path.GetDirectoryName (gacDir);
171
gacDir = Path.GetDirectoryName (gacDir);
172
gacDir = Path.GetDirectoryName (gacDir);
173
string dir = Path.Combine (gacDir, name);
174
return Path.Combine (dir, versionDirName);
176
// .NET 4.0 introduces a new GAC directory structure and location.
177
// Assembly version directory names are now prefixed with the CLR version
178
// Since there can be different assembly versions for different target CLR runtimes,
179
// we now look for the best match, that is, the assembly with the higher CLR version
181
var currentVersion = new Version (Environment.Version.Major, Environment.Version.Minor);
183
foreach (var gacDir in GetDotNetGacDirectories ()) {
184
var asmDir = Path.Combine (gacDir, name);
185
if (!Directory.Exists (asmDir))
187
Version bestVersion = new Version (0, 0);
188
string bestDir = null;
189
foreach (var dir in Directory.GetDirectories (asmDir, "v*_" + versionDirName)) {
190
var dirName = Path.GetFileName (dir);
191
i = dirName.IndexOf ('_');
193
if (Version.TryParse (dirName.Substring (1, i - 1), out av)) {
194
if (av == currentVersion)
196
else if (av < currentVersion && av > bestVersion) {
206
// Look in the old GAC. There are no CLR prefixes here
208
foreach (var gacDir in GetLegacyDotNetGacDirectories ()) {
209
var asmDir = Path.Combine (gacDir, name);
210
asmDir = Path.Combine (asmDir, versionDirName);
211
if (Directory.Exists (asmDir))
218
static IEnumerable<string> GetLegacyDotNetGacDirectories ()
220
var winDir = Path.GetFullPath (Environment.SystemDirectory + "\\..");
222
string gacDir = winDir + "\\assembly\\GAC";
223
if (Directory.Exists (gacDir))
225
if (Directory.Exists (gacDir + "_32"))
226
yield return gacDir + "_32";
227
if (Directory.Exists (gacDir + "_64"))
228
yield return gacDir + "_64";
229
if (Directory.Exists (gacDir + "_MSIL"))
230
yield return gacDir + "_MSIL";
233
static IEnumerable<string> GetDotNetGacDirectories ()
235
var winDir = Path.GetFullPath (Environment.SystemDirectory + "\\..");
237
string gacDir = winDir + "\\Microsoft.NET\\assembly\\GAC";
238
if (Directory.Exists (gacDir))
240
if (Directory.Exists (gacDir + "_32"))
241
yield return gacDir + "_32";
242
if (Directory.Exists (gacDir + "_64"))
243
yield return gacDir + "_64";
244
if (Directory.Exists (gacDir + "_MSIL"))
245
yield return gacDir + "_MSIL";