ikvm-fork/runtime/classpath.cs

1624 строки
41 KiB
C#

/*
Copyright (C) 2002, 2003, 2004, 2005, 2006 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;
using System.Security.Permissions;
using IKVM.Attributes;
using IKVM.Runtime;
using IKVM.Internal;
namespace IKVM.NativeCode.java
{
namespace lang
{
namespace reflect
{
public class VMArray
{
public static object createObjectArray(object clazz, int dim)
{
if(dim >= 0)
{
try
{
TypeWrapper wrapper = TypeWrapper.FromClass(clazz);
wrapper.Finish();
return System.Array.CreateInstance(wrapper.TypeAsArrayType, dim);
}
catch(RetargetableJavaException x)
{
throw x.ToJava();
}
}
throw JavaException.NegativeArraySizeException();
}
}
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 int GetRealModifiers(object clazz)
{
return (int)TypeWrapper.FromClass(clazz).Modifiers;
}
public static object GetReturnType(object methodCookie)
{
MethodWrapper wrapper = (MethodWrapper)methodCookie;
TypeWrapper retType = wrapper.ReturnType;
retType = retType.EnsureLoadable(wrapper.DeclaringType.GetClassLoader());
return retType.ClassObject;
}
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].EnsureLoadable(wrapper.DeclaringType.GetClassLoader());
parameterClasses[i] = paramType.ClassObject;
}
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();
}
}
public static string GetSignature(object methodCookie)
{
MethodWrapper wrapper = (MethodWrapper)methodCookie;
return wrapper.DeclaringType.GetGenericMethodSignature(wrapper);
}
public static object GetDefaultValue(Object methodCookie)
{
MethodWrapper wrapper = (MethodWrapper)methodCookie;
return wrapper.DeclaringType.GetAnnotationDefault(wrapper);
}
[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] = JVM.Library.unbox(args[i]);
// NOTE we depend on the fact that the .NET reflection parameter type
// widening rules are the same as in Java, but to have this work for byte
// we need to convert byte to sbyte.
if(argsCopy[i] is byte && argWrappers[i] != PrimitiveTypeWrapper.BYTE)
{
argsCopy[i] = (sbyte)(byte)argsCopy[i];
}
}
else
{
argsCopy[i] = args[i];
}
}
// if the method is an interface method, we must explicitly run <clinit>,
// because .NET reflection doesn't
if(mw.DeclaringType.IsInterface)
{
mw.DeclaringType.RunClassInit();
}
object retval;
try
{
retval = mw.Invoke(o, argsCopy, false);
}
catch(MethodAccessException)
{
// this can happen if we're calling a non-public method and the call stack doesn't have ReflectionPermission.MemberAccess
throw JavaException.IllegalAccessException("System.MethodAccessException for {0}.{1}", mw.DeclaringType.Name, mw.Name);
}
if(mw.ReturnType.IsPrimitive && mw.ReturnType != PrimitiveTypeWrapper.VOID)
{
retval = JVM.Library.box(retval);
}
return retval;
}
catch(RetargetableJavaException x)
{
throw x.ToJava();
}
}
}
public class VMFieldImpl
{
public static string GetName(object fieldCookie)
{
FieldWrapper wrapper = (FieldWrapper)fieldCookie;
return wrapper.Name;
}
public static int GetModifiers(object memberCookie)
{
MemberWrapper wrapper = (MemberWrapper)memberCookie;
return (int)wrapper.Modifiers;
}
public static object GetDeclaringClass(object memberCookie)
{
MemberWrapper wrapper = (MemberWrapper)memberCookie;
return wrapper.DeclaringType.ClassObject;
}
public static object GetFieldType(object fieldCookie)
{
FieldWrapper wrapper = (FieldWrapper)fieldCookie;
TypeWrapper fieldType = wrapper.FieldTypeWrapper;
fieldType = fieldType.EnsureLoadable(wrapper.DeclaringType.GetClassLoader());
return fieldType.ClassObject;
}
public static string GetSignature(object fieldCookie)
{
FieldWrapper wrapper = (FieldWrapper)fieldCookie;
return wrapper.DeclaringType.GetGenericFieldSignature(wrapper);
}
public static void RunClassInit(object clazz)
{
TypeWrapper.FromClass(clazz).RunClassInit();
}
public static bool CheckAccess(object memberCookie, object instance, object callerTypeWrapper)
{
MemberWrapper member = (MemberWrapper)memberCookie;
if(callerTypeWrapper != null)
{
TypeWrapper instanceTypeWrapper;
if(member.IsStatic || instance == null)
{
instanceTypeWrapper = member.DeclaringType;
}
else
{
instanceTypeWrapper = IKVM.Runtime.Util.GetTypeWrapperFromObject(instance);
}
return member.IsAccessibleFrom(member.DeclaringType, (TypeWrapper)callerTypeWrapper, instanceTypeWrapper);
}
else
{
return member.IsPublic && member.DeclaringType.IsPublic;
}
}
public static object GetValue(object fieldCookie, object o)
{
Profiler.Enter("Field.GetValue");
try
{
FieldWrapper wrapper = (FieldWrapper)fieldCookie;
// if the field is an interface field, we must explicitly run <clinit>,
// because .NET reflection doesn't
if(wrapper.DeclaringType.IsInterface)
{
wrapper.DeclaringType.RunClassInit();
}
try
{
return wrapper.GetValue(o);
}
#if !COMPACT_FRAMEWORK
catch(FieldAccessException)
{
// this can happen if we're accessing a non-public field and the call stack doesn't have ReflectionPermission.MemberAccess
throw JavaException.IllegalAccessException("System.FieldAccessException for {0}.{1}", wrapper.DeclaringType.Name, wrapper.Name);
}
#endif
finally
{
}
}
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 the field is an interface field, we must explicitly run <clinit>,
// because .NET reflection doesn't
if(wrapper.DeclaringType.IsInterface)
{
wrapper.DeclaringType.RunClassInit();
}
try
{
wrapper.SetValue(o, v);
}
#if !COMPACT_FRAMEWORK
catch(FieldAccessException)
{
// this can happen if we're accessing a non-public field and the call stack doesn't have ReflectionPermission.MemberAccess
throw JavaException.IllegalAccessException("System.FieldAccessException for {0}.{1}", wrapper.DeclaringType.Name, wrapper.Name);
}
#endif
finally
{
}
}
finally
{
Profiler.Leave("Field.SetValue");
}
}
}
}
public class VMRuntime
{
public static int nativeLoad(string filename, object classLoader)
{
#if !COMPACT_FRAMEWORK
return IKVM.Runtime.JniHelper.LoadLibrary(filename, ClassLoaderWrapper.GetClassLoaderWrapper(classLoader));
#else
return 0;
#endif
}
}
public class VMDouble
{
public static double parseDouble(string s)
{
if(s.Length == 0) goto error;
int first = 0;
while(s[first] <= ' ')
{
first++;
if(first == s.Length) goto error;
}
int last = s.Length - 1;
while(s[last] <= ' ')
{
last--;
if(first > last) goto error;
}
bool sign = false;
if(s[first] == '-')
{
sign = true;
first++;
if(first > last) goto error;
}
else if(s[first] == '+')
{
first++;
if(first > last) goto error;
}
if(last - first == 7 && string.CompareOrdinal(s, first, "Infinity", 0, 8) == 0)
{
return sign ? double.NegativeInfinity : double.PositiveInfinity;
}
if(last - first == 2 && string.CompareOrdinal(s, first, "NaN", 0, 3) == 0)
{
return double.NaN;
}
// Java allows 'f' or 'd' at the end
if("dfDF".IndexOf(s[last]) >= 0)
{
last--;
if(first > last) goto error;
}
bool dot = false;
bool exp = false;
for(int i = first; i <= last; i++)
{
char c = s[i];
if(c >= '0' && c <= '9')
{
// ok
}
else if(c == '.')
{
if(dot || exp) goto error;
dot = true;
}
else if(c == 'e' || c == 'E')
{
if(i == first || i == last || exp) goto error;
if(s[i + 1] == '-' || s[i + 1] == '+')
{
i++;
if(i == last) goto error;
}
exp = true;
}
else goto error;
}
if(first != 0 || last != s.Length - 1)
{
s = s.Substring(first, last - first + 1);
}
try
{
// I doubt that this is fully correct, but since we don't implement FP properly,
// we can probably get away with this as well.
double d = double.Parse(s, System.Globalization.CultureInfo.InvariantCulture);
return sign ? -d : d;
}
catch(OverflowException)
{
return sign ? double.NegativeInfinity : double.PositiveInfinity;
}
catch(FormatException x)
{
// this can't happen, since we already validated the format of the string
System.Diagnostics.Debug.Fail(x.ToString());
}
error:
throw JavaException.NumberFormatException("For input string: \"{0}\"", s);
}
}
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);
#if COMPACT_FRAMEWORK
// TODO
try
{
JVM.CoreAssembly.GetManifestResourceStream(name).Close();
return JVM.CoreAssembly;
}
catch(FileNotFoundException)
{
return null;
}
#else
foreach(Assembly asm in AppDomain.CurrentDomain.GetAssemblies())
{
if(!(asm is System.Reflection.Emit.AssemblyBuilder))
{
if(asm.GetManifestResourceInfo(name) != null)
{
return asm;
}
}
}
return null;
#endif
}
public static Assembly[] findResourceAssemblies(string name)
{
name = JVM.MangleResourceName(name);
#if COMPACT_FRAMEWORK
// TODO figure this out
try
{
JVM.CoreAssembly.GetManifestResourceStream(name).Close();
return new Assembly[] { JVM.CoreAssembly };
}
catch(FileNotFoundException)
{
return new Assembly[0];
}
#else
ArrayList list = new ArrayList();
foreach(Assembly asm in AppDomain.CurrentDomain.GetAssemblies())
{
if(!(asm is System.Reflection.Emit.AssemblyBuilder))
{
if(asm.GetManifestResourceInfo(name) != null)
{
list.Add(asm);
}
}
}
return (Assembly[])list.ToArray(typeof(Assembly));
#endif
}
public static object loadClass(string name, bool resolve)
{
try
{
TypeWrapper type = ClassLoaderWrapper.GetBootstrapClassLoader().LoadClassByDottedNameFast(name);
if(type != null)
{
return type.ClassObject;
}
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 PrimitiveTypeWrapper.BOOLEAN.ClassObject;
case 'B':
return PrimitiveTypeWrapper.BYTE.ClassObject;
case 'C':
return PrimitiveTypeWrapper.CHAR.ClassObject;
case 'D':
return PrimitiveTypeWrapper.DOUBLE.ClassObject;
case 'F':
return PrimitiveTypeWrapper.FLOAT.ClassObject;
case 'I':
return PrimitiveTypeWrapper.INT.ClassObject;
case 'J':
return PrimitiveTypeWrapper.LONG.ClassObject;
case 'S':
return PrimitiveTypeWrapper.SHORT.ClassObject;
case 'V':
return PrimitiveTypeWrapper.VOID.ClassObject;
default:
throw new InvalidOperationException();
}
}
public static object defineClassImpl(object classLoader, string name, byte[] data, int offset, int length, object protectionDomain)
{
#if COMPACT_FRAMEWORK
throw JavaException.NoClassDefFoundError("Class loading is not supported on the Compact Framework");
#else
Profiler.Enter("ClassLoader.defineClass");
try
{
try
{
ClassFile classFile = new ClassFile(data, offset, length, name);
if(name != null && classFile.Name != name)
{
throw new NoClassDefFoundError(name + " (wrong name: " + classFile.Name + ")");
}
TypeWrapper type = ClassLoaderWrapper.GetClassLoaderWrapper(classLoader).DefineClass(classFile, protectionDomain);
return type.ClassObject;
}
catch(RetargetableJavaException x)
{
throw x.ToJava();
}
}
finally
{
Profiler.Leave("ClassLoader.defineClass");
}
#endif
}
public static string getPackageName(Type type)
{
string name;
#if !COMPACT_FRAMEWORK
if(type.Assembly is System.Reflection.Emit.AssemblyBuilder)
{
name = ClassLoaderWrapper.GetWrapperFromType(type).Name;
}
else
#endif
if(type.Module.IsDefined(typeof(JavaModuleAttribute), false))
{
name = CompiledTypeWrapper.GetName(type);
}
else
{
name = DotNetTypeWrapper.GetName(type);
}
int dot = name.LastIndexOf('.');
if(dot > 0)
{
return name.Substring(0, dot);
}
return null;
}
public static object findLoadedClass(object javaClassLoader, string name)
{
ClassLoaderWrapper loader = ClassLoaderWrapper.GetClassLoaderWrapper(javaClassLoader);
TypeWrapper wrapper = loader.GetLoadedClass(name);
if(wrapper != null)
{
return wrapper.ClassObject;
}
// For compatibility with Sun's JDK 1.4, we also find array variations of already loaded classes
if(name.StartsWith("[") && name.EndsWith(";"))
{
int rank = 1;
while(name[rank] == '[')
{
rank++;
}
if(name[rank] == 'L' && name[rank + 1] != '[')
{
wrapper = loader.GetLoadedClass(name.Substring(rank + 1, name.Length - (rank + 2)));
if(wrapper != null)
{
return wrapper.MakeArrayType(rank).ClassObject;
}
}
}
return null;
}
}
public class VMClass
{
public static void throwException(Exception e)
{
throw e;
}
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 baseWrapper.ClassObject;
}
return null;
}
public static object getComponentClassFromWrapper(object wrapper)
{
TypeWrapper typeWrapper = (TypeWrapper)wrapper;
if(typeWrapper.IsArray)
{
return typeWrapper.ElementTypeWrapper.ClassObject;
}
return null;
}
public static object forName(string name, bool initialize, object classLoader)
{
try
{
ClassLoaderWrapper classLoaderWrapper = ClassLoaderWrapper.GetClassLoaderWrapper(classLoader);
TypeWrapper type = classLoaderWrapper.LoadClassByDottedName(name);
if(initialize && !type.IsArray)
{
type.Finish();
type.RunClassInit();
}
return type.ClassObject;
}
catch(RetargetableJavaException x)
{
throw x.ToJava();
}
}
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 object getClassLoader0(object wrapper)
{
return ((TypeWrapper)wrapper).GetClassLoader().GetJavaClassLoader();
}
public static object[] GetDeclaredMethods(object cwrapper, bool getMethods, bool publicOnly)
{
Profiler.Enter("VMClass.GetDeclaredMethods");
try
{
TypeWrapper wrapper = (TypeWrapper)cwrapper;
wrapper.Finish();
// 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++)
{
// 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(!JVM.EnableReflectionOnMethodsWithUnloadableTypeParameters)
{
methods[i].ReturnType.EnsureLoadable(wrapper.GetClassLoader());
TypeWrapper[] args = methods[i].GetParameters();
for(int j = 0; j < args.Length; j++)
{
args[j].EnsureLoadable(wrapper.GetClassLoader());
}
}
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();
ArrayList list = new ArrayList();
for(int i = 0; i < fields.Length; i++)
{
if(fields[i].IsHideFromReflection)
{
// skip
}
else if(publicOnly && !fields[i].IsPublic)
{
// caller is only asking for public field, so we don't return this non-public field
}
else
{
fields[i].FieldTypeWrapper.EnsureLoadable(wrapper.GetClassLoader());
list.Add(fields[i]);
}
}
return (FieldWrapper[])list.ToArray(typeof(FieldWrapper));
}
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] = wrappers[i].ClassObject;
}
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 declaring.ClassObject;
}
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] = interfaceWrappers[i].ClassObject;
}
return interfaces;
}
catch(RetargetableJavaException x)
{
throw x.ToJava();
}
}
public static int GetModifiers(Object cwrapper, bool ignoreInnerClassesAttribute)
{
try
{
TypeWrapper wrapper = (TypeWrapper)cwrapper;
// NOTE unless ignoreInnerClassesAttribute is true, we don't return the modifiers from
// the TypeWrapper, because for inner classes the reflected modifiers are different
// from the physical ones
Modifiers modifiers = ignoreInnerClassesAttribute ?
wrapper.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();
}
}
public static int GetRawModifiers(Object cwrapper)
{
TypeWrapper wrapper = (TypeWrapper)cwrapper;
return (int)wrapper.Modifiers;
}
public static string GetClassSignature(object cwrapper)
{
TypeWrapper wrapper = (TypeWrapper)cwrapper;
return wrapper.GetGenericSignature();
}
public static object GetEnclosingClass(object cwrapper)
{
try
{
TypeWrapper wrapper = (TypeWrapper)cwrapper;
wrapper.Finish();
string[] enclosing = wrapper.GetEnclosingMethod();
if(enclosing != null)
{
TypeWrapper enclosingClass = wrapper.GetClassLoader().LoadClassByDottedNameFast(enclosing[0]);
if(enclosingClass == null)
{
throw JavaException.NoClassDefFoundError(enclosing[0]);
}
return enclosingClass.ClassObject;
}
if (wrapper.DeclaringTypeWrapper != null)
{
wrapper.DeclaringTypeWrapper.EnsureLoadable(wrapper.GetClassLoader());
return wrapper.DeclaringTypeWrapper.ClassObject;
}
return null;
}
catch(RetargetableJavaException x)
{
throw x.ToJava();
}
}
public static object GetEnclosingMethod(object cwrapper)
{
try
{
TypeWrapper wrapper = (TypeWrapper)cwrapper;
string[] enclosing = wrapper.GetEnclosingMethod();
if(enclosing != null && enclosing[1] != null && enclosing[1] != "<init>")
{
TypeWrapper enclosingClass = wrapper.GetClassLoader().LoadClassByDottedNameFast(enclosing[0]);
if(enclosingClass == null)
{
throw JavaException.NoClassDefFoundError(enclosing[0]);
}
MethodWrapper mw = enclosingClass.GetMethodWrapper(enclosing[1], enclosing[2], false);
if(mw != null && !mw.IsHideFromReflection)
{
return JVM.Library.newMethod(mw.DeclaringType.ClassObject, mw);
}
}
return null;
}
catch(RetargetableJavaException x)
{
throw x.ToJava();
}
}
public static object GetEnclosingConstructor(object cwrapper)
{
try
{
TypeWrapper wrapper = (TypeWrapper)cwrapper;
string[] enclosing = wrapper.GetEnclosingMethod();
if(enclosing != null && enclosing[1] == "<init>")
{
TypeWrapper enclosingClass = wrapper.GetClassLoader().LoadClassByDottedNameFast(enclosing[0]);
if(enclosingClass == null)
{
throw JavaException.NoClassDefFoundError(enclosing[0]);
}
MethodWrapper mw = enclosingClass.GetMethodWrapper(enclosing[1], enclosing[2], false);
if(mw != null && !mw.IsHideFromReflection)
{
return JVM.Library.newConstructor(mw.DeclaringType.ClassObject, mw);
}
}
return null;
}
catch(RetargetableJavaException x)
{
throw x.ToJava();
}
}
public static object[] GetDeclaredAnnotations(object cwrapper)
{
TypeWrapper wrapper = (TypeWrapper)cwrapper;
return wrapper.GetDeclaredAnnotations();
}
}
}
namespace io
{
public class VMObjectStreamClass
{
public static bool hasClassInitializer(object clazz)
{
TypeWrapper wrapper = TypeWrapper.FromClass(clazz);
try
{
wrapper.Finish();
}
catch(RetargetableJavaException x)
{
x.ToJava();
}
wrapper.RunClassInit();
Type type = wrapper.TypeAsTBD;
if(!type.IsArray && type.TypeInitializer != null)
{
return !AttributeHelper.IsHideFromJava(type.TypeInitializer);
}
return false;
}
private static FieldWrapper GetFieldWrapperFromField(object field)
{
return (FieldWrapper)JVM.Library.getWrapperFromField(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, byte 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 VMObjectInputStream
{
public static object allocateObject(object clazz, object constructor_clazz, object constructor)
{
Profiler.Enter("ObjectInputStream.allocateObject");
try
{
TypeWrapper wrapper = TypeWrapper.FromClass(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)
object obj = System.Runtime.Serialization.FormatterServices.GetUninitializedObject(wrapper.TypeAsBaseType);
MethodWrapper mw = (MethodWrapper)JVM.Library.getWrapperFromMethodOrConstructor(constructor);
// TODO do we need error handling?
mw.Invoke(obj, null, false);
return obj;
}
catch(RetargetableJavaException x)
{
throw x.ToJava();
}
finally
{
Profiler.Leave("ObjectInputStream.allocateObject");
}
}
}
}
#if !COMPACT_FRAMEWORK
namespace security
{
public class VMAccessController
{
public static object getClassFromFrame(System.Diagnostics.StackFrame frame)
{
return gnu.classpath.VMStackWalker.getClassFromType(frame.GetMethod().DeclaringType);
}
}
}
#endif
}
namespace IKVM.NativeCode.gnu.java.net.protocol.ikvmres
{
#if !WHIDBEY
class LZInputStream : Stream
{
private Stream inp;
private int[] ptr_tbl;
private int[] char_tbl;
private int[] stack;
private int table_size;
private int count;
private int bitoff;
private int bitbuf;
private int prev = -1;
private int bits;
private int cc;
private int fc;
private int sp;
public LZInputStream(Stream inp)
{
this.inp = inp;
bitoff = 0;
count = 0;
table_size = 256;
bits = 9;
ptr_tbl = new int[table_size];
char_tbl = new int[table_size];
stack = new int[table_size];
sp = 0;
cc = prev = incode();
stack[sp++] = cc;
}
private int read()
{
if (sp == 0)
{
if (stack.Length != table_size)
{
stack = new int[table_size];
}
int ic = cc = incode();
if (cc == -1)
{
return -1;
}
if (count >= 0 && cc >= count + 256)
{
stack[sp++] = fc;
cc = prev;
ic = find(prev, fc);
}
while (cc >= 256)
{
stack[sp++] = char_tbl[cc - 256];
cc = ptr_tbl[cc - 256];
}
fc = stack[sp++] = cc;
if (count >= 0)
{
ptr_tbl[count] = prev;
char_tbl[count] = fc;
}
count++;
if (count == table_size)
{
count = -1;
if (bits == 12)
{
table_size = 256;
bits = 9;
}
else
{
bits++;
table_size = (1 << bits) - 256;
}
ptr_tbl = null;
char_tbl = null;
ptr_tbl = new int[table_size];
char_tbl= new int[table_size];
}
prev = ic;
}
return stack[--sp] & 0xFF;
}
private int find(int p, int c)
{
int i;
for (i = 0; i < count; i++)
{
if (ptr_tbl[i] == p && char_tbl[i] == c)
{
break;
}
}
return i + 256;
}
private int incode()
{
while (bitoff < bits)
{
int v = inp.ReadByte();
if (v == -1)
{
return -1;
}
bitbuf |= (v & 0xFF) << bitoff;
bitoff += 8;
}
bitoff -= bits;
int result = bitbuf;
bitbuf >>= bits;
result -= bitbuf << bits;
return result;
}
public override int Read(byte[] b, int off, int len)
{
int i = 0;
for (; i < len ; i++)
{
int r = read();
if(r == -1)
{
break;
}
b[off + i] = (byte)r;
}
return i;
}
public override bool CanRead
{
get
{
return true;
}
}
public override bool CanSeek
{
get
{
return false;
}
}
public override bool CanWrite
{
get
{
return false;
}
}
public override void Flush()
{
throw new NotSupportedException();
}
public override long Length
{
get
{
throw new NotSupportedException();
}
}
public override long Position
{
get
{
throw new NotSupportedException();
}
set
{
throw new NotSupportedException();
}
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException();
}
public override void SetLength(long value)
{
throw new NotSupportedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
throw new NotSupportedException();
}
}
#endif // !WHIDBEY
public class Handler
{
public static Stream ReadResourceFromAssemblyImpl(Assembly asm, string resource)
{
#if WHIDBEY
Stream s = asm.GetManifestResourceStream(JVM.MangleResourceName(resource.Substring(1)));
if(s == null)
{
throw new FileNotFoundException("resource " + resource + " not found in assembly " + asm.FullName);
}
switch (s.ReadByte())
{
case 0:
return s;
case 1:
return new System.IO.Compression.DeflateStream(s, System.IO.Compression.CompressionMode.Decompress, false);
default:
throw new IOException("Unsupported resource encoding for resource " + resource + " found in assembly " + asm.FullName);
}
#else
using(Stream s = asm.GetManifestResourceStream(JVM.MangleResourceName(resource.Substring(1))))
{
if(s == null)
{
throw new FileNotFoundException("resource " + resource + " not found in assembly " + asm.FullName);
}
using(System.Resources.ResourceReader r = new System.Resources.ResourceReader(s))
{
foreach(DictionaryEntry de in r)
{
if((string)de.Key == "lz")
{
return new LZInputStream(new MemoryStream((byte[])de.Value));
}
else if((string)de.Key == "ikvm")
{
return new MemoryStream((byte[])de.Value);
}
else
{
throw new IOException("Unsupported resource encoding " + de.Key + " for resource " + resource + " found in assembly " + asm.FullName);
}
}
throw new IOException("Invalid resource " + resource + " found in assembly " + asm.FullName);
}
}
#endif
}
}
}
namespace IKVM.NativeCode.gnu.classpath
{
public class VMSystemProperties
{
public static string getVersion()
{
try
{
return JVM.SafeGetAssemblyVersion(typeof(VMSystemProperties).Assembly).ToString();
}
catch(Exception)
{
return "(unknown)";
}
}
}
public class VMStackWalker
{
public static object getClassFromType(Type type)
{
TypeWrapper.AssertFinished(type);
if(type == null)
{
return null;
}
return ClassLoaderWrapper.GetWrapperFromType(type).ClassObject;
}
public static object getClassLoaderFromType(Type type)
{
// global methods have no type
if(type == null)
{
return JVM.Library.getSystemClassLoader();
}
else if(type.Module is System.Reflection.Emit.ModuleBuilder)
{
return ClassLoaderWrapper.GetWrapperFromType(type).GetClassLoader().GetJavaClassLoader();
}
else if(ClassLoaderWrapper.IsCoreAssemblyType(type))
{
return null;
}
else
{
return JVM.Library.getSystemClassLoader();
}
}
public static Type getJNIEnvType()
{
return typeof(IKVM.Runtime.JNIEnv);
}
public static bool isHideFromJava(MethodBase mb)
{
return mb.IsDefined(typeof(HideFromJavaAttribute), false)
|| mb.IsDefined(typeof(HideFromReflectionAttribute), false);
}
}
}
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).
#if !COMPACT_FRAMEWORK
[SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
#endif
public unsafe sealed class Pointer
{
[HideFromJava]
private byte* pb;
public Pointer(IntPtr p)
{
this.pb = (byte*)p;
}
public IntPtr p()
{
return new IntPtr(pb);
}
public byte ReadByte(int index)
{
return pb[index];
}
public void WriteByte(int index, byte b)
{
pb[index] = b;
}
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];
}
}
}
}
namespace ikvm.@internal
{
public interface LibraryVMInterface
{
object loadClass(object classLoader, string name);
object newClass(object wrapper, object protectionDomain);
object getWrapperFromClass(object clazz);
object getWrapperFromField(object field);
object getWrapperFromMethodOrConstructor(object methodOrConstructor);
object getWrapperFromClassLoader(object classLoader);
void setWrapperForClassLoader(object classLoader, object wrapper);
object getSystemClassLoader();
object box(object val);
object unbox(object val);
Exception mapException(Exception t);
void printStackTrace(Exception t);
void jniWaitUntilLastThread();
void jniDetach();
void setThreadGroup(object group);
object newConstructor(object clazz, object wrapper);
object newMethod(object clazz, object wrapper);
object newField(object clazz, object wrapper);
object newDirectByteBuffer(IntPtr address, int capacity);
IntPtr getDirectBufferAddress(object buffer);
int getDirectBufferCapacity(object buffer);
void setProperties(System.Collections.Hashtable props);
bool runFinalizersOnExit();
object newAnnotation(object classLoader, object definition);
object newAnnotationElementValue(object classLoader, object expectedClass, object definition);
Exception newIllegalAccessError(string msg);
Exception newIllegalAccessException(string msg);
Exception newIncompatibleClassChangeError(string msg);
Exception newLinkageError(string msg);
Exception newVerifyError(string msg);
Exception newClassCircularityError(string msg);
Exception newClassFormatError(string msg);
Exception newUnsupportedClassVersionError(string msg);
Exception newNoClassDefFoundError(string msg);
Exception newClassNotFoundException(string msg);
Exception newUnsatisfiedLinkError(string msg);
Exception newIllegalArgumentException(string msg);
Exception newNegativeArraySizeException();
Exception newArrayStoreException();
Exception newIndexOutOfBoundsException(string msg);
Exception newStringIndexOutOfBoundsException();
Exception newInvocationTargetException(Exception t);
Exception newUnknownHostException(string msg);
Exception newArrayIndexOutOfBoundsException();
Exception newNumberFormatException(string msg);
Exception newNullPointerException();
Exception newClassCastException(string msg);
Exception newNoSuchFieldError(string msg);
Exception newNoSuchMethodError(string msg);
Exception newInstantiationError(string msg);
Exception newInstantiationException(string msg);
Exception newInterruptedException();
Exception newIllegalMonitorStateException();
}
}