зеркало из https://github.com/mono/ikvm-fork.git
no message
This commit is contained in:
Родитель
ca68c87f68
Коммит
5dcfa2b55a
|
@ -96,17 +96,6 @@ Object* JNI::UnwrapGlobalRef(jobject o)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
void* CreateDebugWrapper(String* name, void* pfunc)
|
||||
{
|
||||
char* pstub = new char[6];
|
||||
pstub[0] = 0x90;
|
||||
pstub[1] = 0xe8;
|
||||
*((void**)&pstub[2]) = pfunc;
|
||||
return pstub;
|
||||
}
|
||||
*/
|
||||
|
||||
IntPtr JNI::GetJniFuncPtr(String* method, String* sig, String* clazz)
|
||||
{
|
||||
System::Text::StringBuilder* mangledSig = new System::Text::StringBuilder();
|
||||
|
|
|
@ -113,13 +113,30 @@ public:
|
|||
public __gc class VM
|
||||
{
|
||||
public:
|
||||
static MethodBase* GetMethod(Object* clazz, String* name, String* sig, bool isStatic)
|
||||
static IntPtr GetMethodCookie(Object* clazz, String* name, String* sig, bool isStatic)
|
||||
{
|
||||
return JniHelper::GetMethod(clazz, name, sig, isStatic);
|
||||
return JniHelper::GetMethodCookie(clazz, name, sig, isStatic);
|
||||
}
|
||||
static FieldInfo* GetField(Object* clazz, String* name, String* sig, bool isStatic)
|
||||
static String* GetMethodArgList(IntPtr cookie)
|
||||
{
|
||||
return JniHelper::GetField(clazz, name, sig, isStatic);
|
||||
return JniHelper::GetMethodArgList(cookie);
|
||||
}
|
||||
[StackTraceInfo(Hidden = true)]
|
||||
static Object* InvokeMethod(IntPtr cookie, Object* obj, Object* args[], bool nonVirtual)
|
||||
{
|
||||
return JniHelper::InvokeMethod(cookie, obj, args, nonVirtual);
|
||||
}
|
||||
static IntPtr GetFieldCookie(Object* clazz, String* name, String* sig, bool isStatic)
|
||||
{
|
||||
return JniHelper::GetFieldCookie(clazz, name, sig, isStatic);
|
||||
}
|
||||
static Object* GetFieldValue(IntPtr cookie, Object* obj)
|
||||
{
|
||||
return JniHelper::GetFieldValue(cookie, obj);
|
||||
}
|
||||
static void SetFieldValue(IntPtr cookie, Object* obj, Object* value)
|
||||
{
|
||||
JniHelper::SetFieldValue(cookie, obj, value);
|
||||
}
|
||||
static Object* FindClass(String* javaName)
|
||||
{
|
||||
|
|
|
@ -249,72 +249,26 @@ jobject JNIEnv::AllocObject(jclass cls)
|
|||
|
||||
jmethodID JNIEnv::FindMethodID(jclass cls, const char* name, const char* sig, bool isstatic)
|
||||
{
|
||||
MethodBase* m = VM::GetMethod(UnwrapRef(cls), StringFromUTF8(name), StringFromUTF8(sig), isstatic);
|
||||
if(!m)
|
||||
jmethodID mid = (jmethodID)(void*)VM::GetMethodCookie(UnwrapRef(cls), StringFromUTF8(name), StringFromUTF8(sig), isstatic);
|
||||
if(!mid)
|
||||
{
|
||||
//Console::WriteLine("Method not found: {0}{1} (static = {2})", StringFromUTF8(name), StringFromUTF8(sig), __box(isstatic));
|
||||
// TODO set the exception message
|
||||
ThrowNew(FindClass("java/lang/NoSuchMethodError"), "");
|
||||
return 0;
|
||||
}
|
||||
// TODO jmethodID must be cached and delete'd!!! As it stands, we have a huge leak...
|
||||
// also, don't forget to Free the GCHandle...
|
||||
jmethodID mid = new _jmethodID;
|
||||
mid->method = (void*)(IntPtr)GCHandle::Alloc(m);
|
||||
int argc = 0;
|
||||
for(int i = 1; sig[i] != ')'; i++)
|
||||
{
|
||||
switch(sig[i])
|
||||
{
|
||||
case 'I':
|
||||
case 'Z':
|
||||
case 'S':
|
||||
case 'C':
|
||||
case 'B':
|
||||
mid->args[argc++] = 'I';
|
||||
break;
|
||||
case 'L':
|
||||
while(sig[i] != ';') i++;
|
||||
mid->args[argc++] = 'L';
|
||||
break;
|
||||
case '[':
|
||||
while(sig[i] == '[') i++;
|
||||
if(sig[i] == 'L') while(sig[i] != ';') i++;
|
||||
mid->args[argc++] = 'L';
|
||||
break;
|
||||
case 'D':
|
||||
mid->args[argc++] = 'D';
|
||||
break;
|
||||
case 'F':
|
||||
mid->args[argc++] = 'F';
|
||||
break;
|
||||
case 'J':
|
||||
mid->args[argc++] = 'J';
|
||||
break;
|
||||
}
|
||||
if(argc == 256)
|
||||
{
|
||||
// it isn't valid for a Java method to have more than 256 arguments,
|
||||
// so this cannot happen for valid classes
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
mid->args[argc] = 0;
|
||||
return mid;
|
||||
}
|
||||
|
||||
jfieldID JNIEnv::FindFieldID(jclass cls, const char* name, const char* sig, bool isstatic)
|
||||
{
|
||||
FieldInfo* f = VM::GetField(UnwrapRef(cls), StringFromUTF8(name), StringFromUTF8(sig), isstatic);
|
||||
if(!f)
|
||||
jfieldID fid = (jfieldID)(void*)VM::GetFieldCookie(UnwrapRef(cls), StringFromUTF8(name), StringFromUTF8(sig), isstatic);
|
||||
if(!fid)
|
||||
{
|
||||
// TODO what is the proper handling of this
|
||||
assert(false);
|
||||
throw new NotImplementedException("field not found");
|
||||
// TODO set the exception message
|
||||
ThrowNew(FindClass("java/lang/NoSuchFieldError"), "");
|
||||
return 0;
|
||||
}
|
||||
// TODO jfieldID must be cached and delete'd!!! As it stands, we have a huge leak...
|
||||
// also, don't forget to Free the GCHandle...
|
||||
jfieldID fid = new _jfieldID;
|
||||
fid->field = (void*)(IntPtr)GCHandle::Alloc(f);
|
||||
return fid;
|
||||
}
|
||||
|
||||
|
@ -323,11 +277,70 @@ jmethodID JNIEnv::GetStaticMethodID(jclass cls, const char *name, const char *si
|
|||
return FindMethodID(cls, name, sig, true);
|
||||
}
|
||||
|
||||
static int GetMethodArgs(jmethodID methodID, char* sig)
|
||||
{
|
||||
int count = 0;
|
||||
String* s = VM::GetMethodArgList(methodID);
|
||||
for(int i = 0; i < s->Length; i++)
|
||||
{
|
||||
*sig++ = (char)s->get_Chars(i);
|
||||
count++;
|
||||
}
|
||||
*sig = 0;
|
||||
return count;
|
||||
}
|
||||
|
||||
Object* JNIEnv::InvokeHelper(jobject object, jmethodID methodID, jvalue* args)
|
||||
{
|
||||
assert(!pLocalRefs->PendingException);
|
||||
assert(methodID);
|
||||
|
||||
char sig[257];
|
||||
int argc = GetMethodArgs(methodID, sig);
|
||||
Object* argarray __gc[] = new Object*[argc];
|
||||
for(int i = 0; i < argc; i++)
|
||||
{
|
||||
switch(sig[i])
|
||||
{
|
||||
case 'Z':
|
||||
argarray[i] = __box(args[i].z != JNI_FALSE);
|
||||
break;
|
||||
case 'B':
|
||||
argarray[i] = __box((char)args[i].b);
|
||||
break;
|
||||
case 'C':
|
||||
argarray[i] = __box((__wchar_t)args[i].c);
|
||||
break;
|
||||
case 'S':
|
||||
argarray[i] = __box((short)args[i].s);
|
||||
break;
|
||||
case 'I':
|
||||
argarray[i] = __box((int)args[i].i);
|
||||
break;
|
||||
case 'J':
|
||||
argarray[i] = __box((__int64)args[i].j);
|
||||
break;
|
||||
case 'F':
|
||||
argarray[i] = __box((float)args[i].f);
|
||||
break;
|
||||
case 'D':
|
||||
argarray[i] = __box((double)args[i].d);
|
||||
break;
|
||||
case 'L':
|
||||
argarray[i] = UnwrapRef(args[i].l);
|
||||
break;
|
||||
}
|
||||
}
|
||||
try
|
||||
{
|
||||
return VM::InvokeMethod(methodID, UnwrapRef(object), argarray, false);
|
||||
}
|
||||
catch(Exception* x)
|
||||
{
|
||||
pLocalRefs->PendingException = x;
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
MethodBase* m = __try_cast<MethodBase*>(GCHandle::op_Explicit((IntPtr)methodID->method).Target);
|
||||
ParameterInfo* p __gc[] = m->GetParameters();
|
||||
Object* argarray __gc[] = new Object*[p->Length];
|
||||
|
@ -410,6 +423,7 @@ Object* JNIEnv::InvokeHelper(jobject object, jmethodID methodID, jvalue* args)
|
|||
pLocalRefs->PendingException = x->InnerException;
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void JNICALL JNIEnv::CallStaticVoidMethodA(jclass cls, jmethodID methodID, jvalue* args)
|
||||
|
@ -420,12 +434,17 @@ void JNICALL JNIEnv::CallStaticVoidMethodA(jclass cls, jmethodID methodID, jvalu
|
|||
|
||||
void JNICALL JNIEnv::CallStaticVoidMethodV(jclass clazz, jmethodID methodID, va_list args)
|
||||
{
|
||||
int argc = strlen(methodID->args);
|
||||
char arglist[257];
|
||||
int argc = GetMethodArgs(methodID, arglist);
|
||||
jvalue* argarray = (jvalue*)_alloca(argc * sizeof(jvalue));
|
||||
for(int i = 0; i < argc; i++)
|
||||
{
|
||||
switch(methodID->args[i])
|
||||
switch(arglist[i])
|
||||
{
|
||||
case 'Z':
|
||||
case 'B':
|
||||
case 'S':
|
||||
case 'C':
|
||||
case 'I':
|
||||
argarray[i].i = va_arg(args, int);
|
||||
break;
|
||||
|
@ -457,12 +476,17 @@ void JNIEnv::CallStaticVoidMethod(jclass clazz, jmethodID methodID, ...)
|
|||
#define STATIC_METHOD_IMPL(Type,type) \
|
||||
type JNICALL JNIEnv::CallStatic##Type##MethodV(jclass clazz, jmethodID methodID, va_list args)\
|
||||
{\
|
||||
int argc = strlen(methodID->args);\
|
||||
char sig[257];\
|
||||
int argc = GetMethodArgs(methodID, sig);\
|
||||
jvalue* argarray = (jvalue*)_alloca(argc * sizeof(jvalue));\
|
||||
for(int i = 0; i < argc; i++)\
|
||||
{\
|
||||
switch(methodID->args[i])\
|
||||
switch(sig[i])\
|
||||
{\
|
||||
case 'Z':\
|
||||
case 'B':\
|
||||
case 'S':\
|
||||
case 'C':\
|
||||
case 'I':\
|
||||
argarray[i].i = va_arg(args, int);\
|
||||
break;\
|
||||
|
@ -543,13 +567,11 @@ jfieldID JNICALL JNIEnv::GetStaticFieldID(jclass cls, const char *name, const ch
|
|||
#define GET_SET_FIELD(Type,type,cpptype) \
|
||||
void JNICALL JNIEnv::Set##Type##Field(jobject obj, jfieldID fieldID, type val)\
|
||||
{\
|
||||
FieldInfo* pField = __try_cast<FieldInfo*>(GCHandle::op_Explicit((IntPtr)fieldID->field).Target);\
|
||||
pField->SetValue(UnwrapRef(obj), __box((cpptype)val));\
|
||||
VM::SetFieldValue((IntPtr)fieldID, UnwrapRef(obj), __box((cpptype)val));\
|
||||
}\
|
||||
type JNICALL JNIEnv::Get##Type##Field(jobject obj, jfieldID fieldID)\
|
||||
{\
|
||||
FieldInfo* pField = __try_cast<FieldInfo*>(GCHandle::op_Explicit((IntPtr)fieldID->field).Target);\
|
||||
return __unbox<cpptype>(pField->GetValue(UnwrapRef(obj)));\
|
||||
return __unbox<cpptype>(VM::GetFieldValue((IntPtr)fieldID, UnwrapRef(obj)));\
|
||||
}
|
||||
|
||||
GET_SET_FIELD(Boolean,jboolean,bool)
|
||||
|
@ -563,14 +585,12 @@ GET_SET_FIELD(Double,jdouble,double)
|
|||
|
||||
void JNICALL JNIEnv::SetObjectField(jobject obj, jfieldID fieldID, jobject val)
|
||||
{
|
||||
FieldInfo* pField = __try_cast<FieldInfo*>(GCHandle::op_Explicit((IntPtr)fieldID->field).Target);
|
||||
pField->SetValue(UnwrapRef(obj), UnwrapRef(val));
|
||||
VM::SetFieldValue((IntPtr)fieldID, UnwrapRef(obj), UnwrapRef(val));
|
||||
}
|
||||
|
||||
jobject JNICALL JNIEnv::GetObjectField(jobject obj, jfieldID fieldID)
|
||||
{
|
||||
FieldInfo* pField = __try_cast<FieldInfo*>(GCHandle::op_Explicit((IntPtr)fieldID->field).Target);
|
||||
return (jobject)(void*)pLocalRefs->MakeLocalRef(pField->GetValue(UnwrapRef(obj)));
|
||||
return (jobject)(void*)pLocalRefs->MakeLocalRef(VM::GetFieldValue((IntPtr)fieldID, UnwrapRef(obj)));
|
||||
}
|
||||
#pragma unmanaged
|
||||
|
||||
|
@ -603,12 +623,17 @@ type JNIEnv::Call##Type##Method(jobject obj, jmethodID methodID, ...) \
|
|||
}\
|
||||
type JNICALL JNIEnv::Call##Type##MethodV(jobject obj, jmethodID methodID, va_list args)\
|
||||
{\
|
||||
int argc = strlen(methodID->args);\
|
||||
char sig[257];\
|
||||
int argc = GetMethodArgs(methodID, sig);\
|
||||
jvalue* argarray = (jvalue*)_alloca(argc * sizeof(jvalue));\
|
||||
for(int i = 0; i < argc; i++)\
|
||||
{\
|
||||
switch(methodID->args[i])\
|
||||
switch(sig[i])\
|
||||
{\
|
||||
case 'Z':\
|
||||
case 'B':\
|
||||
case 'S':\
|
||||
case 'C':\
|
||||
case 'I':\
|
||||
argarray[i].i = va_arg(args, int);\
|
||||
break;\
|
||||
|
@ -674,12 +699,17 @@ void JNIEnv::CallVoidMethod(jobject obj, jmethodID methodID, ...)
|
|||
|
||||
void JNICALL JNIEnv::CallVoidMethodV(jobject obj, jmethodID methodID, va_list args)
|
||||
{
|
||||
int argc = strlen(methodID->args);
|
||||
char sig[257];
|
||||
int argc = GetMethodArgs(methodID, sig);
|
||||
jvalue* argarray = (jvalue*)_alloca(argc * sizeof(jvalue));
|
||||
for(int i = 0; i < argc; i++)
|
||||
{
|
||||
switch(methodID->args[i])
|
||||
switch(sig[i])
|
||||
{
|
||||
case 'Z':
|
||||
case 'B':
|
||||
case 'S':
|
||||
case 'C':
|
||||
case 'I':
|
||||
argarray[i].i = va_arg(args, int);
|
||||
break;
|
||||
|
@ -857,12 +887,17 @@ jobject JNICALL JNIEnv::NewObject(jclass clazz, jmethodID methodID, ...)
|
|||
|
||||
jobject JNICALL JNIEnv::NewObjectV(jclass clazz, jmethodID methodID, va_list args)
|
||||
{
|
||||
int argc = strlen(methodID->args);
|
||||
char sig[257];
|
||||
int argc = GetMethodArgs(methodID, sig);
|
||||
jvalue* argarray = (jvalue*)_alloca(argc * sizeof(jvalue));
|
||||
for(int i = 0; i < argc; i++)
|
||||
{
|
||||
switch(methodID->args[i])
|
||||
switch(sig[i])
|
||||
{
|
||||
case 'Z':
|
||||
case 'B':
|
||||
case 'S':
|
||||
case 'C':
|
||||
case 'I':
|
||||
argarray[i].i = va_arg(args, int);
|
||||
break;
|
||||
|
|
|
@ -94,13 +94,10 @@ typedef struct _jfieldID* jfieldID;
|
|||
|
||||
struct _jmethodID
|
||||
{
|
||||
void* method;
|
||||
char args[257]; // 'I', 'J', 'L', 'D' or 'F', and terminated by '\0'
|
||||
};
|
||||
|
||||
struct _jfieldID
|
||||
{
|
||||
void* field;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -78,18 +78,13 @@ public class ByteCodeHelper
|
|||
TypeWrapper wrapper = classLoader.LoadClassBySlashedName(clazz);
|
||||
wrapper.Finish();
|
||||
// TODO who checks that the arg types are loadable?
|
||||
// TODO instead of getting the constructor from the type, we should use the (future) reflection support in MethodWrapper
|
||||
//MethodWrapper mw = wrapper.GetMethodWrapper(new MethodDescriptor(classLoader, name, sig), false);
|
||||
// TODO handle error, check access, etc.
|
||||
ConstructorInfo constructor = wrapper.Type.GetConstructor(classLoader.ArgTypeListFromSig(sig));
|
||||
try
|
||||
// TODO check accessibility
|
||||
MethodWrapper mw = wrapper.GetMethodWrapper(new MethodDescriptor(classLoader, name, sig), false);
|
||||
if(mw == null)
|
||||
{
|
||||
return constructor.Invoke(args);
|
||||
}
|
||||
catch(TargetInvocationException x)
|
||||
{
|
||||
ExceptionHelper.MapExceptionFast(x);
|
||||
throw x.InnerException;
|
||||
// TODO throw the appropriate exception
|
||||
throw new NotImplementedException("constructor missing");
|
||||
}
|
||||
return mw.Invoke(null, args, false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -127,7 +127,7 @@ class ClassLoaderWrapper
|
|||
internal void LoadRemappedTypes()
|
||||
{
|
||||
nativeMethods = new Hashtable();
|
||||
// TODO interfaces have java/lang/Object as the base type (do they really?)
|
||||
// NOTE interfaces have *not* java/lang/Object as the base type (even though they do in the class file)
|
||||
types["java.lang.Cloneable"] = new RemappedTypeWrapper(this, ModifiersAttribute.GetModifiers(typeof(java.lang.Cloneable)), "java/lang/Cloneable", typeof(java.lang.Cloneable), new TypeWrapper[0], null);
|
||||
typeToTypeWrapper.Add(typeof(java.lang.Cloneable), types["java.lang.Cloneable"]);
|
||||
types["java.io.Serializable"] = new RemappedTypeWrapper(this, ModifiersAttribute.GetModifiers(typeof(java.io.Serializable)), "java/io/Serializable", typeof(java.io.Serializable), new TypeWrapper[0], null);
|
||||
|
@ -360,7 +360,7 @@ class ClassLoaderWrapper
|
|||
// TODO copy accessibility from element type
|
||||
wrapper = new RemappedTypeWrapper(this, modifiers, name, array, interfaces, GetBootstrapClassLoader().LoadClassByDottedName("java.lang.Object"));
|
||||
MethodInfo clone = typeof(Array).GetMethod("Clone");
|
||||
MethodWrapper mw = new MethodWrapper(wrapper, mdClone, clone, Modifiers.Public);
|
||||
MethodWrapper mw = new MethodWrapper(wrapper, mdClone, clone, null, Modifiers.Public);
|
||||
mw.EmitCall = CodeEmitter.Create(OpCodes.Callvirt, clone);
|
||||
mw.EmitCallvirt = CodeEmitter.Create(OpCodes.Callvirt, clone);
|
||||
wrapper.AddMethod(mw);
|
||||
|
|
|
@ -212,7 +212,7 @@ public class ExceptionHelper
|
|||
for(int i = stackTrace.Count - 1; i >= 0; i--)
|
||||
{
|
||||
StackTraceElement ste = (StackTraceElement)stackTrace[i];
|
||||
if(ste.getClassName() == "System.Reflection.RuntimeMethodInfo")
|
||||
if(ste.getClassName() == "System.Reflection.MethodBase")
|
||||
{
|
||||
// skip method invocation by reflection, if it is at the top of the stack
|
||||
chop++;
|
||||
|
@ -242,12 +242,13 @@ public class ExceptionHelper
|
|||
Append(tracePart1);
|
||||
if(tracePart2 != null)
|
||||
{
|
||||
bool chopFirst = stackTrace.Count != 0;
|
||||
// don't have a clue why this was here, but it doesn't work for jni.class
|
||||
//bool chopFirst = stackTrace.Count != 0;
|
||||
Append(tracePart2);
|
||||
if(chopFirst && stackTrace.Count > 0 && JVM.CleanStackTraces)
|
||||
{
|
||||
stackTrace.RemoveAt(0);
|
||||
}
|
||||
//if(chopFirst && stackTrace.Count > 0 && JVM.CleanStackTraces)
|
||||
//{
|
||||
// stackTrace.RemoveAt(0);
|
||||
//}
|
||||
}
|
||||
tracePart1 = null;
|
||||
tracePart2 = null;
|
||||
|
|
|
@ -22,58 +22,91 @@
|
|||
|
||||
*/
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
public sealed class JniHelper
|
||||
{
|
||||
public static System.Reflection.MethodBase GetMethod(object clazz, string name, string sig, bool isStatic)
|
||||
public static IntPtr GetMethodCookie(object clazz, string name, string sig, bool isStatic)
|
||||
{
|
||||
// TODO this is totally broken, because JNI needs to support redirection
|
||||
TypeWrapper wrapper = ClassLoaderWrapper.GetWrapperFromType(NativeCode.java.lang.Class.getType(clazz));
|
||||
wrapper.Finish();
|
||||
MethodDescriptor md = new MethodDescriptor(wrapper.GetClassLoader(), name, sig);
|
||||
BindingFlags bindings = BindingFlags.Public | BindingFlags.NonPublic;
|
||||
if(isStatic)
|
||||
MethodWrapper mw = wrapper.GetMethodWrapper(new MethodDescriptor(wrapper.GetClassLoader(), name, sig), true);
|
||||
if(mw != null)
|
||||
{
|
||||
bindings |= BindingFlags.Static;
|
||||
}
|
||||
else
|
||||
{
|
||||
bindings |= BindingFlags.Instance;
|
||||
}
|
||||
if(name == "<init>")
|
||||
{
|
||||
return wrapper.Type.GetConstructor(bindings, null, md.ArgTypes, null);
|
||||
}
|
||||
Type type = wrapper.Type;
|
||||
while(type != null)
|
||||
{
|
||||
MethodInfo m = type.GetMethod(name, bindings, null, CallingConventions.Standard, md.ArgTypes, null);
|
||||
if(m != null)
|
||||
if(mw.IsStatic == isStatic)
|
||||
{
|
||||
return m;
|
||||
return mw.Cookie;
|
||||
}
|
||||
type = type.BaseType;
|
||||
}
|
||||
return null;
|
||||
return (IntPtr)0;
|
||||
}
|
||||
|
||||
public static System.Reflection.FieldInfo GetField(object clazz, string name, string sig, bool isStatic)
|
||||
// this method returns a simplified method argument descriptor.
|
||||
// some examples:
|
||||
// "()V" -> ""
|
||||
// "(ILjava/lang/String;)I" -> "IL"
|
||||
// "([Ljava/lang/String;)V" -> "L"
|
||||
public static string GetMethodArgList(IntPtr cookie)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
string s = MethodWrapper.FromCookie(cookie).Descriptor.Signature;
|
||||
for(int i = 1;; i++)
|
||||
{
|
||||
switch(s[i])
|
||||
{
|
||||
case '[':
|
||||
while(s[i] == '[') i++;
|
||||
if(s[i] == 'L')
|
||||
{
|
||||
while(s[i] != ';') i++;
|
||||
}
|
||||
sb.Append('L');
|
||||
break;
|
||||
case 'L':
|
||||
while(s[i] != ';') i++;
|
||||
sb.Append('L');
|
||||
break;
|
||||
case ')':
|
||||
return sb.ToString();
|
||||
default:
|
||||
sb.Append(s[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[StackTraceInfo(Hidden = true)]
|
||||
public static object InvokeMethod(IntPtr cookie, object obj, object[] args, bool nonVirtual)
|
||||
{
|
||||
return MethodWrapper.FromCookie(cookie).Invoke(obj, args, nonVirtual);
|
||||
}
|
||||
|
||||
public static IntPtr GetFieldCookie(object clazz, string name, string sig, bool isStatic)
|
||||
{
|
||||
// TODO this is totally broken, because JNI needs to support redirection
|
||||
TypeWrapper wrapper = ClassLoaderWrapper.GetWrapperFromType(NativeCode.java.lang.Class.getType(clazz));
|
||||
wrapper.Finish();
|
||||
MethodDescriptor md = new MethodDescriptor(wrapper.GetClassLoader(), name, sig);
|
||||
BindingFlags bindings = BindingFlags.Public | BindingFlags.NonPublic;
|
||||
if(isStatic)
|
||||
// TODO GetFieldWrapper should take sig (what about searching the base classes?)
|
||||
FieldWrapper fw = wrapper.GetFieldWrapper(name);
|
||||
if(fw != null)
|
||||
{
|
||||
bindings |= BindingFlags.Static;
|
||||
if(fw.IsStatic == isStatic)
|
||||
{
|
||||
return fw.Cookie;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bindings |= BindingFlags.Instance;
|
||||
}
|
||||
return wrapper.Type.GetField(name, bindings);
|
||||
return (IntPtr)0;
|
||||
}
|
||||
|
||||
public static void SetFieldValue(IntPtr cookie, object obj, object val)
|
||||
{
|
||||
FieldWrapper.FromCookie(cookie).SetValue(obj, val);
|
||||
}
|
||||
|
||||
public static object GetFieldValue(IntPtr cookie, object obj)
|
||||
{
|
||||
return FieldWrapper.FromCookie(cookie).GetValue(obj);
|
||||
}
|
||||
|
||||
public static object FindClass(string javaName)
|
||||
|
|
|
@ -164,8 +164,7 @@ public class StringHelper
|
|||
|
||||
public static bool startsWith(string s, string prefix, int toffset)
|
||||
{
|
||||
// TODO
|
||||
throw new NotImplementedException();
|
||||
return s.Substring(toffset).StartsWith(prefix);
|
||||
}
|
||||
|
||||
public static void getChars(string s, int srcBegin, int srcEnd, char[] dst, int dstBegin)
|
||||
|
|
|
@ -1781,6 +1781,7 @@ class DynamicTypeWrapper : TypeWrapper
|
|||
if(retTypeWrapper.IsUnloadable)
|
||||
{
|
||||
CustomAttributeBuilder attrib = new CustomAttributeBuilder(typeof(UnloadableTypeAttribute).GetConstructor(new Type[] { typeof(string) }), new object[] { retTypeWrapper.Name });
|
||||
// TODO DefineParameter(0, ...) throws an exception, even though this looks like the way to do it...
|
||||
((MethodBuilder)method).DefineParameter(0, ParameterAttributes.None, null).SetCustomAttribute(attrib);
|
||||
}
|
||||
for(int i = 0; i < argTypeWrappers.Length; i++)
|
||||
|
@ -2029,7 +2030,7 @@ class RemappedTypeWrapper : TypeWrapper
|
|||
invokevirtual = CodeEmitter.Create(OpCodes.Callvirt, (MethodInfo)overrideMethod);
|
||||
}
|
||||
}
|
||||
MethodWrapper mw = new MethodWrapper(this, md, overrideMethod, modifiers);
|
||||
MethodWrapper mw = new MethodWrapper(this, md, overrideMethod, redirect, modifiers);
|
||||
mw.EmitNewobj = newopc;
|
||||
mw.EmitCall = invokespecial;
|
||||
mw.EmitCallvirt = invokevirtual;
|
||||
|
@ -2143,7 +2144,7 @@ class RemappedTypeWrapper : TypeWrapper
|
|||
newopc = constructor.newobj;
|
||||
invokespecial = constructor.invokespecial;
|
||||
}
|
||||
MethodWrapper mw = new MethodWrapper(this, md, null, modifiers);
|
||||
MethodWrapper mw = new MethodWrapper(this, md, null, null, modifiers);
|
||||
mw.EmitNewobj = newopc;
|
||||
mw.EmitCall = invokespecial;
|
||||
if(retcast != null)
|
||||
|
@ -2551,7 +2552,7 @@ class NetExpTypeWrapper : TypeWrapper
|
|||
if(md.Name == "<init>" && type.IsSubclassOf(typeof(MulticastDelegate)))
|
||||
{
|
||||
// TODO set method flags
|
||||
MethodWrapper method = new MethodWrapper(this, md, null, Modifiers.Public);
|
||||
MethodWrapper method = new MethodWrapper(this, md, null, null, Modifiers.Public);
|
||||
// TODO what class loader should we use?
|
||||
TypeWrapper iface = ClassLoaderWrapper.GetBootstrapClassLoader().LoadClassBySlashedName(classFile.Name + "$Method");
|
||||
iface.Finish();
|
||||
|
@ -2812,7 +2813,7 @@ class CompiledTypeWrapper : TypeWrapper
|
|||
{
|
||||
return null;
|
||||
}
|
||||
MethodWrapper method = new MethodWrapper(this, md, mb, ModifiersAttribute.GetModifiers(mb));
|
||||
MethodWrapper method = new MethodWrapper(this, md, mb, null, ModifiersAttribute.GetModifiers(mb));
|
||||
if(mb is ConstructorInfo)
|
||||
{
|
||||
method.EmitCall = CodeEmitter.Create(OpCodes.Call, (ConstructorInfo)mb);
|
||||
|
@ -3116,9 +3117,11 @@ public abstract class CodeEmitter
|
|||
|
||||
sealed class MethodWrapper
|
||||
{
|
||||
private IntPtr cookie;
|
||||
private TypeWrapper declaringType;
|
||||
private MethodDescriptor md;
|
||||
private MethodBase originalMethod;
|
||||
private MethodBase redirMethod;
|
||||
private Modifiers modifiers;
|
||||
private bool isRemappedVirtual;
|
||||
private bool isRemappedOverride;
|
||||
|
@ -3126,13 +3129,14 @@ sealed class MethodWrapper
|
|||
internal CodeEmitter EmitCallvirt;
|
||||
internal CodeEmitter EmitNewobj;
|
||||
|
||||
// TODO creation of MethodWrappers should be cleaned up (and every instance should support Invoke())
|
||||
internal static MethodWrapper Create(TypeWrapper declaringType, MethodDescriptor md, MethodBase originalMethod, MethodBase method, Modifiers modifiers)
|
||||
{
|
||||
if(method == null)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
MethodWrapper wrapper = new MethodWrapper(declaringType, md, originalMethod, modifiers);
|
||||
MethodWrapper wrapper = new MethodWrapper(declaringType, md, originalMethod, method, modifiers);
|
||||
if(method is ConstructorInfo)
|
||||
{
|
||||
wrapper.EmitCall = CodeEmitter.Create(OpCodes.Call, (ConstructorInfo)method);
|
||||
|
@ -3162,8 +3166,13 @@ sealed class MethodWrapper
|
|||
return wrapper;
|
||||
}
|
||||
|
||||
internal MethodWrapper(TypeWrapper declaringType, MethodDescriptor md, MethodBase originalMethod, Modifiers modifiers)
|
||||
internal MethodWrapper(TypeWrapper declaringType, MethodDescriptor md, MethodBase originalMethod, MethodBase method, Modifiers modifiers)
|
||||
{
|
||||
if(method != originalMethod)
|
||||
{
|
||||
redirMethod = method;
|
||||
Debug.Assert(!(method is MethodBuilder));
|
||||
}
|
||||
this.declaringType = declaringType;
|
||||
this.md = md;
|
||||
// NOTE originalMethod may be null
|
||||
|
@ -3171,6 +3180,23 @@ sealed class MethodWrapper
|
|||
this.modifiers = modifiers;
|
||||
}
|
||||
|
||||
internal IntPtr Cookie
|
||||
{
|
||||
get
|
||||
{
|
||||
if(cookie == (IntPtr)0)
|
||||
{
|
||||
cookie = (IntPtr)System.Runtime.InteropServices.GCHandle.Alloc(this);
|
||||
}
|
||||
return cookie;
|
||||
}
|
||||
}
|
||||
|
||||
internal static MethodWrapper FromCookie(IntPtr cookie)
|
||||
{
|
||||
return (MethodWrapper)((System.Runtime.InteropServices.GCHandle)cookie).Target;
|
||||
}
|
||||
|
||||
internal TypeWrapper DeclaringType
|
||||
{
|
||||
get
|
||||
|
@ -3342,6 +3368,85 @@ sealed class MethodWrapper
|
|||
return (modifiers & Modifiers.Abstract) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
internal object Invoke(object obj, object[] args, bool nonVirtual)
|
||||
{
|
||||
// TODO instead of looking up the method using reflection, we should use the method object passed into the
|
||||
// constructor
|
||||
if(IsStatic)
|
||||
{
|
||||
MethodInfo method = this.originalMethod != null && !(this.originalMethod is MethodBuilder) ? (MethodInfo)this.originalMethod : declaringType.Type.GetMethod(md.Name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, md.ArgTypes, null);
|
||||
try
|
||||
{
|
||||
return method.Invoke(null, args);
|
||||
}
|
||||
catch(TargetInvocationException x)
|
||||
{
|
||||
throw ExceptionHelper.MapExceptionFast(x.InnerException);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// calling <init> without an instance means that we're constructing a new instance
|
||||
// NOTE this means that we cannot detect a NullPointerException when calling <init>
|
||||
if(md.Name == "<init>")
|
||||
{
|
||||
if(obj == null)
|
||||
{
|
||||
ConstructorInfo constructor = this.originalMethod != null && !(this.originalMethod is ConstructorBuilder) ? (ConstructorInfo)this.originalMethod : declaringType.Type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, CallingConventions.Standard, md.ArgTypes, null);
|
||||
try
|
||||
{
|
||||
return constructor.Invoke(args);
|
||||
}
|
||||
catch(TargetInvocationException x)
|
||||
{
|
||||
throw ExceptionHelper.MapExceptionFast(x.InnerException);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotImplementedException("invoking constructor on existing instance");
|
||||
}
|
||||
}
|
||||
if(nonVirtual)
|
||||
{
|
||||
throw new NotImplementedException("non-virtual reflective method invocation non implemented");
|
||||
}
|
||||
MethodInfo method = (MethodInfo)this.originalMethod;
|
||||
if(redirMethod != null)
|
||||
{
|
||||
method = (MethodInfo)redirMethod;
|
||||
if(method.IsStatic)
|
||||
{
|
||||
// we've been redirected to a static method, so we have to copy the this into the args
|
||||
object[] oldargs = args;
|
||||
args = new object[args.Length + 1];
|
||||
args[0] = obj;
|
||||
oldargs.CopyTo(args, 1);
|
||||
obj = null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(method is MethodBuilder || method == null)
|
||||
{
|
||||
method = declaringType.Type.GetMethod(md.Name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, md.ArgTypes, null);
|
||||
}
|
||||
if(method == null)
|
||||
{
|
||||
throw new NotImplementedException("method not found: " + this.declaringType.Name + "." + md.Name + md.Signature);
|
||||
}
|
||||
}
|
||||
try
|
||||
{
|
||||
return method.Invoke(obj, args);
|
||||
}
|
||||
catch(TargetInvocationException x)
|
||||
{
|
||||
throw ExceptionHelper.MapExceptionFast(x.InnerException);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CastEmitter : CodeEmitter
|
||||
|
@ -3395,6 +3500,7 @@ sealed class FieldWrapper
|
|||
private string name;
|
||||
private string sig;
|
||||
private Modifiers modifiers;
|
||||
private IntPtr cookie;
|
||||
internal CodeEmitter EmitGet;
|
||||
internal CodeEmitter EmitSet;
|
||||
|
||||
|
@ -3410,6 +3516,23 @@ sealed class FieldWrapper
|
|||
this.modifiers = modifiers;
|
||||
}
|
||||
|
||||
internal IntPtr Cookie
|
||||
{
|
||||
get
|
||||
{
|
||||
if(cookie == (IntPtr)0)
|
||||
{
|
||||
cookie = (IntPtr)System.Runtime.InteropServices.GCHandle.Alloc(this);
|
||||
}
|
||||
return cookie;
|
||||
}
|
||||
}
|
||||
|
||||
internal static FieldWrapper FromCookie(IntPtr cookie)
|
||||
{
|
||||
return (FieldWrapper)((System.Runtime.InteropServices.GCHandle)cookie).Target;
|
||||
}
|
||||
|
||||
internal TypeWrapper DeclaringType
|
||||
{
|
||||
get
|
||||
|
@ -3609,4 +3732,34 @@ sealed class FieldWrapper
|
|||
}
|
||||
return field;
|
||||
}
|
||||
|
||||
internal void SetValue(object obj, object val)
|
||||
{
|
||||
// TODO this is a broken implementation (for one thing, it needs to support redirection)
|
||||
BindingFlags bindings = BindingFlags.Public | BindingFlags.NonPublic;
|
||||
if(IsStatic)
|
||||
{
|
||||
bindings |= BindingFlags.Static;
|
||||
}
|
||||
else
|
||||
{
|
||||
bindings |= BindingFlags.Instance;
|
||||
}
|
||||
DeclaringType.Type.GetField(name, bindings).SetValue(obj, val);
|
||||
}
|
||||
|
||||
internal object GetValue(object obj)
|
||||
{
|
||||
// TODO this is a broken implementation (for one thing, it needs to support redirection)
|
||||
BindingFlags bindings = BindingFlags.Public | BindingFlags.NonPublic;
|
||||
if(IsStatic)
|
||||
{
|
||||
bindings |= BindingFlags.Static;
|
||||
}
|
||||
else
|
||||
{
|
||||
bindings |= BindingFlags.Instance;
|
||||
}
|
||||
return DeclaringType.Type.GetField(name, bindings).GetValue(obj);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -172,6 +172,59 @@ namespace NativeCode.java
|
|||
}
|
||||
}
|
||||
|
||||
internal class JavaWrapper
|
||||
{
|
||||
private static Type java_lang_Integer = ClassLoaderWrapper.GetType("java.lang.Integer");
|
||||
private static Type java_lang_Short = ClassLoaderWrapper.GetType("java.lang.Short");
|
||||
private static Type java_lang_Boolean = ClassLoaderWrapper.GetType("java.lang.Boolean");
|
||||
private static Type java_lang_Long = ClassLoaderWrapper.GetType("java.lang.Long");
|
||||
|
||||
internal static object Box(object o)
|
||||
{
|
||||
if(o is int)
|
||||
{
|
||||
return Activator.CreateInstance(java_lang_Integer, new object[] { o });
|
||||
}
|
||||
else if(o is bool)
|
||||
{
|
||||
return Activator.CreateInstance(java_lang_Boolean, new object[] { o });
|
||||
}
|
||||
else if(o is long)
|
||||
{
|
||||
return Activator.CreateInstance(java_lang_Long, new object[] { o });
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotImplementedException(o.GetType().FullName);
|
||||
}
|
||||
}
|
||||
|
||||
internal static object Unbox(object o)
|
||||
{
|
||||
Type type = o.GetType();
|
||||
if(type == java_lang_Integer)
|
||||
{
|
||||
return java_lang_Integer.GetMethod("intValue").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_Long)
|
||||
{
|
||||
return java_lang_Long.GetMethod("longValue").Invoke(o, new object[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotImplementedException(o.GetType().FullName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Method
|
||||
{
|
||||
public static String GetName(object methodCookie)
|
||||
|
@ -211,98 +264,25 @@ namespace NativeCode.java
|
|||
return new object[0];
|
||||
}
|
||||
|
||||
[StackTraceInfo(Hidden = true)]
|
||||
public static object Invoke(object methodCookie, object o, object[] args)
|
||||
{
|
||||
// TODO this is a very lame implementation, no where near correct
|
||||
MethodWrapper wrapper = (MethodWrapper)methodCookie;
|
||||
wrapper.DeclaringType.Finish();
|
||||
TypeWrapper[] argWrappers = wrapper.GetParameters();
|
||||
Type[] argTypes = new Type[argWrappers.Length];
|
||||
for(int i = 0; i < argTypes.Length; i++)
|
||||
MethodWrapper mw = (MethodWrapper)methodCookie;
|
||||
mw.DeclaringType.Finish();
|
||||
TypeWrapper[] argWrappers = mw.GetParameters();
|
||||
for(int i = 0; i < argWrappers.Length; i++)
|
||||
{
|
||||
argWrappers[i].Finish();
|
||||
argTypes[i] = argWrappers[i].Type;
|
||||
if(argTypes[i].IsPrimitive)
|
||||
if(argWrappers[i].IsPrimitive)
|
||||
{
|
||||
if(argTypes[i] == typeof(int))
|
||||
{
|
||||
args[i] = ClassLoaderWrapper.GetType("java.lang.Integer").GetMethod("intValue").Invoke(args[i], new object[0]);
|
||||
}
|
||||
else if(argTypes[i] == typeof(bool))
|
||||
{
|
||||
args[i] = ClassLoaderWrapper.GetType("java.lang.Boolean").GetMethod("booleanValue").Invoke(args[i], new object[0]);
|
||||
}
|
||||
else if(argTypes[i] == typeof(short))
|
||||
{
|
||||
args[i] = ClassLoaderWrapper.GetType("java.lang.Short").GetMethod("shortValue").Invoke(args[i], new object[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotImplementedException("argtype: " + argTypes[i].FullName);
|
||||
}
|
||||
args[i] = JavaWrapper.Unbox(args[i]);
|
||||
}
|
||||
}
|
||||
try
|
||||
object retval = mw.Invoke(o, args, false);
|
||||
if(mw.ReturnType.IsPrimitive && mw.ReturnType != PrimitiveTypeWrapper.VOID)
|
||||
{
|
||||
if(wrapper.Name == "<init>")
|
||||
{
|
||||
if(o == null)
|
||||
{
|
||||
return wrapper.DeclaringType.Type.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null, argTypes, null).Invoke(args);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotImplementedException("invoking constructor on existing instance");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MethodInfo mi;
|
||||
if(wrapper.GetMethod() is NetSystem.Reflection.Emit.MethodBuilder || wrapper.GetMethod() == null)
|
||||
{
|
||||
mi = wrapper.DeclaringType.Type.GetMethod(wrapper.Name, BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null, argTypes, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
mi = (MethodInfo)wrapper.GetMethod();
|
||||
}
|
||||
if(mi == null)
|
||||
{
|
||||
throw new InvalidOperationException("Method not found: " + wrapper.DeclaringType.Name + "." + wrapper.Name + wrapper.Descriptor.Signature);
|
||||
}
|
||||
object retval = mi.Invoke(o, args);
|
||||
if(wrapper.ReturnType.Type.IsValueType)
|
||||
{
|
||||
if(wrapper.ReturnType.Type == typeof(int))
|
||||
{
|
||||
retval = Activator.CreateInstance(ClassLoaderWrapper.GetType("java.lang.Integer"), new object[] { (int)retval });
|
||||
}
|
||||
else if(wrapper.ReturnType.Type == typeof(bool))
|
||||
{
|
||||
retval = Activator.CreateInstance(ClassLoaderWrapper.GetType("java.lang.Boolean"), new object[] { (bool)retval });
|
||||
}
|
||||
else if(wrapper.ReturnType.Type == typeof(void))
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotImplementedException("rettype: " + wrapper.ReturnType.Type.FullName);
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
retval = JavaWrapper.Box(retval);
|
||||
}
|
||||
catch(TargetInvocationException x)
|
||||
{
|
||||
throw JavaException.InvocationTargetException(ExceptionHelper.MapException(x.InnerException, typeof(Exception)));
|
||||
}
|
||||
}
|
||||
|
||||
// TODO remove this, it isn't used anymore
|
||||
public static Exception mapException(Exception x)
|
||||
{
|
||||
return ExceptionHelper.MapException(x, typeof(Exception));
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -366,20 +346,21 @@ namespace NativeCode.java
|
|||
{
|
||||
MethodInfo m = properties.GetType().GetMethod("setProperty");
|
||||
// TODO set all these properties to something useful
|
||||
m.Invoke(properties, new string[] { "java.version", "1.1" });
|
||||
m.Invoke(properties, new string[] { "java.version", "1.3" });
|
||||
m.Invoke(properties, new string[] { "java.vendor", "Jeroen Frijters" });
|
||||
m.Invoke(properties, new string[] { "java.vendor.url", "http://jeroen.nu/" });
|
||||
m.Invoke(properties, new string[] { "java.home", "" });
|
||||
m.Invoke(properties, new string[] { "java.vm.specification.version", "" });
|
||||
m.Invoke(properties, new string[] { "java.vm.specification.vendor", "" });
|
||||
m.Invoke(properties, new string[] { "java.vm.specification.name", "" });
|
||||
m.Invoke(properties, new string[] { "java.vm.version", "" });
|
||||
m.Invoke(properties, new string[] { "java.vm.vendor", "" });
|
||||
m.Invoke(properties, new string[] { "java.vm.name", "" });
|
||||
m.Invoke(properties, new string[] { "java.specification.version", "" });
|
||||
m.Invoke(properties, new string[] { "java.specification.vendor", "" });
|
||||
m.Invoke(properties, new string[] { "java.specification.name", "" });
|
||||
m.Invoke(properties, new string[] { "java.class.version", "" });
|
||||
m.Invoke(properties, new string[] { "java.vendor.url", "http://ikvm.net/" });
|
||||
// HACK using the Assembly.Location property isn't correct
|
||||
m.Invoke(properties, new string[] { "java.home", new FileInfo(typeof(Runtime).Assembly.Location).DirectoryName });
|
||||
m.Invoke(properties, new string[] { "java.vm.specification.version", "1.0" });
|
||||
m.Invoke(properties, new string[] { "java.vm.specification.vendor", "Sun Microsystems Inc." });
|
||||
m.Invoke(properties, new string[] { "java.vm.specification.name", "Java Virtual Machine Specification" });
|
||||
m.Invoke(properties, new string[] { "java.vm.version", typeof(Runtime).Assembly.GetName().Version.ToString() });
|
||||
m.Invoke(properties, new string[] { "java.vm.vendor", "Jeroen Frijters" });
|
||||
m.Invoke(properties, new string[] { "java.vm.name", "IKVM.NET" });
|
||||
m.Invoke(properties, new string[] { "java.specification.version", "1.3" });
|
||||
m.Invoke(properties, new string[] { "java.specification.vendor", "Sun Microsystems Inc." });
|
||||
m.Invoke(properties, new string[] { "java.specification.name", "Java Platform API Specification" });
|
||||
m.Invoke(properties, new string[] { "java.class.version", "48.0" });
|
||||
string classpath = Environment.GetEnvironmentVariable("CLASSPATH");
|
||||
if(classpath == null)
|
||||
{
|
||||
|
@ -390,15 +371,20 @@ namespace NativeCode.java
|
|||
m.Invoke(properties, new string[] { "java.io.tmpdir", Path.GetTempPath() });
|
||||
m.Invoke(properties, new string[] { "java.compiler", "" });
|
||||
m.Invoke(properties, new string[] { "java.ext.dirs", "" });
|
||||
m.Invoke(properties, new string[] { "os.name", "Windows" });
|
||||
m.Invoke(properties, new string[] { "os.arch", "" });
|
||||
m.Invoke(properties, new string[] { "os.version", Environment.OSVersion.ToString() });
|
||||
// NOTE os.name *must* contain "Windows" when running on Windows, because Classpath tests on that
|
||||
string osname = Environment.OSVersion.ToString();
|
||||
string osver = Environment.OSVersion.Version.ToString();
|
||||
// HACK if the osname contains the version, we remove it
|
||||
osname = osname.Replace(osver, "").Trim();
|
||||
m.Invoke(properties, new string[] { "os.name", osname });
|
||||
m.Invoke(properties, new string[] { "os.arch", Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE") });
|
||||
m.Invoke(properties, new string[] { "os.version", osver });
|
||||
m.Invoke(properties, new string[] { "file.separator", Path.DirectorySeparatorChar.ToString() });
|
||||
m.Invoke(properties, new string[] { "file.encoding", "8859_1" });
|
||||
m.Invoke(properties, new string[] { "path.separator", Path.PathSeparator.ToString() });
|
||||
m.Invoke(properties, new string[] { "line.separator", Environment.NewLine });
|
||||
m.Invoke(properties, new string[] { "user.name", Environment.UserName });
|
||||
m.Invoke(properties, new string[] { "user.home", "" });
|
||||
m.Invoke(properties, new string[] { "user.home", Environment.GetEnvironmentVariable("USERPROFILE") });
|
||||
m.Invoke(properties, new string[] { "user.dir", Environment.CurrentDirectory });
|
||||
m.Invoke(properties, new string[] { "awt.toolkit", "ikvm.awt.NetToolkit, awt, Version=1.0, Culture=neutral, PublicKeyToken=null" });
|
||||
}
|
||||
|
@ -416,6 +402,7 @@ namespace NativeCode.java
|
|||
|
||||
public static int nativeLoad(object obj, string filename)
|
||||
{
|
||||
// TODO native libraries somehow need to be scoped by class loader
|
||||
return JVM.JniProvider.LoadNativeLibrary(filename);
|
||||
}
|
||||
|
||||
|
@ -656,39 +643,6 @@ namespace NativeCode.java
|
|||
}
|
||||
}
|
||||
|
||||
/* not used anymore
|
||||
public class System
|
||||
{
|
||||
public static bool isWordsBigEndian()
|
||||
{
|
||||
return !BitConverter.IsLittleEndian;
|
||||
}
|
||||
|
||||
private static long timebase = ((TimeZone.CurrentTimeZone.ToUniversalTime(DateTime.Now) - new DateTime(1970, 1, 1)).Ticks / 10000L) - Environment.TickCount;
|
||||
|
||||
public static long currentTimeMillis()
|
||||
{
|
||||
// NOTE this wraps after 24.9 days, but it is much faster than calling DateTime.Now every time
|
||||
return timebase + Environment.TickCount;
|
||||
}
|
||||
|
||||
public static void setErr0(object printStream)
|
||||
{
|
||||
ClassLoaderWrapper.GetType("java.lang.System").GetField("err", BindingFlags.Static | BindingFlags.NonPublic).SetValue(null, printStream);
|
||||
}
|
||||
|
||||
public static void setIn0(object inputStream)
|
||||
{
|
||||
ClassLoaderWrapper.GetType("java.lang.System").GetField("in", BindingFlags.Static | BindingFlags.NonPublic).SetValue(null, inputStream);
|
||||
}
|
||||
|
||||
public static void setOut0(object printStream)
|
||||
{
|
||||
ClassLoaderWrapper.GetType("java.lang.System").GetField("out", BindingFlags.Static | BindingFlags.NonPublic).SetValue(null, printStream);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
public class VMSystem
|
||||
{
|
||||
public static void arraycopy(object src, int srcStart, object dest, int destStart, int len)
|
||||
|
|
|
@ -481,7 +481,7 @@ class Compiler
|
|||
throw new NotImplementedException("branch into try block not implemented: " + clazz.Name + "." + m.Method.Name + m.Method.Signature + " (index = " + exceptionIndex + ", pc = " + instr.PC + ")");
|
||||
}
|
||||
|
||||
// every instruction has an associated label, for now
|
||||
// TODO for now, every instruction has an associated label, optimize this
|
||||
if(true)
|
||||
{
|
||||
object label = labels[instr.PC];
|
||||
|
@ -991,166 +991,147 @@ class Compiler
|
|||
thisType = null;
|
||||
}
|
||||
MethodWrapper method = (thisType != null) ? GetMethod(cpi, thisType, instr.NormalizedOpCode) : null;
|
||||
CodeEmitter emit = null;
|
||||
if(instr.NormalizedOpCode == NormalizedByteCode.__invokespecial)
|
||||
{
|
||||
if(cpi.Name == "<init>")
|
||||
emit = method.EmitCall;
|
||||
}
|
||||
else
|
||||
{
|
||||
emit = method.EmitCallvirt;
|
||||
}
|
||||
if(instr.NormalizedOpCode == NormalizedByteCode.__invokespecial && cpi.Name == "<init>")
|
||||
{
|
||||
if(VerifierTypeWrapper.IsNew(type))
|
||||
{
|
||||
if(VerifierTypeWrapper.IsNew(type))
|
||||
if(!thisType.IsUnloadable && (thisType.IsAbstract || thisType.IsInterface))
|
||||
{
|
||||
if(!thisType.IsUnloadable && (thisType.IsAbstract || thisType.IsInterface))
|
||||
// the CLR gets confused when we do a newobj on an abstract class,
|
||||
// so we set method to null, to basically just comment out the constructor
|
||||
// call (the InstantiationError was already emitted at the "new" bytecode)
|
||||
method = null;
|
||||
}
|
||||
// we have to construct a list of all the unitialized references to the object
|
||||
// we're about to create on the stack, so that we can reconstruct the stack after
|
||||
// the "newobj" instruction
|
||||
int trivcount = 0;
|
||||
bool nontrivial = false;
|
||||
bool[] stackfix = new bool[ma.GetStackHeight(i) - (argcount + 1)];
|
||||
bool[] localsfix = new bool[m.MaxLocals];
|
||||
for(int j = 0; j < stackfix.Length; j++)
|
||||
{
|
||||
if(ma.GetRawStackTypeWrapper(i, argcount + 1 + j) == type)
|
||||
{
|
||||
// the CLR gets confused when we do a newobj on an abstract class,
|
||||
// so we set method to null, to basically just comment out the constructor
|
||||
// call (the InstantiationError was already emitted at the "new" bytecode)
|
||||
method = null;
|
||||
stackfix[j] = true;
|
||||
if(trivcount == j)
|
||||
{
|
||||
trivcount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// if there is other stuff on the stack between the new object
|
||||
// references, we need to do more work to construct the proper stack
|
||||
// layout after the newobj instruction
|
||||
nontrivial = true;
|
||||
}
|
||||
}
|
||||
// we have to construct a list of all the unitialized references to the object
|
||||
// we're about to create on the stack, so that we can reconstruct the stack after
|
||||
// the "newobj" instruction
|
||||
int trivcount = 0;
|
||||
bool nontrivial = false;
|
||||
bool[] stackfix = new bool[ma.GetStackHeight(i) - (argcount + 1)];
|
||||
bool[] localsfix = new bool[m.MaxLocals];
|
||||
}
|
||||
for(int j = 0; j < localsfix.Length; j++)
|
||||
{
|
||||
if(ma.GetLocalTypeWrapper(i, j) == type)
|
||||
{
|
||||
localsfix[j] = true;
|
||||
nontrivial = true;
|
||||
}
|
||||
}
|
||||
if(method != null)
|
||||
{
|
||||
method.EmitNewobj.Emit(ilGenerator);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int j = 0; j < argcount; j++)
|
||||
{
|
||||
ilGenerator.Emit(OpCodes.Pop);
|
||||
}
|
||||
ilGenerator.Emit(OpCodes.Ldnull);
|
||||
}
|
||||
if(java_lang_Throwable == null)
|
||||
{
|
||||
java_lang_Throwable = ClassLoaderWrapper.GetBootstrapClassLoader().LoadClassBySlashedName("java/lang/Throwable");
|
||||
}
|
||||
if(thisType.IsSubTypeOf(java_lang_Throwable))
|
||||
{
|
||||
// HACK if the next instruction isn't an athrow, we need to
|
||||
// call fillInStackTrace, because the object might be used
|
||||
// to print out a stack trace without ever being thrown
|
||||
if(code[i + 1].NormalizedOpCode != NormalizedByteCode.__athrow)
|
||||
{
|
||||
ilGenerator.Emit(OpCodes.Dup);
|
||||
ilGenerator.Emit(OpCodes.Call, fillInStackTraceMethod);
|
||||
ilGenerator.Emit(OpCodes.Pop);
|
||||
}
|
||||
}
|
||||
if(nontrivial)
|
||||
{
|
||||
// this could be done a little more efficiently, but since in practice this
|
||||
// code never runs (for code compiled from Java source) it doesn't
|
||||
// really matter
|
||||
LocalBuilder newobj = ilGenerator.DeclareLocal(thisType.Type);
|
||||
ilGenerator.Emit(OpCodes.Stloc, newobj);
|
||||
LocalBuilder[] tempstack = new LocalBuilder[stackfix.Length];
|
||||
for(int j = 0; j < stackfix.Length; j++)
|
||||
{
|
||||
if(ma.GetRawStackTypeWrapper(i, argcount + 1 + j) == type)
|
||||
if(!stackfix[j])
|
||||
{
|
||||
stackfix[j] = true;
|
||||
if(trivcount == j)
|
||||
TypeWrapper stacktype = ma.GetRawStackTypeWrapper(i, argcount + 1 + j);
|
||||
// it could be another new object reference (not from current invokespecial <init>
|
||||
// instruction)
|
||||
if(stacktype == VerifierTypeWrapper.Null)
|
||||
{
|
||||
trivcount++;
|
||||
// TODO handle null stack entries
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
else
|
||||
else if(!VerifierTypeWrapper.IsNew(stacktype))
|
||||
{
|
||||
// if there is other stuff on the stack between the new object
|
||||
// references, we need to do more work to construct the proper stack
|
||||
// layout after the newobj instruction
|
||||
nontrivial = true;
|
||||
LocalBuilder lb = ilGenerator.DeclareLocal(stacktype.TypeOrUnloadableAsObject);
|
||||
ilGenerator.Emit(OpCodes.Stloc, lb);
|
||||
tempstack[j] = lb;
|
||||
}
|
||||
}
|
||||
}
|
||||
for(int j = stackfix.Length - 1; j >= 0; j--)
|
||||
{
|
||||
if(stackfix[j])
|
||||
{
|
||||
ilGenerator.Emit(OpCodes.Ldloc, newobj);
|
||||
}
|
||||
else if(tempstack[j] != null)
|
||||
{
|
||||
ilGenerator.Emit(OpCodes.Ldloc, tempstack[j]);
|
||||
}
|
||||
}
|
||||
for(int j = 0; j < localsfix.Length; j++)
|
||||
{
|
||||
if(ma.GetLocalTypeWrapper(i, j) == type)
|
||||
if(localsfix[j])
|
||||
{
|
||||
localsfix[j] = true;
|
||||
nontrivial = true;
|
||||
}
|
||||
}
|
||||
if(method != null)
|
||||
{
|
||||
method.EmitNewobj.Emit(ilGenerator);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int j = 0; j < argcount; j++)
|
||||
{
|
||||
ilGenerator.Emit(OpCodes.Pop);
|
||||
}
|
||||
ilGenerator.Emit(OpCodes.Ldnull);
|
||||
}
|
||||
if(java_lang_Throwable == null)
|
||||
{
|
||||
java_lang_Throwable = ClassLoaderWrapper.GetBootstrapClassLoader().LoadClassBySlashedName("java/lang/Throwable");
|
||||
}
|
||||
if(thisType.IsSubTypeOf(java_lang_Throwable))
|
||||
{
|
||||
// HACK if the next instruction isn't an athrow, we need to
|
||||
// call fillInStackTrace, because the object might be used
|
||||
// to print out a stack trace without ever being thrown
|
||||
if(code[i + 1].NormalizedOpCode != NormalizedByteCode.__athrow)
|
||||
{
|
||||
ilGenerator.Emit(OpCodes.Dup);
|
||||
ilGenerator.Emit(OpCodes.Call, fillInStackTraceMethod);
|
||||
ilGenerator.Emit(OpCodes.Pop);
|
||||
}
|
||||
}
|
||||
if(nontrivial)
|
||||
{
|
||||
// this could be done a little more efficiently, but since in practice this
|
||||
// code never runs (for code compiled from Java source) it doesn't
|
||||
// really matter
|
||||
LocalBuilder newobj = ilGenerator.DeclareLocal(thisType.Type);
|
||||
ilGenerator.Emit(OpCodes.Stloc, newobj);
|
||||
LocalBuilder[] tempstack = new LocalBuilder[stackfix.Length];
|
||||
for(int j = 0; j < stackfix.Length; j++)
|
||||
{
|
||||
if(!stackfix[j])
|
||||
{
|
||||
TypeWrapper stacktype = ma.GetRawStackTypeWrapper(i, argcount + 1 + j);
|
||||
// it could be another new object reference (not from current invokespecial <init>
|
||||
// instruction)
|
||||
if(stacktype == VerifierTypeWrapper.Null)
|
||||
{
|
||||
// TODO handle null stack entries
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
else if(!VerifierTypeWrapper.IsNew(stacktype))
|
||||
{
|
||||
LocalBuilder lb = ilGenerator.DeclareLocal(stacktype.TypeOrUnloadableAsObject);
|
||||
ilGenerator.Emit(OpCodes.Stloc, lb);
|
||||
tempstack[j] = lb;
|
||||
}
|
||||
}
|
||||
}
|
||||
for(int j = stackfix.Length - 1; j >= 0; j--)
|
||||
{
|
||||
if(stackfix[j])
|
||||
{
|
||||
ilGenerator.Emit(OpCodes.Ldloc, newobj);
|
||||
}
|
||||
else if(tempstack[j] != null)
|
||||
{
|
||||
ilGenerator.Emit(OpCodes.Ldloc, tempstack[j]);
|
||||
}
|
||||
}
|
||||
for(int j = 0; j < localsfix.Length; j++)
|
||||
{
|
||||
if(localsfix[j])
|
||||
{
|
||||
ilGenerator.Emit(OpCodes.Ldloc, newobj);
|
||||
ilGenerator.Emit(OpCodes.Stloc, GetLocal(typeof(object), j));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(trivcount == 0)
|
||||
{
|
||||
ilGenerator.Emit(OpCodes.Pop);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int j = 1; j < trivcount; j++)
|
||||
{
|
||||
ilGenerator.Emit(OpCodes.Dup);
|
||||
}
|
||||
ilGenerator.Emit(OpCodes.Ldloc, newobj);
|
||||
ilGenerator.Emit(OpCodes.Stloc, GetLocal(typeof(object), j));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(method != null)
|
||||
if(trivcount == 0)
|
||||
{
|
||||
method.EmitCall.Emit(ilGenerator);
|
||||
ilGenerator.Emit(OpCodes.Pop);
|
||||
}
|
||||
else
|
||||
{
|
||||
// if we're a constructor and the call to the base class constructor
|
||||
// wasn't accessible, we need make sure that there is no code path that
|
||||
// returns from the constructor, otherwise the method will be not verifiable
|
||||
// TODO this isn't anywhere near a proper solution, but for the time being it works
|
||||
// some things to consider:
|
||||
// - only pull this full when calls to the base class constructor fail
|
||||
// - when control flow is complex, this trivial solution will not work
|
||||
ilGenerator.Emit(OpCodes.Ldnull);
|
||||
ilGenerator.Emit(OpCodes.Throw);
|
||||
return;
|
||||
// for(int j = 0; j < argcount + 1; j++)
|
||||
// {
|
||||
// ilGenerator.Emit(OpCodes.Pop);
|
||||
// }
|
||||
// EmitPlaceholder(cpi.Signature.Substring(cpi.Signature.LastIndexOf(')') + 1));
|
||||
for(int j = 1; j < trivcount; j++)
|
||||
{
|
||||
ilGenerator.Emit(OpCodes.Dup);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1162,19 +1143,29 @@ class Compiler
|
|||
}
|
||||
else
|
||||
{
|
||||
for(int j = 0; j < argcount + 1; j++)
|
||||
{
|
||||
ilGenerator.Emit(OpCodes.Pop);
|
||||
}
|
||||
EmitPlaceholder(cpi.GetRetType(classLoader));
|
||||
// if we're a constructor and the call to the base class constructor
|
||||
// wasn't accessible, we need make sure that there is no code path that
|
||||
// returns from the constructor, otherwise the method will be not verifiable
|
||||
// TODO this isn't anywhere near a proper solution, but for the time being it works
|
||||
// some things to consider:
|
||||
// - only pull this full when calls to the base class constructor fail
|
||||
// - when control flow is complex, this trivial solution will not work
|
||||
ilGenerator.Emit(OpCodes.Ldnull);
|
||||
ilGenerator.Emit(OpCodes.Throw);
|
||||
return;
|
||||
// for(int j = 0; j < argcount + 1; j++)
|
||||
// {
|
||||
// ilGenerator.Emit(OpCodes.Pop);
|
||||
// }
|
||||
// EmitPlaceholder(cpi.Signature.Substring(cpi.Signature.LastIndexOf(')') + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(method != null)
|
||||
if(emit != null)
|
||||
{
|
||||
method.EmitCallvirt.Emit(ilGenerator);
|
||||
emit.Emit(ilGenerator);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2244,7 +2235,7 @@ class Compiler
|
|||
// we cannot use EmitError, because that will yield an invalid constructor (that doesn't call the superclass constructor)
|
||||
if(IsUnloadable(cpi))
|
||||
{
|
||||
MethodWrapper dummy = new MethodWrapper(null, null, null, Modifiers.Synthetic);
|
||||
MethodWrapper dummy = new MethodWrapper(null, null, null, null, Modifiers.Synthetic);
|
||||
if(invoke == NormalizedByteCode.__invokespecial)
|
||||
{
|
||||
dummy.EmitNewobj = new DynamicNewEmitter(classLoader, clazz, cpi);
|
||||
|
|
|
@ -1599,7 +1599,8 @@ class MethodAnalyzer
|
|||
}
|
||||
case NormalizedByteCode.__monitorenter:
|
||||
case NormalizedByteCode.__monitorexit:
|
||||
// TODO is this allowed to be an uninitialized object?
|
||||
// TODO these bytecodes are allowed on an uninitialized object, but
|
||||
// we don't support that at the moment...
|
||||
s.PopObjectType();
|
||||
break;
|
||||
case NormalizedByteCode.__return:
|
||||
|
|
|
@ -1,316 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2002 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
|
||||
|
||||
*/
|
||||
|
||||
package ikvm.awt;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.datatransfer.*;
|
||||
import java.awt.image.*;
|
||||
import java.awt.peer.*;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import java.awt.List;
|
||||
|
||||
public class NetToolkit extends Toolkit
|
||||
{
|
||||
private static EventQueue eventQueue = new EventQueue();
|
||||
|
||||
// NOTE "native" is just an easy way to say I haven't implemented it yet
|
||||
|
||||
protected java.awt.peer.ButtonPeer createButton(Button target) throws HeadlessException
|
||||
{
|
||||
return new NetButtonPeer();
|
||||
}
|
||||
|
||||
protected java.awt.peer.TextFieldPeer createTextField(TextField target) throws HeadlessException
|
||||
{
|
||||
return new NetTextFieldPeer();
|
||||
}
|
||||
|
||||
protected native java.awt.peer.LabelPeer createLabel(Label target) throws HeadlessException;
|
||||
protected native java.awt.peer.ListPeer createList(List target) throws HeadlessException;
|
||||
protected native java.awt.peer.CheckboxPeer createCheckbox(Checkbox target)
|
||||
throws HeadlessException;
|
||||
protected native java.awt.peer.ScrollbarPeer createScrollbar(Scrollbar target)
|
||||
throws HeadlessException;
|
||||
protected native java.awt.peer.ScrollPanePeer createScrollPane(ScrollPane target)
|
||||
throws HeadlessException;
|
||||
|
||||
protected java.awt.peer.TextAreaPeer createTextArea(TextArea target) throws HeadlessException
|
||||
{
|
||||
return new NetTextAreaPeer();
|
||||
}
|
||||
|
||||
protected native java.awt.peer.ChoicePeer createChoice(Choice target)
|
||||
throws HeadlessException;
|
||||
|
||||
protected java.awt.peer.FramePeer createFrame(Frame target) throws HeadlessException
|
||||
{
|
||||
return new NetFramePeer();
|
||||
}
|
||||
|
||||
protected native java.awt.peer.CanvasPeer createCanvas(Canvas target);
|
||||
|
||||
protected java.awt.peer.PanelPeer createPanel(Panel target)
|
||||
{
|
||||
return new NetPanelPeer();
|
||||
}
|
||||
|
||||
protected native java.awt.peer.WindowPeer createWindow(Window target)
|
||||
throws HeadlessException;
|
||||
protected native java.awt.peer.DialogPeer createDialog(Dialog target)
|
||||
throws HeadlessException;
|
||||
protected native java.awt.peer.MenuBarPeer createMenuBar(MenuBar target)
|
||||
throws HeadlessException;
|
||||
protected native java.awt.peer.MenuPeer createMenu(Menu target)
|
||||
throws HeadlessException;
|
||||
protected native java.awt.peer.PopupMenuPeer createPopupMenu(PopupMenu target)
|
||||
throws HeadlessException;
|
||||
protected native java.awt.peer.MenuItemPeer createMenuItem(MenuItem target)
|
||||
throws HeadlessException;
|
||||
protected native java.awt.peer.FileDialogPeer createFileDialog(FileDialog target)
|
||||
throws HeadlessException;
|
||||
protected native java.awt.peer.CheckboxMenuItemPeer createCheckboxMenuItem(CheckboxMenuItem target)
|
||||
throws HeadlessException;
|
||||
protected native java.awt.peer.FontPeer getFontPeer(String name, int style);
|
||||
public native Dimension getScreenSize() throws HeadlessException;
|
||||
public native int getScreenResolution() throws HeadlessException;
|
||||
public native ColorModel getColorModel()
|
||||
throws HeadlessException;
|
||||
public native String[] getFontList();
|
||||
public native FontMetrics getFontMetrics(Font font);
|
||||
public native void sync();
|
||||
public native Image getImage(String filename);
|
||||
public native Image getImage(URL url);
|
||||
public native Image createImage(String filename);
|
||||
public native Image createImage(URL url);
|
||||
public native boolean prepareImage(Image image,
|
||||
int width,
|
||||
int height,
|
||||
ImageObserver observer);
|
||||
public native int checkImage(Image image,
|
||||
int width,
|
||||
int height,
|
||||
ImageObserver observer);
|
||||
public native Image createImage(ImageProducer producer);
|
||||
public native Image createImage(byte[] imagedata,
|
||||
int imageoffset,
|
||||
int imagelength);
|
||||
public native PrintJob getPrintJob(Frame frame,
|
||||
String jobtitle,
|
||||
Properties props);
|
||||
public native void beep();
|
||||
public native Clipboard getSystemClipboard()
|
||||
throws HeadlessException;
|
||||
|
||||
protected EventQueue getSystemEventQueueImpl()
|
||||
{
|
||||
return eventQueue;
|
||||
}
|
||||
|
||||
// public native java.awt.dnd.peer.DragSourceContextPeer createDragSourceContextPeer(DragGestureEvent dge)
|
||||
// throws InvalidDnDOperationException;
|
||||
// public native Map mapInputMethodHighlight(InputMethodHighlight highlight)
|
||||
// throws HeadlessException;
|
||||
}
|
||||
|
||||
class NetComponentPeer implements ComponentPeer
|
||||
{
|
||||
public native int checkImage(Image img, int width, int height, ImageObserver ob);
|
||||
public native Image createImage(ImageProducer prod);
|
||||
public native Image createImage(int width, int height);
|
||||
public native void disable();
|
||||
public native void dispose();
|
||||
public native void enable();
|
||||
public native ColorModel getColorModel();
|
||||
public native FontMetrics getFontMetrics(Font f);
|
||||
public native Graphics getGraphics();
|
||||
public native Point getLocationOnScreen();
|
||||
public native Dimension getMinimumSize();
|
||||
|
||||
public Dimension getPreferredSize()
|
||||
{
|
||||
System.out.println("NOTE: NetComponentPeer.getPreferredSize not implemented");
|
||||
return new Dimension(0, 0);
|
||||
}
|
||||
|
||||
public Toolkit getToolkit()
|
||||
{
|
||||
return Toolkit.getDefaultToolkit();
|
||||
}
|
||||
|
||||
public native void handleEvent(AWTEvent e);
|
||||
public native void hide();
|
||||
public native boolean isFocusTraversable();
|
||||
public native Dimension minimumSize();
|
||||
|
||||
public Dimension preferredSize()
|
||||
{
|
||||
System.out.println("NOTE: NetComponentPeer.preferredSize not implemented");
|
||||
return new Dimension(0, 0);
|
||||
}
|
||||
|
||||
public native void paint(Graphics graphics);
|
||||
public native boolean prepareImage(Image img, int width, int height, ImageObserver ob);
|
||||
public native void print(Graphics graphics);
|
||||
public native void repaint(long tm, int x, int y, int width, int height);
|
||||
public native void requestFocus();
|
||||
public native void reshape(int x, int y, int width, int height);
|
||||
public native void setBackground(Color color);
|
||||
public native void setBounds(int x, int y, int width, int height);
|
||||
public native void setCursor(Cursor cursor);
|
||||
|
||||
public void setEnabled(boolean enabled)
|
||||
{
|
||||
System.out.println("NOTE: NetComponentPeer.setEnabled not implemented");
|
||||
}
|
||||
|
||||
public native void setFont(Font font);
|
||||
public native void setForeground(Color color);
|
||||
|
||||
public void setVisible(boolean visible)
|
||||
{
|
||||
System.out.println("NOTE: NetComponentPeer.setVisible not implemented");
|
||||
}
|
||||
|
||||
public native void show();
|
||||
public native GraphicsConfiguration getGraphicsConfiguration();
|
||||
|
||||
public void setEventMask (long mask)
|
||||
{
|
||||
System.out.println("NOTE: NetComponentPeer.setEventMask not implemented");
|
||||
}
|
||||
}
|
||||
|
||||
class NetButtonPeer extends NetComponentPeer implements ButtonPeer
|
||||
{
|
||||
public native void setLabel(String label);
|
||||
}
|
||||
|
||||
class NetTextComponentPeer extends NetComponentPeer implements TextComponentPeer
|
||||
{
|
||||
public native int getSelectionEnd();
|
||||
public native int getSelectionStart();
|
||||
|
||||
public String getText()
|
||||
{
|
||||
System.out.println("NOTE: NetTextComponentPeer.getText not implemented");
|
||||
return "";
|
||||
}
|
||||
|
||||
public void setText(String text)
|
||||
{
|
||||
System.out.println("NOTE: NetTextComponentPeer.setText not implemented");
|
||||
}
|
||||
|
||||
public native void select(int start_pos, int end_pos);
|
||||
public native void setEditable(boolean editable);
|
||||
public native int getCaretPosition();
|
||||
public native void setCaretPosition(int pos);
|
||||
}
|
||||
|
||||
class NetTextFieldPeer extends NetTextComponentPeer implements TextFieldPeer
|
||||
{
|
||||
public native Dimension minimumSize(int len);
|
||||
public native Dimension preferredSize(int len);
|
||||
public native Dimension getMinimumSize(int len);
|
||||
|
||||
public Dimension getPreferredSize(int len)
|
||||
{
|
||||
System.out.println("NOTE: NetTextFieldPeer.getPreferredSize not implemented");
|
||||
return new Dimension(0, 0);
|
||||
}
|
||||
|
||||
public native void setEchoChar(char echo_char);
|
||||
public native void setEchoCharacter(char echo_char);
|
||||
}
|
||||
|
||||
class NetTextAreaPeer extends NetTextComponentPeer implements TextAreaPeer
|
||||
{
|
||||
public void insert(String text, int pos)
|
||||
{
|
||||
System.out.println("NOTE: NetTextAreaPeer.insert not implemented");
|
||||
}
|
||||
|
||||
public native void insertText(String text, int pos);
|
||||
public native Dimension minimumSize(int rows, int cols);
|
||||
public native Dimension getMinimumSize(int rows, int cols);
|
||||
public native Dimension preferredSize(int rows, int cols);
|
||||
|
||||
public Dimension getPreferredSize(int rows, int cols)
|
||||
{
|
||||
System.out.println("NOTE: NetTextAreaPeer.getPreferredSize not implemented");
|
||||
return new Dimension(0, 0);
|
||||
}
|
||||
|
||||
public native void replaceRange(String text, int start_pos, int end_pos);
|
||||
public native void replaceText(String text, int start_pos, int end_pos);
|
||||
}
|
||||
|
||||
class NetContainerPeer extends NetComponentPeer implements ContainerPeer
|
||||
{
|
||||
public native Insets insets();
|
||||
|
||||
public Insets getInsets()
|
||||
{
|
||||
System.out.println("NOTE: NetContainerPeer.getInsets not implemented");
|
||||
return new Insets(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
public void beginValidate()
|
||||
{
|
||||
System.out.println("NOTE: NetContainerPeer.beginValidate not implemented");
|
||||
}
|
||||
|
||||
public void endValidate()
|
||||
{
|
||||
System.out.println("NOTE: NetContainerPeer.endValidate not implemented");
|
||||
}
|
||||
}
|
||||
|
||||
class NetPanelPeer extends NetContainerPeer implements PanelPeer
|
||||
{
|
||||
}
|
||||
|
||||
class NetWindowPeer extends NetContainerPeer implements WindowPeer
|
||||
{
|
||||
public native void toBack();
|
||||
|
||||
public void toFront()
|
||||
{
|
||||
System.out.println("NOTE: NetWindowPeer.toFront not implemented");
|
||||
}
|
||||
}
|
||||
|
||||
class NetFramePeer extends NetWindowPeer implements FramePeer
|
||||
{
|
||||
NetFramePeer()
|
||||
{
|
||||
}
|
||||
|
||||
public native void setIconImage(Image image);
|
||||
public native void setMenuBar(MenuBar mb);
|
||||
public native void setResizable(boolean resizable);
|
||||
public native void setTitle(String title);
|
||||
}
|
|
@ -248,35 +248,18 @@ public final class Constructor
|
|||
throws InstantiationException, IllegalAccessException,
|
||||
InvocationTargetException
|
||||
{
|
||||
return Method.Invoke(methodCookie, null, args);
|
||||
/*
|
||||
if(Modifier.isAbstract(clazz.getModifiers()))
|
||||
{
|
||||
throw new InstantiationException();
|
||||
}
|
||||
// TODO check args and accessibility
|
||||
try
|
||||
{
|
||||
if(false) throw new MemberAccessException();
|
||||
if(false) throw new ArgumentException();
|
||||
if(false) throw new TargetParameterCountException();
|
||||
if(false) throw new TargetInvocationException(null);
|
||||
// TODO wrappers need to be unwrapped (e.g. java.lang.Integer -> boxed System.Int32)
|
||||
return ci.Invoke(args);
|
||||
return Method.Invoke(methodCookie, null, args);
|
||||
}
|
||||
catch(MemberAccessException x1)
|
||||
catch(Throwable x)
|
||||
{
|
||||
throw new IllegalAccessException(x1.get_Message());
|
||||
throw new InvocationTargetException(x);
|
||||
}
|
||||
catch(ArgumentException x2)
|
||||
{
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
catch(TargetParameterCountException x3)
|
||||
{
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
catch(TargetInvocationException x4)
|
||||
{
|
||||
InstantiationException ie = new InstantiationException();
|
||||
ie.initCause(Method.mapException(x4.get_InnerException()));
|
||||
throw ie;
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
|
|
@ -307,70 +307,16 @@ public final class Method extends AccessibleObject implements Member
|
|||
public Object invoke(Object o, Object[] args)
|
||||
throws IllegalAccessException, InvocationTargetException
|
||||
{
|
||||
// TODO
|
||||
return Invoke(methodCookie, o, args);
|
||||
/*
|
||||
// TODO check args and accessibility
|
||||
try
|
||||
{
|
||||
if(false) throw new MemberAccessException();
|
||||
if(false) throw new ArgumentException();
|
||||
if(false) throw new TargetParameterCountException();
|
||||
if(false) throw new TargetInvocationException(null);
|
||||
ParameterInfo[] params = method.GetParameters();
|
||||
for(int i = 0; i < params.length; i++)
|
||||
{
|
||||
Type type = params[i].get_ParameterType();
|
||||
if(type.get_IsPrimitive())
|
||||
{
|
||||
if(type == BoxHelper.INT)
|
||||
{
|
||||
args[i] = BoxHelper.boxInteger(((Integer)args[i]).intValue());
|
||||
}
|
||||
else if(type == BoxHelper.BOOLEAN)
|
||||
{
|
||||
args[i] = BoxHelper.boxBoolean(((java.lang.Boolean)args[i]).booleanValue());
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InternalError("method invoke arg boxing not implemented for " + type.get_FullName());
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO wrappers need to be unwrapped (e.g. java.lang.Integer -> boxed System.Int32)
|
||||
Object retval = method.Invoke(o, args);
|
||||
Type rettype = method.get_ReturnType();
|
||||
if(rettype.get_IsPrimitive())
|
||||
{
|
||||
if(rettype == BoxHelper.INT)
|
||||
{
|
||||
retval = new Integer(BoxHelper.unboxInteger(retval));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InternalError("method invoke retval unboxing not implemented for " + rettype.get_FullName());
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
return Invoke(methodCookie, o, args);
|
||||
}
|
||||
catch(MemberAccessException x1)
|
||||
catch(Throwable x)
|
||||
{
|
||||
throw new IllegalAccessException(x1.get_Message());
|
||||
throw new InvocationTargetException(x);
|
||||
}
|
||||
catch(ArgumentException x2)
|
||||
{
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
catch(TargetParameterCountException x3)
|
||||
{
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
catch(TargetInvocationException x4)
|
||||
{
|
||||
throw new InvocationTargetException(mapException(x4.get_InnerException()));
|
||||
}
|
||||
*/
|
||||
}
|
||||
static native Object Invoke(Object methodCookie, Object o, Object[] args);
|
||||
|
||||
static native Throwable mapException(Throwable x);
|
||||
static native Object Invoke(Object methodCookie, Object o, Object[] args);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче