ikvm-fork/runtime/classpath.cs

1549 строки
42 KiB
C#

/*
Copyright (C) 2002, 2003, 2004 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.Collections;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using System.Text;
using System.Security.Permissions;
using IKVM.Attributes;
using IKVM.Runtime;
using IKVM.Internal;
using NetSystem = System;
namespace IKVM.NativeCode.java
{
namespace lang
{
namespace reflect
{
public class Proxy
{
// NOTE not used, only here to shut up ikvmc during compilation of IKVM.GNU.Classpath.dll
public static object getProxyClass0(object o1, object o2)
{
throw new InvalidOperationException();
}
// NOTE not used, only here to shut up ikvmc during compilation of IKVM.GNU.Classpath.dll
public static object getProxyData0(object o1, object o2)
{
throw new InvalidOperationException();
}
// NOTE not used, only here to shut up ikvmc during compilation of IKVM.GNU.Classpath.dll
public static object generateProxyClass0(object o1, object o2)
{
throw new InvalidOperationException();
}
}
public class Array
{
public static object createObjectArray(object clazz, int dim)
{
if(dim >= 0)
{
return NetSystem.Array.CreateInstance(VMClass.getWrapperFromClass(clazz).TypeAsArrayType, dim);
}
throw JavaException.NegativeArraySizeException();
}
}
internal class JavaWrapper
{
private static Type java_lang_Byte = ClassLoaderWrapper.LoadClassCritical("java.lang.Byte").TypeAsTBD;
private static Type java_lang_Boolean = ClassLoaderWrapper.LoadClassCritical("java.lang.Boolean").TypeAsTBD;
private static Type java_lang_Short = ClassLoaderWrapper.LoadClassCritical("java.lang.Short").TypeAsTBD;
private static Type java_lang_Character = ClassLoaderWrapper.LoadClassCritical("java.lang.Character").TypeAsTBD;
private static Type java_lang_Integer = ClassLoaderWrapper.LoadClassCritical("java.lang.Integer").TypeAsTBD;
private static Type java_lang_Long = ClassLoaderWrapper.LoadClassCritical("java.lang.Long").TypeAsTBD;
private static Type java_lang_Float = ClassLoaderWrapper.LoadClassCritical("java.lang.Float").TypeAsTBD;
private static Type java_lang_Double = ClassLoaderWrapper.LoadClassCritical("java.lang.Double").TypeAsTBD;
internal static object Box(object o)
{
if(o is sbyte)
{
return Activator.CreateInstance(java_lang_Byte, new object[] { o });
}
else if(o is byte)
{
return Activator.CreateInstance(java_lang_Byte, new object[] { (sbyte)(byte)o });
}
else if(o is bool)
{
return Activator.CreateInstance(java_lang_Boolean, new object[] { o });
}
else if(o is short)
{
return Activator.CreateInstance(java_lang_Short, new object[] { o });
}
else if(o is ushort)
{
return Activator.CreateInstance(java_lang_Short, new object[] { (short)(ushort)o });
}
else if(o is char)
{
return Activator.CreateInstance(java_lang_Character, new object[] { o });
}
else if(o is int)
{
return Activator.CreateInstance(java_lang_Integer, new object[] { o });
}
else if(o is uint)
{
return Activator.CreateInstance(java_lang_Integer, new object[] { (int)(uint)o });
}
else if(o is long)
{
return Activator.CreateInstance(java_lang_Long, new object[] { o });
}
else if(o is ulong)
{
return Activator.CreateInstance(java_lang_Long, new object[] { (long)(ulong)o });
}
else if(o is float)
{
return Activator.CreateInstance(java_lang_Float, new object[] { o });
}
else if(o is double)
{
return Activator.CreateInstance(java_lang_Double, new object[] { o });
}
else if(o is Enum)
{
Type enumType = Enum.GetUnderlyingType(o.GetType());
if(enumType == typeof(byte) || enumType == typeof(sbyte))
{
return JavaWrapper.Box((sbyte)((IConvertible)o).ToInt32(null));
}
else if(enumType == typeof(short) || enumType == typeof(ushort))
{
return JavaWrapper.Box((short)((IConvertible)o).ToInt32(null));
}
else if(enumType == typeof(int))
{
return JavaWrapper.Box(((IConvertible)o).ToInt32(null));
}
else if(enumType == typeof(uint))
{
return JavaWrapper.Box(unchecked((int)((IConvertible)o).ToUInt32(null)));
}
else if(enumType == typeof(long))
{
return JavaWrapper.Box(((IConvertible)o).ToInt64(null));
}
else if(enumType == typeof(ulong))
{
return JavaWrapper.Box(unchecked((long)((IConvertible)o).ToUInt64(null)));
}
else
{
throw new InvalidOperationException();
}
}
else
{
throw new NotImplementedException(o.GetType().FullName);
}
}
internal static object Unbox(object o)
{
Type type = o.GetType();
if(type == java_lang_Byte)
{
return java_lang_Byte.GetMethod("byteValue").Invoke(o, new object[0]);
}
else if(type == java_lang_Boolean)
{
return java_lang_Boolean.GetMethod("booleanValue").Invoke(o, new object[0]);
}
else if(type == java_lang_Short)
{
return java_lang_Short.GetMethod("shortValue").Invoke(o, new object[0]);
}
else if(type == java_lang_Character)
{
return java_lang_Character.GetMethod("charValue").Invoke(o, new object[0]);
}
else if(type == java_lang_Integer)
{
return java_lang_Integer.GetMethod("intValue").Invoke(o, new object[0]);
}
else if(type == java_lang_Long)
{
return java_lang_Long.GetMethod("longValue").Invoke(o, new object[0]);
}
else if(type == java_lang_Float)
{
return java_lang_Float.GetMethod("floatValue").Invoke(o, new object[0]);
}
else if(type == java_lang_Double)
{
return java_lang_Double.GetMethod("doubleValue").Invoke(o, new object[0]);
}
else
{
throw JavaException.IllegalArgumentException(type.FullName);
}
}
}
public class Method
{
public static String GetName(object methodCookie)
{
MethodWrapper wrapper = (MethodWrapper)methodCookie;
return wrapper.Name;
}
public static int GetModifiers(object methodCookie)
{
MethodWrapper wrapper = (MethodWrapper)methodCookie;
return (int)wrapper.Modifiers;
}
public static object GetReturnType(object methodCookie)
{
MethodWrapper wrapper = (MethodWrapper)methodCookie;
TypeWrapper retType = wrapper.ReturnType;
// HACK we should have a better plan than this
if(retType.IsUnloadable)
{
retType = wrapper.DeclaringType.GetClassLoader().FieldTypeWrapperFromSig(retType.SigName);
}
return VMClass.getClassFromWrapper(retType);
}
public static object[] GetParameterTypes(object methodCookie)
{
MethodWrapper wrapper = (MethodWrapper)methodCookie;
TypeWrapper[] parameters = wrapper.GetParameters();
object[] parameterClasses = new object[parameters.Length];
for(int i = 0; i < parameters.Length; i++)
{
TypeWrapper paramType = parameters[i];
// HACK we should have a better plan than this
if(paramType.IsUnloadable)
{
paramType = wrapper.DeclaringType.GetClassLoader().FieldTypeWrapperFromSig(paramType.SigName);
}
parameterClasses[i] = VMClass.getClassFromWrapper(paramType);
}
return parameterClasses;
}
public static string[] GetExceptionTypes(object methodCookie)
{
try
{
MethodWrapper wrapper = (MethodWrapper)methodCookie;
wrapper.DeclaringType.Finish();
return wrapper.GetExceptions();
}
catch(RetargetableJavaException x)
{
throw x.ToJava();
}
}
[HideFromJava]
public static object Invoke(object methodCookie, object o, object[] args)
{
try
{
object[] argsCopy = new Object[args != null ? args.Length : 0];
MethodWrapper mw = (MethodWrapper)methodCookie;
mw.DeclaringType.Finish();
TypeWrapper[] argWrappers = mw.GetParameters();
for(int i = 0; i < argWrappers.Length; i++)
{
if(argWrappers[i].IsPrimitive)
{
if(args[i] == null)
{
throw JavaException.IllegalArgumentException("primitive wrapper null");
}
argsCopy[i] = JavaWrapper.Unbox(args[i]);
}
else
{
argsCopy[i] = args[i];
}
}
object retval = mw.Invoke(o, argsCopy, false);
if(mw.ReturnType.IsPrimitive && mw.ReturnType != PrimitiveTypeWrapper.VOID)
{
retval = JavaWrapper.Box(retval);
}
return retval;
}
catch(RetargetableJavaException x)
{
throw x.ToJava();
}
}
}
public class Field
{
public static string GetName(object fieldCookie)
{
FieldWrapper wrapper = (FieldWrapper)fieldCookie;
return wrapper.Name;
}
public static int GetModifiers(object fieldCookie)
{
FieldWrapper wrapper = (FieldWrapper)fieldCookie;
return (int)wrapper.Modifiers;
}
public static object GetFieldType(object fieldCookie)
{
FieldWrapper wrapper = (FieldWrapper)fieldCookie;
TypeWrapper fieldType = wrapper.FieldTypeWrapper;
// HACK we should have a better plan than this
if(fieldType.IsUnloadable)
{
fieldType = wrapper.DeclaringType.GetClassLoader().FieldTypeWrapperFromSig(fieldType.SigName);
}
return VMClass.getClassFromWrapper(fieldType);
}
public static bool isSamePackage(object a, object b)
{
return VMClass.getWrapperFromClass(a).IsInSamePackageAs(VMClass.getWrapperFromClass(b));
}
public static object getClassFromFrame(NetSystem.Diagnostics.StackFrame frame)
{
Type type = frame.GetMethod().DeclaringType;
if(type == null)
{
return null;
}
return VMClass.getClassFromType(type);
}
public static object GetValue(object fieldCookie, object o)
{
Profiler.Enter("Field.GetValue");
try
{
FieldWrapper wrapper = (FieldWrapper)fieldCookie;
object val = wrapper.GetValue(o);
if(wrapper.FieldTypeWrapper.IsPrimitive)
{
val = JavaWrapper.Box(val);
}
return val;
}
finally
{
Profiler.Leave("Field.GetValue");
}
}
public static void SetValue(object fieldCookie, object o, object v)
{
Profiler.Enter("Field.SetValue");
try
{
FieldWrapper wrapper = (FieldWrapper)fieldCookie;
if(wrapper.IsFinal)
{
// NOTE Java runs the class initializer when trying to set a final field
wrapper.DeclaringType.RunClassInit();
// NOTE even if the caller is the class itself, it still isn't legal
throw JavaException.IllegalAccessException("Field is final");
}
if(wrapper.FieldTypeWrapper.IsPrimitive)
{
v = JavaWrapper.Unbox(v);
}
wrapper.SetValue(o, v);
}
finally
{
Profiler.Leave("Field.SetValue");
}
}
}
}
public class VMRuntime
{
public static string getVersion()
{
return typeof(VMRuntime).Assembly.GetName().Version.ToString();
}
public static int nativeLoad(string filename)
{
return IKVM.Runtime.JniHelper.LoadLibrary(filename);
}
}
public class Math
{
public static double pow(double x, double y)
{
return NetSystem.Math.Pow(x, y);
}
public static double exp(double d)
{
return NetSystem.Math.Exp(d);
}
public static double rint(double d)
{
return NetSystem.Math.Round(d);
}
public static double IEEEremainder(double f1, double f2)
{
if(double.IsInfinity(f2) && !double.IsInfinity(f1))
{
return f1;
}
return NetSystem.Math.IEEERemainder(f1, f2);
}
public static double sqrt(double d)
{
return NetSystem.Math.Sqrt(d);
}
public static double floor(double d)
{
return NetSystem.Math.Floor(d);
}
public static double ceil(double d)
{
return NetSystem.Math.Ceiling(d);
}
public static double log(double d)
{
return NetSystem.Math.Log(d);
}
public static double sin(double d)
{
return NetSystem.Math.Sin(d);
}
public static double asin(double d)
{
return NetSystem.Math.Asin(d);
}
public static double cos(double d)
{
return NetSystem.Math.Cos(d);
}
public static double acos(double d)
{
return NetSystem.Math.Acos(d);
}
public static double tan(double d)
{
return NetSystem.Math.Tan(d);
}
public static double atan(double d)
{
return NetSystem.Math.Atan(d);
}
public static double atan2(double y, double x)
{
if(double.IsInfinity(y) && double.IsInfinity(x))
{
if(double.IsPositiveInfinity(y))
{
if(double.IsPositiveInfinity(x))
{
return NetSystem.Math.PI / 4.0;
}
else
{
return NetSystem.Math.PI * 3.0 / 4.0;
}
}
else
{
if(double.IsPositiveInfinity(x))
{
return - NetSystem.Math.PI / 4.0;
}
else
{
return - NetSystem.Math.PI * 3.0 / 4.0;
}
}
}
return NetSystem.Math.Atan2(y, x);
}
}
public class Double
{
public static void initIDs()
{
}
public static double parseDouble(string s)
{
try
{
if(s.Trim() == "+Infinity")
{
return double.PositiveInfinity;
}
// TODO I doubt that this is correct
return double.Parse(s, System.Globalization.CultureInfo.InvariantCulture);
}
catch(FormatException x)
{
throw JavaException.NumberFormatException(x.Message);
}
}
public static string toString(double d, bool isFloat)
{
if(isFloat)
{
float f = (float)d;
// TODO this is not correct, we need to use the Java algorithm of converting a float to string
if(float.IsNaN(f))
{
return "NaN";
}
if(float.IsNegativeInfinity(f))
{
return "-Infinity";
}
if(float.IsPositiveInfinity(f))
{
return "Infinity";
}
// HACK really lame hack to apprioximate the Java behavior a little bit
string s = f.ToString(System.Globalization.CultureInfo.InvariantCulture);
if(s.IndexOf('.') == -1)
{
s += ".0";
}
// make sure -0.0 renders correctly
if(d == 0.0 && BitConverter.DoubleToInt64Bits(d) < 0)
{
return "-" + s;
}
return s;
}
else
{
StringBuilder sb = new StringBuilder();
DoubleToString.append(sb, d);
return sb.ToString();
}
}
}
public class VMSecurityManager
{
public static object getClassContext()
{
ArrayList ar = new ArrayList();
NetSystem.Diagnostics.StackTrace st = new NetSystem.Diagnostics.StackTrace();
for(int i = 0; i < st.FrameCount; i++)
{
NetSystem.Diagnostics.StackFrame frame = st.GetFrame(i);
// HACK very insecure
// TODO handle reflection scenario
if(frame.GetMethod().Name != "getClassContext")
{
Type type = frame.GetMethod().DeclaringType;
if(type != null)
{
ar.Add(VMClass.getClassFromType(type));
}
}
}
return ar.ToArray(CoreClasses.java.lang.Class.Wrapper.TypeAsArrayType);
}
public static object currentClassLoader()
{
// TODO handle PrivilegedAction
NetSystem.Diagnostics.StackTrace st = new NetSystem.Diagnostics.StackTrace();
for(int i = 0; i < st.FrameCount; i++)
{
NetSystem.Diagnostics.StackFrame frame = st.GetFrame(i);
Type type = frame.GetMethod().DeclaringType;
if(type != null)
{
TypeWrapper wrapper = ClassLoaderWrapper.GetWrapperFromTypeFast(type);
if(wrapper != null && wrapper.GetClassLoader().GetJavaClassLoader() != null)
{
return wrapper.GetClassLoader().GetJavaClassLoader();
}
}
}
return null;
}
}
public class VMSystem
{
public static void arraycopy(object src, int srcStart, object dest, int destStart, int len)
{
ByteCodeHelper.arraycopy(src, srcStart, dest, destStart, len);
}
public static void setErr(object printStream)
{
TypeWrapper tw = ClassLoaderWrapper.LoadClassCritical("java.lang.System");
FieldWrapper fw = tw.GetFieldWrapper("err", "Ljava.io.PrintStream;");
fw.SetValue(null, printStream);
}
public static void setIn(object inputStream)
{
TypeWrapper tw = ClassLoaderWrapper.LoadClassCritical("java.lang.System");
FieldWrapper fw = tw.GetFieldWrapper("in", "Ljava.io.InputStream;");
fw.SetValue(null, inputStream);
}
public static void setOut(object printStream)
{
TypeWrapper tw = ClassLoaderWrapper.LoadClassCritical("java.lang.System");
FieldWrapper fw = tw.GetFieldWrapper("out", "Ljava.io.PrintStream;");
fw.SetValue(null, printStream);
}
}
public class VMClassLoader
{
public static Assembly findResourceAssembly(string name)
{
name = JVM.MangleResourceName(name);
foreach(Assembly asm in AppDomain.CurrentDomain.GetAssemblies())
{
if(!(asm is NetSystem.Reflection.Emit.AssemblyBuilder))
{
if(asm.GetManifestResourceInfo(name) != null)
{
return asm;
}
}
}
return null;
}
public static Assembly[] findResourceAssemblies(string name)
{
name = JVM.MangleResourceName(name);
ArrayList list = new ArrayList();
foreach(Assembly asm in AppDomain.CurrentDomain.GetAssemblies())
{
if(!(asm is NetSystem.Reflection.Emit.AssemblyBuilder))
{
if(asm.GetManifestResourceInfo(name) != null)
{
list.Add(asm);
}
}
}
return (Assembly[])list.ToArray(typeof(Assembly));
}
public static object loadClass(string name, bool resolve)
{
try
{
TypeWrapper type = ClassLoaderWrapper.GetBootstrapClassLoader().LoadClassByDottedNameFast(name);
if(type != null)
{
return VMClass.getClassFromWrapper(type);
}
return null;
}
catch(RetargetableJavaException x)
{
throw x.ToJava();
}
}
public static object getBootstrapClassLoader()
{
return ClassLoaderWrapper.GetJavaBootstrapClassLoader();
}
public static object getPrimitiveClass(char type)
{
switch(type)
{
case 'Z':
return VMClass.getClassFromWrapper(PrimitiveTypeWrapper.BOOLEAN);
case 'B':
return VMClass.getClassFromWrapper(PrimitiveTypeWrapper.BYTE);
case 'C':
return VMClass.getClassFromWrapper(PrimitiveTypeWrapper.CHAR);
case 'D':
return VMClass.getClassFromWrapper(PrimitiveTypeWrapper.DOUBLE);
case 'F':
return VMClass.getClassFromWrapper(PrimitiveTypeWrapper.FLOAT);
case 'I':
return VMClass.getClassFromWrapper(PrimitiveTypeWrapper.INT);
case 'J':
return VMClass.getClassFromWrapper(PrimitiveTypeWrapper.LONG);
case 'S':
return VMClass.getClassFromWrapper(PrimitiveTypeWrapper.SHORT);
case 'V':
return VMClass.getClassFromWrapper(PrimitiveTypeWrapper.VOID);
default:
throw new InvalidOperationException();
}
}
public static object defineClass(object classLoader, string name, byte[] data, int offset, int length, object protectionDomain)
{
Profiler.Enter("ClassLoader.defineClass");
try
{
try
{
ClassFile classFile = new ClassFile(data, offset, length, name, false);
if(name != null && classFile.Name != name)
{
throw new NoClassDefFoundError(name + " (wrong name: " + classFile.Name + ")");
}
lock(VMClass.LockObject)
{
TypeWrapper type = ClassLoaderWrapper.GetClassLoaderWrapper(classLoader).DefineClass(classFile);
try
{
return VMClass.CreateClassInstance(type, protectionDomain);
}
catch(Exception x)
{
// this is a critical failure, because otherwise we would open the window to a situation
// where a Type exists without a Class and then if getClass() was called on an instance
// of that type, a new Class would be created without the proper protectionDomain
JVM.CriticalFailure("Unable to create Class", x);
throw;
}
}
}
catch(RetargetableJavaException x)
{
throw x.ToJava();
}
}
finally
{
Profiler.Leave("ClassLoader.defineClass");
}
}
}
public class VMClass
{
private static Hashtable map = new Hashtable();
private delegate object LookupDelegate(object o);
private delegate object CreateClassDelegate(object o, object pd);
private static CreateClassDelegate createClass;
private static LookupDelegate getWrapper;
internal static object LockObject
{
get
{
return map.SyncRoot;
}
}
public static void throwException(Exception e)
{
throw e;
}
// NOTE when you call this method, you must own the VMClass.LockObject monitor
internal static object CreateClassInstance(TypeWrapper wrapper, object protectionDomain)
{
if(createClass == null)
{
TypeWrapper tw = ClassLoaderWrapper.LoadClassCritical("java.lang.VMClass");
tw.Finish();
createClass = (CreateClassDelegate)Delegate.CreateDelegate(typeof(CreateClassDelegate), tw.TypeAsTBD.GetMethod("createClass", BindingFlags.Static | BindingFlags.Public));
// HACK to make sure we don't run into any problems creating class objects for classes that
// participate in the VMClass static initialization, we first do a bogus call to initialize
// the machinery (I ran into this when running ikvmstub on IKVM.GNU.Classpath.dll)
createClass(null, null);
object o = map[wrapper];
if(o != null)
{
return o;
}
}
object clazz = createClass(wrapper, protectionDomain);
map.Add(wrapper, clazz);
return clazz;
}
public static bool IsAssignableFrom(object w1, object w2)
{
return ((TypeWrapper)w2).IsAssignableTo((TypeWrapper)w1);
}
public static bool IsInterface(object wrapper)
{
return ((TypeWrapper)wrapper).IsInterface;
}
public static bool IsArray(object wrapper)
{
return ((TypeWrapper)wrapper).IsArray;
}
public static object GetSuperClassFromWrapper(object wrapper)
{
TypeWrapper baseWrapper = ((TypeWrapper)wrapper).BaseTypeWrapper;
if(baseWrapper != null)
{
return getClassFromWrapper(baseWrapper);
}
return null;
}
public static object getComponentClassFromWrapper(object wrapper)
{
TypeWrapper typeWrapper = (TypeWrapper)wrapper;
if(typeWrapper.IsArray)
{
return getClassFromWrapper(typeWrapper.ElementTypeWrapper);
}
return null;
}
public static object loadArrayClass(string name, object classLoader)
{
try
{
ClassLoaderWrapper classLoaderWrapper = ClassLoaderWrapper.GetClassLoaderWrapper(classLoader);
TypeWrapper type = classLoaderWrapper.LoadClassByDottedName(name);
return VMClass.getClassFromWrapper(type);
}
catch(RetargetableJavaException x)
{
throw x.ToJava();
}
}
internal static TypeWrapper getWrapperFromClass(object clazz)
{
if(getWrapper == null)
{
TypeWrapper tw = ClassLoaderWrapper.LoadClassCritical("java.lang.VMClass");
tw.Finish();
getWrapper = (LookupDelegate)Delegate.CreateDelegate(typeof(LookupDelegate), tw.TypeAsTBD.GetMethod("getWrapperFromClass", BindingFlags.Static | BindingFlags.Public));
}
return (TypeWrapper)getWrapper(clazz);
}
internal static object getClassFromWrapper(TypeWrapper wrapper)
{
NetSystem.Diagnostics.Debug.Assert(!wrapper.IsUnloadable);
lock(VMClass.LockObject)
{
object clazz = map[wrapper];
if(clazz == null)
{
clazz = CreateClassInstance(wrapper, null);
}
return clazz;
}
}
internal static object getClassFromType(Type type)
{
TypeWrapper.AssertFinished(type);
if(type == null)
{
return null;
}
return getClassFromWrapper(ClassLoaderWrapper.GetWrapperFromType(type));
}
public static string GetName(object wrapper)
{
TypeWrapper typeWrapper = (TypeWrapper)wrapper;
if(typeWrapper.IsPrimitive)
{
if(typeWrapper == PrimitiveTypeWrapper.VOID)
{
return "void";
}
else if(typeWrapper == PrimitiveTypeWrapper.BYTE)
{
return "byte";
}
else if(typeWrapper == PrimitiveTypeWrapper.BOOLEAN)
{
return "boolean";
}
else if(typeWrapper == PrimitiveTypeWrapper.SHORT)
{
return "short";
}
else if(typeWrapper == PrimitiveTypeWrapper.CHAR)
{
return "char";
}
else if(typeWrapper == PrimitiveTypeWrapper.INT)
{
return "int";
}
else if(typeWrapper == PrimitiveTypeWrapper.LONG)
{
return "long";
}
else if(typeWrapper == PrimitiveTypeWrapper.FLOAT)
{
return "float";
}
else if(typeWrapper == PrimitiveTypeWrapper.DOUBLE)
{
return "double";
}
else
{
throw new InvalidOperationException();
}
}
return typeWrapper.Name;
}
public static void initialize(object cwrapper)
{
TypeWrapper wrapper = (TypeWrapper)cwrapper;
wrapper.Finish();
wrapper.RunClassInit();
}
public static object getClassLoader0(object wrapper)
{
return ((TypeWrapper)wrapper).GetClassLoader().GetJavaClassLoader();
}
public static object getClassLoaderFromType(Type type)
{
return ClassLoaderWrapper.GetWrapperFromType(type).GetClassLoader().GetJavaClassLoader();
}
public static object[] GetDeclaredMethods(object cwrapper, bool getMethods, bool publicOnly)
{
Profiler.Enter("VMClass.GetDeclaredMethods");
try
{
TypeWrapper wrapper = (TypeWrapper)cwrapper;
// we need to look through the array for unloadable types, because we may not let them
// escape into the 'wild'
MethodWrapper[] methods = wrapper.GetMethods();
ArrayList list = new ArrayList();
for(int i = 0; i < methods.Length; i++)
{
methods[i].Link();
// we don't want to expose "hideFromReflection" methods (one reason is that it would
// mess up the serialVersionUID computation)
if(!methods[i].IsHideFromReflection)
{
if(methods[i].Name == "<clinit>")
{
// not reported back
}
else if(publicOnly && !methods[i].IsPublic)
{
// caller is only asking for public methods, so we don't return this non-public method
}
else if((methods[i].Name == "<init>") != getMethods)
{
if(methods[i].ReturnType.IsUnloadable)
{
// HACK we should have a better plan than this
if(wrapper.GetClassLoader().LoadClassByDottedNameFast(methods[i].ReturnType.Name) == null)
{
throw JavaException.NoClassDefFoundError(methods[i].ReturnType.Name);
}
}
TypeWrapper[] args = methods[i].GetParameters();
for(int j = 0; j < args.Length; j++)
{
if(args[j].IsUnloadable)
{
// HACK we should have a better plan than this
if(wrapper.GetClassLoader().LoadClassByDottedNameFast(args[j].Name) == null)
{
throw JavaException.NoClassDefFoundError(args[j].Name);
}
}
}
list.Add(methods[i]);
}
}
}
return (MethodWrapper[])list.ToArray(typeof(MethodWrapper));
}
catch(RetargetableJavaException x)
{
throw x.ToJava();
}
finally
{
Profiler.Leave("VMClass.GetDeclaredMethods");
}
}
public static object[] GetDeclaredFields(object cwrapper, bool publicOnly)
{
Profiler.Enter("VMClass.GetDeclaredFields");
try
{
TypeWrapper wrapper = (TypeWrapper)cwrapper;
// we need to finish the type otherwise all fields will not be in the field map yet
wrapper.Finish();
FieldWrapper[] fields = wrapper.GetFields();
if(publicOnly)
{
ArrayList list = new ArrayList();
for(int i = 0; i < fields.Length; i++)
{
if(fields[i].IsPublic)
{
list.Add(fields[i]);
}
}
fields = (FieldWrapper[])list.ToArray(typeof(FieldWrapper));
}
// we need to look through the array for unloadable types, because we may not let them
// escape into the 'wild'
for(int i = 0; i < fields.Length; i++)
{
if(fields[i].FieldTypeWrapper.IsUnloadable)
{
// HACK we should have a better plan than this
if(wrapper.GetClassLoader().LoadClassByDottedNameFast(fields[i].FieldTypeWrapper.Name) == null)
{
throw JavaException.NoClassDefFoundError(fields[i].FieldTypeWrapper.Name);
}
}
}
return fields;
}
catch(RetargetableJavaException x)
{
throw x.ToJava();
}
finally
{
Profiler.Leave("VMClass.GetDeclaredFields");
}
}
public static object[] GetDeclaredClasses(object cwrapper, bool publicOnly)
{
try
{
TypeWrapper wrapper = (TypeWrapper)cwrapper;
// NOTE to get at the InnerClasses we need to finish the type
wrapper.Finish();
TypeWrapper[] wrappers = wrapper.InnerClasses;
if(publicOnly)
{
ArrayList list = new ArrayList();
for(int i = 0; i < wrappers.Length; i++)
{
if(wrappers[i].IsUnloadable)
{
throw JavaException.NoClassDefFoundError(wrappers[i].Name);
}
// because the VM lacks any support for nested visibility control, we
// cannot rely on the publicness of the type here, but instead we have
// to look at the reflective modifiers
wrappers[i].Finish();
if((wrappers[i].ReflectiveModifiers & Modifiers.Public) != 0)
{
list.Add(wrappers[i]);
}
}
wrappers = (TypeWrapper[])list.ToArray(typeof(TypeWrapper));
}
object[] innerclasses = new object[wrappers.Length];
for(int i = 0; i < innerclasses.Length; i++)
{
if(wrappers[i].IsUnloadable)
{
throw JavaException.NoClassDefFoundError(wrappers[i].Name);
}
innerclasses[i] = getClassFromWrapper(wrappers[i]);
}
return innerclasses;
}
catch(RetargetableJavaException x)
{
throw x.ToJava();
}
}
public static object GetDeclaringClass(object cwrapper)
{
try
{
TypeWrapper wrapper = (TypeWrapper)cwrapper;
// before we can call DeclaringTypeWrapper, we need to finish the type
wrapper.Finish();
TypeWrapper declaring = wrapper.DeclaringTypeWrapper;
if(declaring == null)
{
return null;
}
if(declaring.IsUnloadable)
{
throw JavaException.NoClassDefFoundError(declaring.Name);
}
return getClassFromWrapper(declaring);
}
catch(RetargetableJavaException x)
{
throw x.ToJava();
}
}
public static object[] GetInterfaces(object cwrapper)
{
try
{
TypeWrapper wrapper = (TypeWrapper)cwrapper;
TypeWrapper[] interfaceWrappers = wrapper.Interfaces;
object[] interfaces = new object[interfaceWrappers.Length];
for(int i = 0; i < interfaces.Length; i++)
{
interfaces[i] = getClassFromWrapper(interfaceWrappers[i]);
}
return interfaces;
}
catch(RetargetableJavaException x)
{
throw x.ToJava();
}
}
public static int GetModifiers(Object cwrapper)
{
try
{
TypeWrapper wrapper = (TypeWrapper)cwrapper;
// NOTE we don't return the modifiers from the TypeWrapper, because for inner classes
// the reflected modifiers are different from the physical ones
Modifiers modifiers = wrapper.ReflectiveModifiers;
// only returns public, protected, private, final, static, abstract and interface (as per
// the documentation of Class.getModifiers())
Modifiers mask = Modifiers.Public | Modifiers.Protected | Modifiers.Private | Modifiers.Final |
Modifiers.Static | Modifiers.Abstract | Modifiers.Interface;
return (int)(modifiers & mask);
}
catch(RetargetableJavaException x)
{
throw x.ToJava();
}
}
}
}
namespace io
{
public class VMObjectStreamClass
{
public static bool hasClassInitializer(object clazz)
{
TypeWrapper wrapper = NativeCode.java.lang.VMClass.getWrapperFromClass(clazz);
wrapper.Finish();
Type type = wrapper.TypeAsTBD;
try
{
if(!type.IsArray && type.TypeInitializer != null)
{
return !AttributeHelper.IsHideFromJava(type.TypeInitializer);
}
return false;
}
catch(Exception x)
{
Console.WriteLine(type.FullName);
Console.WriteLine(x);
return false;
}
}
private static FieldWrapper GetFieldWrapperFromField(object field)
{
// TODO optimize this
return (FieldWrapper)field.GetType().GetField("fieldCookie", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(field);
}
public static void setDoubleNative(object field, object obj, double val)
{
GetFieldWrapperFromField(field).SetValue(obj, val);
}
public static void setFloatNative(object field, object obj, float val)
{
GetFieldWrapperFromField(field).SetValue(obj, val);
}
public static void setLongNative(object field, object obj, long val)
{
GetFieldWrapperFromField(field).SetValue(obj, val);
}
public static void setIntNative(object field, object obj, int val)
{
GetFieldWrapperFromField(field).SetValue(obj, val);
}
public static void setShortNative(object field, object obj, short val)
{
GetFieldWrapperFromField(field).SetValue(obj, val);
}
public static void setCharNative(object field, object obj, char val)
{
GetFieldWrapperFromField(field).SetValue(obj, val);
}
public static void setByteNative(object field, object obj, sbyte val)
{
GetFieldWrapperFromField(field).SetValue(obj, val);
}
public static void setBooleanNative(object field, object obj, bool val)
{
GetFieldWrapperFromField(field).SetValue(obj, val);
}
public static void setObjectNative(object field, object obj, object val)
{
GetFieldWrapperFromField(field).SetValue(obj, val);
}
}
public class ObjectInputStream
{
public static object currentClassLoader(object sm)
{
// TODO calling currentClassLoader in SecurityManager results in null being returned, so we use our own
// version for now, don't know what the security implications of this are
// SECURITY
return NativeCode.java.lang.VMSecurityManager.currentClassLoader();
}
public static object allocateObject(object ois, object clazz)
{
Profiler.Enter("ObjectInputStream.allocateObject");
try
{
TypeWrapper wrapper = NativeCode.java.lang.VMClass.getWrapperFromClass(clazz);
// if we're trying to deserialize a string as a TC_OBJECT, just return an emtpy string (Sun does the same)
if(wrapper == CoreClasses.java.lang.String.Wrapper)
{
return "";
}
wrapper.Finish();
// TODO do we need error handling? (e.g. when trying to instantiate an interface or abstract class)
return NetSystem.Runtime.Serialization.FormatterServices.GetUninitializedObject(wrapper.TypeAsBaseType);
}
finally
{
Profiler.Leave("ObjectInputStream.allocateObject");
}
}
public static void callConstructor(object ois, object clazz, object obj)
{
Profiler.Enter("ObjectInputStream.callConstructor");
try
{
TypeWrapper type = NativeCode.java.lang.VMClass.getWrapperFromClass(clazz);
// if we're trying to deserialize a string as a TC_OBJECT, we already have an initialized emtpy string
// so there is no need to call the constructor (which wouldn't work anyway).
if(!(obj is string))
{
MethodWrapper mw = type.GetMethodWrapper(new MethodDescriptor("<init>", "()V"), false);
if(mw == null)
{
// TODO what should we do here?
throw new NotImplementedException();
}
// TODO instead of calling link, we should probably Finish the wrapper
mw.Link();
// TODO what about exceptions? (should they be unwrapped?)
mw.Invoke(obj, null, false);
}
}
finally
{
Profiler.Leave("ObjectInputStream.callConstructor");
}
}
}
}
namespace net
{
public class InetAddress
{
public static sbyte[] lookupInaddrAny()
{
return new sbyte[] { 0, 0, 0, 0 };
}
public static string getLocalHostname()
{
// TODO error handling
return NetSystem.Net.Dns.GetHostName();
}
public static sbyte[][] getHostByName(string name)
{
// TODO error handling
try
{
NetSystem.Net.IPHostEntry he = NetSystem.Net.Dns.GetHostByName(name);
NetSystem.Net.IPAddress[] addresses = he.AddressList;
sbyte[][] list = new sbyte[addresses.Length][];
for(int i = 0; i < addresses.Length; i++)
{
byte[] address = addresses[i].GetAddressBytes();
sbyte[] sb = new sbyte[address.Length];
for(int j = 0; j < sb.Length; j++)
{
sb[j] = (sbyte)address[j];
}
list[i] = sb;
}
return list;
}
catch(Exception x)
{
throw JavaException.UnknownHostException(x.Message);
}
}
public static string getHostByAddr(byte[] address)
{
string s;
try
{
s = NetSystem.Net.Dns.GetHostByAddress(string.Format("{0}.{1}.{2}.{3}", address[0], address[1], address[2], address[3])).HostName;
}
catch(NetSystem.Net.Sockets.SocketException x)
{
throw JavaException.UnknownHostException(x.Message);
}
try
{
NetSystem.Net.Dns.GetHostByName(s);
}
catch(NetSystem.Net.Sockets.SocketException)
{
// FXBUG .NET framework bug
// HACK if GetHostByAddress returns a netbios name, it appends the default DNS suffix, but if the
// machine's netbios name isn't the same as the DNS hostname, this might result in an unresolvable
// name, if that happens we chop of the DNS suffix.
int idx = s.IndexOf('.');
if(idx > 0)
{
return s.Substring(0, idx);
}
}
return s;
}
}
}
namespace security
{
public class VMAccessController
{
public static object getClassFromFrame(NetSystem.Diagnostics.StackFrame frame)
{
return NativeCode.java.lang.VMClass.getClassFromType(frame.GetMethod().DeclaringType);
}
}
}
}
namespace IKVM.NativeCode.gnu.java.net.protocol.ikvmres
{
public class IkvmresURLConnection
{
public static string MangleResourceName(string name)
{
return JVM.MangleResourceName(name);
}
}
}
namespace IKVM.NativeCode.gnu.java.nio.channels
{
public class FileChannelImpl
{
private static readonly MethodInfo mono_1_0_Flush;
private static readonly MethodInfo mono_1_1_Flush;
static FileChannelImpl()
{
try
{
FlushFileBuffers(new IntPtr(-1));
}
catch(TypeLoadException)
{
// If we end up here, we're not running on Windows, so we'll try two Mono specific methods.
// The first one is using Mono.Posix, this is part of the documented public Mono API.
Type t = Type.GetType("Mono.Posix.Syscall, Mono.Posix");
if(t != null)
{
mono_1_1_Flush = t.GetMethod("fsync", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(int) }, new ParameterModifier[0]);
}
// HACK when we're running on Mono 1.0 we have to use an undocument internal method to flush the handle
if(mono_1_1_Flush == null)
{
t = Type.GetType("System.IO.MonoIO");
if(t != null)
{
mono_1_0_Flush = t.GetMethod("Flush", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(IntPtr), Type.GetType("System.IO.MonoIOError&") }, new ParameterModifier[0]);
}
}
}
}
// NOTE this method implements a platform specific way to flush the underlying OS file buffers to disk
public static bool flush(FileStream fs)
{
if(mono_1_0_Flush != null)
{
object[] args = new object[] { fs.Handle, null };
mono_1_0_Flush.Invoke(null, args);
return ((IConvertible)args[1]).ToInt32(null) == 0;
}
else if(mono_1_1_Flush != null)
{
object[] args = new object[] { fs.Handle.ToInt32() };
return (int)mono_1_1_Flush.Invoke(null, args) == 0;
}
else
{
try
{
return FlushFileBuffers(fs.Handle);
}
catch(TypeLoadException)
{
// we're apparently running on a alternate runtime, so we'll just pretend that flush succeeded
Tracer.Warning(Tracer.Runtime, "FlushFileBuffers/fsync not supported on this runtime");
return true;
}
}
}
[DllImport("kernel32")]
private extern static bool FlushFileBuffers(IntPtr handle);
}
}
namespace gnu.classpath
{
// This type lives here, because we don't want unverifiable code in IKVM.GNU.Classpath
// (as that would prevents us from verifying it during the build process).
public unsafe sealed class RawData
{
[HideFromJava]
private sbyte* pb;
public RawData(IntPtr p)
{
this.pb = (sbyte*)p;
}
public IntPtr p()
{
return new IntPtr(pb);
}
// NOTE the IKVM.Runtime doesn't have the AllowPartiallyTrustedCallersAttribute so this
// security attribute isn't really needed, but to be extra safe we add the explicit link
// demand to these dangerous methods.
[SecurityPermission(SecurityAction.LinkDemand, Unrestricted = true)]
public sbyte ReadByte(int index)
{
return pb[index];
}
[SecurityPermission(SecurityAction.LinkDemand, Unrestricted = true)]
public void WriteByte(int index, sbyte b)
{
pb[index] = b;
}
[SecurityPermission(SecurityAction.LinkDemand, Unrestricted = true)]
public void MoveMemory(int dst_offset, int src_offset, int count)
{
if(dst_offset < src_offset)
{
while(count-- > 0)
pb[dst_offset++] = pb[src_offset++];
}
else
{
dst_offset += count;
src_offset += count;
while(count-- > 0)
pb[--dst_offset] = pb[--src_offset];
}
}
}
}