зеркало из https://github.com/mono/ikvm-fork.git
291 строка
7.3 KiB
C#
291 строка
7.3 KiB
C#
/*
|
|
Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Jeroen Frijters
|
|
|
|
This software is provided 'as-is', without any express or implied
|
|
warranty. In no event will the authors be held liable for any damages
|
|
arising from the use of this software.
|
|
|
|
Permission is granted to anyone to use this software for any purpose,
|
|
including commercial applications, and to alter it and redistribute it
|
|
freely, subject to the following restrictions:
|
|
|
|
1. The origin of this software must not be misrepresented; you must not
|
|
claim that you wrote the original software. If you use this software
|
|
in a product, an acknowledgment in the product documentation would be
|
|
appreciated but is not required.
|
|
2. Altered source versions must be plainly marked as such, and must not be
|
|
misrepresented as being the original software.
|
|
3. This notice may not be removed or altered from any source distribution.
|
|
|
|
Jeroen Frijters
|
|
jeroen@frijters.net
|
|
|
|
*/
|
|
using System;
|
|
using System.Threading;
|
|
using System.Reflection;
|
|
using System.IO;
|
|
using System.Collections;
|
|
using System.Diagnostics;
|
|
using System.Text;
|
|
using System.Security;
|
|
using System.Security.Permissions;
|
|
using IKVM.Attributes;
|
|
using IKVM.Internal;
|
|
|
|
#if !STATIC_COMPILER && !COMPACT_FRAMEWORK
|
|
namespace IKVM.Internal
|
|
{
|
|
public sealed class Starter
|
|
{
|
|
private Starter() {}
|
|
|
|
public static void PrepareForSaveDebugImage()
|
|
{
|
|
JVM.IsSaveDebugImage = true;
|
|
}
|
|
|
|
public static void SaveDebugImage()
|
|
{
|
|
DynamicClassLoader.Instance.SaveDebugImage();
|
|
}
|
|
|
|
public static bool EnableReflectionOnMethodsWithUnloadableTypeParameters
|
|
{
|
|
get
|
|
{
|
|
return JVM.EnableReflectionOnMethodsWithUnloadableTypeParameters;
|
|
}
|
|
set
|
|
{
|
|
JVM.EnableReflectionOnMethodsWithUnloadableTypeParameters = value;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif // !STATIC_COMPILER && !COMPACT_FRAMEWORK
|
|
|
|
namespace IKVM.Internal
|
|
{
|
|
class JVM
|
|
{
|
|
#if STATIC_COMPILER
|
|
internal const bool IsStaticCompiler = true;
|
|
internal const bool FinishingForDebugSave = false;
|
|
internal const bool IsSaveDebugImage = false;
|
|
#else
|
|
internal const bool IsStaticCompiler = false;
|
|
private static bool enableReflectionOnMethodsWithUnloadableTypeParameters;
|
|
private static bool finishingForDebugSave;
|
|
#if !FIRST_PASS
|
|
private static ikvm.@internal.LibraryVMInterface lib;
|
|
#endif
|
|
internal static bool IsSaveDebugImage;
|
|
#endif // STATIC_COMPILER
|
|
private static Assembly coreAssembly;
|
|
|
|
internal static Version SafeGetAssemblyVersion(Assembly asm)
|
|
{
|
|
// Assembly.GetName().Version requires FileIOPermission,
|
|
// so we parse the FullName manually :-(
|
|
string name = asm.FullName;
|
|
int start = name.IndexOf(", Version=");
|
|
if(start >= 0)
|
|
{
|
|
start += 10;
|
|
int end = name.IndexOf(',', start);
|
|
if(end >= 0)
|
|
{
|
|
return new Version(name.Substring(start, end - start));
|
|
}
|
|
}
|
|
return new Version();
|
|
}
|
|
|
|
internal static string SafeGetEnvironmentVariable(string name)
|
|
{
|
|
try
|
|
{
|
|
return Environment.GetEnvironmentVariable(name);
|
|
}
|
|
catch(SecurityException)
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
|
|
internal static Assembly CoreAssembly
|
|
{
|
|
get
|
|
{
|
|
#if !STATIC_COMPILER
|
|
if(coreAssembly == null)
|
|
{
|
|
#if FIRST_PASS
|
|
throw new InvalidOperationException("This version of IKVM.Runtime.dll was compiled with FIRST_PASS defined.");
|
|
#else
|
|
coreAssembly = typeof(ikvm.@internal.Library).Assembly;
|
|
#endif
|
|
}
|
|
#endif // !STATIC_COMPILER
|
|
return coreAssembly;
|
|
}
|
|
set
|
|
{
|
|
coreAssembly = value;
|
|
}
|
|
}
|
|
|
|
#if !STATIC_COMPILER
|
|
internal static ikvm.@internal.LibraryVMInterface Library
|
|
{
|
|
get
|
|
{
|
|
#if FIRST_PASS
|
|
throw new InvalidOperationException("This version of IKVM.Runtime.dll was compiled with FIRST_PASS defined.");
|
|
#else
|
|
if(lib == null)
|
|
{
|
|
lib = ikvm.@internal.Library.getImpl();
|
|
}
|
|
return lib;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
public static bool EnableReflectionOnMethodsWithUnloadableTypeParameters
|
|
{
|
|
get
|
|
{
|
|
return enableReflectionOnMethodsWithUnloadableTypeParameters;
|
|
}
|
|
set
|
|
{
|
|
enableReflectionOnMethodsWithUnloadableTypeParameters = value;
|
|
}
|
|
}
|
|
|
|
internal static bool FinishingForDebugSave
|
|
{
|
|
get
|
|
{
|
|
return finishingForDebugSave;
|
|
}
|
|
set
|
|
{
|
|
finishingForDebugSave = value;
|
|
}
|
|
}
|
|
#endif // !STATIC_COMPILER
|
|
|
|
internal static bool IsUnix
|
|
{
|
|
get
|
|
{
|
|
#if WHIDBEY
|
|
return Environment.OSVersion.Platform == PlatformID.Unix;
|
|
#else
|
|
PlatformID pid = Environment.OSVersion.Platform;
|
|
return pid != PlatformID.Win32NT && pid != PlatformID.Win32S && pid != PlatformID.Win32Windows && pid != PlatformID.WinCE;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
internal static string MangleResourceName(string name)
|
|
{
|
|
// FXBUG there really shouldn't be any need to mangle the resource names,
|
|
// but in order for ILDASM/ILASM round tripping to work reliably, we have
|
|
// to make sure that we don't produce resource names that'll cause ILDASM
|
|
// to generate invalid filenames.
|
|
StringBuilder sb = new StringBuilder("ikvm__", name.Length + 6);
|
|
foreach(char c in name)
|
|
{
|
|
if("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-+.()$#@~=&{}[]0123456789`".IndexOf(c) != -1)
|
|
{
|
|
sb.Append(c);
|
|
}
|
|
else if(c == '/')
|
|
{
|
|
sb.Append('!');
|
|
}
|
|
else
|
|
{
|
|
sb.Append('%');
|
|
sb.Append(string.Format("{0:X4}", (int)c));
|
|
}
|
|
}
|
|
return sb.ToString();
|
|
}
|
|
|
|
internal static void CriticalFailure(string message, Exception x)
|
|
{
|
|
try
|
|
{
|
|
Tracer.Error(Tracer.Runtime, "CRITICAL FAILURE: {0}", message);
|
|
Type messageBox = null;
|
|
#if !STATIC_COMPILER
|
|
// NOTE we use reflection to invoke MessageBox.Show, to make sure we run in environments where WinForms isn't available
|
|
Assembly winForms = IsUnix ? null : Assembly.Load("System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");
|
|
if(winForms != null)
|
|
{
|
|
messageBox = winForms.GetType("System.Windows.Forms.MessageBox");
|
|
}
|
|
#endif
|
|
new ReflectionPermission(ReflectionPermissionFlag.MemberAccess
|
|
#if !WHIDBEY
|
|
| ReflectionPermissionFlag.TypeInformation
|
|
#endif
|
|
).Assert();
|
|
message = String.Format("****** Critical Failure: {1} ******{0}{0}" +
|
|
"PLEASE FILE A BUG REPORT FOR IKVM.NET WHEN YOU SEE THIS MESSAGE{0}{0}" +
|
|
(messageBox != null ? "(on Windows you can use Ctrl+C to copy the contents of this message to the clipboard){0}{0}" : "") +
|
|
"{2}{0}" +
|
|
"{3}{0}" +
|
|
"{4}",
|
|
Environment.NewLine,
|
|
message,
|
|
x,
|
|
x != null ? new StackTrace(x, true).ToString() : "",
|
|
new StackTrace(true));
|
|
CodeAccessPermission.RevertAssert();
|
|
if(messageBox != null)
|
|
{
|
|
try
|
|
{
|
|
Version ver = SafeGetAssemblyVersion(typeof(JVM).Assembly);
|
|
messageBox.InvokeMember("Show", BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.Public, null, null, new object[] { message, "IKVM.NET " + ver + " Critical Failure" });
|
|
}
|
|
catch
|
|
{
|
|
Console.Error.WriteLine(message);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Console.Error.WriteLine(message);
|
|
}
|
|
}
|
|
catch(Exception ex)
|
|
{
|
|
Console.Error.WriteLine(ex);
|
|
}
|
|
finally
|
|
{
|
|
Environment.Exit(666);
|
|
}
|
|
}
|
|
|
|
// this method resolves types in IKVM.Runtime.dll
|
|
// (the version of IKVM.Runtime.dll that we're running
|
|
// with can be different from the one we're compiling against.)
|
|
internal static Type LoadType(Type type)
|
|
{
|
|
#if WHIDBEY && STATIC_COMPILER
|
|
return StaticCompiler.GetType(type.FullName);
|
|
#else
|
|
return type;
|
|
#endif
|
|
}
|
|
}
|
|
}
|