This commit is contained in:
jfrijters 2002-12-18 16:00:25 +00:00
Коммит 59d175f020
75 изменённых файлов: 29777 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,81 @@
/*
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
*/
#include "stdafx.h"
using namespace System::Reflection;
using namespace System::Runtime::CompilerServices;
//
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
//
[assembly:AssemblyTitleAttribute("")];
[assembly:AssemblyDescriptionAttribute("")];
[assembly:AssemblyConfigurationAttribute("")];
[assembly:AssemblyCompanyAttribute("")];
[assembly:AssemblyProductAttribute("")];
[assembly:AssemblyCopyrightAttribute("")];
[assembly:AssemblyTrademarkAttribute("")];
[assembly:AssemblyCultureAttribute("")];
//
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the value or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly:AssemblyVersionAttribute("1.0.1060.22610")];
//
// In order to sign your assembly you must specify a key to use. Refer to the
// Microsoft .NET Framework documentation for more information on assembly signing.
//
// Use the attributes below to control which key is used for signing.
//
// Notes:
// (*) If no key is specified, the assembly is not signed.
// (*) KeyName refers to a key that has been installed in the Crypto Service
// Provider (CSP) on your machine. KeyFile refers to a file which contains
// a key.
// (*) If the KeyFile and the KeyName values are both specified, the
// following processing occurs:
// (1) If the KeyName can be found in the CSP, that key is used.
// (2) If the KeyName does not exist and the KeyFile does exist, the key
// in the KeyFile is installed into the CSP and used.
// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
// When specifying the KeyFile, the location of the KeyFile should be
// relative to the project directory.
// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
// documentation for more information on this.
//
[assembly:AssemblyDelaySignAttribute(false)];
[assembly:AssemblyKeyFileAttribute("")];
[assembly:AssemblyKeyNameAttribute("")];

144
IK.VM.JNI/IK.VM.JNI.vcproj Normal file
Просмотреть файл

@ -0,0 +1,144 @@
<?xml version="1.0" encoding = "Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.00"
Name="IK.VM.JNI"
ProjectGUID="{4D400F9D-68A1-4066-95F6-85AF0E58B710}"
Keyword="ManagedCProj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="Debug"
IntermediateDirectory="Debug"
ConfigurationType="2"
CharacterSet="2"
ManagedExtensions="TRUE">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG"
MinimalRebuild="FALSE"
BasicRuntimeChecks="0"
RuntimeLibrary="1"
TreatWChar_tAsBuiltInType="TRUE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="3"
WarningLevel="3"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)/IK.VM.JNI.dll"
LinkIncremental="2"
GenerateDebugInformation="TRUE"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="Release"
IntermediateDirectory="Release"
ConfigurationType="2"
CharacterSet="2"
ManagedExtensions="TRUE">
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
PreprocessorDefinitions="WIN32;NDEBUG"
MinimalRebuild="FALSE"
TreatWChar_tAsBuiltInType="TRUE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="3"
WarningLevel="3"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)/IK.VM.JNI.dll"
LinkIncremental="1"
GenerateDebugInformation="TRUE"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
</Configuration>
</Configurations>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm">
<File
RelativePath="AssemblyInfo.cpp">
</File>
<File
RelativePath="Stdafx.cpp">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"/>
</FileConfiguration>
</File>
<File
RelativePath="jni.cpp">
</File>
<File
RelativePath="jnienv.cpp">
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc">
<File
RelativePath="Stdafx.h">
</File>
<File
RelativePath="jni.h">
</File>
<File
RelativePath="jnienv.h">
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;r">
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

5
IK.VM.JNI/Stdafx.cpp Normal file
Просмотреть файл

@ -0,0 +1,5 @@
// stdafx.cpp : source file that includes just the standard includes
// jni.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information
#include "stdafx.h"

9
IK.VM.JNI/Stdafx.h Normal file
Просмотреть файл

@ -0,0 +1,9 @@
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently,
// but are changed infrequently
#pragma once
#using <mscorlib.dll>
#include <windows.h>

Просмотреть файл

@ -0,0 +1,6 @@
<?xml version="1.0"?>
<project name="ik.vm.jni" default="ik.vm.jni">
<target name="ik.vm.jni">
<echo message="*** TODO ***" />
</target>
</project>

178
IK.VM.JNI/jni.cpp Normal file
Просмотреть файл

@ -0,0 +1,178 @@
/*
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
*/
#include "stdafx.h"
#include <malloc.h>
#include "jnienv.h"
#include "jni.h"
#pragma managed
#include <stdio.h>
using namespace System;
using namespace System::Collections;
using namespace System::Runtime::InteropServices;
int JNI::LoadNativeLibrary(String* name)
{
HMODULE hMod = LoadLibrary(name);
if(!hMod)
{
return 0;
}
libs->Add(__box((int)hMod));
return 1;
}
jobject JNI::MakeGlobalRef(Object* o)
{
if(!o)
{
return 0;
}
// TODO search for an empty slot before adding it to the end...
return (jobject)-(globalRefs->Add(o) + 1);
}
void JNI::DeleteGlobalRef(jobject o)
{
if(o)
{
int i = int(o);
if(i < 0)
{
globalRefs->Item[(-i) - 1] = 0;
return;
}
DebugBreak();
}
}
Object* JNI::UnwrapGlobalRef(jobject o)
{
if(!o)
{
return 0;
}
int i = int(o);
if(i < 0)
{
return globalRefs->Item[(-i) - 1];
}
DebugBreak();
return 0;
}
IntPtr JNI::GetJniFuncPtr(String* method, String* sig, String* clazz)
{
System::Text::StringBuilder* mangledSig = new System::Text::StringBuilder();
int sp = 0;
for(int i = 1; sig->Chars[i] != ')'; i++)
{
switch(sig->Chars[i])
{
case '[':
mangledSig->Append(S"_3");
sp += 4;
while(sig->Chars[++i] == '[')
{
mangledSig->Append(S"_3");
}
mangledSig->Append(sig->Chars[i]);
if(sig->Chars[i] == 'L')
{
while(sig->Chars[++i] != ';')
{
if(sig->Chars[i] == '/')
{
mangledSig->Append(S"_");
}
else
{
mangledSig->Append(sig->Chars[i]);
}
}
mangledSig->Append(S"_2");
}
break;
case 'L':
sp += 4;
mangledSig->Append(S"L");
while(sig->Chars[++i] != ';')
{
if(sig->Chars[i] == '/')
{
mangledSig->Append(S"_");
}
else
{
mangledSig->Append(sig->Chars[i]);
}
}
mangledSig->Append(S"_2");
break;
case 'J':
case 'D':
mangledSig->Append(sig->Chars[i]);
sp += 8;
break;
case 'F':
case 'I':
case 'C':
case 'Z':
case 'S':
case 'B':
mangledSig->Append(sig->Chars[i]);
sp += 4;
break;
default:
DebugBreak();
throw new NotImplementedException();
}
}
void* func = 0;
// TODO implement this correctly
String* methodName = String::Format(S"_Java_{0}_{1}@{2}", clazz->Replace(S"_", S"_1")->Replace('/', '_'), method->Replace(S"_", S"_1"), __box(sp + 8));
for(int i = 0; i < libs->Count; i++)
{
HMODULE hMod = (HMODULE)__unbox<int>(libs->Item[i]);
func = GetProcAddress(hMod, methodName);
if(func)
{
return (IntPtr)func;
}
}
methodName = String::Concat(String::Format(S"_Java_{0}_{1}__{2}@", clazz->Replace(S"_", S"_1")->Replace('/', '_'), method->Replace(S"_", S"_1"), mangledSig), __box(sp + 8));
for(int i = 0; i < libs->Count; i++)
{
HMODULE hMod = (HMODULE)__unbox<int>(libs->Item[i]);
func = GetProcAddress(hMod, methodName);
if(func)
{
return (IntPtr)func;
}
}
throw VM::UnsatisfiedLinkError(methodName);
}

245
IK.VM.JNI/jni.h Normal file
Просмотреть файл

@ -0,0 +1,245 @@
/*
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
*/
#pragma once
using namespace System;
using namespace System::Collections;
using namespace System::Runtime::InteropServices;
using namespace System::Reflection;
class JNIEnv;
#pragma managed
public __value class LocalRefStruct;
// NOTE this __value type needs to have the *exact* same layout as the unmanaged JNIENv class
__value struct JNIEnvContainer
{
void* pVtable;
LocalRefStruct __nogc* pLocalRefStruct;
};
public __value class LocalRefStruct
{
[ThreadStatic]
static JNIEnvContainer jniEnv;
LocalRefStruct __nogc* pPrevLocalRefCache;
Object* loc1;
Object* loc2;
Object* loc3;
Object* loc4;
Object* loc5;
Object* loc6;
Object* loc7;
Object* loc8;
Object* loc9;
Object* loc10;
Object* overflow __gc[];
Exception* pendingException;
public:
static JNIEnv* GetEnv()
{
if(jniEnv.pVtable != 0)
{
return (JNIEnv*)(void*)&jniEnv;
}
return 0;
}
IntPtr Enter()
{
if(jniEnv.pVtable == 0)
{
// HACK initialize the vtable ptr
JNIEnv env;
jniEnv.pVtable = *((void**)&env);
}
pPrevLocalRefCache = jniEnv.pLocalRefStruct;
// NOTE since this __value type can (should) only be allocated on the stack,
// it is "safe" to store the this pointer in a __nogc*, but the compiler
// doesn't know this, so we have to use a __pin* to bypass its checks.
LocalRefStruct __pin* pPinHack = this;
jniEnv.pLocalRefStruct = pPinHack;
return (IntPtr)&jniEnv;
}
void Leave()
{
jniEnv.pLocalRefStruct = pPrevLocalRefCache;
if(pendingException)
{
// TODO retain the stack trace of the exception object
throw pendingException;
}
}
__property Exception* get_PendingException()
{
return pendingException;
}
__property void set_PendingException(Exception* exception)
{
pendingException = exception;
}
IntPtr MakeLocalRef(Object* o)
{
if(o == 0)
{
return 0;
}
Object** p = &loc1;
for(int i = 0; i < 10; i++)
{
if(p[i] == 0)
{
p[i] = o;
return i + 1;
}
}
if(!overflow)
{
// HACK we use a very large dynamic table size, because we don't yet support growing it
overflow = new Object* __gc[256];
}
for(int i = 0; i < overflow->Length; i++)
{
if(overflow[i] == 0)
{
overflow[i] = o;
return i + 11;
}
}
throw new NotImplementedException(S"Growing the localref table is not implemented");
}
void DeleteLocalRef(jobject o)
{
int i = (int)o;
if(i < 0)
{
DebugBreak();
}
if(i > 0)
{
if(i <= 10)
{
Object** p = &loc1;
p[i - 1] = 0;
}
else
{
overflow[i - 11] = 0;
}
}
}
Object* UnwrapLocalRef(IntPtr localref)
{
if(localref == 0)
{
return 0;
}
if(int(localref) <= 10)
{
Object** p = &loc1;
return p[int(localref) - 1];
}
else
{
return overflow[int(localref) - 11];
}
}
};
public __gc class JNI
{
static ArrayList* libs = new ArrayList();
static ArrayList* globalRefs = new ArrayList();
[DllImport("kernel32")]
[System::Security::SuppressUnmanagedCodeSecurityAttribute]
static HMODULE LoadLibrary(String* lpLibFileName);
[DllImport("kernel32")]
[System::Security::SuppressUnmanagedCodeSecurityAttribute]
static void* GetProcAddress(HMODULE hMod, String* lpProcName);
public:
static int LoadNativeLibrary(String* name);
static IntPtr GetJniFuncPtr(String* method, String* sig, String* clazz);
static jobject MakeGlobalRef(Object* o);
static void DeleteGlobalRef(jobject o);
static Object* UnwrapGlobalRef(jobject o);
};
public __gc interface IJniHack
{
public:
virtual MethodBase* GetMethod(Object* clazz, String* name, String* sig, bool isStatic)=0;
virtual FieldInfo* GetField(Object* clazz, String* name, String* sig, bool isStatic)=0;
virtual Object* FindClass(String* name)=0;
virtual Exception* UnsatisfiedLinkError(String* msg)=0;
virtual Object* GetClassFromType(Type* type)=0;
};
public __gc class VM
{
private:
static IJniHack* pJniHack = 0;
static VM()
{
pJniHack = __try_cast<IJniHack*>(Activator::CreateInstance(Assembly::Load(S"ik.vm.net")->GetType(S"JniHack")));
}
public:
// NOTE we use this nasty construct to avoid a compile time dependency on JVM.DLL (which already has a compile time
// dependency on us)
static MethodBase* GetMethod(Object* clazz, String* name, String* sig, bool isStatic)
{
return pJniHack->GetMethod(clazz, name, sig, isStatic);
}
static FieldInfo* GetField(Object* clazz, String* name, String* sig, bool isStatic)
{
return pJniHack->GetField(clazz, name, sig, isStatic);
}
static Object* FindClass(String* javaName)
{
return pJniHack->FindClass(javaName);
}
static Exception* UnsatisfiedLinkError(String* msg)
{
return pJniHack->UnsatisfiedLinkError(msg);
}
static Object* GetClassFromType(Type* type)
{
return pJniHack->GetClassFromType(type);
}
};
template<class T> T __unbox(Object* o)
{
// HACK the MC++ compiler has a bug when unboxing, the static_cast<> is to work around that bug
return *(static_cast<T __gc*>(__try_cast<__box T*>(o)));
}

1097
IK.VM.JNI/jnienv.cpp Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

440
IK.VM.JNI/jnienv.h Normal file
Просмотреть файл

@ -0,0 +1,440 @@
/*
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
*/
#pragma unmanaged
#define JNI_TRUE 1
#define JNI_FALSE 0
typedef struct {
char *name;
char *signature;
void *fnPtr;
} JNINativeMethod;
#define JNI_VERSION_1_1 0x00010001
#define JNI_VERSION_1_2 0x00010002
#define JNI_VERSION_1_4 0x00010004
/*
* possible return values for JNI functions.
*/
#define JNI_OK 0
#define JNI_ERR (-1)
#define JNI_EDETACHED (-2)
#define JNI_EVERSION (-3)
/*
* used in ReleaseScalarArrayElements
*/
#define JNI_COMMIT 1
#define JNI_ABORT 2
class JavaVM;
#define JNIEXPORT
#define JNICALL __stdcall
#ifndef _HELPERTYPES_
#define _HELPERTYPES_
class _jobject {};
class _jclass : public _jobject {};
class _jstring : public _jobject {};
class _jthrowable : public _jobject {};
class Array$ : public _jobject {};
class ObjectArray$ : public Array$ {};
class BooleanArray$ : public Array$ {};
class ByteArray$ : public Array$ {};
class CharArray$ : public Array$ {};
class ShortArray$ : public Array$ {};
class IntArray$ : public Array$ {};
class LongArray$ : public Array$ {};
class FloatArray$ : public Array$ {};
class DoubleArray$ : public Array$ {};
#endif //_HELPERTYPES_
typedef class _jclass* jclass;
typedef class _jobject* jobject;
typedef class _jstring* jstring;
typedef class _jthrowable* jthrowable;
typedef class Array$* jarray;
typedef class ObjectArray$* jobjectArray;
typedef class BooleanArray$* jbooleanArray;
typedef class ByteArray$* jbyteArray;
typedef class CharArray$* jcharArray;
typedef class ShortArray$* jshortArray;
typedef class IntArray$* jintArray;
typedef class LongArray$* jlongArray;
typedef class FloatArray$* jfloatArray;
typedef class DoubleArray$* jdoubleArray;
typedef struct _jmethodID* jmethodID;
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;
};
/*
* JNI Types
*/
typedef unsigned char jboolean;
typedef unsigned short jchar;
typedef short jshort;
typedef float jfloat;
typedef double jdouble;
typedef long jint;
typedef __int64 jlong;
typedef signed char jbyte;
typedef jint jsize;
typedef union jvalue {
jboolean z;
jbyte b;
jchar c;
jshort s;
jint i;
jlong j;
jfloat f;
jdouble d;
jobject l;
} jvalue;
public __value class LocalRefStruct;
public __gc class System::Object;
class JNIEnv
{
LocalRefStruct __nogc* pLocalRefs;
System::Object __gc* UnwrapRef(jobject o);
jmethodID FindMethodID(jclass cls, const char* name, const char* sig, bool isstatic);
System::Object __gc* InvokeHelper(jobject object, jmethodID methodID, jvalue* args);
jfieldID FindFieldID(jclass cls, const char* name, const char* sig, bool isstatic);
public:
JNIEnv();
~JNIEnv();
virtual void JNICALL reserved0();
virtual void JNICALL reserved1();
virtual void JNICALL reserved2();
virtual void JNICALL reserved3();
virtual jint JNICALL GetVersion();
virtual jclass JNICALL DefineClass(const char *name, jobject loader, const jbyte *buf, jsize len);
virtual jclass JNICALL FindClass(const char *name);
virtual void JNICALL reserved4();
virtual void JNICALL reserved5();
virtual void JNICALL reserved6();
virtual jclass JNICALL GetSuperclass(jclass sub);
virtual jboolean JNICALL IsAssignableFrom(jclass sub, jclass sup);
virtual void JNICALL reserved7();
virtual jint JNICALL Throw(jthrowable obj);
virtual jint JNICALL ThrowNew(jclass clazz, const char *msg);
virtual jthrowable JNICALL ExceptionOccurred();
virtual void JNICALL ExceptionDescribe();
virtual void JNICALL ExceptionClear();
virtual void JNICALL FatalError(const char *msg);
virtual void JNICALL reserved8();
virtual void JNICALL reserved9();
virtual jobject JNICALL NewGlobalRef(jobject lobj);
virtual void JNICALL DeleteGlobalRef(jobject gref);
virtual void JNICALL DeleteLocalRef(jobject obj);
virtual jboolean JNICALL IsSameObject(jobject obj1, jobject obj2);
virtual void JNICALL reserved10();
virtual void JNICALL reserved11();
virtual jobject JNICALL AllocObject(jclass clazz);
virtual jobject JNICALL NewObject(jclass clazz, jmethodID methodID, ...);
virtual jobject JNICALL NewObjectV(jclass clazz, jmethodID methodID, va_list args);
virtual jobject JNICALL NewObjectA(jclass clazz, jmethodID methodID, jvalue *args);
virtual jclass JNICALL GetObjectClass(jobject obj);
virtual jboolean JNICALL IsInstanceOf(jobject obj, jclass clazz);
virtual jmethodID JNICALL GetMethodID(jclass clazz, const char *name, const char *sig);
virtual jobject JNICALL CallObjectMethod(jobject obj, jmethodID methodID, ...);
virtual jobject JNICALL CallObjectMethodV(jobject obj, jmethodID methodID, va_list args);
virtual jobject JNICALL CallObjectMethodA(jobject obj, jmethodID methodID, jvalue * args);
virtual jboolean JNICALL CallBooleanMethod(jobject obj, jmethodID methodID, ...);
virtual jboolean JNICALL CallBooleanMethodV(jobject obj, jmethodID methodID, va_list args);
virtual jboolean JNICALL CallBooleanMethodA(jobject obj, jmethodID methodID, jvalue * args);
virtual jbyte JNICALL CallByteMethod(jobject obj, jmethodID methodID, ...);
virtual jbyte JNICALL CallByteMethodV(jobject obj, jmethodID methodID, va_list args);
virtual jbyte JNICALL CallByteMethodA(jobject obj, jmethodID methodID, jvalue *args);
virtual jchar JNICALL CallCharMethod(jobject obj, jmethodID methodID, ...);
virtual jchar JNICALL CallCharMethodV(jobject obj, jmethodID methodID, va_list args);
virtual jchar JNICALL CallCharMethodA(jobject obj, jmethodID methodID, jvalue *args);
virtual jshort JNICALL CallShortMethod(jobject obj, jmethodID methodID, ...);
virtual jshort JNICALL CallShortMethodV(jobject obj, jmethodID methodID, va_list args);
virtual jshort JNICALL CallShortMethodA(jobject obj, jmethodID methodID, jvalue *args);
virtual jint JNICALL CallIntMethod(jobject obj, jmethodID methodID, ...);
virtual jint JNICALL CallIntMethodV(jobject obj, jmethodID methodID, va_list args);
virtual jint JNICALL CallIntMethodA(jobject obj, jmethodID methodID, jvalue *args);
virtual jlong JNICALL CallLongMethod(jobject obj, jmethodID methodID, ...);
virtual jlong JNICALL CallLongMethodV(jobject obj, jmethodID methodID, va_list args);
virtual jlong JNICALL CallLongMethodA(jobject obj, jmethodID methodID, jvalue *args);
virtual jfloat JNICALL CallFloatMethod(jobject obj, jmethodID methodID, ...);
virtual jfloat JNICALL CallFloatMethodV(jobject obj, jmethodID methodID, va_list args);
virtual jfloat JNICALL CallFloatMethodA(jobject obj, jmethodID methodID, jvalue *args);
virtual jdouble JNICALL CallDoubleMethod(jobject obj, jmethodID methodID, ...);
virtual jdouble JNICALL CallDoubleMethodV(jobject obj, jmethodID methodID, va_list args);
virtual jdouble JNICALL CallDoubleMethodA(jobject obj, jmethodID methodID, jvalue *args);
virtual void JNICALL CallVoidMethod(jobject obj, jmethodID methodID, ...);
virtual void JNICALL CallVoidMethodV(jobject obj, jmethodID methodID, va_list args);
virtual void JNICALL CallVoidMethodA(jobject obj, jmethodID methodID, jvalue * args);
virtual jobject JNICALL CallNonvirtualObjectMethod(jobject obj, jclass clazz, jmethodID methodID, ...);
virtual jobject JNICALL CallNonvirtualObjectMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args);
virtual jobject JNICALL CallNonvirtualObjectMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue * args);
virtual jboolean JNICALL CallNonvirtualBooleanMethod(jobject obj, jclass clazz, jmethodID methodID, ...);
virtual jboolean JNICALL CallNonvirtualBooleanMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args);
virtual jboolean JNICALL CallNonvirtualBooleanMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue * args);
virtual jbyte JNICALL CallNonvirtualByteMethod(jobject obj, jclass clazz, jmethodID methodID, ...);
virtual jbyte JNICALL CallNonvirtualByteMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args);
virtual jbyte JNICALL CallNonvirtualByteMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args);
virtual jchar JNICALL CallNonvirtualCharMethod(jobject obj, jclass clazz, jmethodID methodID, ...);
virtual jchar JNICALL CallNonvirtualCharMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args);
virtual jchar JNICALL CallNonvirtualCharMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args);
virtual jshort JNICALL CallNonvirtualShortMethod(jobject obj, jclass clazz, jmethodID methodID, ...);
virtual jshort JNICALL CallNonvirtualShortMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args);
virtual jshort JNICALL CallNonvirtualShortMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args);
virtual jint JNICALL CallNonvirtualIntMethod(jobject obj, jclass clazz, jmethodID methodID, ...);
virtual jint JNICALL CallNonvirtualIntMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args);
virtual jint JNICALL CallNonvirtualIntMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args);
virtual jlong JNICALL CallNonvirtualLongMethod(jobject obj, jclass clazz, jmethodID methodID, ...);
virtual jlong JNICALL CallNonvirtualLongMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args);
virtual jlong JNICALL CallNonvirtualLongMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args);
virtual jfloat JNICALL CallNonvirtualFloatMethod(jobject obj, jclass clazz, jmethodID methodID, ...);
virtual jfloat JNICALL CallNonvirtualFloatMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args);
virtual jfloat JNICALL CallNonvirtualFloatMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args);
virtual jdouble JNICALL CallNonvirtualDoubleMethod(jobject obj, jclass clazz, jmethodID methodID, ...);
virtual jdouble JNICALL CallNonvirtualDoubleMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args);
virtual jdouble JNICALL CallNonvirtualDoubleMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args);
virtual void JNICALL CallNonvirtualVoidMethod(jobject obj, jclass clazz, jmethodID methodID, ...);
virtual void JNICALL CallNonvirtualVoidMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args);
virtual void JNICALL CallNonvirtualVoidMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue * args);
virtual jfieldID JNICALL GetFieldID(jclass clazz, const char *name, const char *sig);
virtual jobject JNICALL GetObjectField(jobject obj, jfieldID fieldID);
virtual jboolean JNICALL GetBooleanField(jobject obj, jfieldID fieldID);
virtual jbyte JNICALL GetByteField(jobject obj, jfieldID fieldID);
virtual jchar JNICALL GetCharField(jobject obj, jfieldID fieldID);
virtual jshort JNICALL GetShortField(jobject obj, jfieldID fieldID);
virtual jint JNICALL GetIntField(jobject obj, jfieldID fieldID);
virtual jlong JNICALL GetLongField(jobject obj, jfieldID fieldID);
virtual jfloat JNICALL GetFloatField(jobject obj, jfieldID fieldID);
virtual jdouble JNICALL GetDoubleField(jobject obj, jfieldID fieldID);
virtual void JNICALL SetObjectField(jobject obj, jfieldID fieldID, jobject val);
virtual void JNICALL SetBooleanField(jobject obj, jfieldID fieldID, jboolean val);
virtual void JNICALL SetByteField(jobject obj, jfieldID fieldID, jbyte val);
virtual void JNICALL SetCharField(jobject obj, jfieldID fieldID, jchar val);
virtual void JNICALL SetShortField(jobject obj, jfieldID fieldID, jshort val);
virtual void JNICALL SetIntField(jobject obj, jfieldID fieldID, jint val);
virtual void JNICALL SetLongField(jobject obj, jfieldID fieldID, jlong val);
virtual void JNICALL SetFloatField(jobject obj, jfieldID fieldID, jfloat val);
virtual void JNICALL SetDoubleField(jobject obj, jfieldID fieldID, jdouble val);
virtual jmethodID JNICALL GetStaticMethodID(jclass clazz, const char *name, const char *sig);
virtual jobject JNICALL CallStaticObjectMethod(jclass clazz, jmethodID methodID, ...);
virtual jobject JNICALL CallStaticObjectMethodV(jclass clazz, jmethodID methodID, va_list args);
virtual jobject JNICALL CallStaticObjectMethodA(jclass clazz, jmethodID methodID, jvalue *args);
virtual jboolean JNICALL CallStaticBooleanMethod(jclass clazz, jmethodID methodID, ...);
virtual jboolean JNICALL CallStaticBooleanMethodV(jclass clazz, jmethodID methodID, va_list args);
virtual jboolean JNICALL CallStaticBooleanMethodA(jclass clazz, jmethodID methodID, jvalue *args);
virtual jbyte JNICALL CallStaticByteMethod(jclass clazz, jmethodID methodID, ...);
virtual jbyte JNICALL CallStaticByteMethodV(jclass clazz, jmethodID methodID, va_list args);
virtual jbyte JNICALL CallStaticByteMethodA(jclass clazz, jmethodID methodID, jvalue *args);
virtual jchar JNICALL CallStaticCharMethod(jclass clazz, jmethodID methodID, ...);
virtual jchar JNICALL CallStaticCharMethodV(jclass clazz, jmethodID methodID, va_list args);
virtual jchar JNICALL CallStaticCharMethodA(jclass clazz, jmethodID methodID, jvalue *args);
virtual jshort JNICALL CallStaticShortMethod(jclass clazz, jmethodID methodID, ...);
virtual jshort JNICALL CallStaticShortMethodV(jclass clazz, jmethodID methodID, va_list args);
virtual jshort JNICALL CallStaticShortMethodA(jclass clazz, jmethodID methodID, jvalue *args);
virtual jint JNICALL CallStaticIntMethod(jclass clazz, jmethodID methodID, ...);
virtual jint JNICALL CallStaticIntMethodV(jclass clazz, jmethodID methodID, va_list args);
virtual jint JNICALL CallStaticIntMethodA(jclass clazz, jmethodID methodID, jvalue *args);
virtual jlong JNICALL CallStaticLongMethod(jclass clazz, jmethodID methodID, ...);
virtual jlong JNICALL CallStaticLongMethodV(jclass clazz, jmethodID methodID, va_list args);
virtual jlong JNICALL CallStaticLongMethodA(jclass clazz, jmethodID methodID, jvalue *args);
virtual jfloat JNICALL CallStaticFloatMethod(jclass clazz, jmethodID methodID, ...);
virtual jfloat JNICALL CallStaticFloatMethodV(jclass clazz, jmethodID methodID, va_list args);
virtual jfloat JNICALL CallStaticFloatMethodA(jclass clazz, jmethodID methodID, jvalue *args);
virtual jdouble JNICALL CallStaticDoubleMethod(jclass clazz, jmethodID methodID, ...);
virtual jdouble JNICALL CallStaticDoubleMethodV(jclass clazz, jmethodID methodID, va_list args);
virtual jdouble JNICALL CallStaticDoubleMethodA(jclass clazz, jmethodID methodID, jvalue *args);
virtual void JNICALL CallStaticVoidMethod(jclass cls, jmethodID methodID, ...);
virtual void JNICALL CallStaticVoidMethodV(jclass cls, jmethodID methodID, va_list args);
virtual void JNICALL CallStaticVoidMethodA(jclass cls, jmethodID methodID, jvalue * args);
virtual jfieldID JNICALL GetStaticFieldID(jclass clazz, const char *name, const char *sig);
virtual jobject JNICALL GetStaticObjectField(jclass clazz, jfieldID fieldID);
virtual jboolean JNICALL GetStaticBooleanField(jclass clazz, jfieldID fieldID);
virtual jbyte JNICALL GetStaticByteField(jclass clazz, jfieldID fieldID);
virtual jchar JNICALL GetStaticCharField(jclass clazz, jfieldID fieldID);
virtual jshort JNICALL GetStaticShortField(jclass clazz, jfieldID fieldID);
virtual jint JNICALL GetStaticIntField(jclass clazz, jfieldID fieldID);
virtual jlong JNICALL GetStaticLongField(jclass clazz, jfieldID fieldID);
virtual jfloat JNICALL GetStaticFloatField(jclass clazz, jfieldID fieldID);
virtual jdouble JNICALL GetStaticDoubleField(jclass clazz, jfieldID fieldID);
virtual void JNICALL SetStaticObjectField(jclass clazz, jfieldID fieldID, jobject value);
virtual void JNICALL SetStaticBooleanField(jclass clazz, jfieldID fieldID, jboolean value);
virtual void JNICALL SetStaticByteField(jclass clazz, jfieldID fieldID, jbyte value);
virtual void JNICALL SetStaticCharField(jclass clazz, jfieldID fieldID, jchar value);
virtual void JNICALL SetStaticShortField(jclass clazz, jfieldID fieldID, jshort value);
virtual void JNICALL SetStaticIntField(jclass clazz, jfieldID fieldID, jint value);
virtual void JNICALL SetStaticLongField(jclass clazz, jfieldID fieldID, jlong value);
virtual void JNICALL SetStaticFloatField(jclass clazz, jfieldID fieldID, jfloat value);
virtual void JNICALL SetStaticDoubleField(jclass clazz, jfieldID fieldID, jdouble value);
virtual jstring JNICALL NewString(const jchar *unicode, jsize len);
virtual jsize JNICALL GetStringLength(jstring str);
virtual const jchar *JNICALL GetStringChars(jstring str, jboolean *isCopy);
virtual void JNICALL ReleaseStringChars(jstring str, const jchar *chars);
virtual jstring JNICALL NewStringUTF(const char *utf);
virtual jsize JNICALL GetStringUTFLength(jstring str);
virtual const char* JNICALL GetStringUTFChars(jstring str, jboolean *isCopy);
virtual void JNICALL ReleaseStringUTFChars(jstring str, const char* chars);
virtual jsize JNICALL GetArrayLength(jarray array);
virtual jobjectArray JNICALL NewObjectArray(jsize len, jclass clazz, jobject init);
virtual jobject JNICALL GetObjectArrayElement(jobjectArray array, jsize index);
virtual void JNICALL SetObjectArrayElement(jobjectArray array, jsize index, jobject val);
virtual jbooleanArray JNICALL NewBooleanArray(jsize len);
virtual jbyteArray JNICALL NewByteArray(jsize len);
virtual jcharArray JNICALL NewCharArray(jsize len);
virtual jshortArray JNICALL NewShortArray(jsize len);
virtual jintArray JNICALL NewIntArray(jsize len);
virtual jlongArray JNICALL NewLongArray(jsize len);
virtual jfloatArray JNICALL NewFloatArray(jsize len);
virtual jdoubleArray JNICALL NewDoubleArray(jsize len);
virtual jboolean * JNICALL GetBooleanArrayElements(jbooleanArray array, jboolean *isCopy);
virtual jbyte * JNICALL GetByteArrayElements(jbyteArray array, jboolean *isCopy);
virtual jchar * JNICALL GetCharArrayElements(jcharArray array, jboolean *isCopy);
virtual jshort * JNICALL GetShortArrayElements(jshortArray array, jboolean *isCopy);
virtual jint * JNICALL GetIntArrayElements(jintArray array, jboolean *isCopy);
virtual jlong * JNICALL GetLongArrayElements(jlongArray array, jboolean *isCopy);
virtual jfloat * JNICALL GetFloatArrayElements(jfloatArray array, jboolean *isCopy);
virtual jdouble * JNICALL GetDoubleArrayElements(jdoubleArray array, jboolean *isCopy);
virtual void JNICALL ReleaseBooleanArrayElements(jbooleanArray array, jboolean *elems, jint mode);
virtual void JNICALL ReleaseByteArrayElements(jbyteArray array, jbyte *elems, jint mode);
virtual void JNICALL ReleaseCharArrayElements(jcharArray array, jchar *elems, jint mode);
virtual void JNICALL ReleaseShortArrayElements(jshortArray array, jshort *elems, jint mode);
virtual void JNICALL ReleaseIntArrayElements(jintArray array, jint *elems, jint mode);
virtual void JNICALL ReleaseLongArrayElements(jlongArray array, jlong *elems, jint mode);
virtual void JNICALL ReleaseFloatArrayElements(jfloatArray array, jfloat *elems, jint mode);
virtual void JNICALL ReleaseDoubleArrayElements(jdoubleArray array, jdouble *elems, jint mode);
virtual void JNICALL GetBooleanArrayRegion(jbooleanArray array, jsize start, jsize l, jboolean *buf);
virtual void JNICALL GetByteArrayRegion(jbyteArray array, jsize start, jsize len, jbyte *buf);
virtual void JNICALL GetCharArrayRegion(jcharArray array, jsize start, jsize len, jchar *buf);
virtual void JNICALL GetShortArrayRegion(jshortArray array, jsize start, jsize len, jshort *buf);
virtual void JNICALL GetIntArrayRegion(jintArray array, jsize start, jsize len, jint *buf);
virtual void JNICALL GetLongArrayRegion(jlongArray array, jsize start, jsize len, jlong *buf);
virtual void JNICALL GetFloatArrayRegion(jfloatArray array, jsize start, jsize len, jfloat *buf);
virtual void JNICALL GetDoubleArrayRegion(jdoubleArray array, jsize start, jsize len, jdouble *buf);
virtual void JNICALL SetBooleanArrayRegion(jbooleanArray array, jsize start, jsize l, jboolean *buf);
virtual void JNICALL SetByteArrayRegion(jbyteArray array, jsize start, jsize len, jbyte *buf);
virtual void JNICALL SetCharArrayRegion(jcharArray array, jsize start, jsize len, jchar *buf);
virtual void JNICALL SetShortArrayRegion(jshortArray array, jsize start, jsize len, jshort *buf);
virtual void JNICALL SetIntArrayRegion(jintArray array, jsize start, jsize len, jint *buf);
virtual void JNICALL SetLongArrayRegion(jlongArray array, jsize start, jsize len, jlong *buf);
virtual void JNICALL SetFloatArrayRegion(jfloatArray array, jsize start, jsize len, jfloat *buf);
virtual void JNICALL SetDoubleArrayRegion(jdoubleArray array, jsize start, jsize len, jdouble *buf);
virtual jint JNICALL RegisterNatives(jclass clazz, const JNINativeMethod *methods, jint nMethods);
virtual jint JNICALL UnregisterNatives(jclass clazz);
virtual jint JNICALL MonitorEnter(jobject obj);
virtual jint JNICALL MonitorExit(jobject obj);
virtual jint JNICALL GetJavaVM(JavaVM **vm);
};
class JavaVM
{
public:
virtual void JNICALL reserved0();
virtual void JNICALL reserved1();
virtual void JNICALL reserved2();
virtual jint JNICALL DestroyJavaVM();
virtual jint JNICALL AttachCurrentThread(void **penv, void *args);
virtual jint JNICALL DetachCurrentThread();
virtual jint JNICALL GetEnv(void **penv, jint version);
virtual jint JNICALL AttachCurrentThreadAsDaemon(void **penv, void *args);
};

81
IK.VM.NET/AssemblyInfo.cs Normal file
Просмотреть файл

@ -0,0 +1,81 @@
/*
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
*/
using System.Reflection;
using System.Runtime.CompilerServices;
//
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
//
[assembly: AssemblyTitle("IK.VM.NET")]
[assembly: AssemblyDescription("JVM for .NET")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("Copyright (C) 2002 Jeroen Frijters")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
//
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("1.0.*")]
//
// In order to sign your assembly you must specify a key to use. Refer to the
// Microsoft .NET Framework documentation for more information on assembly signing.
//
// Use the attributes below to control which key is used for signing.
//
// Notes:
// (*) If no key is specified, the assembly is not signed.
// (*) KeyName refers to a key that has been installed in the Crypto Service
// Provider (CSP) on your machine. KeyFile refers to a file which contains
// a key.
// (*) If the KeyFile and the KeyName values are both specified, the
// following processing occurs:
// (1) If the KeyName can be found in the CSP, that key is used.
// (2) If the KeyName does not exist and the KeyFile does exist, the key
// in the KeyFile is installed into the CSP and used.
// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
// When specifying the KeyFile, the location of the KeyFile should be
// relative to the project output directory which is
// %Project Directory%\obj\<configuration>. For example, if your KeyFile is
// located in the project directory, you would specify the AssemblyKeyFile
// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
// documentation for more information on this.
//
[assembly: AssemblyDelaySign(false)]
[assembly: AssemblyKeyFile("")]
[assembly: AssemblyKeyName("")]

Просмотреть файл

@ -0,0 +1,177 @@
/*
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
*/
using System;
using System.IO;
sealed class BigEndianBinaryReader
{
private byte[] buf;
private int pos;
internal BigEndianBinaryReader(byte[] buf)
: this(buf, 0)
{
}
internal BigEndianBinaryReader(byte[] buf, int offset)
{
this.buf = buf;
this.pos = offset;
}
internal BigEndianBinaryReader Duplicate()
{
return new BigEndianBinaryReader(buf, pos);
}
internal int Position
{
get
{
return pos;
}
}
internal void Skip(int count)
{
pos += count;
}
internal byte ReadByte()
{
return buf[pos++];
}
internal sbyte ReadSByte()
{
return (sbyte)buf[pos++];
}
internal double ReadDouble()
{
return BitConverter.Int64BitsToDouble(ReadInt64());
}
internal short ReadInt16()
{
short s = (short)((buf[pos] << 8) + buf[pos + 1]);
pos += 2;
return s;
}
internal int ReadInt32()
{
int i = (int)((buf[pos] << 24) + (buf[pos + 1] << 16) + (buf[pos + 2] << 8) + buf[pos + 3]);
pos += 4;
return i;
}
internal long ReadInt64()
{
uint i1 = (uint)((buf[pos] << 24) + (buf[pos + 1] << 16) + (buf[pos + 2] << 8) + buf[pos + 3]);
uint i2 = (uint)((buf[pos + 4] << 24) + (buf[pos + 5] << 16) + (buf[pos + 6] << 8) + buf[pos + 7]);
long l = (((long)i1) << 32) + i2;
pos += 8;
return l;
}
internal float ReadSingle()
{
return BitConverter.ToSingle(BitConverter.GetBytes(ReadInt32()), 0);
}
internal string ReadString()
{
int len = ReadUInt16();
// special code path for ASCII strings (which occur *very* frequently)
for(int j = 0; j < len; j++)
{
if(buf[pos + j] >= 128)
{
// NOTE we *cannot* use System.Text.UTF8Encoding, because this is *not* compatible
// (esp. for embedded nulls)
char[] ch = new char[len];
int l = 0;
for(int i = 0; i < len; i++)
{
int c = buf[pos + i];
int char2, char3;
switch (c >> 4)
{
case 0:
if(c == 0)
{
throw new FormatException();
}
break;
case 1: case 2: case 3: case 4: case 5: case 6: case 7:
// 0xxxxxxx
break;
case 12: case 13:
// 110x xxxx 10xx xxxx
char2 = buf[pos + ++i];
if((char2 & 0xc0) != 0x80)
{
throw new FormatException();
}
c = (((c & 0x1F) << 6) | (char2 & 0x3F));
break;
case 14:
// 1110 xxxx 10xx xxxx 10xx xxxx
char2 = buf[pos + ++i];
char3 = buf[pos + ++i];
if((char2 & 0xc0) != 0x80 || (char3 & 0xc0) != 0x80)
{
throw new FormatException();
}
c = (((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0));
break;
default:
throw new FormatException();
}
ch[l++] = (char)c;
}
pos += len;
return new String(ch, 0, l);
}
}
string s = System.Text.ASCIIEncoding.ASCII.GetString(buf, pos, len);
pos += len;
return s;
}
internal ushort ReadUInt16()
{
ushort s = (ushort)((buf[pos] << 8) + buf[pos + 1]);
pos += 2;
return s;
}
internal uint ReadUInt32()
{
uint i = (uint)((buf[pos] << 24) + (buf[pos + 1] << 16) + (buf[pos + 2] << 8) + buf[pos + 3]);
pos += 4;
return i;
}
}

676
IK.VM.NET/ByteCode.cs Normal file
Просмотреть файл

@ -0,0 +1,676 @@
/*
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
*/
using System;
enum ByteCode
{
__nop = 0,
__aconst_null = 1,
__iconst_m1 = 2,
__iconst_0 = 3,
__iconst_1 = 4,
__iconst_2 = 5,
__iconst_3 = 6,
__iconst_4 = 7,
__iconst_5 = 8,
__lconst_0 = 9,
__lconst_1 = 10,
__fconst_0 = 11,
__fconst_1 = 12,
__fconst_2 = 13,
__dconst_0 = 14,
__dconst_1 = 15,
__bipush = 16,
__sipush = 17,
__ldc = 18,
__ldc_w = 19,
__ldc2_w = 20,
__iload = 21,
__lload = 22,
__fload = 23,
__dload = 24,
__aload = 25,
__iload_0 = 26,
__iload_1 = 27,
__iload_2 = 28,
__iload_3 = 29,
__lload_0 = 30,
__lload_1 = 31,
__lload_2 = 32,
__lload_3 = 33,
__fload_0 = 34,
__fload_1 = 35,
__fload_2 = 36,
__fload_3 = 37,
__dload_0 = 38,
__dload_1 = 39,
__dload_2 = 40,
__dload_3 = 41,
__aload_0 = 42,
__aload_1 = 43,
__aload_2 = 44,
__aload_3 = 45,
__iaload = 46,
__laload = 47,
__faload = 48,
__daload = 49,
__aaload = 50,
__baload = 51,
__caload = 52,
__saload = 53,
__istore = 54,
__lstore = 55,
__fstore = 56,
__dstore = 57,
__astore = 58,
__istore_0 = 59,
__istore_1 = 60,
__istore_2 = 61,
__istore_3 = 62,
__lstore_0 = 63,
__lstore_1 = 64,
__lstore_2 = 65,
__lstore_3 = 66,
__fstore_0 = 67,
__fstore_1 = 68,
__fstore_2 = 69,
__fstore_3 = 70,
__dstore_0 = 71,
__dstore_1 = 72,
__dstore_2 = 73,
__dstore_3 = 74,
__astore_0 = 75,
__astore_1 = 76,
__astore_2 = 77,
__astore_3 = 78,
__iastore = 79,
__lastore = 80,
__fastore = 81,
__dastore = 82,
__aastore = 83,
__bastore = 84,
__castore = 85,
__sastore = 86,
__pop = 87,
__pop2 = 88,
__dup = 89,
__dup_x1 = 90,
__dup_x2 = 91,
__dup2 = 92,
__dup2_x1 = 93,
__dup2_x2 = 94,
__swap = 95,
__iadd = 96,
__ladd = 97,
__fadd = 98,
__dadd = 99,
__isub = 100,
__lsub = 101,
__fsub = 102,
__dsub = 103,
__imul = 104,
__lmul = 105,
__fmul = 106,
__dmul = 107,
__idiv = 108,
__ldiv = 109,
__fdiv = 110,
__ddiv = 111,
__irem = 112,
__lrem = 113,
__frem = 114,
__drem = 115,
__ineg = 116,
__lneg = 117,
__fneg = 118,
__dneg = 119,
__ishl = 120,
__lshl = 121,
__ishr = 122,
__lshr = 123,
__iushr = 124,
__lushr = 125,
__iand = 126,
__land = 127,
__ior = 128,
__lor = 129,
__ixor = 130,
__lxor = 131,
__iinc = 132,
__i2l = 133,
__i2f = 134,
__i2d = 135,
__l2i = 136,
__l2f = 137,
__l2d = 138,
__f2i = 139,
__f2l = 140,
__f2d = 141,
__d2i = 142,
__d2l = 143,
__d2f = 144,
__i2b = 145,
__i2c = 146,
__i2s = 147,
__lcmp = 148,
__fcmpl = 149,
__fcmpg = 150,
__dcmpl = 151,
__dcmpg = 152,
__ifeq = 153,
__ifne = 154,
__iflt = 155,
__ifge = 156,
__ifgt = 157,
__ifle = 158,
__if_icmpeq = 159,
__if_icmpne = 160,
__if_icmplt = 161,
__if_icmpge = 162,
__if_icmpgt = 163,
__if_icmple = 164,
__if_acmpeq = 165,
__if_acmpne = 166,
__goto = 167,
__jsr = 168,
__ret = 169,
__tableswitch = 170,
__lookupswitch = 171,
__ireturn = 172,
__lreturn = 173,
__freturn = 174,
__dreturn = 175,
__areturn = 176,
__return = 177,
__getstatic = 178,
__putstatic = 179,
__getfield = 180,
__putfield = 181,
__invokevirtual = 182,
__invokespecial = 183,
__invokestatic = 184,
__invokeinterface = 185,
__xxxunusedxxx = 186,
__new = 187,
__newarray = 188,
__anewarray = 189,
__arraylength = 190,
__athrow = 191,
__checkcast = 192,
__instanceof = 193,
__monitorenter = 194,
__monitorexit = 195,
__wide = 196,
__multianewarray = 197,
__ifnull = 198,
__ifnonnull = 199,
__goto_w = 200,
__jsr_w = 201
}
enum NormalizedByteCode
{
__nop = 0,
__aconst_null = 1,
__iconst = -1,
__lconst_0 = 9,
__lconst_1 = 10,
__fconst_0 = 11,
__fconst_1 = 12,
__fconst_2 = 13,
__dconst_0 = 14,
__dconst_1 = 15,
__ldc = 18,
__iload = 21,
__lload = 22,
__fload = 23,
__dload = 24,
__aload = 25,
__iaload = 46,
__laload = 47,
__faload = 48,
__daload = 49,
__aaload = 50,
__baload = 51,
__caload = 52,
__saload = 53,
__istore = 54,
__lstore = 55,
__fstore = 56,
__dstore = 57,
__astore = 58,
__iastore = 79,
__lastore = 80,
__fastore = 81,
__dastore = 82,
__aastore = 83,
__bastore = 84,
__castore = 85,
__sastore = 86,
__pop = 87,
__pop2 = 88,
__dup = 89,
__dup_x1 = 90,
__dup_x2 = 91,
__dup2 = 92,
__dup2_x1 = 93,
__dup2_x2 = 94,
__swap = 95,
__iadd = 96,
__ladd = 97,
__fadd = 98,
__dadd = 99,
__isub = 100,
__lsub = 101,
__fsub = 102,
__dsub = 103,
__imul = 104,
__lmul = 105,
__fmul = 106,
__dmul = 107,
__idiv = 108,
__ldiv = 109,
__fdiv = 110,
__ddiv = 111,
__irem = 112,
__lrem = 113,
__frem = 114,
__drem = 115,
__ineg = 116,
__lneg = 117,
__fneg = 118,
__dneg = 119,
__ishl = 120,
__lshl = 121,
__ishr = 122,
__lshr = 123,
__iushr = 124,
__lushr = 125,
__iand = 126,
__land = 127,
__ior = 128,
__lor = 129,
__ixor = 130,
__lxor = 131,
__iinc = 132,
__i2l = 133,
__i2f = 134,
__i2d = 135,
__l2i = 136,
__l2f = 137,
__l2d = 138,
__f2i = 139,
__f2l = 140,
__f2d = 141,
__d2i = 142,
__d2l = 143,
__d2f = 144,
__i2b = 145,
__i2c = 146,
__i2s = 147,
__lcmp = 148,
__fcmpl = 149,
__fcmpg = 150,
__dcmpl = 151,
__dcmpg = 152,
__ifeq = 153,
__ifne = 154,
__iflt = 155,
__ifge = 156,
__ifgt = 157,
__ifle = 158,
__if_icmpeq = 159,
__if_icmpne = 160,
__if_icmplt = 161,
__if_icmpge = 162,
__if_icmpgt = 163,
__if_icmple = 164,
__if_acmpeq = 165,
__if_acmpne = 166,
__goto = 167,
__jsr = 168,
__ret = 169,
__lookupswitch = 171,
__ireturn = 172,
__lreturn = 173,
__freturn = 174,
__dreturn = 175,
__areturn = 176,
__return = 177,
__getstatic = 178,
__putstatic = 179,
__getfield = 180,
__putfield = 181,
__invokevirtual = 182,
__invokespecial = 183,
__invokestatic = 184,
__invokeinterface = 185,
__new = 187,
__newarray = 188,
__anewarray = 189,
__arraylength = 190,
__athrow = 191,
__checkcast = 192,
__instanceof = 193,
__monitorenter = 194,
__monitorexit = 195,
__multianewarray = 197,
__ifnull = 198,
__ifnonnull = 199,
}
enum ByteCodeMode
{
Unused,
Simple,
Constant_1,
Constant_2,
Branch_2,
Local_1,
Local_2,
Constant_2_1_1,
Immediate_1,
Immediate_2,
Local_1_Immediate_1,
Local_2_Immediate_2,
Tableswitch,
Lookupswitch,
Constant_2_Immediate_1,
Branch_4
}
struct ByteCodeMetaData
{
private static ByteCodeMetaData[] data = new ByteCodeMetaData[202];
private ByteCodeMode reg;
private ByteCodeMode wide;
private NormalizedByteCode normbc;
private int arg;
private bool hasFixedArg;
private ByteCodeMetaData(ByteCode bc, ByteCodeMode reg, ByteCodeMode wide)
{
this.reg = reg;
this.wide = wide;
this.normbc = (NormalizedByteCode)Enum.Parse(typeof(NormalizedByteCode), bc.ToString());
this.arg = 0;
this.hasFixedArg = false;
data[(int)bc] = this;
}
private ByteCodeMetaData(ByteCode bc, NormalizedByteCode normbc, ByteCodeMode reg, ByteCodeMode wide)
{
this.reg = reg;
this.wide = wide;
this.normbc = normbc;
this.arg = 0;
this.hasFixedArg = false;
data[(int)bc] = this;
}
private ByteCodeMetaData(ByteCode bc, NormalizedByteCode normbc, int arg, ByteCodeMode reg, ByteCodeMode wide)
{
this.reg = reg;
this.wide = wide;
this.normbc = normbc;
this.arg = arg;
this.hasFixedArg = true;
data[(int)bc] = this;
}
internal static NormalizedByteCode GetNormalizedByteCode(ByteCode bc)
{
return data[(int)bc].normbc;
}
internal static int GetArg(ByteCode bc, int arg)
{
if(data[(int)bc].hasFixedArg)
{
return data[(int)bc].arg;
}
return arg;
}
internal static ByteCodeMode GetMode(ByteCode bc)
{
return data[(int)bc].reg;
}
internal static ByteCodeMode GetWideMode(ByteCode bc)
{
ByteCodeMode m = data[(int)bc].wide;
if(m == ByteCodeMode.Unused)
{
throw new ArgumentException("Wide version of " + bc + " is not a valid instruction", "bc");
}
return m;
}
static ByteCodeMetaData()
{
new ByteCodeMetaData(ByteCode.__nop, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__aconst_null, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__iconst_m1, NormalizedByteCode.__iconst, -1, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__iconst_0, NormalizedByteCode.__iconst, 0, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__iconst_1, NormalizedByteCode.__iconst, 1, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__iconst_2, NormalizedByteCode.__iconst, 2, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__iconst_3, NormalizedByteCode.__iconst, 3, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__iconst_4, NormalizedByteCode.__iconst, 4, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__iconst_5, NormalizedByteCode.__iconst, 5, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__lconst_0, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__lconst_1, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__fconst_0, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__fconst_1, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__fconst_2, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__dconst_0, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__dconst_1, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__bipush, NormalizedByteCode.__iconst, ByteCodeMode.Immediate_1, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__sipush, NormalizedByteCode.__iconst, ByteCodeMode.Immediate_2, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__ldc, ByteCodeMode.Constant_1, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__ldc_w, NormalizedByteCode.__ldc, ByteCodeMode.Constant_2, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__ldc2_w, NormalizedByteCode.__ldc, ByteCodeMode.Constant_2, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__iload, ByteCodeMode.Local_1, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__lload, ByteCodeMode.Local_1, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__fload, ByteCodeMode.Local_1, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__dload, ByteCodeMode.Local_1, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__aload, ByteCodeMode.Local_1, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__iload_0, NormalizedByteCode.__iload, 0, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__iload_1, NormalizedByteCode.__iload, 1, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__iload_2, NormalizedByteCode.__iload, 2, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__iload_3, NormalizedByteCode.__iload, 3, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__lload_0, NormalizedByteCode.__lload, 0, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__lload_1, NormalizedByteCode.__lload, 1, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__lload_2, NormalizedByteCode.__lload, 2, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__lload_3, NormalizedByteCode.__lload, 3, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__fload_0, NormalizedByteCode.__fload, 0, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__fload_1, NormalizedByteCode.__fload, 1, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__fload_2, NormalizedByteCode.__fload, 2, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__fload_3, NormalizedByteCode.__fload, 3, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__dload_0, NormalizedByteCode.__dload, 0, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__dload_1, NormalizedByteCode.__dload, 1, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__dload_2, NormalizedByteCode.__dload, 2, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__dload_3, NormalizedByteCode.__dload, 3, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__aload_0, NormalizedByteCode.__aload, 0, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__aload_1, NormalizedByteCode.__aload, 1, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__aload_2, NormalizedByteCode.__aload, 2, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__aload_3, NormalizedByteCode.__aload, 3, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__iaload, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__laload, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__faload, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__daload, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__aaload, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__baload, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__caload, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__saload, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__istore, ByteCodeMode.Local_1, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__lstore, ByteCodeMode.Local_1, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__fstore, ByteCodeMode.Local_1, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__dstore, ByteCodeMode.Local_1, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__astore, ByteCodeMode.Local_1, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__istore_0, NormalizedByteCode.__istore, 0, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__istore_1, NormalizedByteCode.__istore, 1, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__istore_2, NormalizedByteCode.__istore, 2, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__istore_3, NormalizedByteCode.__istore, 3, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__lstore_0, NormalizedByteCode.__lstore, 0, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__lstore_1, NormalizedByteCode.__lstore, 1, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__lstore_2, NormalizedByteCode.__lstore, 2, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__lstore_3, NormalizedByteCode.__lstore, 3, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__fstore_0, NormalizedByteCode.__fstore, 0, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__fstore_1, NormalizedByteCode.__fstore, 1, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__fstore_2, NormalizedByteCode.__fstore, 2, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__fstore_3, NormalizedByteCode.__fstore, 3, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__dstore_0, NormalizedByteCode.__dstore, 0, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__dstore_1, NormalizedByteCode.__dstore, 1, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__dstore_2, NormalizedByteCode.__dstore, 2, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__dstore_3, NormalizedByteCode.__dstore, 3, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__astore_0, NormalizedByteCode.__astore, 0, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__astore_1, NormalizedByteCode.__astore, 1, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__astore_2, NormalizedByteCode.__astore, 2, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__astore_3, NormalizedByteCode.__astore, 3, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__iastore, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__lastore, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__fastore, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__dastore, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__aastore, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__bastore, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__castore, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__sastore, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__pop, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__pop2, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__dup, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__dup_x1, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__dup_x2, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__dup2, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__dup2_x1, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__dup2_x2, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__swap, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__iadd, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__ladd, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__fadd, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__dadd, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__isub, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__lsub, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__fsub, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__dsub, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__imul, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__lmul, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__fmul, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__dmul, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__idiv, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__ldiv, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__fdiv, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__ddiv, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__irem, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__lrem, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__frem, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__drem, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__ineg, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__lneg, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__fneg, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__dneg, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__ishl, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__lshl, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__ishr, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__lshr, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__iushr, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__lushr, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__iand, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__land, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__ior, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__lor, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__ixor, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__lxor, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__iinc, ByteCodeMode.Local_1_Immediate_1, ByteCodeMode.Local_2_Immediate_2);
new ByteCodeMetaData(ByteCode.__i2l, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__i2f, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__i2d, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__l2i, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__l2f, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__l2d, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__f2i, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__f2l, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__f2d, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__d2i, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__d2l, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__d2f, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__i2b, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__i2c, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__i2s, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__lcmp, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__fcmpl, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__fcmpg, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__dcmpl, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__dcmpg, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__ifeq, ByteCodeMode.Branch_2, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__ifne, ByteCodeMode.Branch_2, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__iflt, ByteCodeMode.Branch_2, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__ifge, ByteCodeMode.Branch_2, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__ifgt, ByteCodeMode.Branch_2, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__ifle, ByteCodeMode.Branch_2, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__if_icmpeq, ByteCodeMode.Branch_2, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__if_icmpne, ByteCodeMode.Branch_2, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__if_icmplt, ByteCodeMode.Branch_2, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__if_icmpge, ByteCodeMode.Branch_2, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__if_icmpgt, ByteCodeMode.Branch_2, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__if_icmple, ByteCodeMode.Branch_2, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__if_acmpeq, ByteCodeMode.Branch_2, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__if_acmpne, ByteCodeMode.Branch_2, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__goto, ByteCodeMode.Branch_2, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__jsr, ByteCodeMode.Branch_2, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__ret, ByteCodeMode.Local_1, ByteCodeMode.Local_2);
new ByteCodeMetaData(ByteCode.__tableswitch, NormalizedByteCode.__lookupswitch, ByteCodeMode.Tableswitch, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__lookupswitch, ByteCodeMode.Lookupswitch, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__ireturn, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__lreturn, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__freturn, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__dreturn, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__areturn, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__return, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__getstatic, ByteCodeMode.Constant_2, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__putstatic, ByteCodeMode.Constant_2, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__getfield, ByteCodeMode.Constant_2, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__putfield, ByteCodeMode.Constant_2, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__invokevirtual, ByteCodeMode.Constant_2, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__invokespecial, ByteCodeMode.Constant_2, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__invokestatic, ByteCodeMode.Constant_2, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__invokeinterface, ByteCodeMode.Constant_2_1_1, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__xxxunusedxxx, NormalizedByteCode.__nop, ByteCodeMode.Unused, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__new, ByteCodeMode.Constant_2, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__newarray, ByteCodeMode.Immediate_1, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__anewarray, ByteCodeMode.Constant_2, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__arraylength, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__athrow, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__checkcast, ByteCodeMode.Constant_2, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__instanceof, ByteCodeMode.Constant_2, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__monitorenter, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__monitorexit, ByteCodeMode.Simple, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__wide, NormalizedByteCode.__nop, ByteCodeMode.Unused, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__multianewarray, ByteCodeMode.Constant_2_Immediate_1, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__ifnull, ByteCodeMode.Branch_2, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__ifnonnull, ByteCodeMode.Branch_2, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__goto_w, NormalizedByteCode.__goto, ByteCodeMode.Branch_4, ByteCodeMode.Unused);
new ByteCodeMetaData(ByteCode.__jsr_w, NormalizedByteCode.__jsr, ByteCodeMode.Branch_4, ByteCodeMode.Unused);
}
}

Просмотреть файл

@ -0,0 +1,72 @@
/*
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
*/
using System;
public class ByteCodeHelper
{
public static object multianewarray(RuntimeTypeHandle typeHandle, int[] lengths)
{
for(int i = 0; i < lengths.Length; i++)
{
if(lengths[i] < 0)
{
throw JavaException.NegativeArraySizeException();
}
}
return MultianewarrayHelper(Type.GetTypeFromHandle(typeHandle).GetElementType(), lengths, 0);
}
private static object MultianewarrayHelper(Type elemType, int[] lengths, int index)
{
object o = Array.CreateInstance(elemType, lengths[index++]);
if(index < lengths.Length)
{
elemType = elemType.GetElementType();
object[] a = (object[])o;
for(int i = 0; i < a.Length; i++)
{
a[i] = MultianewarrayHelper(elemType, lengths, index);
}
}
return o;
}
public static void monitorenter(object o)
{
if(o == null)
{
throw new NullReferenceException();
}
System.Threading.Monitor.Enter(o);
}
public static void monitorexit(object o)
{
if(o == null)
{
throw new NullReferenceException();
}
System.Threading.Monitor.Exit(o);
}
}

1579
IK.VM.NET/ClassFile.cs Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,900 @@
#define DEBUG
/*
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
*/
using System;
using System.Reflection.Emit;
using System.Reflection;
using System.IO;
using System.Collections;
using System.Xml;
using System.Diagnostics;
class ClassLoaderWrapper
{
private static bool arrayConstructionHack;
private static ArrayList ikvmAssemblies = new ArrayList();
private static Hashtable assemblyToClassLoaderWrapper = new Hashtable();
private static Hashtable javaClassLoaderToClassLoaderWrapper = new Hashtable();
private static ArrayList classLoaders = new ArrayList();
private static Hashtable dynamicTypes = new Hashtable();
// TODO typeToTypeWrapper should be an identity hashtable
private static Hashtable typeToTypeWrapper = new Hashtable();
private static ClassLoaderWrapper bootstrapClassLoader;
private object javaClassLoader;
private MethodInfo loadClassMethod;
private Hashtable types = new Hashtable();
private Hashtable nativeMethods;
// HACK moduleBuilder is static, because multiple dynamic assemblies is broken (TypeResolve doesn't fire)
// so for the time being, we share one dynamic assembly among all classloaders
private static ModuleBuilder moduleBuilder;
// HACK this is used by the ahead-of-time compiler to overrule the bootstrap classloader
internal static void SetBootstrapClassLoader(ClassLoaderWrapper bootstrapClassLoader)
{
if(ClassLoaderWrapper.bootstrapClassLoader != null)
{
throw new InvalidOperationException();
}
ClassLoaderWrapper.bootstrapClassLoader = bootstrapClassLoader;
}
static ClassLoaderWrapper()
{
AppDomain.CurrentDomain.TypeResolve += new ResolveEventHandler(OnTypeResolve);
AppDomain.CurrentDomain.AssemblyLoad += new AssemblyLoadEventHandler(OnAssemblyLoad);
foreach(Assembly a in AppDomain.CurrentDomain.GetAssemblies())
{
if(a.IsDefined(typeof(IKVMAssemblyAttribute), false) && !(a is AssemblyBuilder))
{
ikvmAssemblies.Add(a);
}
}
}
private static void OnAssemblyLoad(object sender, AssemblyLoadEventArgs e)
{
if(e.LoadedAssembly.IsDefined(typeof(IKVMAssemblyAttribute), false) && !(e.LoadedAssembly is AssemblyBuilder))
{
ikvmAssemblies.Add(e.LoadedAssembly);
}
}
private static Assembly OnTypeResolve(object sender, ResolveEventArgs args)
{
//Console.WriteLine("OnTypeResolve: " + args.Name);
if(arrayConstructionHack)
{
return null;
}
try
{
TypeWrapper type = (TypeWrapper)dynamicTypes[args.Name];
if(type == null)
{
return null;
}
type.Finish();
return type.Type.Assembly;
}
catch(Exception x)
{
// TODO don't catch the exception here... But, the problem is that Type.GetType() swallows all exceptions
// that occur here, unless throwOnError is set, but in some (most?) cases you don't want the exception if it only
// means that the class cannot be found...
Console.WriteLine(x);
Console.WriteLine(new StackTrace(true));
throw;
}
}
internal ClassLoaderWrapper(object javaClassLoader)
{
this.javaClassLoader = javaClassLoader;
if(javaClassLoader != null)
{
loadClassMethod = javaClassLoader.GetType().GetMethod("loadClass", BindingFlags.Public | BindingFlags.Instance, null, CallingConventions.Standard, new Type[] { typeof(string) }, null);
if(loadClassMethod == null)
{
throw new InvalidOperationException();
}
}
classLoaders.Add(this);
}
internal void LoadRemappedTypes()
{
nativeMethods = new Hashtable();
// TODO interfaces have java/lang/Object as the base type (do they really?)
types["java.lang.Cloneable"] = new RemappedTypeWrapper(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(ModifiersAttribute.GetModifiers(typeof(java.io.Serializable)), "java/io/Serializable", typeof(java.io.Serializable), new TypeWrapper[0], null);
typeToTypeWrapper.Add(typeof(java.io.Serializable), types["java.io.Serializable"]);
MapXml.Root map = null;
using(Stream s = Assembly.GetExecutingAssembly().GetManifestResourceStream("map.xml"))
{
// TODO the XmlSerializer generates a bunch of C# code and compiles that. This is very slow, we probably
// shouldn't use it.
System.Xml.Serialization.XmlSerializer ser = new System.Xml.Serialization.XmlSerializer(typeof(MapXml.Root));
map = (MapXml.Root)ser.Deserialize(s);
}
foreach(MapXml.Class c in map.remappings)
{
TypeWrapper baseWrapper = null;
// HACK need to resolve the base type or put it in the XML
if(c.Type != "System.Object")
{
baseWrapper = (TypeWrapper)types["java.lang.Object"];
}
string name = c.Name;
Modifiers modifiers = (Modifiers)c.Modifiers;
// TODO specify interfaces
TypeWrapper tw = new RemappedTypeWrapper(modifiers, name.Replace('.', '/'), Type.GetType(c.Type, true), new TypeWrapper[0], baseWrapper);
types.Add(name, tw);
typeToTypeWrapper.Add(tw.Type, tw);
}
foreach(MapXml.Class c in map.remappings)
{
((RemappedTypeWrapper)types[c.Name]).LoadRemappings(c);
}
// native methods
foreach(MapXml.Class c in map.nativeMethods)
{
string className = c.Name;
foreach(MapXml.Method method in c.Methods)
{
string methodName = method.Name;
string methodSig = method.Sig;
nativeMethods[className + "." + methodName + methodSig] = method;
}
}
}
internal TypeWrapper LoadClassBySlashedName(string name)
{
// OPTIMIZE
return LoadClassByDottedName(name.Replace('/', '.'));
}
// TODO implement vmspec 5.3.4 Loading Constraints
internal TypeWrapper LoadClassByDottedName(string name)
{
TypeWrapper type = (TypeWrapper)types[name];
if(type != null)
{
return type;
}
if(name.Length > 1 && name[0] == '[')
{
int dims = 1;
while(name[dims] == '[')
{
dims++;
}
switch(name[dims])
{
case 'L':
{
type = LoadClassByDottedName(name.Substring(dims + 1, name.IndexOf(';', dims) - dims - 1));
type = type.GetClassLoader().CreateArrayType(name, type.Type, dims);
return type;
}
case 'B':
return GetBootstrapClassLoader().CreateArrayType(name, typeof(sbyte), dims);
case 'C':
return GetBootstrapClassLoader().CreateArrayType(name, typeof(char), dims);
case 'D':
return GetBootstrapClassLoader().CreateArrayType(name, typeof(double), dims);
case 'F':
return GetBootstrapClassLoader().CreateArrayType(name, typeof(float), dims);
case 'I':
return GetBootstrapClassLoader().CreateArrayType(name, typeof(int), dims);
case 'J':
return GetBootstrapClassLoader().CreateArrayType(name, typeof(long), dims);
case 'S':
return GetBootstrapClassLoader().CreateArrayType(name, typeof(short), dims);
case 'Z':
return GetBootstrapClassLoader().CreateArrayType(name, typeof(bool), dims);
default:
// TODO I'm not sure this is the right exception here (instead we could throw a NoClassDefFoundError)
throw JavaException.ClassNotFoundException(name);
}
}
if(javaClassLoader == null)
{
// HACK if the name contains a comma, we assume it is an assembly qualified name
if(name.IndexOf(',') != -1)
{
Type t = Type.GetType(name);
if(t != null)
{
return GetCompiledTypeWrapper(t);
}
}
type = GetBootstrapType(name);
if(type != null)
{
return type;
}
throw JavaException.ClassNotFoundException(name);
}
else
{
// OPTIMIZE this should be optimized
try
{
object clazz;
// NOTE just like Java does (I think), we take the classloader lock before calling the loadClass method
lock(javaClassLoader)
{
clazz = loadClassMethod.Invoke(javaClassLoader, new object[] { name });
}
type = (TypeWrapper)clazz.GetType().GetField("wrapper", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(clazz);
if(type == null)
{
Type t = (Type)clazz.GetType().GetField("type", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(clazz);
ClassLoaderWrapper loader = GetClassLoader(t);
type = (TypeWrapper)loader.types[name];
if(type == null)
{
// this shouldn't be possible
throw new InvalidOperationException(name + ", this = " + javaClassLoader);
}
}
// NOTE we're caching types loaded by parent classloaders as well!
// TODO not sure if this is correct
if(type.GetClassLoader() != this)
{
if(types[name] != type)
{
types.Add(name, type);
}
}
return type;
}
catch(TargetInvocationException x)
{
ExceptionHelper.MapExceptionFast(x);
throw x.InnerException;
}
}
}
private TypeWrapper GetCompiledTypeWrapper(Type type)
{
Debug.Assert(!(type is TypeBuilder));
// only the bootstrap classloader can own compiled types
Debug.Assert(javaClassLoader == null);
string name = NativeCode.java.lang.Class.getName(type);
TypeWrapper wrapper = (TypeWrapper)types[name];
if(wrapper == null)
{
TypeWrapper baseType;
if(type.BaseType == null)
{
baseType = LoadClassByDottedName("java.lang.Object");
}
else
{
baseType = GetWrapperFromType(type.BaseType);
}
wrapper = new CompiledTypeWrapper(name.Replace('.', '/'), type, baseType);
types.Add(name, wrapper);
// TODO shouldn't we add the <type,wrapper> to the typeToTypeWrapper hashtable?
}
return wrapper;
}
internal virtual Type GetBootstrapTypeRaw(string name)
{
// TODO consider the thread safety aspects of this (if another thread triggers a load of an IKVM assembly,
// the collection enumerator will throw a version exception)
foreach(Assembly a in ikvmAssemblies)
{
Type t = a.GetType(name);
if(t != null)
{
return t;
}
}
return null;
}
internal virtual TypeWrapper GetBootstrapType(string name)
{
Type t = GetBootstrapTypeRaw(name);
if(t != null)
{
return GetCompiledTypeWrapper(t);
}
return null;
}
private TypeWrapper CreateArrayType(string name, Type elementType, int dims)
{
// TODO array accessibility should be the same as the elementType's accessibility
// (and this should be enforced)
TypeWrapper wrapper = (TypeWrapper)types[name];
if(wrapper == null)
{
String netname = "[]";
for(int i = 1; i < dims; i++)
{
netname += "[]";
}
Type array;
if(elementType.Module is ModuleBuilder)
{
// HACK ModuleBuilder.GetType() is broken (I think), it fires a TypeResolveEvent when
// you try to construct an array type from an unfinished type. I don't think it should
// do that. We have to work around that by setting a global flag (yuck) to prevent us
// from responding to the TypeResolveEvent.
arrayConstructionHack = true;
try
{
array = ((ModuleBuilder)elementType.Module).GetType(elementType.FullName + netname);
}
finally
{
arrayConstructionHack = false;
}
}
else
{
array = elementType.Assembly.GetType(elementType.FullName + netname, true);
}
TypeWrapper[] interfaces = new TypeWrapper[2];
interfaces[0] = GetBootstrapClassLoader().LoadClassByDottedName("java.lang.Cloneable");
interfaces[1] = GetBootstrapClassLoader().LoadClassByDottedName("java.io.Serializable");
MethodDescriptor mdClone = new MethodDescriptor(GetBootstrapClassLoader(), "clone", "()Ljava/lang/Object;");
Modifiers modifiers = Modifiers.Final | Modifiers.Public;
// TODO copy accessibility from element type
wrapper = new RemappedTypeWrapper(modifiers, name, array, interfaces, GetBootstrapClassLoader().LoadClassByDottedName("java.lang.Object"));
MethodInfo clone = typeof(Array).GetMethod("Clone");
MethodWrapper mw = new MethodWrapper(wrapper, mdClone, clone, Modifiers.Public);
mw.EmitCall = CodeEmitter.Create(OpCodes.Callvirt, clone);
mw.EmitCallvirt = CodeEmitter.Create(OpCodes.Callvirt, clone);
wrapper.AddMethod(mw);
types.Add(name, wrapper);
}
return wrapper;
}
// TODO make sure class isn't defined already
// TODO check for circularity
// TODO disallow anyone other than the bootstrap classloader defining classes in the "java." package
internal TypeWrapper DefineClass(ClassFile f)
{
// TODO shouldn't this check be in ClassFile.cs?
if(f.Name.Length == 0 || f.Name[0] == '[')
{
throw JavaException.ClassFormatError("Bad name");
}
TypeWrapper type;
// TODO if the class doesn't exist, LoadClassBySlashedName throws a ClassNotFoundException, but
// we need to catch that and throw a NoClassDefFoundError (because that is unchecked)
// TODO also figure out what should happen if LoadClassBySlashedName throws another exception (custom class loaders
// can throw whatever exception they want)
TypeWrapper baseType = LoadClassBySlashedName(f.SuperClass);
// if the base type isn't public, it must be in the same package
if(!baseType.IsPublic)
{
if(baseType.GetClassLoader() != this || f.PackageName != baseType.PackageName)
{
throw JavaException.IllegalAccessError("Class {0} cannot access its superclass {1}", f.Name, baseType.Name);
}
}
if(baseType.IsFinal)
{
throw JavaException.VerifyError("Cannot inherit from final class");
}
if(baseType.IsInterface)
{
throw JavaException.IncompatibleClassChangeError("Class {0} has interface {1} as superclass", f.Name, baseType.Name);
}
string dotnetType = f.NetExpTypeAttribute;
if(dotnetType != null)
{
type = new NetExpTypeWrapper(f, dotnetType, baseType);
}
else
{
type = new DynamicTypeWrapper(f.Name, f, baseType, this, nativeMethods);
dynamicTypes.Add(f.Name.Replace('/', '.'), type);
}
types.Add(f.Name.Replace('/', '.'), type);
return type;
}
internal object GetJavaClassLoader()
{
return javaClassLoader;
}
internal static void SaveDebugImage(object mainClass)
{
// HACK we iterate 3 times, in the hopes that that will be enough. We really should let FinishAll return a boolean whether
// anything was done, and continue iterating until all FinishAlls return false.
for(int i = 0; i < 3; i++)
{
foreach(ClassLoaderWrapper wrapper in classLoaders)
{
wrapper.FinishAll();
}
}
// HACK use reflection to get the type from the class
Type mainType = NativeCode.java.lang.Class.getType(mainClass);
MethodInfo main = mainType.GetMethod("main", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] { typeof(string[]) }, null);
AssemblyBuilder asm = ((AssemblyBuilder)moduleBuilder.Assembly);
asm.SetEntryPoint(main, PEFileKinds.ConsoleApplication);
asm.Save(moduleBuilder.Name);
}
// this version isn't used at the moment, because multi assembly type references are broken in the CLR
internal static void SaveDebugImage__MultiAssemblyVersion(object mainClass)
{
// HACK we iterate 3 times, in the hopes that that will be enough. We really should let FinishAll return a boolean whether
// anything was done, and continue iterating until all FinishAlls return false.
for(int i = 0; i < 3; i++)
{
foreach(DictionaryEntry entry in assemblyToClassLoaderWrapper)
{
AssemblyBuilder asm = (AssemblyBuilder)entry.Key;
ClassLoaderWrapper loader = (ClassLoaderWrapper)entry.Value;
loader.FinishAll();
}
}
// HACK use reflection to get the type from the class
Type mainType = NativeCode.java.lang.Class.getType(mainClass);
MethodInfo main = mainType.GetMethod("main", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] { typeof(string[]) }, null);
foreach(DictionaryEntry entry in ClassLoaderWrapper.assemblyToClassLoaderWrapper)
{
AssemblyBuilder asm = (AssemblyBuilder)entry.Key;
ClassLoaderWrapper loader = (ClassLoaderWrapper)entry.Value;
if(mainType.Assembly.Equals(asm))
{
asm.SetEntryPoint(main, PEFileKinds.ConsoleApplication);
}
asm.Save(asm.GetName().Name);
}
}
internal void FinishAll()
{
int prevCount = -1;
while(prevCount != types.Count)
{
prevCount = types.Count;
ArrayList l = new ArrayList();
foreach(TypeWrapper t in types.Values)
{
l.Add(t);
}
foreach(TypeWrapper t in l)
{
t.Finish();
}
}
}
internal ModuleBuilder ModuleBuilder
{
get
{
lock(this)
{
if(moduleBuilder == null)
{
moduleBuilder = CreateModuleBuilder();
lock(assemblyToClassLoaderWrapper.SyncRoot)
{
assemblyToClassLoaderWrapper[moduleBuilder.Assembly] = this;
}
}
return moduleBuilder;
}
}
}
protected virtual ModuleBuilder CreateModuleBuilder()
{
AssemblyName name = new AssemblyName();
name.Name = "ikvm_dynamic_assembly__" + (javaClassLoader == null ? "bootstrap" : javaClassLoader);
AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.RunAndSave);
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(name.Name, JVM.Debug);
if(JVM.Debug)
{
CustomAttributeBuilder debugAttr = new CustomAttributeBuilder(typeof(DebuggableAttribute).GetConstructor(new Type[] { typeof(bool), typeof(bool) }), new object[] { true, true });
moduleBuilder.SetCustomAttribute(debugAttr);
}
return moduleBuilder;
}
internal Type ExpressionType(string type)
{
// HACK to ease the burden of the compiler, we support the Lret pseudo type here
if(type.StartsWith("Lret;"))
{
return typeof(int);
}
if(type == "Lnull")
{
throw new InvalidOperationException("ExpressionType for Lnull requested");
}
int index = 0;
return SigDecoder(ref index, type);
}
// NOTE: this will ignore anything following the sig marker (so that it can be used to decode method signatures)
private Type SigDecoder(ref int index, string sig)
{
switch(sig[index++])
{
case 'B':
return typeof(sbyte);
case 'C':
return typeof(char);
case 'D':
return typeof(double);
case 'F':
return typeof(float);
case 'I':
return typeof(int);
case 'J':
return typeof(long);
case 'L':
{
int pos = index;
index = sig.IndexOf(';', index) + 1;
return LoadClassBySlashedName(sig.Substring(pos, index - pos - 1)).Type;
}
case 'S':
return typeof(short);
case 'Z':
return typeof(bool);
case 'V':
return typeof(void);
case '[':
{
// TODO this can be optimized
string array = "[";
while(sig[index] == '[')
{
index++;
array += "[";
}
switch(sig[index])
{
case 'L':
{
int pos = index;
index = sig.IndexOf(';', index) + 1;
return LoadClassBySlashedName(array + sig.Substring(pos, index - pos)).Type;
}
case 'B':
case 'C':
case 'D':
case 'F':
case 'I':
case 'J':
case 'S':
case 'Z':
return LoadClassBySlashedName(array + sig[index++]).Type;
default:
throw new InvalidOperationException(sig.Substring(index));
}
}
default:
throw new InvalidOperationException("Invalid at " + index + " in " + sig);
}
}
internal Type RetTypeFromSig(string sig)
{
int index = sig.IndexOf(')') + 1;
return SigDecoder(ref index, sig);
}
internal Type[] ArgTypeListFromSig(string sig)
{
if(sig[1] == ')')
{
return Type.EmptyTypes;
}
ArrayList list = new ArrayList();
for(int i = 1; sig[i] != ')';)
{
list.Add(SigDecoder(ref i, sig));
}
Type[] types = new Type[list.Count];
list.CopyTo(types);
return types;
}
// NOTE: this will ignore anything following the sig marker (so that it can be used to decode method signatures)
private TypeWrapper SigDecoderWrapper(ref int index, string sig)
{
switch(sig[index++])
{
case 'B':
return PrimitiveTypeWrapper.BYTE;
case 'C':
return PrimitiveTypeWrapper.CHAR;
case 'D':
return PrimitiveTypeWrapper.DOUBLE;
case 'F':
return PrimitiveTypeWrapper.FLOAT;
case 'I':
return PrimitiveTypeWrapper.INT;
case 'J':
return PrimitiveTypeWrapper.LONG;
case 'L':
{
int pos = index;
index = sig.IndexOf(';', index) + 1;
return LoadClassBySlashedName(sig.Substring(pos, index - pos - 1));
}
case 'S':
return PrimitiveTypeWrapper.SHORT;
case 'Z':
return PrimitiveTypeWrapper.BOOLEAN;
case 'V':
return PrimitiveTypeWrapper.VOID;
case '[':
{
// TODO this can be optimized
string array = "[";
while(sig[index] == '[')
{
index++;
array += "[";
}
switch(sig[index])
{
case 'L':
{
int pos = index;
index = sig.IndexOf(';', index) + 1;
return LoadClassBySlashedName(array + sig.Substring(pos, index - pos));
}
case 'B':
case 'C':
case 'D':
case 'F':
case 'I':
case 'J':
case 'S':
case 'Z':
return LoadClassBySlashedName(array + sig[index++]);
default:
throw new InvalidOperationException(sig.Substring(index));
}
}
default:
throw new InvalidOperationException(sig.Substring(index));
}
}
internal TypeWrapper RetTypeWrapperFromSig(string sig)
{
int index = sig.IndexOf(')') + 1;
return SigDecoderWrapper(ref index, sig);
}
internal TypeWrapper[] ArgTypeWrapperListFromSig(string sig)
{
if(sig[1] == ')')
{
return new TypeWrapper[0];
}
ArrayList list = new ArrayList();
for(int i = 1; sig[i] != ')';)
{
list.Add(SigDecoderWrapper(ref i, sig));
}
TypeWrapper[] types = new TypeWrapper[list.Count];
list.CopyTo(types);
return types;
}
// subType and baseType are Java class name (e.g. java/lang/Object)
internal bool IsSubType(string subType, string baseType)
{
return LoadClassBySlashedName(subType).IsSubTypeOf(LoadClassBySlashedName(baseType));
}
internal string FindCommonBaseType(string type1, string type2)
{
TypeWrapper t1 = LoadClassBySlashedName(type1);
TypeWrapper t2 = LoadClassBySlashedName(type2);
if(t1 == t2)
{
return type1;
}
if(t1.IsInterface || t2.IsInterface)
{
// TODO I don't know how finding the common base for interfaces is defined, but
// for now I'm just doing the naive thing
// UPDATE according to a paper by Alessandro Coglio & Allen Goldberg titled
// "Type Safety in the JVM: Some Problems in Java 2 SDK 1.2 and Proposed Solutions"
// the common base of two interfaces is java/lang/Object, and there is special
// treatment for java/lang/Object types that allow it to be assigned to any interface
// type, the JVM's typesafety then depends on the invokeinterface instruction to make
// sure that the reference actually implements the interface.
// So strictly speaking, the code below isn't correct, but it works, so for now it stays in.
if(t1.ImplementsInterface(t2))
{
return t2.Name;
}
if(t2.ImplementsInterface(t1))
{
return t1.Name;
}
return "java/lang/Object";
}
Stack st1 = new Stack();
Stack st2 = new Stack();
while(t1 != null)
{
st1.Push(t1);
t1 = t1.BaseTypeWrapper;
}
while(t2 != null)
{
st2.Push(t2);
t2 = t2.BaseTypeWrapper;
}
TypeWrapper type = null;
for(;;)
{
t1 = st1.Count > 0 ? (TypeWrapper)st1.Pop() : null;
t2 = st2.Count > 0 ? (TypeWrapper)st2.Pop() : null;
if(t1 != t2)
{
return type.Name;
}
type = t1;
}
}
internal static ClassLoaderWrapper GetBootstrapClassLoader()
{
if(bootstrapClassLoader == null)
{
bootstrapClassLoader = new ClassLoaderWrapper(null);
bootstrapClassLoader.LoadRemappedTypes();
}
return bootstrapClassLoader;
}
internal static ClassLoaderWrapper GetClassLoaderWrapper(object javaClassLoader)
{
if(javaClassLoader == null)
{
return GetBootstrapClassLoader();
}
ClassLoaderWrapper wrapper = (ClassLoaderWrapper)javaClassLoaderToClassLoaderWrapper[javaClassLoader];
if(wrapper == null)
{
wrapper = new ClassLoaderWrapper(javaClassLoader);
javaClassLoaderToClassLoaderWrapper[javaClassLoader] = wrapper;
}
return wrapper;
}
internal static ClassLoaderWrapper GetClassLoader(Type type)
{
Debug.Assert(!(type is TypeBuilder));
TypeWrapper wrapper = GetWrapperFromTypeFast(type);
if(wrapper != null)
{
return wrapper.GetClassLoader();
}
return GetBootstrapClassLoader();
// ClassLoaderWrapper loader = (ClassLoaderWrapper)assemblyToClassLoaderWrapper[type.Assembly];
// if(loader == null)
// {
// loader = GetBootstrapClassLoader();
// }
// return loader;
}
// This only returns the wrapper for a Type if that wrapper has already been created, otherwise
// it returns null
// If the wrapper doesn't exist, that means that the type is either a .NET type or a pre-compiled Java class
internal static TypeWrapper GetWrapperFromTypeFast(Type type)
{
Debug.Assert(!(type is TypeBuilder));
return (TypeWrapper)typeToTypeWrapper[type];
}
internal static TypeWrapper GetWrapperFromType(Type type)
{
Debug.Assert(!(type is TypeBuilder));
TypeWrapper wrapper = GetWrapperFromTypeFast(type);
if(wrapper == null)
{
// if the wrapper doesn't already exist, that must mean that the type
// is a .NET type (or a pre-compiled Java class), which means that it
// was "loaded" by the bootstrap classloader
// TODO think up a scheme to deal with .NET types that have the same name. Since all .NET types
// appear in the boostrap classloader, we need to devise a scheme to mangle the class name
if(type.IsPrimitive || type == typeof(void))
{
if(type == typeof(void))
{
return PrimitiveTypeWrapper.VOID;
}
else if(type == typeof(sbyte))
{
return PrimitiveTypeWrapper.BYTE;
}
else if(type == typeof(char))
{
return PrimitiveTypeWrapper.CHAR;
}
else if(type == typeof(double))
{
return PrimitiveTypeWrapper.DOUBLE;
}
else if(type == typeof(float))
{
return PrimitiveTypeWrapper.FLOAT;
}
else if(type == typeof(int))
{
return PrimitiveTypeWrapper.INT;
}
else if(type == typeof(long))
{
return PrimitiveTypeWrapper.LONG;
}
else if(type == typeof(short))
{
return PrimitiveTypeWrapper.SHORT;
}
else if(type == typeof(bool))
{
return PrimitiveTypeWrapper.BOOLEAN;
}
}
wrapper = GetBootstrapClassLoader().GetCompiledTypeWrapper(type);
}
return wrapper;
}
internal static void SetWrapperForType(Type type, TypeWrapper wrapper)
{
Debug.Assert(!(type is TypeBuilder));
typeToTypeWrapper.Add(type, wrapper);
}
// name is dot separated (e.g. java.lang.Object)
internal static Type GetType(string name)
{
TypeWrapper wrapper = GetBootstrapClassLoader().LoadClassByDottedName(name);
// TODO think about this Finish here
wrapper.Finish();
return wrapper.Type;
}
}

539
IK.VM.NET/DoubleToString.cs Normal file
Просмотреть файл

@ -0,0 +1,539 @@
// NOTE this code was adapted from source code accompanying the article
// http://www.onjava.com/pub/a/onjava/2000/12/15/formatting_doubles.html?page=2
// by Jack Shirazi
using System;
using System.Text;
public class DoubleToString
{
//Hardcode some arrays to make them quickly available
private static readonly string[] ZEROS = new string[] {
"",
"0",
"00",
"000",
"0000",
"00000",
"000000",
"0000000",
"00000000",
"000000000",
"0000000000",
"00000000000",
"000000000000",
"0000000000000",
"00000000000000",
"000000000000000",
"0000000000000000",
"00000000000000000",
"000000000000000000",
"0000000000000000000",
"00000000000000000000"
};
private static readonly char[] charForDigit = new char[] {
'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','g','h',
'i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'
};
//And required double related constants.
private const long DoubleSignMask = long.MinValue;
private const long DoubleExpMask = 0x7ff0000000000000L;
private const long DoubleFractMask= ~(DoubleSignMask|DoubleExpMask);
private const int DoubleExpShift = 52;
private const int DoubleExpBias = 1023;
private static readonly double[] d_tenthPowers = new double[] {
1e-323D, 1e-322D, 1e-321D, 1e-320D, 1e-319D, 1e-318D, 1e-317D, 1e-316D, 1e-315D, 1e-314D,
1e-313D, 1e-312D, 1e-311D, 1e-310D, 1e-309D, 1e-308D, 1e-307D, 1e-306D, 1e-305D, 1e-304D,
1e-303D, 1e-302D, 1e-301D, 1e-300D, 1e-299D, 1e-298D, 1e-297D, 1e-296D, 1e-295D, 1e-294D,
1e-293D, 1e-292D, 1e-291D, 1e-290D, 1e-289D, 1e-288D, 1e-287D, 1e-286D, 1e-285D, 1e-284D,
1e-283D, 1e-282D, 1e-281D, 1e-280D, 1e-279D, 1e-278D, 1e-277D, 1e-276D, 1e-275D, 1e-274D,
1e-273D, 1e-272D, 1e-271D, 1e-270D, 1e-269D, 1e-268D, 1e-267D, 1e-266D, 1e-265D, 1e-264D,
1e-263D, 1e-262D, 1e-261D, 1e-260D, 1e-259D, 1e-258D, 1e-257D, 1e-256D, 1e-255D, 1e-254D,
1e-253D, 1e-252D, 1e-251D, 1e-250D, 1e-249D, 1e-248D, 1e-247D, 1e-246D, 1e-245D, 1e-244D,
1e-243D, 1e-242D, 1e-241D, 1e-240D, 1e-239D, 1e-238D, 1e-237D, 1e-236D, 1e-235D, 1e-234D,
1e-233D, 1e-232D, 1e-231D, 1e-230D, 1e-229D, 1e-228D, 1e-227D, 1e-226D, 1e-225D, 1e-224D,
1e-223D, 1e-222D, 1e-221D, 1e-220D, 1e-219D, 1e-218D, 1e-217D, 1e-216D, 1e-215D, 1e-214D,
1e-213D, 1e-212D, 1e-211D, 1e-210D, 1e-209D, 1e-208D, 1e-207D, 1e-206D, 1e-205D, 1e-204D,
1e-203D, 1e-202D, 1e-201D, 1e-200D, 1e-199D, 1e-198D, 1e-197D, 1e-196D, 1e-195D, 1e-194D,
1e-193D, 1e-192D, 1e-191D, 1e-190D, 1e-189D, 1e-188D, 1e-187D, 1e-186D, 1e-185D, 1e-184D,
1e-183D, 1e-182D, 1e-181D, 1e-180D, 1e-179D, 1e-178D, 1e-177D, 1e-176D, 1e-175D, 1e-174D,
1e-173D, 1e-172D, 1e-171D, 1e-170D, 1e-169D, 1e-168D, 1e-167D, 1e-166D, 1e-165D, 1e-164D,
1e-163D, 1e-162D, 1e-161D, 1e-160D, 1e-159D, 1e-158D, 1e-157D, 1e-156D, 1e-155D, 1e-154D,
1e-153D, 1e-152D, 1e-151D, 1e-150D, 1e-149D, 1e-148D, 1e-147D, 1e-146D, 1e-145D, 1e-144D,
1e-143D, 1e-142D, 1e-141D, 1e-140D, 1e-139D, 1e-138D, 1e-137D, 1e-136D, 1e-135D, 1e-134D,
1e-133D, 1e-132D, 1e-131D, 1e-130D, 1e-129D, 1e-128D, 1e-127D, 1e-126D, 1e-125D, 1e-124D,
1e-123D, 1e-122D, 1e-121D, 1e-120D, 1e-119D, 1e-118D, 1e-117D, 1e-116D, 1e-115D, 1e-114D,
1e-113D, 1e-112D, 1e-111D, 1e-110D, 1e-109D, 1e-108D, 1e-107D, 1e-106D, 1e-105D, 1e-104D,
1e-103D, 1e-102D, 1e-101D, 1e-100D, 1e-99D, 1e-98D, 1e-97D, 1e-96D, 1e-95D, 1e-94D,
1e-93D, 1e-92D, 1e-91D, 1e-90D, 1e-89D, 1e-88D, 1e-87D, 1e-86D, 1e-85D, 1e-84D,
1e-83D, 1e-82D, 1e-81D, 1e-80D, 1e-79D, 1e-78D, 1e-77D, 1e-76D, 1e-75D, 1e-74D,
1e-73D, 1e-72D, 1e-71D, 1e-70D, 1e-69D, 1e-68D, 1e-67D, 1e-66D, 1e-65D, 1e-64D,
1e-63D, 1e-62D, 1e-61D, 1e-60D, 1e-59D, 1e-58D, 1e-57D, 1e-56D, 1e-55D, 1e-54D,
1e-53D, 1e-52D, 1e-51D, 1e-50D, 1e-49D, 1e-48D, 1e-47D, 1e-46D, 1e-45D, 1e-44D,
1e-43D, 1e-42D, 1e-41D, 1e-40D, 1e-39D, 1e-38D, 1e-37D, 1e-36D, 1e-35D, 1e-34D,
1e-33D, 1e-32D, 1e-31D, 1e-30D, 1e-29D, 1e-28D, 1e-27D, 1e-26D, 1e-25D, 1e-24D,
1e-23D, 1e-22D, 1e-21D, 1e-20D, 1e-19D, 1e-18D, 1e-17D, 1e-16D, 1e-15D, 1e-14D,
1e-13D, 1e-12D, 1e-11D, 1e-10D, 1e-9D, 1e-8D, 1e-7D, 1e-6D, 1e-5D, 1e-4D,
1e-3D, 1e-2D, 1e-1D, 1e0D, 1e1D, 1e2D, 1e3D, 1e4D,
1e5D, 1e6D, 1e7D, 1e8D, 1e9D, 1e10D, 1e11D, 1e12D, 1e13D, 1e14D,
1e15D, 1e16D, 1e17D, 1e18D, 1e19D, 1e20D, 1e21D, 1e22D, 1e23D, 1e24D,
1e25D, 1e26D, 1e27D, 1e28D, 1e29D, 1e30D, 1e31D, 1e32D, 1e33D, 1e34D,
1e35D, 1e36D, 1e37D, 1e38D, 1e39D, 1e40D, 1e41D, 1e42D, 1e43D, 1e44D,
1e45D, 1e46D, 1e47D, 1e48D, 1e49D, 1e50D, 1e51D, 1e52D, 1e53D, 1e54D,
1e55D, 1e56D, 1e57D, 1e58D, 1e59D, 1e60D, 1e61D, 1e62D, 1e63D, 1e64D,
1e65D, 1e66D, 1e67D, 1e68D, 1e69D, 1e70D, 1e71D, 1e72D, 1e73D, 1e74D,
1e75D, 1e76D, 1e77D, 1e78D, 1e79D, 1e80D, 1e81D, 1e82D, 1e83D, 1e84D,
1e85D, 1e86D, 1e87D, 1e88D, 1e89D, 1e90D, 1e91D, 1e92D, 1e93D, 1e94D,
1e95D, 1e96D, 1e97D, 1e98D, 1e99D, 1e100D, 1e101D, 1e102D, 1e103D, 1e104D,
1e105D, 1e106D, 1e107D, 1e108D, 1e109D, 1e110D, 1e111D, 1e112D, 1e113D, 1e114D,
1e115D, 1e116D, 1e117D, 1e118D, 1e119D, 1e120D, 1e121D, 1e122D, 1e123D, 1e124D,
1e125D, 1e126D, 1e127D, 1e128D, 1e129D, 1e130D, 1e131D, 1e132D, 1e133D, 1e134D,
1e135D, 1e136D, 1e137D, 1e138D, 1e139D, 1e140D, 1e141D, 1e142D, 1e143D, 1e144D,
1e145D, 1e146D, 1e147D, 1e148D, 1e149D, 1e150D, 1e151D, 1e152D, 1e153D, 1e154D,
1e155D, 1e156D, 1e157D, 1e158D, 1e159D, 1e160D, 1e161D, 1e162D, 1e163D, 1e164D,
1e165D, 1e166D, 1e167D, 1e168D, 1e169D, 1e170D, 1e171D, 1e172D, 1e173D, 1e174D,
1e175D, 1e176D, 1e177D, 1e178D, 1e179D, 1e180D, 1e181D, 1e182D, 1e183D, 1e184D,
1e185D, 1e186D, 1e187D, 1e188D, 1e189D, 1e190D, 1e191D, 1e192D, 1e193D, 1e194D,
1e195D, 1e196D, 1e197D, 1e198D, 1e199D, 1e200D, 1e201D, 1e202D, 1e203D, 1e204D,
1e205D, 1e206D, 1e207D, 1e208D, 1e209D, 1e210D, 1e211D, 1e212D, 1e213D, 1e214D,
1e215D, 1e216D, 1e217D, 1e218D, 1e219D, 1e220D, 1e221D, 1e222D, 1e223D, 1e224D,
1e225D, 1e226D, 1e227D, 1e228D, 1e229D, 1e230D, 1e231D, 1e232D, 1e233D, 1e234D,
1e235D, 1e236D, 1e237D, 1e238D, 1e239D, 1e240D, 1e241D, 1e242D, 1e243D, 1e244D,
1e245D, 1e246D, 1e247D, 1e248D, 1e249D, 1e250D, 1e251D, 1e252D, 1e253D, 1e254D,
1e255D, 1e256D, 1e257D, 1e258D, 1e259D, 1e260D, 1e261D, 1e262D, 1e263D, 1e264D,
1e265D, 1e266D, 1e267D, 1e268D, 1e269D, 1e270D, 1e271D, 1e272D, 1e273D, 1e274D,
1e275D, 1e276D, 1e277D, 1e278D, 1e279D, 1e280D, 1e281D, 1e282D, 1e283D, 1e284D,
1e285D, 1e286D, 1e287D, 1e288D, 1e289D, 1e290D, 1e291D, 1e292D, 1e293D, 1e294D,
1e295D, 1e296D, 1e297D, 1e298D, 1e299D, 1e300D, 1e301D, 1e302D, 1e303D, 1e304D,
1e305D, 1e306D, 1e307D, 1e308D
};
public void appendFormatted(StringBuilder s, double d, int numFractDigits,
char decimalPoint, char thousandsSeparator, int numDigitsSeparated,
char negativePrefix, char negativeSuffix)
{
//First check for the special cases, +/-infinity, Not-a-number and -0.0
if (d == double.NegativeInfinity)
{
//d == -Infinity
if (negativePrefix != '\uFFFF')
s.Append(negativePrefix);
s.Append("Infinity");
if (negativeSuffix != '\uFFFF')
s.Append(negativeSuffix);
}
else if (d == double.PositiveInfinity)
//d == Infinity
s.Append("Infinity");
else if (d != d)
//d == NaN
s.Append("NaN");
else if (d == 0.0)
{
if ( (BitConverter.DoubleToInt64Bits(d) & DoubleSignMask) != 0)
{
//d == -0.0
if (negativePrefix != '\uFFFF')
s.Append(negativePrefix);
s.Append('0').Append(decimalPoint).Append(ZEROS[numFractDigits]);
if (negativeSuffix != '\uFFFF')
s.Append(negativeSuffix);
}
else
//d == 0.0
s.Append('0').Append(decimalPoint).Append(ZEROS[numFractDigits]);
}
else
{
//convert to a positive format, and record whether we have a negative
//number so that we know later whether to add the negativeSuffix
bool negative = false;
if (d < 0)
{
//Even if the number is negative, we only need to set the
//negative flag if there is a printable negativeSuffix
if (negativeSuffix != '\uFFFF')
negative = true;
if (negativePrefix != '\uFFFF')
s.Append(negativePrefix);
d = -d;
}
//Find the magnitude. This is basically the exponent in normal form.
int mag = magnitude(d);
//First off, if the number is too small for the given format, we
//only print 0.0..., which makes this real quick
if ( (mag + numFractDigits) < 0)
{
appendNearlyZeroNumber(s, d, mag, numFractDigits, decimalPoint);
if (negative)
s.Append(negativeSuffix);
return;
}
long l;
//Now scale the double to the biggest long value we need
//We need to handle the smallest magnitudes differently because of rounding errors
//This test is unlikely to ever be true. It would require numFractDigits
//to be 305 or more, which is pretty unlikely.
if (mag < -305)
l = (long) ((d*1E18) / d_tenthPowers[mag + 324]);
else
l = (long) (d / d_tenthPowers[mag + 323 - 17]);
//And round up if necessary. Add one to the numFractDigits digit if the
//numFractDigits+1 digit is 5 or greater. It is useful to know that
//given a long, l, the nth digit is obtained using the formula
// nthDigit = (l/(tenthPower(l)/l_tenthPowers[n-1]))%10;
long l_tenthPower = tenthPower(l);
//The numFractDigits+1 digit of the double is the
//numFractDigits+1+magnitude digit of the long.
//We only need worry about digits within the long. Very large numbers are
//not rounded because all the digits after the decimal points are 0 anyway
if (numFractDigits+mag+1 < l_tenthPowers.Length)
{
long digit = (l/(l_tenthPower/l_tenthPowers[numFractDigits+mag+1]))%10;
if (digit >= 5)
{
l += l_tenthPower/l_tenthPowers[numFractDigits+mag];
}
}
//And now we just print out our long, with the decimal point character
//inserted in the right place, using as many places as we wanted.
appendAsDouble(s, l, l_tenthPower, mag, numFractDigits, decimalPoint, thousandsSeparator,
numDigitsSeparated, negativePrefix, negativeSuffix);
//Finally, append the negativeSuffix if necessary
if (negative)
s.Append(negativeSuffix);
}
}
public void appendAsDouble(StringBuilder s, long l, long l_mag, int d_magnitude,
int numFractDigits, char decimalPoint, char thousandsSeparator,
int numDigitsSeparated, char negativePrefix, char negativeSuffix)
{
//If the magnitude is negative, we have a 0.xxx number
if (d_magnitude < 0)
{
s.Append('0').Append(decimalPoint).Append(ZEROS[-d_magnitude-1]);
//And just print successive digits until we have reached numFractDigits
//First decrement numFractDigits by the number of digits already printed
numFractDigits += d_magnitude;
//get the magnitude of l
long c;
while(numFractDigits-- >= 0)
{
//Get the leading character (e.g. '62345/10000 = 6' using integer-divide)
c = l/l_mag;
//Append the digit character for this digit (e.g. number is 6, so character is '6')
s.Append(charForDigit[(int) c]);
//Multiply by the leading digit by the magnitude so that we can eliminate the leading digit
//(e.g. 6 * 10000 = 60000)
c *= l_mag;
//and eliminate the leading digit (e.g. 62345-60000 = 2345)
if ( c <= l)
l -= c;
//Decrease the magnitude by 10, and repeat the loop.
l_mag = l_mag/10;
}
}
else
{
//Just keep printing until magnitude is 0
long c;
while(d_magnitude-- >= 0)
{
if (l_mag == 0) {s.Append('0');continue;}
//Get the leading character (e.g. '62345/10000 = 6' using integer-divide)
c = l/l_mag;
//Append the digit character for this digit (e.g. number is 6, so character is '6')
s.Append(charForDigit[(int) c]);
//Don't forget about the thousands separator
if (d_magnitude % numDigitsSeparated == (numDigitsSeparated-1))
s.Append(thousandsSeparator);
//Multiply by the leading digit by the magnitude so that we can eliminate the leading digit
//(e.g. 6 * 10000 = 60000)
c *= l_mag;
//and eliminate the leading digit (e.g. 62345-60000 = 2345)
if ( c <= l)
l -= c;
//Decrease the magnitude by 10, and repeat the loop.
l_mag = l_mag/10;
}
s.Append(decimalPoint);
if (l_mag == 0)
s.Append(ZEROS[numFractDigits]);
else
{
while(numFractDigits-- > 0)
{
if (l_mag == 0) {s.Append('0');continue;}
//Get the leading character (e.g. '62345/10000 = 6' using integer-divide)
c = l/l_mag;
//Append the digit character for this digit (e.g. number is 6, so character is '6')
s.Append(charForDigit[(int) c]);
//Multiply by the leading digit by the magnitude so that we can eliminate the leading digit
//(e.g. 6 * 10000 = 60000)
c *= l_mag;
//and eliminate the leading digit (e.g. 62345-60000 = 2345)
if ( c <= l)
l -= c;
//Decrease the magnitude by 10, and repeat the loop.
l_mag = l_mag/10;
}
}
}
}
private void appendNearlyZeroNumber(StringBuilder s, double d, int d_magnitude,
int numFractDigits, char decimalPoint)
{
if (d_magnitude + numFractDigits == -1)
{
//Possibly too small, depends on whether the top digit is 5 or greater
//So we have to scale to get the leading digit
int i;
if (d_magnitude < -305)
//Probably not necessary. Who is going to print 305 places?
i = (int) ((d*1E19) / d_tenthPowers[d_magnitude + 324 + 18]);
else
i = (int) (d / d_tenthPowers[d_magnitude + 323]);
if (i >= 5)
{
//Not too small, we get to round up
s.Append('0').Append(decimalPoint).Append(ZEROS[numFractDigits-1]);
s.Append('1');
}
else
{
//Definitely too small. Just print zeros
s.Append('0').Append(decimalPoint).Append(ZEROS[numFractDigits]);
}
}
else
{
//Definitely too small
s.Append('0').Append(decimalPoint).Append(ZEROS[numFractDigits]);
}
}
/**
* Assumes i is positive. Returns the magnitude of i in base 10.
*/
private static long tenthPower(long i)
{
if (i < 10L) return 1;
else if (i < 100L) return 10L;
else if (i < 1000L) return 100L;
else if (i < 10000L) return 1000L;
else if (i < 100000L) return 10000L;
else if (i < 1000000L) return 100000L;
else if (i < 10000000L) return 1000000L;
else if (i < 100000000L) return 10000000L;
else if (i < 1000000000L) return 100000000L;
else if (i < 10000000000L) return 1000000000L;
else if (i < 100000000000L) return 10000000000L;
else if (i < 1000000000000L) return 100000000000L;
else if (i < 10000000000000L) return 1000000000000L;
else if (i < 100000000000000L) return 10000000000000L;
else if (i < 1000000000000000L) return 100000000000000L;
else if (i < 10000000000000000L) return 1000000000000000L;
else if (i < 100000000000000000L) return 10000000000000000L;
else if (i < 1000000000000000000L) return 100000000000000000L;
else return 1000000000000000000L;
}
private static int magnitude(double d)
{
//It works. What else can I say.
long doubleToLongBits = BitConverter.DoubleToInt64Bits(d);
int magnitude =
(int) ((((doubleToLongBits & DoubleExpMask) >> DoubleExpShift) - DoubleExpBias) * 0.301029995663981);
if (magnitude < -323)
magnitude = -323;
else if (magnitude > 308)
magnitude = 308;
if (d >= d_tenthPowers[magnitude+323])
{
while(magnitude < 309 && d >= d_tenthPowers[magnitude+323])
magnitude++;
magnitude--;
return magnitude;
}
else
{
while(magnitude > -324 && d < d_tenthPowers[magnitude+323])
magnitude--;
return magnitude;
}
}
private static long[] l_tenthPowers = {
1,
10L,
100L,
1000L,
10000L,
100000L,
1000000L,
10000000L,
100000000L,
1000000000L,
10000000000L,
100000000000L,
1000000000000L,
10000000000000L,
100000000000000L,
1000000000000000L,
10000000000000000L,
100000000000000000L,
1000000000000000000L,
};
public static void append(StringBuilder s, double d)
{
if (d == double.NegativeInfinity)
s.Append("-Infinity");
else if (d == double.PositiveInfinity)
s.Append("Infinity");
else if (d != d)
s.Append("NaN");
else if (d == 0.0)
{
if ( (BitConverter.DoubleToInt64Bits(d) & DoubleSignMask) != 0)
s.Append('-');
s.Append("0.0");
}
else
{
if (d < 0)
{
s.Append('-');
d = -d;
}
if (d >= 0.001 && d < 0.01)
{
long i = (long) (d * 1E20);
i = i%100 >= 50 ? (i/100) + 1 : i/100;
s.Append("0.00");
appendFractDigits(s, i,-1);
}
else if (d >= 0.01 && d < 0.1)
{
long i = (long) (d * 1E19);
i = i%100 >= 50 ? (i/100) + 1 : i/100;
s.Append("0.0");
appendFractDigits(s, i,-1);
}
else if (d >= 0.1 && d < 1)
{
long i = (long) (d * 1E18);
i = i%100 >= 50 ? (i/100) + 1 : i/100;
s.Append("0.");
appendFractDigits(s, i,-1);
}
else if (d >= 1 && d < 10)
{
long i = (long) (d * 1E17);
i = i%100 >= 50 ? (i/100) + 1 : i/100;
appendFractDigits(s, i,1);
}
else if (d >= 10 && d < 100)
{
long i = (long) (d * 1E16);
i = i%100 >= 50 ? (i/100) + 1 : i/100;
appendFractDigits(s, i,2);
}
else if (d >= 100 && d < 1000)
{
long i = (long) (d * 1E15);
i = i%100 >= 50 ? (i/100) + 1 : i/100;
appendFractDigits(s, i,3);
}
else if (d >= 1000 && d < 10000)
{
long i = (long) (d * 1E14);
i = i%100 >= 50 ? (i/100) + 1 : i/100;
appendFractDigits(s, i,4);
}
else if (d >= 10000 && d < 100000)
{
long i = (long) (d * 1E13);
i = i%100 >= 50 ? (i/100) + 1 : i/100;
appendFractDigits(s, i,5);
}
else if (d >= 100000 && d < 1000000)
{
long i = (long) (d * 1E12);
i = i%100 >= 50 ? (i/100) + 1 : i/100;
appendFractDigits(s, i,6);
}
else if (d >= 1000000 && d < 10000000)
{
long i = (long) (d * 1E11);
i = i%100 >= 50 ? (i/100) + 1 : i/100;
appendFractDigits(s, i,7);
}
else
{
int mag = magnitude(d);
long i;
if (mag < -305)
i = (long) (d*1E18 / d_tenthPowers[mag + 324]);
else
i = (long) (d / d_tenthPowers[mag + 323 - 17]);
i = i%100 >= 50 ? (i/100) + 1 : i/100;
appendFractDigits(s, i, 1);
s.Append('E');
append(s,mag);
}
}
}
private static void appendFractDigits(StringBuilder s, long i, int decimalOffset)
{
long mag = tenthPower(i);
long c;
while ( i > 0 )
{
c = i/mag;
s.Append(charForDigit[(int) c]);
decimalOffset--;
if (decimalOffset == 0)
s.Append('.');
c *= mag;
if ( c <= i)
i -= c;
mag = mag/10;
}
if (i != 0)
s.Append(charForDigit[(int) i]);
else if (decimalOffset > 0)
{
s.Append(ZEROS[decimalOffset]);
decimalOffset = 1;
}
decimalOffset--;
if (decimalOffset == 0)
s.Append(".0");
else if (decimalOffset == -1)
s.Append('0');
}
}

Просмотреть файл

@ -0,0 +1,659 @@
/*
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
*/
using System;
using System.Reflection;
using System.Diagnostics;
using System.Text;
using System.Collections;
using java.lang;
using ClassHelper = NativeCode.java.lang.Class;
public class ExceptionHelper
{
// the contents of the NULL_STRING should be empty (because when the exception propagates to other .NET code
// it will return that text as the Message property), but it *must* be a copy, because we need to be
// able to distinguish it from a user specified blank string
private static readonly string NULL_STRING = string.Copy("");
private class ExceptionInfoHelper
{
private static readonly Exception CAUSE_NOT_SET = new Exception();
private ArrayList stackTrace = new ArrayList();
private Exception cause;
[StackTraceInfo(Hidden = true)]
internal ExceptionInfoHelper(Exception x)
{
Append(new StackTrace(x, true));
bool chopFirst = stackTrace.Count != 0;
Append(new StackTrace(true));
if(chopFirst && stackTrace.Count > 0 && JVM.CleanStackTraces)
{
stackTrace.RemoveAt(0);
}
cause = x.InnerException;
if(cause == null)
{
cause = CAUSE_NOT_SET;
}
}
internal Exception Cause
{
get
{
return cause == CAUSE_NOT_SET ? null : cause;
}
set
{
if(cause == CAUSE_NOT_SET)
{
cause = value;
}
else
{
throw JavaException.IllegalStateException("Throwable cause already initialized");
}
}
}
internal void ResetStackTrace()
{
stackTrace.Clear();
Append(new StackTrace(true));
}
private static bool IsPrivateScope(MethodBase mb)
{
// HACK shouldn't there be a better way to determine whether a method is privatescope?
return !mb.IsPrivate && !mb.IsFamily && !mb.IsFamilyAndAssembly && !mb.IsFamilyOrAssembly && !mb.IsPublic;
}
private void Append(StackTrace st)
{
if(st.FrameCount > 0)
{
int baseSize = stackTrace.Count;
for(int i = 0; i < st.FrameCount; i++)
{
StackFrame frame = st.GetFrame(i);
MethodBase m = frame.GetMethod();
// TODO I may need more safety checks like these
if(m.DeclaringType == null || m.ReflectedType == null)
{
continue;
}
if(m.DeclaringType == typeof(System.Runtime.CompilerServices.RuntimeHelpers)
|| m.DeclaringType == typeof(JNI) // HACK we exclude the JNI class from the stack trace
|| m.DeclaringType.IsSubclassOf(typeof(System.Reflection.MethodInfo))
|| IsPrivateScope(m)) // NOTE we assume that privatescope methods are always stubs that we should exclude
{
if(JVM.CleanStackTraces)
{
continue;
}
}
string methodName = frame.GetMethod().Name;
if(methodName == ".ctor")
{
methodName = "<init>";
}
else if(methodName == ".cctor")
{
methodName = "<clinit>";
}
int lineNumber = frame.GetFileLineNumber();
if(lineNumber == 0)
{
lineNumber = -1;
}
string fileName = frame.GetFileName();
if(fileName != null)
{
fileName = new System.IO.FileInfo(fileName).Name;
}
string className = ClassHelper.getName(frame.GetMethod().ReflectedType);
bool native = false;
if(m.IsDefined(typeof(ModifiersAttribute), false))
{
object[] methodFlagAttribs = m.GetCustomAttributes(typeof(ModifiersAttribute), false);
if(methodFlagAttribs.Length == 1)
{
ModifiersAttribute modifiersAttrib = (ModifiersAttribute)methodFlagAttribs[0];
if(modifiersAttrib.IsSynthetic)
{
continue;
}
if((modifiersAttrib.Modifiers & Modifiers.Native) != 0)
{
native = true;
}
}
}
if(JVM.CleanStackTraces)
{
object[] attribs = m.DeclaringType.GetCustomAttributes(typeof(StackTraceInfoAttribute), false);
if(attribs.Length == 1)
{
StackTraceInfoAttribute sta = (StackTraceInfoAttribute)attribs[0];
if(sta.EatFrames > 0)
{
stackTrace.RemoveRange(stackTrace.Count - sta.EatFrames, sta.EatFrames);
}
if(sta.Hidden)
{
continue;
}
if(sta.Truncate)
{
stackTrace.RemoveRange(baseSize, stackTrace.Count - baseSize);
continue;
}
if(sta.Class != null)
{
className = sta.Class;
}
}
attribs = m.GetCustomAttributes(typeof(StackTraceInfoAttribute), false);
if(attribs.Length == 1)
{
StackTraceInfoAttribute sta = (StackTraceInfoAttribute)attribs[0];
if(sta.EatFrames > 0)
{
int eat = Math.Min(stackTrace.Count, sta.EatFrames);
stackTrace.RemoveRange(stackTrace.Count - eat, eat);
}
if(sta.Hidden)
{
continue;
}
if(sta.Truncate)
{
stackTrace.RemoveRange(baseSize, stackTrace.Count - baseSize);
continue;
}
if(sta.Class != null)
{
className = sta.Class;
}
}
}
stackTrace.Add(new StackTraceElement(fileName, lineNumber, className, methodName, native));
}
if(JVM.CleanStackTraces)
{
int chop = 0;
for(int i = stackTrace.Count - 1; i >= 0; i--)
{
StackTraceElement ste = (StackTraceElement)stackTrace[i];
if(ste.getClassName() == "System.Reflection.RuntimeMethodInfo")
{
// skip method invocation by reflection, if it is at the top of the stack
chop++;
}
else
{
break;
}
}
stackTrace.RemoveRange(stackTrace.Count - chop, chop);
}
}
}
internal StackTraceElement[] StackTrace
{
get
{
return (StackTraceElement[])stackTrace.ToArray(typeof(StackTraceElement));
}
set
{
stackTrace = new ArrayList(value);
}
}
}
// TODO this should be an "identity" hashtable instead of "equality"
private static WeakHashtable exceptions = new WeakHashtable();
public static void printStackTrace(Exception x)
{
if(x == null)
{
throw new NullReferenceException();
}
Type type = ClassLoaderWrapper.GetType("java.lang.System");
object err = type.GetProperty("err").GetValue(null, null);
printStackTrace(x, err);
}
public static void printStackTrace(Exception x, object printStreamOrWriter)
{
if(x == null)
{
throw new NullReferenceException();
}
StringBuilder sb = new StringBuilder();
sb.Append(toString_Virtual(x)).Append(Environment.NewLine);
StackTraceElement[] stack = getStackTrace_Virtual(x);
for(int i = 0; i < stack .Length; i++)
{
sb.Append("\tat ").Append(stack[i]).Append(Environment.NewLine);
}
Exception cause = getCause_Virtual(x);
while(cause != null)
{
sb.Append("Caused by: ").Append(toString_Virtual(cause)).Append(Environment.NewLine);
// Cause stacktrace
StackTraceElement[] parentStack = stack;
stack = getStackTrace_Virtual(cause);
bool equal = false; // Is rest of stack equal to parent frame?
for(int i = 0; i < stack.Length && !equal; i++)
{
// Check if we already printed the rest of the stack
// since it was the tail of the parent stack
int remaining = stack.Length - i;
int element = i;
int parentElement = parentStack.Length - remaining;
equal = parentElement >= 0
&& parentElement < parentStack.Length; // be optimistic
while(equal && element < stack.Length)
{
if(stack[element].Equals(parentStack[parentElement]))
{
element++;
parentElement++;
}
else
{
equal = false;
}
}
// Print stacktrace element or indicate the rest is equal
if(!equal)
{
sb.Append("\tat ").Append(stack[i]).Append(Environment.NewLine);
}
else
{
sb.Append("\t... ").Append(remaining).Append(" more").Append(Environment.NewLine);
break; // from stack printing for loop
}
}
cause = getCause_Virtual(cause);
}
// NOTE since we use reflection to lookup the print method each time, we can use this one method for both
// the printStackTrace(..., PrintStream) & printStackTrace(..., PrintWriter) versions
MethodInfo write = printStreamOrWriter.GetType().GetMethod("print", BindingFlags.Public | BindingFlags.Instance, null, CallingConventions.Standard, new Type[] { typeof(string) }, null);
write.Invoke(printStreamOrWriter, new object[] { sb.ToString() });
}
public static Exception initCause(Exception x, Exception cause)
{
if(x == null)
{
throw new NullReferenceException();
}
if(cause == x)
{
throw JavaException.IllegalArgumentException("Cause cannot be self");
}
ExceptionInfoHelper eih = (ExceptionInfoHelper)exceptions[x];
if(eih == null)
{
eih = new ExceptionInfoHelper(x);
exceptions[x] = eih;
}
eih.Cause = cause;
return x;
}
public static Exception getCause(Exception x)
{
if(x == null)
{
throw new NullReferenceException();
}
ExceptionInfoHelper eih = (ExceptionInfoHelper)exceptions[x];
if(eih == null)
{
return x.InnerException;
}
return eih.Cause;
}
public static StackTraceElement[] getStackTrace(Exception x)
{
if(x == null)
{
throw new NullReferenceException();
}
ExceptionInfoHelper ei = (ExceptionInfoHelper)exceptions[x];
if(ei == null)
{
return new StackTraceElement[0];
}
return ei.StackTrace;
}
public static void setStackTrace(Exception x, StackTraceElement[] stackTrace)
{
if(x == null)
{
throw new NullReferenceException();
}
for(int i = 0; i < stackTrace.Length; i++)
{
if(stackTrace[i] == null)
{
throw new NullReferenceException();
}
}
ExceptionInfoHelper ei = (ExceptionInfoHelper)exceptions[x];
if(ei == null)
{
ei = new ExceptionInfoHelper(x);
exceptions[x] = ei;
}
ei.StackTrace = stackTrace;
}
public static string NullString
{
get
{
return NULL_STRING;
}
}
public static string FilterMessage(string message)
{
if(message == null)
{
message = NULL_STRING;
}
return message;
}
public static string GetMessageFromCause(Exception cause)
{
if(cause == null)
{
return NULL_STRING;
}
return toString_Virtual(cause);
}
public static string getMessage(Exception x)
{
if(x == null)
{
throw new NullReferenceException();
}
string message = x.Message;
if(message == NULL_STRING)
{
message = null;
}
return message;
}
public static string getLocalizedMessage(Exception x)
{
if(x == null)
{
throw new NullReferenceException();
}
return getMessage_Virtual(x);
}
[StackTraceInfo(Hidden = true)]
public static Exception fillInStackTrace(Exception x)
{
if(x == null)
{
throw new NullReferenceException();
}
ExceptionInfoHelper eih = (ExceptionInfoHelper)exceptions[x];
if(eih == null)
{
eih = new ExceptionInfoHelper(x);
exceptions[x] = eih;
}
else
{
eih.ResetStackTrace();
}
return x;
}
[StackTraceInfo(Hidden = true)]
public static Exception MapExceptionFast(Exception t)
{
if(exceptions.ContainsKey(t))
{
return t;
}
return MapException(t, typeof(Exception));
}
[StackTraceInfo(Truncate = true)]
public static Exception MapException(Exception t, Type handler)
{
//Console.WriteLine("MapException: {0}, {1}", t, handler);
//Console.WriteLine(new StackTrace(t));
Exception org = t;
Type type = t.GetType();
// TODO don't remap if the exception already has associated ExceptionInfoHelper object (this means
// that the .NET exception was thrown from Java code, explicitly).
if(type == typeof(NullReferenceException))
{
t = (Exception)Activator.CreateInstance(ClassLoaderWrapper.GetType("java.lang.NullPointerException"));
}
else if(type == typeof(IndexOutOfRangeException))
{
t = (Exception)Activator.CreateInstance(ClassLoaderWrapper.GetType("java.lang.ArrayIndexOutOfBoundsException"));
}
else if(type == typeof(InvalidCastException))
{
t = (Exception)Activator.CreateInstance(ClassLoaderWrapper.GetType("java.lang.ClassCastException"));
}
else if(type == typeof(TypeInitializationException))
{
t = (Exception)MapExceptionFast(t.InnerException);
if(!ClassLoaderWrapper.GetType("java.lang.Error").IsInstanceOfType(t))
{
ConstructorInfo constructor = ClassLoaderWrapper.GetType("java.lang.ExceptionInInitializerError").GetConstructor(new Type[] { typeof(Exception) });
t = (Exception)constructor.Invoke(new object[] { t });
}
}
else if(type == typeof(System.Threading.SynchronizationLockException))
{
t = (Exception)Activator.CreateInstance(ClassLoaderWrapper.GetType("java.lang.IllegalMonitorStateException"));
}
else if(type == typeof(System.Threading.ThreadInterruptedException))
{
t = (Exception)Activator.CreateInstance(ClassLoaderWrapper.GetType("java.lang.InterruptedException"));
}
else if(type == typeof(OutOfMemoryException))
{
t = (Exception)Activator.CreateInstance(ClassLoaderWrapper.GetType("java.lang.OutOfMemoryError"));
}
else if(type == typeof(DivideByZeroException))
{
t = (Exception)Activator.CreateInstance(ClassLoaderWrapper.GetType("java.lang.ArithmeticException"), new object[] { "/ by zero" });
}
else if(type == typeof(ArrayTypeMismatchException))
{
t = (Exception)Activator.CreateInstance(ClassLoaderWrapper.GetType("java.lang.ArrayStoreException"));
}
else if(type == typeof(StackOverflowException))
{
t = (Exception)Activator.CreateInstance(ClassLoaderWrapper.GetType("java.lang.StackOverflowError"));
}
else if(type == typeof(System.Security.VerificationException))
{
t = (Exception)Activator.CreateInstance(ClassLoaderWrapper.GetType("java.lang.VerifyError"));
}
else if(type == typeof(System.Threading.ThreadAbortException))
{
System.Threading.ThreadAbortException abort = (System.Threading.ThreadAbortException)t;
if(abort.ExceptionState is Exception)
{
t = (Exception)abort.ExceptionState;
}
else
{
t = (Exception)Activator.CreateInstance(ClassLoaderWrapper.GetType("java.lang.ThreadDeath"));
}
System.Threading.Thread.ResetAbort();
}
else if(type == typeof(OverflowException))
{
// TODO make sure the originating method was from an IK.VM.NET generated assembly, because if it was
// generated by non-Java code, this remapping is obviously bogus.
t = (Exception)Activator.CreateInstance(ClassLoaderWrapper.GetType("java.lang.NegativeArraySizeException"));
}
else if(type.FullName.StartsWith("System.") && type != typeof(TargetInvocationException))
{
// TODO this is just for debugging
Console.WriteLine("caught: {0}, handler: {1}", t.GetType().FullName, handler.FullName);
Console.WriteLine(t);
}
if(!exceptions.ContainsKey(t))
{
exceptions.Add(t, new ExceptionInfoHelper(org));
Exception inner = org.InnerException;
if(inner != null && !exceptions.ContainsKey(inner))
{
exceptions.Add(inner, new ExceptionInfoHelper(inner));
}
}
return handler.IsInstanceOfType(t) ? t : null;
}
public static string toString(Exception x)
{
if(x == null)
{
throw new NullReferenceException();
}
string message = getLocalizedMessage_Virtual(x);
if(message == null)
{
return ClassHelper.getName(x.GetType());
}
return ClassHelper.getName(x.GetType()) + ": " + message;
}
// below are some helper properties to support calling virtual methods on Throwable
private delegate string toString_Delegate(Exception x);
private static toString_Delegate toString_Virtual_;
private static toString_Delegate toString_Virtual
{
get
{
if(toString_Virtual_ == null)
{
MethodInfo method = ClassLoaderWrapper.GetType("java.lang.Throwable$VirtualMethodsHelper").GetMethod("toString");
toString_Virtual_ = (toString_Delegate)Delegate.CreateDelegate(typeof(toString_Delegate), method);
}
return toString_Virtual_;
}
}
private delegate string getMessage_Delegate(Exception x);
private static getMessage_Delegate getMessage_Virtual_;
private static getMessage_Delegate getMessage_Virtual
{
get
{
if(getMessage_Virtual_ == null)
{
MethodInfo method = ClassLoaderWrapper.GetType("java.lang.Throwable$VirtualMethodsHelper").GetMethod("getMessage");
getMessage_Virtual_ = (getMessage_Delegate)Delegate.CreateDelegate(typeof(getMessage_Delegate), method);
}
return getMessage_Virtual_;
}
}
private delegate StackTraceElement[] getStackTrace_Delegate(Exception x);
private static getStackTrace_Delegate getStackTrace_Virtual_;
private static getStackTrace_Delegate getStackTrace_Virtual
{
get
{
if(getStackTrace_Virtual_ == null)
{
MethodInfo method = ClassLoaderWrapper.GetType("java.lang.Throwable$VirtualMethodsHelper").GetMethod("getStackTrace");
getStackTrace_Virtual_ = (getStackTrace_Delegate)Delegate.CreateDelegate(typeof(getStackTrace_Delegate), method);
}
return getStackTrace_Virtual_;
}
}
private delegate Exception getCause_Delegate(Exception x);
private static getCause_Delegate getCause_Virtual_;
private static getCause_Delegate getCause_Virtual
{
get
{
if(getCause_Virtual_ == null)
{
MethodInfo method = ClassLoaderWrapper.GetType("java.lang.Throwable$VirtualMethodsHelper").GetMethod("getCause");
getCause_Virtual_ = (getCause_Delegate)Delegate.CreateDelegate(typeof(getCause_Delegate), method);
}
return getCause_Virtual_;
}
}
private delegate string getLocalizedMessage_Delegate(Exception x);
private static getLocalizedMessage_Delegate getLocalizedMessage_Virtual_;
private static getLocalizedMessage_Delegate getLocalizedMessage_Virtual
{
get
{
if(getLocalizedMessage_Virtual_ == null)
{
MethodInfo method = ClassLoaderWrapper.GetType("java.lang.Throwable$VirtualMethodsHelper").GetMethod("getLocalizedMessage");
getLocalizedMessage_Virtual_ = (getLocalizedMessage_Delegate)Delegate.CreateDelegate(typeof(getLocalizedMessage_Delegate), method);
}
return getLocalizedMessage_Virtual_;
}
}
[StackTraceInfo(Hidden = true)]
public static void ThrowHack(Exception x)
{
throw x;
}
}

192
IK.VM.NET/IK.VM.NET.csproj Normal file
Просмотреть файл

@ -0,0 +1,192 @@
<VisualStudioProject>
<CSHARP
ProjectType = "Local"
ProductVersion = "7.0.9466"
SchemaVersion = "1.0"
ProjectGuid = "{F5C7B588-0403-4AF2-A4DE-5697DE21BC2C}"
>
<Build>
<Settings
ApplicationIcon = ""
AssemblyKeyContainerName = ""
AssemblyName = "IK.VM.NET"
AssemblyOriginatorKeyFile = ""
DefaultClientScript = "JScript"
DefaultHTMLPageLayout = "Grid"
DefaultTargetSchema = "IE50"
DelaySign = "false"
OutputType = "Library"
RootNamespace = ""
StartupObject = ""
>
<Config
Name = "Debug"
AllowUnsafeBlocks = "false"
BaseAddress = "285212672"
CheckForOverflowUnderflow = "false"
ConfigurationOverrideFile = ""
DefineConstants = "DEBUG;TRACE"
DocumentationFile = ""
DebugSymbols = "true"
FileAlignment = "4096"
IncrementalBuild = "true"
Optimize = "false"
OutputPath = "bin\Debug\"
RegisterForComInterop = "false"
RemoveIntegerChecks = "false"
TreatWarningsAsErrors = "false"
WarningLevel = "4"
/>
<Config
Name = "Release"
AllowUnsafeBlocks = "false"
BaseAddress = "285212672"
CheckForOverflowUnderflow = "false"
ConfigurationOverrideFile = ""
DefineConstants = "TRACE"
DocumentationFile = ""
DebugSymbols = "true"
FileAlignment = "4096"
IncrementalBuild = "false"
Optimize = "true"
OutputPath = "bin\Release\"
RegisterForComInterop = "false"
RemoveIntegerChecks = "false"
TreatWarningsAsErrors = "false"
WarningLevel = "4"
/>
</Settings>
<References>
<Reference
Name = "System"
AssemblyName = "System"
HintPath = "..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.dll"
/>
<Reference
Name = "System.Data"
AssemblyName = "System.Data"
HintPath = "..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.Data.dll"
/>
<Reference
Name = "System.XML"
AssemblyName = "System.Xml"
HintPath = "..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.XML.dll"
/>
<Reference
Name = "IK.VM.JNI"
Project = "{4D400F9D-68A1-4066-95F6-85AF0E58B710}"
Package = "{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}"
/>
</References>
</Build>
<Files>
<Include>
<File
RelPath = "AssemblyInfo.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "attributes.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "BigEndianBinaryReader.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "ByteCode.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "ByteCodeHelper.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "ClassFile.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "ClassLoaderWrapper.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "classpath.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "compiler.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "DoubleToString.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "ExceptionHelper.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "JavaException.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "map.xml"
BuildAction = "EmbeddedResource"
/>
<File
RelPath = "ObjectHelper.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "profiler.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "remapper.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "StringHelper.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "TypeWrapper.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "verifier.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "vm.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "WeakHashtable.cs"
SubType = "Code"
BuildAction = "Compile"
/>
</Include>
</Files>
</CSHARP>
</VisualStudioProject>

148
IK.VM.NET/JavaException.cs Normal file
Просмотреть файл

@ -0,0 +1,148 @@
/*
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
*/
using System;
using System.Reflection;
sealed class JavaException
{
private JavaException() {}
internal static Exception ClassFormatError(string s, params object[] args)
{
s = String.Format(s, args);
ConstructorInfo ci = ClassLoaderWrapper.GetType("java.lang.ClassFormatError").GetConstructor(new Type[] { typeof(string) });
return (Exception)ci.Invoke(new object[] { s });
}
internal static Exception UnsupportedClassVersionError(string s, params object[] args)
{
s = String.Format(s, args);
ConstructorInfo ci = ClassLoaderWrapper.GetType("java.lang.UnsupportedClassVersionError").GetConstructor(new Type[] { typeof(string) });
return (Exception)ci.Invoke(new object[] { s });
}
internal static Exception IllegalAccessError(string s, params object[] args)
{
s = String.Format(s, args);
ConstructorInfo ci = ClassLoaderWrapper.GetType("java.lang.IllegalAccessError").GetConstructor(new Type[] { typeof(string) });
return (Exception)ci.Invoke(new object[] { s });
}
internal static Exception VerifyError(string s, params object[] args)
{
s = String.Format(s, args);
ConstructorInfo ci = ClassLoaderWrapper.GetType("java.lang.VerifyError").GetConstructor(new Type[] { typeof(string) });
return (Exception)ci.Invoke(new object[] { s });
}
internal static Exception IncompatibleClassChangeError(string s, params object[] args)
{
s = String.Format(s, args);
ConstructorInfo ci = ClassLoaderWrapper.GetType("java.lang.IncompatibleClassChangeError").GetConstructor(new Type[] { typeof(string) });
return (Exception)ci.Invoke(new object[] { s });
}
[ThreadStatic]
private static bool classNotFound;
private class BootstrapClassMissing : Exception {}
internal static Exception ClassNotFoundException(string s, params object[] args)
{
// HACK if java.lang.ClassNotFoundException is not found, this method would recurse until the
// stack overflows, so in order to prevent that, we use this hack
if(JVM.IsStaticCompiler && classNotFound)
{
throw new BootstrapClassMissing();
}
try
{
classNotFound = true;
//Console.WriteLine("ClassNotFoundException: " + s);
s = String.Format(s, args);
ConstructorInfo ci = ClassLoaderWrapper.GetType("java.lang.ClassNotFoundException").GetConstructor(new Type[] { typeof(string) });
return (Exception)ci.Invoke(new object[] { s });
}
catch(BootstrapClassMissing)
{
throw new TypeLoadException("ClassNotFoundException: " + s);
}
finally
{
classNotFound = false;
}
}
internal static Exception NoClassDefFoundError(string s, params object[] args)
{
s = String.Format(s, args);
ConstructorInfo ci = ClassLoaderWrapper.GetType("java.lang.NoClassDefFoundError").GetConstructor(new Type[] { typeof(string) });
return (Exception)ci.Invoke(new object[] { s });
}
internal static Exception UnsatisfiedLinkError(string s, params object[] args)
{
s = String.Format(s, args);
ConstructorInfo ci = ClassLoaderWrapper.GetType("java.lang.UnsatisfiedLinkError").GetConstructor(new Type[] { typeof(string) });
return (Exception)ci.Invoke(new object[] { s });
}
internal static Exception IllegalStateException(string s, params object[] args)
{
s = String.Format(s, args);
ConstructorInfo ci = ClassLoaderWrapper.GetType("java.lang.IllegalStateException").GetConstructor(new Type[] { typeof(string) });
return (Exception)ci.Invoke(new object[] { s });
}
internal static Exception IllegalArgumentException(string s, params object[] args)
{
s = String.Format(s, args);
ConstructorInfo ci = ClassLoaderWrapper.GetType("java.lang.IllegalArgumentException").GetConstructor(new Type[] { typeof(string) });
return (Exception)ci.Invoke(new object[] { s });
}
internal static Exception NegativeArraySizeException()
{
return (Exception)Activator.CreateInstance(ClassLoaderWrapper.GetType("java.lang.NegativeArraySizeException"));
}
internal static Exception InvocationTargetException(Exception x)
{
return (Exception)Activator.CreateInstance(ClassLoaderWrapper.GetType("java.lang.reflect.InvocationTargetException"), new object[] { x });
}
internal static Exception IOException(string s, params object[] args)
{
s = String.Format(s, args);
ConstructorInfo ci = ClassLoaderWrapper.GetType("java.io.IOException").GetConstructor(new Type[] { typeof(string) });
return (Exception)ci.Invoke(new object[] { s });
}
internal static Exception UnknownHostException(string s, params object[] args)
{
s = String.Format(s, args);
ConstructorInfo ci = ClassLoaderWrapper.GetType("java.net.UnknownHostException").GetConstructor(new Type[] { typeof(string) });
return (Exception)ci.Invoke(new object[] { s });
}
}

133
IK.VM.NET/ObjectHelper.cs Normal file
Просмотреть файл

@ -0,0 +1,133 @@
/*
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
*/
using System;
public class ObjectHelper
{
public static void notify(object o)
{
if(o == null)
{
throw new NullReferenceException();
}
System.Threading.Monitor.Pulse(o);
}
public static void notifyAll(object o)
{
if(o == null)
{
throw new NullReferenceException();
}
System.Threading.Monitor.PulseAll(o);
}
public static void wait(object o)
{
if(o == null)
{
throw new NullReferenceException();
}
System.Threading.Monitor.Wait(o);
}
public static void wait(object o, long timeout)
{
wait(o, timeout, 0);
}
public static void wait(object o, long timeout, int nanos)
{
if(o == null)
{
throw new NullReferenceException();
}
if(timeout == 0 && nanos == 0)
{
System.Threading.Monitor.Wait(o);
}
else
{
System.Threading.Monitor.Wait(o, new TimeSpan(timeout * 10000 + (nanos + 99) / 100));
}
}
public static void clonecheck(object o)
{
if(!(o is java.lang.Cloneable))
{
throw (Exception)Activator.CreateInstance(ClassLoaderWrapper.GetType("java.lang.CloneNotSupportedException"));
}
}
public static object virtualclone(object o)
{
// TODO because Object.clone() is protected it is accessible from other classes in the java.lang package,
// so when they clone an array, we end up here (instead of being redirected to System.Array.Clone(), which
// the compiler normally does because Object.clone() is inaccessible)
if(o is Array)
{
return ((Array)o).Clone();
}
clonecheck(o);
// TODO this doesn't happen very often, the only sensible pattern that I can think of that produces code
// that ends up here is as follows:
// class Base {
// public Base CloneMe() { return (Base)clone(); }
// }
// case Derived extends Base {
// protected object clone() { ... }
// }
// One way of implementing this is by calling the clone method thru reflection, not very fast, but
// since this is an uncommon scenario, we might be able to get away with it
throw new NotImplementedException("virtual clone invocation not implemented");
}
public static string toStringVirtual(object o)
{
if(o is Array)
{
return toStringSpecial(o);
}
try
{
return o.ToString();
}
catch(NullReferenceException)
{
return o.GetType().FullName;
}
}
public static string toStringSpecial(object o)
{
// TODO hex string should be formatted differently
return NativeCode.java.lang.Class.getName(o.GetType()) + "@" + o.GetHashCode().ToString("X");
}
public static object getClass(object o)
{
return NativeCode.java.lang.Class.getClassFromType(o.GetType());
}
}

369
IK.VM.NET/StringHelper.cs Normal file
Просмотреть файл

@ -0,0 +1,369 @@
/*
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
*/
using System;
using System.Text;
using System.Reflection;
public class StringHelper
{
public static string NewString(char[] data, int offset, int count, bool dont_copy)
{
return new String(data, offset, count);
}
public static string NewString(sbyte[] sdata)
{
return NewString(sdata, 0, sdata.Length);
}
public static string NewString(sbyte[] sdata, int hibyte)
{
return NewString(sdata, hibyte, 0, sdata.Length);
}
public static string NewString(sbyte[] sdata, int offset, int count)
{
// TODO what encoding should this use?
// TODO could use the unsafe constructor that takes sbyte*, but I don't know if that is worthwhile to be unsafe for
byte[] data = new byte[sdata.Length];
for(int i = 0; i < data.Length; i++)
{
data[i] = (byte)sdata[i];
}
return System.Text.Encoding.ASCII.GetString(data, offset, count);
}
public static string NewString(sbyte[] sdata, int hibyte, int offset, int count)
{
// TODO benchmark this versus using a stringbuilder instead of a char[]
hibyte <<= 8;
char[] data = new char[count];
for(int i = 0; i < count; i++)
{
// TODO what happens for negative bytes?
data[i] = (char)(((byte)sdata[i + offset]) | hibyte);
}
return new String(data);
}
public static string NewString(sbyte[] sdata, string charsetName)
{
return NewString(sdata, 0, sdata.Length, charsetName);
}
public static string NewString(sbyte[] sdata, int offset, int count, string charsetName)
{
// HACK special case for UTF8, I really need to implement this by
// redirecting to the classpath character encoding support
if(charsetName == "UTF8")
{
char[] ch = new Char[count];
int l = 0;
for(int i = 0; i < count; i++)
{
int c = (byte)sdata[offset + i];
int char2, char3;
switch (c >> 4)
{
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
// 0xxxxxxx
break;
case 12: case 13:
// 110x xxxx 10xx xxxx
char2 = (byte)sdata[offset + ++i];
c = (((c & 0x1F) << 6) | (char2 & 0x3F));
break;
case 14:
// 1110 xxxx 10xx xxxx 10xx xxxx
char2 = (byte)sdata[offset + ++i];
char3 = (byte)sdata[offset + ++i];
c = (((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0));
break;
}
ch[l++] = (char)c;
}
return new String(ch, 0, l);
}
// TODO don't use reflection, but write a Java helper class and redirect this method there
Type t = ClassLoaderWrapper.GetType("gnu.java.io.EncodingManager");
object decoder = t.InvokeMember("getDecoder", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static, null, null, new object[] { charsetName });
return new String((char[])decoder.GetType().InvokeMember("convertToChars", BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.Public, null, decoder, new object[] { sdata, offset, count }));
}
public static string valueOf(bool b)
{
return b ? "true" : "false";
}
public static string valueOf(int i)
{
return i.ToString();
}
public static string valueOf(long l)
{
return l.ToString();
}
public static string valueOf(char c)
{
return c.ToString();
}
public static string valueOf(float f)
{
StringBuilder sb = new StringBuilder();
return StringBufferHelper.append(sb, f).ToString();
}
public static string valueOf(double d)
{
StringBuilder sb = new StringBuilder();
return StringBufferHelper.append(sb, d).ToString();
}
public static string valueOf(object o)
{
if(o == null)
{
return "null";
}
return ObjectHelper.toStringVirtual(o);
}
public static string substring(string s, int off, int end)
{
return s.Substring(off, end - off);
}
public static bool startsWith(string s, string prefix, int toffset)
{
// TODO
throw new NotImplementedException();
}
public static void getChars(string s, int srcBegin, int srcEnd, char[] dst, int dstBegin)
{
s.CopyTo(srcBegin, dst, dstBegin, srcEnd - srcBegin);
}
public static int GetCountField(string s)
{
return s.Length;
}
public static char[] GetValueField(string s)
{
return s.ToCharArray();
}
public static int GetOffsetField(string s)
{
return 0;
}
public static bool equalsIgnoreCase(string s1, string s2)
{
return String.Compare(s1, s2, true) == 0;
}
public static int compareToIgnoreCase(string s1, string s2)
{
return String.Compare(s1, s2, true);
}
public static sbyte[] getBytes(string s)
{
byte[] data = System.Text.Encoding.ASCII.GetBytes(s);
sbyte[] sdata = new sbyte[data.Length];
for(int i = 0; i < data.Length; i++)
{
sdata[i] = (sbyte)data[i];
}
return sdata;
}
public static sbyte[] getBytes(string s, string charsetName)
{
// TODO don't use reflection, but write a Java helper class and redirect this method there
char[] ch = s.ToCharArray();
Type t = ClassLoaderWrapper.GetType("gnu.java.io.EncodingManager");
object encoder = t.InvokeMember("getEncoder", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static, null, null, new object[] { charsetName });
return (sbyte[])encoder.GetType().InvokeMember("convertToBytes", BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.Public, null, encoder, new object[] { ch, 0, ch.Length });
}
public static void getBytes(string s, int srcBegin, int srcEnd, sbyte[] dst, int dstBegin)
{
for(int i = 0; i < (srcEnd - srcBegin); i++)
{
dst[i + dstBegin] = (sbyte)s[i + srcBegin];
}
}
public static object subSequence(string s, int offset, int count)
{
// TODO
throw new NotImplementedException();
}
public static bool regionMatches(string s, int toffset, string other, int ooffset, int len)
{
return regionMatches(s, false, toffset, other, ooffset, len);
}
public static bool regionMatches(string s, bool ignoreCase, int toffset, string other, int ooffset, int len)
{
if(toffset < 0 || ooffset < 0 || toffset + len > s.Length || ooffset + len > other.Length)
{
return false;
}
while(--len >= 0)
{
char c1 = s[toffset++];
char c2 = other[ooffset++];
if(c1 != c2 && (!ignoreCase || (Char.ToLower(c1) != Char.ToLower(c2) && (Char.ToUpper(c1) != Char.ToUpper(c2)))))
{
return false;
}
}
return true;
}
// NOTE argument is of type object, because otherwise the code that calls this function
// has to be much more complex
public static int hashCode(object s)
{
int h = 0;
foreach(char c in (string)s)
{
h = h * 31 + c;
}
return h;
}
public static string toUpperCase(string s, object locale)
{
// TODO
return s.ToUpper();
}
}
public class StringBufferHelper
{
public static StringBuilder append(StringBuilder thiz, object o)
{
if(o == null)
{
o = "null";
}
return thiz.Append(ObjectHelper.toStringVirtual(o));
}
public static StringBuilder append(StringBuilder thiz, string s)
{
if(s == null)
{
s = "null";
}
return thiz.Append(s);
}
public static StringBuilder append(StringBuilder thiz, bool b)
{
if(b)
{
return thiz.Append("true");
}
else
{
return thiz.Append("false");
}
}
public static StringBuilder append(StringBuilder thiz, float f)
{
// TODO this is not correct, we need to use the Java algorithm of converting a float to string
if(float.IsNaN(f))
{
thiz.Append("NaN");
return thiz;
}
if(float.IsNegativeInfinity(f))
{
thiz.Append("-Infinity");
return thiz;
}
if(float.IsPositiveInfinity(f))
{
thiz.Append("Infinity");
return thiz;
}
// HACK really lame hack to apprioximate the Java behavior a little bit
string s = f.ToString(System.Globalization.CultureInfo.InvariantCulture);
thiz.Append(s);
if(s.IndexOf('.') == -1)
{
thiz.Append(".0");
}
return thiz;
}
public static StringBuilder append(StringBuilder thiz, double d)
{
DoubleToString.append(thiz, d);
return thiz;
}
public static StringBuilder insert(StringBuilder thiz, int index, string s)
{
if(s == null)
{
s = "null";
}
return thiz.Insert(index, s);
}
public static string substring(StringBuilder thiz, int start, int end)
{
return thiz.ToString(start, end - start);
}
public static string substring(StringBuilder thiz, int start)
{
return thiz.ToString(start, thiz.Length - start);
}
public static StringBuilder replace(StringBuilder thiz, int start, int end, string str)
{
// OPTIMIZE this could be done a little more efficient
thiz.Remove(start, end - start);
thiz.Insert(start, str);
return thiz;
}
public static StringBuilder delete(StringBuilder thiz, int start, int end)
{
return thiz.Remove(start, end - start);
}
}

3253
IK.VM.NET/TypeWrapper.cs Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

214
IK.VM.NET/WeakHashtable.cs Normal file
Просмотреть файл

@ -0,0 +1,214 @@
using System;
using System.Collections;
// TODO implement this properly, instead of this quick hack
public class WeakHashtable : IDictionary
{
private struct KeyValue
{
public WeakReference Key;
public object Value;
}
private KeyValue[] items = new KeyValue[101];
public WeakHashtable()
{
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
public IDictionaryEnumerator GetEnumerator()
{
throw new NotImplementedException();
}
public void Remove(object key)
{
throw new NotImplementedException();
}
public bool Contains(object key)
{
return ContainsKey(key);
}
public bool ContainsKey(object key)
{
lock(this)
{
int index = FindKey(key);
return index != -1 && items[index].Key != null && items[index].Key.Target != null;
}
}
public void Clear()
{
throw new NotImplementedException();
}
public void Add(object key, object value)
{
lock(this)
{
int index = FindKey(key);
if(index != -1 && items[index].Key != null && items[index].Key.Target != null)
{
throw new ArgumentException();
}
int newSize = items.Length;
while(index == -1)
{
Rehash(newSize);
newSize = items.Length * 2 - 1;
index = FindKey(key);
}
items[index].Key = new WeakReference(key);
items[index].Value = value;
}
}
public bool IsReadOnly
{
get
{
return false;
}
}
// this returns the slot containing the key,
// the empty slot that should contain the key, or -1 if the
// table is too full to contain the key
private int FindKey(object key)
{
int start = key.GetHashCode() % items.Length;
int end = (start + 5) % items.Length;
for(int index = start; ; index = (index + 1) % items.Length)
{
if(items[index].Key == null)
{
return index;
}
if(key.Equals(items[index].Key.Target))
{
return index;
}
if(index == end)
{
return -1;
}
}
}
private void Rehash(int newSize)
{
KeyValue[] curr = items;
restart:
items = new KeyValue[newSize];
for(int i = 0; i < curr.Length; i++)
{
if(curr[i].Key != null)
{
object key = curr[i].Key.Target;
if(key != null)
{
int index = FindKey(key);
if(index == -1)
{
newSize = newSize * 2 - 1;
goto restart;
}
items[index].Key = new WeakReference(key);
items[index].Value = curr[i].Value;
}
}
}
}
public object this[object key]
{
get
{
lock(this)
{
int index = FindKey(key);
if(index >= 0)
{
return items[index].Value;
}
return null;
}
}
set
{
lock(this)
{
int index = FindKey(key);
int newSize = items.Length;
while(index == -1)
{
Rehash(newSize);
newSize = items.Length * 2 - 1;
index = FindKey(key);
}
items[index].Key = new WeakReference(key);
items[index].Value = value;
}
}
}
public ICollection Values
{
get
{
throw new NotImplementedException();
}
}
public ICollection Keys
{
get
{
throw new NotImplementedException();
}
}
public bool IsFixedSize
{
get
{
return false;
}
}
public void CopyTo(Array array, int index)
{
throw new NotImplementedException();
}
public bool IsSynchronized
{
get
{
return true;
}
}
public int Count
{
get
{
throw new NotImplementedException();
}
}
public object SyncRoot
{
get
{
return this;
}
}
}

260
IK.VM.NET/attributes.cs Normal file
Просмотреть файл

@ -0,0 +1,260 @@
/*
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
*/
using System;
using System.Reflection;
using System.Reflection.Emit;
[AttributeUsage(AttributeTargets.Class)]
public class OverrideStubTypeAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Assembly)]
public class IKVMAssemblyAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.All)]
public class ModifiersAttribute : Attribute
{
private Modifiers modifiers;
public ModifiersAttribute(Modifiers modifiers)
{
this.modifiers = modifiers;
}
public bool IsSynthetic
{
get
{
return modifiers == Modifiers.Synthetic;
}
}
public Modifiers Modifiers
{
get
{
return modifiers;
}
}
public static Modifiers GetModifiers(MethodBase mb)
{
object[] customAttribute = mb.GetCustomAttributes(typeof(ModifiersAttribute), false);
if(customAttribute.Length == 1)
{
return ((ModifiersAttribute)customAttribute[0]).Modifiers;
}
Modifiers modifiers = 0;
if(mb.IsPublic)
{
modifiers |= Modifiers.Public;
}
if(mb.IsPrivate)
{
modifiers |= Modifiers.Private;
}
if(mb.IsFamily || mb.IsFamilyOrAssembly)
{
modifiers |= Modifiers.Protected;
}
// NOTE Java doesn't support non-virtual methods, but we set the Final modifier for
// non-virtual methods to approximate the semantics
if(mb.IsFinal || (!mb.IsStatic && !mb.IsVirtual))
{
modifiers |= Modifiers.Final;
}
if(mb.IsAbstract)
{
modifiers |= Modifiers.Abstract;
}
if(mb.IsStatic)
{
modifiers |= Modifiers.Static;
}
if((mb.GetMethodImplementationFlags() & MethodImplAttributes.Synchronized) != 0)
{
modifiers |= Modifiers.Synchronized;
}
if((mb.Attributes & MethodAttributes.PinvokeImpl) != 0)
{
modifiers |= Modifiers.Native;
}
return modifiers;
}
public static Modifiers GetModifiers(FieldInfo fi)
{
object[] customAttribute = fi.GetCustomAttributes(typeof(ModifiersAttribute), false);
if(customAttribute.Length == 1)
{
return ((ModifiersAttribute)customAttribute[0]).Modifiers;
}
// NOTE privatescope fields are always treated as synthetic (even when they are in a .NET type, because
// Java wouldn't be able to cope with them anyway, because of potential name clashes)
if((fi.Attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.PrivateScope)
{
return Modifiers.Synthetic;
}
Modifiers modifiers = 0;
if(fi.IsPublic)
{
modifiers |= Modifiers.Public;
}
if(fi.IsPrivate)
{
modifiers |= Modifiers.Private;
}
if(fi.IsFamily || fi.IsFamilyOrAssembly)
{
modifiers |= Modifiers.Protected;
}
if(fi.IsInitOnly || fi.IsLiteral)
{
modifiers |= Modifiers.Final;
}
if(fi.IsNotSerialized)
{
modifiers |= Modifiers.Transient;
}
if(fi.IsStatic)
{
modifiers |= Modifiers.Static;
}
// TODO reflection doesn't support volatile
return modifiers;
}
public static Modifiers GetModifiers(Type type)
{
object[] customAttribute = type.GetCustomAttributes(typeof(ModifiersAttribute), false);
if(customAttribute.Length == 1)
{
return ((ModifiersAttribute)customAttribute[0]).Modifiers;
}
// only returns public, protected, private, final, static, abstract and interface (as per
// the documentation of Class.getModifiers())
Modifiers modifiers = 0;
if(type.IsPublic)
{
modifiers |= Modifiers.Public;
}
if(type.IsNestedPrivate)
{
modifiers |= Modifiers.Private;
}
if(type.IsNestedFamily || type.IsNestedFamORAssem)
{
modifiers |= Modifiers.Protected;
}
if(type.IsSealed)
{
modifiers |= Modifiers.Final;
}
if(type.DeclaringType != null)
{
modifiers |= Modifiers.Static;
}
if(type.IsAbstract)
{
modifiers |= Modifiers.Abstract;
}
if(type.IsInterface)
{
modifiers |= Modifiers.Interface;
}
return modifiers;
}
public static void SetModifiers(MethodBuilder mb, Modifiers modifiers)
{
CustomAttributeBuilder customAttributeBuilder = new CustomAttributeBuilder(typeof(ModifiersAttribute).GetConstructor(new Type[] { typeof(Modifiers) }), new object[] { modifiers });
mb.SetCustomAttribute(customAttributeBuilder);
}
public static void SetModifiers(FieldBuilder fb, Modifiers modifiers)
{
CustomAttributeBuilder customAttributeBuilder = new CustomAttributeBuilder(typeof(ModifiersAttribute).GetConstructor(new Type[] { typeof(Modifiers) }), new object[] { modifiers });
fb.SetCustomAttribute(customAttributeBuilder);
}
}
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Property | AttributeTargets.Class)]
public class StackTraceInfoAttribute : Attribute
{
private bool hidden;
private string className;
private bool truncate;
private int eatFrames;
public bool Hidden
{
get
{
return hidden;
}
set
{
hidden = value;
}
}
public int EatFrames
{
get
{
return eatFrames;
}
set
{
eatFrames = value;
}
}
public string Class
{
get
{
return className;
}
set
{
className = value;
}
}
public bool Truncate
{
get
{
return truncate;
}
set
{
truncate = value;
}
}
}

1636
IK.VM.NET/classpath.cs Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

2450
IK.VM.NET/compiler.cs Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

14
IK.VM.NET/ik.vm.net.build Normal file
Просмотреть файл

@ -0,0 +1,14 @@
<?xml version="1.0"?>
<project name="ik.vm.net" default="ik.vm.net">
<target name="ik.vm.net">
<csc target="library" output="../bin/ik.vm.net.dll">
<sources>
<includes name="*.cs" />
</sources>
<references>
<includes name="../bin/IK.VM.JNI.dll" asis="true" />
</references>
<arg value="/resource:map.xml" />
</csc>
</target>
</project>

446
IK.VM.NET/map.xml Normal file
Просмотреть файл

@ -0,0 +1,446 @@
<?xml version="1.0" encoding="utf-8" ?>
<!--
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
-->
<root>
<remappings>
<class name="java.lang.Object" type="System.Object" modifiers="public">
<constructor sig="()V" modifiers="public" />
<method name="notifyAll" sig="()V" modifiers="public final">
<redirect class="ObjectHelper" name="notifyAll" sig="(Ljava/lang/Object;)V" type="static" />
</method>
<method name="notify" sig="()V" modifiers="public final">
<redirect class="ObjectHelper" name="notify" sig="(Ljava/lang/Object;)V" type="static" />
</method>
<method name="wait" sig="()V" modifiers="public final">
<redirect class="ObjectHelper" name="wait" sig="(Ljava/lang/Object;)V" type="static" />
</method>
<method name="wait" sig="(J)V" modifiers="public final">
<redirect class="ObjectHelper" name="wait" sig="(Ljava/lang/Object;J)V" type="static" />
</method>
<method name="wait" sig="(JI)V" modifiers="public final">
<redirect class="ObjectHelper" name="wait" sig="(Ljava/lang/Object;JI)V" type="static" />
</method>
<method name="getClass" sig="()Ljava/lang/Class;" modifiers="public final">
<redirect class="ObjectHelper" name="getClass" sig="(Ljava/lang/Object;)Ljava/lang/Object;" type="static" />
</method>
<method name="clone" sig="()Ljava/lang/Object;" modifiers="protected">
<invokespecial>
<!-- TODO if we already know statically that the type implements java/lang/Cloneable this check can be omitted -->
<dup />
<call class="ObjectHelper" name="clonecheck" />
<call class="System.Object" name="MemberwiseClone" />
</invokespecial>
<invokevirtual>
<call class="ObjectHelper" name="virtualclone" />
</invokevirtual>
</method>
<!-- virtual methods -->
<!-- TODO every object that doesn't override toString or hashCode will now be called through these
conditional constructs, this is unnecessary (and not very efficient), so I need to figure out a way
to prevent this -->
<method name="toString" sig="()Ljava/lang/String;" modifiers="public">
<override name="ToString" />
<invokespecial>
<call class="ObjectHelper" name="toStringSpecial" />
</invokespecial>
<invokevirtual>
<dup />
<isinst class="System.Array" />
<brfalse name="skip" />
<call class="ObjectHelper" name="toStringSpecial" />
<br name="end" />
<label name="skip" />
<callvirt class="System.Object" name="ToString" />
<label name="end" />
</invokevirtual>
</method>
<method name="hashCode" sig="()I" modifiers="public">
<override name="GetHashCode" />
<invokevirtual>
<dup />
<isinst class="System.String" />
<brfalse name="skip" />
<call class="StringHelper" name="hashCode" />
<br name="end" />
<label name="skip" />
<callvirt class="System.Object" name="GetHashCode" />
<label name="end" />
</invokevirtual>
</method>
<method name="equals" sig="(Ljava/lang/Object;)Z" modifiers="public">
<override name="Equals" />
</method>
<method name="finalize" sig="()V" modifiers="protected">
<override name="Finalize" />
</method>
</class>
<class name="java.lang.String" type="System.String" modifiers="public final">
<constructor sig="()V" modifiers="public">
<!-- TODO -->
<newobj>
<ldstr value="" />
<call class="System.String" name="Copy" />
</newobj>
</constructor>
<constructor sig="([C)V" modifiers="public" />
<constructor sig="([CII)V" modifiers="public" />
<!-- Package private constructor, that we redirect to static helper -->
<constructor sig="([CIIZ)V" modifiers="">
<redirect class="StringHelper" name="NewString" type="static" sig="([CIIZ)Ljava/lang/String;" />
</constructor>
<constructor sig="(Ljava/lang/String;)V" modifiers="public">
<redirect class="System.String" name="Copy" type="static" sig="(Ljava/lang/String;)Ljava/lang/String;" />
</constructor>
<constructor sig="(Ljava/lang/StringBuffer;)V" modifiers="public">
<redirect class="System.Text.StringBuilder" name="ToString" sig="()Ljava/lang/String;" />
</constructor>
<constructor sig="([B)V" modifiers="public">
<redirect class="StringHelper" name="NewString" type="static" sig="([B)Ljava/lang/String;" />
</constructor>
<constructor sig="([BI)V" modifiers="public">
<redirect class="StringHelper" name="NewString" type="static" sig="([BI)Ljava/lang/String;" />
</constructor>
<constructor sig="([BII)V" modifiers="public">
<redirect class="StringHelper" name="NewString" type="static" sig="([BII)Ljava/lang/String;" />
</constructor>
<constructor sig="([BIII)V" modifiers="public">
<redirect class="StringHelper" name="NewString" type="static" sig="([BIII)Ljava/lang/String;" />
</constructor>
<constructor sig="([BLjava/lang/String;)V" modifiers="public">
<redirect class="StringHelper" name="NewString" type="static" sig="([BLjava/lang/String;)Ljava/lang/String;" />
</constructor>
<constructor sig="([BIILjava/lang/String;)V" modifiers="public">
<redirect class="StringHelper" name="NewString" type="static" sig="([BIILjava/lang/String;)Ljava/lang/String;" />
</constructor>
<method name="hashCode" sig="()I" modifiers="public">
<redirect class="StringHelper" type="static" sig="(Ljava/lang/String;)I" />
</method>
<method name="valueOf" sig="(Z)Ljava/lang/String;" modifiers="public static">
<redirect class="StringHelper" />
</method>
<method name="valueOf" sig="(I)Ljava/lang/String;" modifiers="public static">
<redirect class="StringHelper" />
</method>
<method name="valueOf" sig="(J)Ljava/lang/String;" modifiers="public static">
<redirect class="StringHelper" />
</method>
<method name="valueOf" sig="(C)Ljava/lang/String;" modifiers="public static">
<redirect class="StringHelper" />
</method>
<method name="valueOf" sig="(F)Ljava/lang/String;" modifiers="public static">
<redirect class="StringHelper" />
</method>
<method name="valueOf" sig="(D)Ljava/lang/String;" modifiers="public static">
<redirect class="StringHelper" />
</method>
<method name="valueOf" sig="(Ljava/lang/Object;)Ljava/lang/String;" modifiers="public static">
<redirect class="StringHelper" />
</method>
<method name="substring" sig="(I)Ljava/lang/String;" modifiers="public">
<redirect name="Substring" />
</method>
<method name="length" sig="()I" modifiers="public">
<redirect name="get_Length" />
</method>
<method name="charAt" sig="(I)C" modifiers="public">
<redirect name="get_Chars" />
</method>
<method name="substring" sig="(II)Ljava/lang/String;" modifiers="public">
<redirect class="StringHelper" type="static" sig="(Ljava/lang/String;II)Ljava/lang/String;" />
</method>
<method name="indexOf" sig="(I)I" modifiers="public">
<redirect name="IndexOf" sig="(C)I" />
</method>
<method name="indexOf" sig="(II)I" modifiers="public">
<redirect name="IndexOf" sig="(CI)I" />
</method>
<method name="indexOf" sig="(Ljava/lang/String;)I" modifiers="public">
<redirect name="IndexOf" />
</method>
<method name="indexOf" sig="(Ljava/lang/String;I)I" modifiers="public">
<redirect name="IndexOf" />
</method>
<method name="lastIndexOf" sig="(I)I" modifiers="public">
<redirect name="LastIndexOf" sig="(C)I" />
</method>
<method name="lastIndexOf" sig="(II)I" modifiers="public">
<redirect name="LastIndexOf" sig="(CI)I" />
</method>
<method name="lastIndexOf" sig="(Ljava/lang/String;)I" modifiers="public">
<redirect name="LastIndexOf" />
</method>
<method name="toCharArray" sig="()[C" modifiers="public">
<redirect name="ToCharArray" />
</method>
<method name="getChars" sig="(II[CI)V" modifiers="public">
<redirect class="StringHelper" type="static" sig="(Ljava/lang/String;II[CI)V" />
</method>
<method name="startsWith" sig="(Ljava/lang/String;)Z" modifiers="public">
<redirect name="StartsWith" />
</method>
<method name="startsWith" sig="(Ljava/lang/String;I)Z" modifiers="public">
<redirect class="StringHelper" type="static" sig="(Ljava/lang/String;Ljava/lang/String;I)Z" />
</method>
<method name="endsWith" sig="(Ljava/lang/String;)Z" modifiers="public">
<redirect name="EndsWith" />
</method>
<method name="toUpperCase" sig="()Ljava/lang/String;" modifiers="public">
<redirect name="ToUpper" />
</method>
<method name="toUpperCase" sig="(Ljava/util/Locale;)Ljava/lang/String;" modifiers="public">
<redirect class="StringHelper" type="static" sig="(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/String;" />
</method>
<method name="toLowerCase" sig="()Ljava/lang/String;" modifiers="public">
<redirect name="ToLower" />
</method>
<method name="compareToIgnoreCase" sig="(Ljava/lang/String;)I" modifiers="public">
<redirect class="StringHelper" type="static" sig="(Ljava/lang/String;Ljava/lang/String;)I" />
</method>
<method name="equalsIgnoreCase" sig="(Ljava/lang/String;)Z" modifiers="public">
<redirect class="StringHelper" type="static" sig="(Ljava/lang/String;Ljava/lang/String;)Z" />
</method>
<method name="intern" sig="()Ljava/lang/String;" modifiers="public">
<redirect type="static" name="Intern" sig="(Ljava/lang/String;)Ljava/lang/String;" />
</method>
<method name="compareTo" sig="(Ljava/lang/String;)I" modifiers="public">
<redirect name="CompareTo" />
</method>
<method name="replace" sig="(CC)Ljava/lang/String;" modifiers="public">
<redirect name="Replace" />
</method>
<method name="getBytes" sig="()[B" modifiers="public">
<redirect class="StringHelper" type="static" sig="(Ljava/lang/String;)[B" />
</method>
<method name="getBytes" sig="(Ljava/lang/String;)[B" modifiers="public">
<redirect class="StringHelper" type="static" sig="(Ljava/lang/String;Ljava/lang/String;)[B" />
</method>
<method name="subSequence" sig="(II)Ljava/lang/CharSequence;" modifiers="public">
<redirect class="StringHelper" type="static" sig="(Ljava/lang/String;II)Ljava/lang/Object;" />
</method>
<method name="trim" sig="()Ljava/lang/String;" modifiers="public">
<redirect name="Trim" />
</method>
<method name="regionMatches" sig="(ZILjava/lang/String;II)Z" modifiers="public">
<redirect class="StringHelper" type="static" sig="(Ljava/lang/String;ZILjava/lang/String;II)Z" />
</method>
<method name="regionMatches" sig="(ILjava/lang/String;II)Z" modifiers="public">
<redirect class="StringHelper" type="static" sig="(Ljava/lang/String;ILjava/lang/String;II)Z" />
</method>
<method name="getBytes" sig="(II[BI)V" modifiers="public">
<redirect class="StringHelper" type="static" sig="(Ljava/lang/String;II[BI)V" />
</method>
<method name="concat" sig="(Ljava/lang/String;)Ljava/lang/String;" modifiers="public">
<redirect class="System.String" type="static" name="Concat" sig="(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;" />
</method>
<method name="copyValueOf" sig="([CII)Ljava/lang/String;" modifiers="public static">
<invokestatic>
<newobj class="System.String" name=".ctor" sig="([CII)V" />
</invokestatic>
</method>
<!-- NOTE we're redirecting fields to static methods here!
NOTE only reading fields can be redirected
-->
<field name="count" sig="I" modifiers="">
<redirect class="StringHelper" type="static" name="GetCountField" sig="(Ljava/lang/String;)I" />
</field>
<!-- Making a new char array instead of directly accessing the contents of the string, probably isn't
as efficient as the coder of this construct wished for, but hey ;-) At least it works...
TODO we should probably make StringBuffer a native class, to make it perform better
NOTE since StringBuffer is remapped to StringBuilder now, these might not be needed anymore
-->
<method name="zeroBasedStringValue" sig="(Ljava/lang/String;)[C" modifiers="static">
<redirect class="StringHelper" name="GetValueField" />
</method>
<field name="value" sig="[C" modifiers="">
<redirect class="StringHelper" type="static" name="GetValueField" sig="(Ljava/lang/String;)[C" />
</field>
<field name="offset" sig="I" modifiers="">
<redirect class="StringHelper" type="static" name="GetOffsetField" sig="(Ljava/lang/String;)I" />
</field>
</class>
<!-- TODO it is incorrect to map StringBuffer to StringBuilder, because StringBuffer is thread safe, puke! -->
<class name="java.lang.StringBuffer" type="System.Text.StringBuilder" modifiers="public final">
<constructor sig="()V" modifiers="public" />
<constructor sig="(Ljava/lang/String;)V" modifiers="public" />
<constructor sig="(I)V" modifiers="public" />
<method name="length" sig="()I" modifiers="public">
<redirect name="get_Length" />
</method>
<method name="setLength" sig="(I)V" modifiers="public">
<redirect name="set_Length" />
</method>
<method name="ensureCapacity" sig="(I)V" modifiers="public">
<invokevirtual>
<call class="System.Text.StringBuilder" name="EnsureCapacity" />
<pop />
</invokevirtual>
<invokespecial>
<call class="System.Text.StringBuilder" name="EnsureCapacity" />
<pop />
</invokespecial>
</method>
<method name="append" sig="(Ljava/lang/Object;)Ljava/lang/StringBuffer;" modifiers="public">
<redirect class="StringBufferHelper" type="static" sig="(Ljava/lang/StringBuffer;Ljava/lang/Object;)Ljava/lang/StringBuffer;" />
</method>
<method name="append" sig="(Ljava/lang/String;)Ljava/lang/StringBuffer;" modifiers="public">
<redirect class="StringBufferHelper" type="static" sig="(Ljava/lang/StringBuffer;Ljava/lang/String;)Ljava/lang/StringBuffer;" />
</method>
<method name="append" sig="(Z)Ljava/lang/StringBuffer;" modifiers="public">
<redirect class="StringBufferHelper" type="static" sig="(Ljava/lang/StringBuffer;Z)Ljava/lang/StringBuffer;" />
</method>
<method name="append" sig="(C)Ljava/lang/StringBuffer;" modifiers="public">
<redirect name="Append" />
</method>
<method name="append" sig="(I)Ljava/lang/StringBuffer;" modifiers="public">
<redirect name="Append" />
</method>
<method name="append" sig="(J)Ljava/lang/StringBuffer;" modifiers="public">
<redirect name="Append" />
</method>
<method name="append" sig="(F)Ljava/lang/StringBuffer;" modifiers="public">
<redirect class="StringBufferHelper" type="static" sig="(Ljava/lang/StringBuffer;F)Ljava/lang/StringBuffer;" />
</method>
<method name="append" sig="(D)Ljava/lang/StringBuffer;" modifiers="public">
<redirect class="StringBufferHelper" type="static" sig="(Ljava/lang/StringBuffer;D)Ljava/lang/StringBuffer;" />
</method>
<method name="append" sig="([C)Ljava/lang/StringBuffer;" modifiers="public">
<redirect name="Append" />
</method>
<method name="append" sig="([CII)Ljava/lang/StringBuffer;" modifiers="public">
<redirect name="Append" />
</method>
<method name="insert" sig="(IC)Ljava/lang/StringBuffer;" modifiers="public">
<redirect name="Insert" />
</method>
<method name="insert" sig="(ILjava/lang/String;)Ljava/lang/StringBuffer;" modifiers="public">
<redirect class="StringBufferHelper" type="static" sig="(Ljava/lang/StringBuffer;ILjava/lang/String;)Ljava/lang/StringBuffer;" />
</method>
<method name="replace" sig="(IILjava/lang/String;)Ljava/lang/StringBuffer;" modifiers="public">
<redirect class="StringBufferHelper" type="static" sig="(Ljava/lang/StringBuffer;IILjava/lang/String;)Ljava/lang/StringBuffer;" />
</method>
<method name="delete" sig="(II)Ljava/lang/StringBuffer;" modifiers="public">
<redirect class="StringBufferHelper" type="static" sig="(Ljava/lang/StringBuffer;II)Ljava/lang/StringBuffer;" />
</method>
<method name="setCharAt" sig="(IC)V" modifiers="public">
<redirect name="set_Chars" />
</method>
<method name="charAt" sig="(I)C" modifiers="public">
<redirect name="get_Chars" />
</method>
<method name="substring" sig="(II)Ljava/lang/String;" modifiers="public">
<redirect class="StringBufferHelper" type="static" sig="(Ljava/lang/StringBuffer;II)Ljava/lang/String;" />
</method>
<method name="substring" sig="(I)Ljava/lang/String;" modifiers="public">
<redirect class="StringBufferHelper" type="static" sig="(Ljava/lang/StringBuffer;I)Ljava/lang/String;" />
</method>
</class>
<class name="java.lang.Throwable" type="System.Exception" modifiers="public">
<constructor sig="()V" modifiers="public">
<invokespecial>
<call class="ExceptionHelper" name="get_NullString" />
<call class="System.Exception" name=".ctor" sig="(Ljava/lang/String;)V" />
</invokespecial>
</constructor>
<constructor sig="(Ljava/lang/String;)V" modifiers="public">
<invokespecial>
<call class="ExceptionHelper" name="FilterMessage" />
<call class="System.Exception" name=".ctor" sig="(Ljava/lang/String;)V" />
</invokespecial>
</constructor>
<constructor sig="(Ljava/lang/String;Ljava/lang/Throwable;)V" modifiers="public">
<invokespecial>
<stloc name="x" class="System.Exception" />
<call class="ExceptionHelper" name="FilterMessage" />
<ldloc name="x" />
<call class="System.Exception" name=".ctor" sig="(Ljava/lang/String;Ljava/lang/Throwable;)V" />
</invokespecial>
</constructor>
<constructor sig="(Ljava/lang/Throwable;)V" modifiers="public">
<invokespecial>
<stloc name="x" class="System.Exception" />
<ldloc name="x" />
<call class="ExceptionHelper" name="GetMessageFromCause" />
<ldloc name="x" />
<call class="System.Exception" name=".ctor" sig="(Ljava/lang/String;Ljava/lang/Throwable;)V" />
</invokespecial>
</constructor>
<method type="virtual" name="printStackTrace" sig="()V" modifiers="public">
<redirect class="ExceptionHelper" sig="(Ljava/lang/Throwable;)V" type="static" />
</method>
<method type="virtual" name="printStackTrace" sig="(Ljava/io/PrintStream;)V" modifiers="public">
<!-- NOTE both printStackTrace(Ljava/io/PrintStream;)V & printStackTrace(Ljava/io/PrintWriter;)V redirect
to the same method, this is not a bug -->
<redirect class="ExceptionHelper" sig="(Ljava/lang/Throwable;Ljava/lang/Object;)V" type="static" />
</method>
<method type="virtual" name="printStackTrace" sig="(Ljava/io/PrintWriter;)V" modifiers="public">
<!-- NOTE both printStackTrace(Ljava/io/PrintStream;)V & printStackTrace(Ljava/io/PrintWriter;)V redirect
to the same method, this is not a bug -->
<redirect class="ExceptionHelper" sig="(Ljava/lang/Throwable;Ljava/lang/Object;)V" type="static" />
</method>
<method type="virtual" name="getMessage" sig="()Ljava/lang/String;" modifiers="public">
<redirect class="ExceptionHelper" sig="(Ljava/lang/Throwable;)Ljava/lang/String;" type="static" />
</method>
<method type="virtual" name="getLocalizedMessage" sig="()Ljava/lang/String;" modifiers="public">
<redirect class="ExceptionHelper" sig="(Ljava/lang/Throwable;)Ljava/lang/String;" type="static" />
</method>
<method type="virtual" name="fillInStackTrace" sig="()Ljava/lang/Throwable;" modifiers="public">
<redirect class="ExceptionHelper" sig="(Ljava/lang/Throwable;)Ljava/lang/Throwable;" type="static" />
</method>
<method type="virtual" name="initCause" sig="(Ljava/lang/Throwable;)Ljava/lang/Throwable;" modifiers="public">
<redirect class="ExceptionHelper" sig="(Ljava/lang/Throwable;Ljava/lang/Throwable;)Ljava/lang/Throwable;" type="static" />
</method>
<method type="virtual" name="getCause" sig="()Ljava/lang/Throwable;" modifiers="public">
<redirect class="ExceptionHelper" sig="(Ljava/lang/Throwable;)Ljava/lang/Throwable;" type="static" />
</method>
<method type="virtual" name="getStackTrace" sig="()[Ljava/lang/StackTraceElement;" modifiers="public">
<redirect class="ExceptionHelper" sig="(Ljava/lang/Throwable;)[Ljava/lang/StackTraceElement;" type="static" />
</method>
<method type="virtual" name="setStackTrace" sig="([Ljava/lang/StackTraceElement;)V" modifiers="public">
<redirect class="ExceptionHelper" sig="(Ljava/lang/Throwable;[Ljava/lang/StackTraceElement;)V" type="static" />
</method>
<method type="virtual" name="toString" sig="()Ljava/lang/String;" modifiers="public">
<redirect class="ExceptionHelper" sig="(Ljava/lang/Throwable;)Ljava/lang/String;" type="static" />
</method>
</class>
<class name="java.lang.Comparable" type="System.IComparable" modifiers="public interface">
<method name="compareTo" sig="(Ljava/lang/Object;)I" modifiers="public">
<override name="CompareTo" />
</method>
</class>
<!-- TODO java.lang.StackTraceElement shouldn't be here, but it should be represented by a different TypeWrapper (that can take
a .NET type and present it as a Java type -->
<class name="java.lang.StackTraceElement" type="java.lang.StackTraceElement" modifiers="public final">
<!-- TODO fill out the methods -->
</class>
</remappings>
<nativeMethods>
<class name="java.lang.VMSystem">
<method name="identityHashCode" sig="(Ljava/lang/Object;)I">
<ldarg_0 />
<call class="System.Object" name="GetHashCode" />
<ret />
</method>
</class>
</nativeMethods>
</root>

79
IK.VM.NET/profiler.cs Normal file
Просмотреть файл

@ -0,0 +1,79 @@
/*
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
*/
using System;
using System.Collections;
using System.Diagnostics;
class Profiler
{
private static Profiler instance = new Profiler();
private static Hashtable counters = new Hashtable();
private static Stack stack = new Stack();
private class Entry
{
internal long Time;
internal long Count;
}
~Profiler()
{
foreach(DictionaryEntry e in counters)
{
Console.WriteLine("{0} was executed {1} times for a total of {2} ms", e.Key, ((Entry)e.Value).Count, ((Entry)e.Value).Time / 10000);
}
}
[Conditional("PROFILE")]
internal static void Enter(string name)
{
long ticks = DateTime.Now.Ticks;
if(stack.Count > 0)
{
((Entry)stack.Peek()).Time += ticks;
}
Entry e = (Entry)counters[name];
if(e == null)
{
e = new Entry();
counters[name] = e;
}
e.Count++;
e.Time -= ticks;
stack.Push(e);
}
[Conditional("PROFILE")]
internal static void Leave(string name)
{
long ticks = DateTime.Now.Ticks;
stack.Pop();
Entry e = (Entry)counters[name];
e.Time += ticks;
if(stack.Count > 0)
{
((Entry)stack.Peek()).Time -= ticks;
}
}
}

387
IK.VM.NET/remapper.cs Normal file
Просмотреть файл

@ -0,0 +1,387 @@
using System;
using System.Xml.Serialization;
using System.Collections;
using System.Reflection;
using System.Reflection.Emit;
namespace MapXml
{
public abstract class Instruction
{
internal abstract void Generate(Hashtable context, ILGenerator ilgen);
}
[XmlType("ldstr")]
public sealed class Ldstr : Instruction
{
[XmlAttribute("value")]
public string Value;
internal override void Generate(Hashtable context, ILGenerator ilgen)
{
ilgen.Emit(OpCodes.Ldstr, Value);
}
}
[XmlType("call")]
public class Call : Instruction
{
public Call() : this(OpCodes.Call)
{
}
internal Call(OpCode opcode)
{
this.opcode = opcode;
}
[XmlAttribute("class")]
public string Class;
[XmlAttribute("name")]
public string Name;
[XmlAttribute("sig")]
public string Sig;
private MethodBase method;
private OpCode opcode;
internal sealed override void Generate(Hashtable context, ILGenerator ilgen)
{
if(method == null)
{
string name = Name;
if(name == ".ctor")
{
string sig = Sig;
Type[] argTypes = ClassLoaderWrapper.GetBootstrapClassLoader().ArgTypeListFromSig(sig);
method = Type.GetType(Class, true).GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, CallingConventions.Standard, argTypes, null);
}
else
{
method = Type.GetType(Class, true).GetMethod(name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
}
if(method == null)
{
throw new InvalidOperationException("method not found: " + name);
}
}
if(method.IsConstructor)
{
ilgen.Emit(opcode, (ConstructorInfo)method);
}
else
{
ilgen.Emit(opcode, (MethodInfo)method);
}
}
}
[XmlType("callvirt")]
public sealed class Callvirt : Call
{
public Callvirt() : base(OpCodes.Callvirt)
{
}
}
[XmlType("newobj")]
public sealed class NewObj : Call
{
public NewObj() : base(OpCodes.Newobj)
{
}
}
public abstract class Simple : Instruction
{
private OpCode opcode;
public Simple(OpCode opcode)
{
this.opcode = opcode;
}
internal sealed override void Generate(Hashtable context, ILGenerator ilgen)
{
ilgen.Emit(opcode);
}
}
[XmlType("dup")]
public sealed class Dup : Simple
{
public Dup() : base(OpCodes.Dup)
{
}
}
[XmlType("pop")]
public sealed class Pop : Simple
{
public Pop() : base(OpCodes.Pop)
{
}
}
[XmlType("isinst")]
public sealed class IsInst : Instruction
{
[XmlAttribute("class")]
public string Class;
private Type type;
internal override void Generate(Hashtable context, ILGenerator ilgen)
{
if(type == null)
{
type = Type.GetType(Class, true);
}
ilgen.Emit(OpCodes.Isinst, type);
}
}
public abstract class Branch : Instruction
{
private OpCode opcode;
public Branch(OpCode opcode)
{
this.opcode = opcode;
}
internal sealed override void Generate(Hashtable context, ILGenerator ilgen)
{
Label l;
if(context[Name] == null)
{
l = ilgen.DefineLabel();
context[Name] = l;
}
else
{
l = (Label)context[Name];
}
ilgen.Emit(opcode, l);
}
[XmlAttribute("name")]
public string Name;
}
[XmlType("brfalse")]
public sealed class BrFalse : Branch
{
public BrFalse() : base(OpCodes.Brfalse)
{
}
}
[XmlType("br")]
public sealed class Br : Branch
{
public Br() : base(OpCodes.Br)
{
}
}
[XmlType("label")]
public sealed class BrLabel : Instruction
{
[XmlAttribute("name")]
public string Name;
internal override void Generate(Hashtable context, ILGenerator ilgen)
{
Label l;
if(context[Name] == null)
{
l = ilgen.DefineLabel();
context[Name] = l;
}
else
{
l = (Label)context[Name];
}
ilgen.MarkLabel(l);
}
}
[XmlType("stloc")]
public sealed class StLoc : Instruction
{
[XmlAttribute("name")]
public string Name;
[XmlAttribute("class")]
public string Class;
private Type type;
internal override void Generate(Hashtable context, ILGenerator ilgen)
{
LocalBuilder lb = (LocalBuilder)context[Name];
if(lb == null)
{
if(type == null)
{
type = Type.GetType(Class, true);
}
lb = ilgen.DeclareLocal(type);
context[Name] = lb;
}
ilgen.Emit(OpCodes.Stloc, lb);
}
}
[XmlType("ldloc")]
public sealed class LdLoc : Instruction
{
[XmlAttribute("name")]
public string Name;
internal override void Generate(Hashtable context, ILGenerator ilgen)
{
ilgen.Emit(OpCodes.Ldloc, (LocalBuilder)context[Name]);
}
}
[XmlType("ldarg_0")]
public sealed class LdArg_0 : Simple
{
public LdArg_0() : base(OpCodes.Ldarg_0)
{
}
}
[XmlType("ret")]
public sealed class Ret : Simple
{
public Ret() : base(OpCodes.Ret)
{
}
}
public class InstructionList : CodeEmitter
{
[XmlElement(typeof(Ldstr))]
[XmlElement(typeof(Call))]
[XmlElement(typeof(Callvirt))]
[XmlElement(typeof(Dup))]
[XmlElement(typeof(Pop))]
[XmlElement(typeof(IsInst))]
[XmlElement(typeof(BrFalse))]
[XmlElement(typeof(Br))]
[XmlElement(typeof(BrLabel))]
[XmlElement(typeof(NewObj))]
[XmlElement(typeof(StLoc))]
[XmlElement(typeof(LdLoc))]
[XmlElement(typeof(LdArg_0))]
[XmlElement(typeof(Ret))]
public Instruction[] invoke;
internal sealed override void Emit(ILGenerator ilgen)
{
Hashtable context = new Hashtable();
for(int i = 0; i < invoke.Length; i++)
{
invoke[i].Generate(context, ilgen);
}
}
}
public class Constructor
{
[XmlAttribute("sig")]
public string Sig;
[XmlAttribute("modifiers")]
public MapModifiers Modifiers;
public InstructionList invokespecial;
public InstructionList newobj;
public Redirect redirect;
}
public class Redirect
{
[XmlAttribute("class")]
public string Class;
[XmlAttribute("name")]
public string Name;
[XmlAttribute("sig")]
public string Sig;
[XmlAttribute("type")]
public string Type;
}
public class Override
{
[XmlAttribute("name")]
public string Name;
}
public class Method : InstructionList
{
[XmlAttribute("name")]
public string Name;
[XmlAttribute("sig")]
public string Sig;
[XmlAttribute("modifiers")]
public MapModifiers Modifiers;
[XmlAttribute("type")]
public string Type;
public InstructionList invokevirtual;
public InstructionList invokespecial;
public InstructionList invokestatic;
public Redirect redirect;
public Override @override;
}
public class Field
{
[XmlAttribute("name")]
public string Name;
[XmlAttribute("sig")]
public string Sig;
[XmlAttribute("modifiers")]
public MapModifiers Modifiers;
public Redirect redirect;
}
[Flags]
public enum MapModifiers
{
[XmlEnum("public")]
Public = Modifiers.Public,
[XmlEnum("protected")]
Protected = Modifiers.Protected,
[XmlEnum("final")]
Final = Modifiers.Final,
[XmlEnum("interface")]
Interface = Modifiers.Interface,
[XmlEnum("static")]
Static = Modifiers.Static
}
[XmlType("class")]
public class Class
{
[XmlAttribute("name")]
public string Name;
[XmlAttribute("type")]
public string Type;
[XmlAttribute("modifiers")]
public MapModifiers Modifiers;
[XmlElement("constructor")]
public Constructor[] Constructors;
[XmlElement("method")]
public Method[] Methods;
[XmlElement("field")]
public Field[] Fields;
}
[XmlRoot("root")]
public class Root
{
public Class[] remappings;
public Class[] nativeMethods;
}
}

2185
IK.VM.NET/verifier.cs Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

195
IK.VM.NET/vm.cs Normal file
Просмотреть файл

@ -0,0 +1,195 @@
/*
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
*/
using System;
using System.Reflection.Emit;
using System.Reflection;
using System.IO;
using System.Collections;
using System.Xml;
using System.Diagnostics;
public class JVM
{
private static bool debug = false;
private static bool noJniStubs = false;
private static bool isStaticCompiler = false;
public static bool Debug
{
get
{
return debug;
}
set
{
debug = value;
}
}
public static bool NoJniStubs
{
get
{
return noJniStubs;
}
}
public static bool IsStaticCompiler
{
get
{
return isStaticCompiler;
}
}
public static bool CleanStackTraces
{
get
{
return true;
}
}
private class CompilerClassLoader : ClassLoaderWrapper
{
private Hashtable classes;
private string assembly;
private string path;
private AssemblyBuilder assemblyBuilder;
private ModuleBuilder moduleBuilder;
internal CompilerClassLoader(string path, string assembly, Hashtable classes)
: base(null)
{
this.classes = classes;
this.assembly = assembly;
this.path = path;
}
protected override ModuleBuilder CreateModuleBuilder()
{
AssemblyName name = new AssemblyName();
name.Name = assembly;
assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.Save);
CustomAttributeBuilder ikvmAssemblyAttr = new CustomAttributeBuilder(typeof(IKVMAssemblyAttribute).GetConstructor(Type.EmptyTypes), new object[0]);
assemblyBuilder.SetCustomAttribute(ikvmAssemblyAttr);
moduleBuilder = assemblyBuilder.DefineDynamicModule(path, JVM.Debug);
if(JVM.Debug)
{
CustomAttributeBuilder debugAttr = new CustomAttributeBuilder(typeof(DebuggableAttribute).GetConstructor(new Type[] { typeof(bool), typeof(bool) }), new object[] { true, true });
moduleBuilder.SetCustomAttribute(debugAttr);
}
return moduleBuilder;
}
internal override TypeWrapper GetBootstrapType(string name)
{
TypeWrapper type = base.GetBootstrapType(name);
if(type == null)
{
ClassFile f = (ClassFile)classes[name];
if(f != null)
{
type = DefineClass(f);
}
}
return type;
}
internal void SetMain(MethodInfo m, PEFileKinds target)
{
assemblyBuilder.SetEntryPoint(m, target);
}
internal void Save()
{
FinishAll();
assemblyBuilder.Save(path);
}
internal void AddResources(Hashtable resources)
{
foreach(DictionaryEntry d in resources)
{
byte[] buf = (byte[])d.Value;
if(buf.Length > 0)
{
moduleBuilder.DefineInitializedData((string)d.Key, buf, FieldAttributes.Public | FieldAttributes.Static);
}
}
moduleBuilder.CreateGlobalFunctions();
}
}
public static void Compile(string path, string assembly, string mainClass, PEFileKinds target, byte[][] classes, string[] references, bool nojni, Hashtable resources)
{
isStaticCompiler = true;
noJniStubs = nojni;
Hashtable h = new Hashtable();
Console.WriteLine("Parsing class files");
for(int i = 0; i < classes.Length; i++)
{
ClassFile f = new ClassFile(classes[i], 0, classes[i].Length, null);
h[f.Name.Replace('/', '.')] = f;
}
Console.WriteLine("Constructing compiler");
CompilerClassLoader loader = new CompilerClassLoader(path, assembly, h);
ClassLoaderWrapper.SetBootstrapClassLoader(loader);
foreach(string r in references)
{
Assembly.LoadFrom(r);
}
Console.WriteLine("Loading remapped types");
loader.LoadRemappedTypes();
Console.WriteLine("Compiling class files (1)");
foreach(string s in h.Keys)
{
TypeWrapper wrapper = loader.LoadClassByDottedName(s);
if(s == mainClass)
{
MethodWrapper mw = wrapper.GetMethodWrapper(new MethodDescriptor(loader, "main", "([Ljava/lang/String;)V"), false);
if(mw == null)
{
Console.Error.WriteLine("Error: main method not found");
return;
}
MethodInfo method = mw.GetMethod() as MethodInfo;
if(method == null)
{
Console.Error.WriteLine("Error: redirected main method not supported");
return;
}
loader.SetMain(method, target);
}
}
Console.WriteLine("Compiling class files (2)");
loader.AddResources(resources);
loader.Save();
}
public static void SaveDebugImage(object mainClass)
{
ClassLoaderWrapper.SaveDebugImage(mainClass);
}
}

58
awt/AssemblyInfo.cs Normal file
Просмотреть файл

@ -0,0 +1,58 @@
using System.Reflection;
using System.Runtime.CompilerServices;
//
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
//
[assembly: AssemblyTitle("")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
//
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("1.0.*")]
//
// In order to sign your assembly you must specify a key to use. Refer to the
// Microsoft .NET Framework documentation for more information on assembly signing.
//
// Use the attributes below to control which key is used for signing.
//
// Notes:
// (*) If no key is specified, the assembly is not signed.
// (*) KeyName refers to a key that has been installed in the Crypto Service
// Provider (CSP) on your machine. KeyFile refers to a file which contains
// a key.
// (*) If the KeyFile and the KeyName values are both specified, the
// following processing occurs:
// (1) If the KeyName can be found in the CSP, that key is used.
// (2) If the KeyName does not exist and the KeyFile does exist, the key
// in the KeyFile is installed into the CSP and used.
// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
// When specifying the KeyFile, the location of the KeyFile should be
// relative to the project output directory which is
// %Project Directory%\obj\<configuration>. For example, if your KeyFile is
// located in the project directory, you would specify the AssemblyKeyFile
// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
// documentation for more information on this.
//
[assembly: AssemblyDelaySign(false)]
[assembly: AssemblyKeyFile("")]
[assembly: AssemblyKeyName("")]

14
awt/awt.build Normal file
Просмотреть файл

@ -0,0 +1,14 @@
<?xml version="1.0"?>
<project name="awt" default="awt">
<target name="awt">
<csc target="library" output="../bin/awt.dll">
<sources>
<includes name="*.cs" />
</sources>
<references>
<includes name="../bin/classpath.dll" asis="true" />
<includes name="../bin/ik.vm.net.dll" asis="true" />
</references>
</csc>
</target>
</project>

113
awt/awt.csproj Normal file
Просмотреть файл

@ -0,0 +1,113 @@
<VisualStudioProject>
<CSHARP
ProjectType = "Local"
ProductVersion = "7.0.9466"
SchemaVersion = "1.0"
ProjectGuid = "{E00A0FA2-1FD7-4DD9-8C06-7202CE366102}"
>
<Build>
<Settings
ApplicationIcon = ""
AssemblyKeyContainerName = ""
AssemblyName = "awt"
AssemblyOriginatorKeyFile = ""
DefaultClientScript = "JScript"
DefaultHTMLPageLayout = "Grid"
DefaultTargetSchema = "IE50"
DelaySign = "false"
OutputType = "Library"
RootNamespace = "awt"
StartupObject = ""
>
<Config
Name = "Debug"
AllowUnsafeBlocks = "false"
BaseAddress = "285212672"
CheckForOverflowUnderflow = "false"
ConfigurationOverrideFile = ""
DefineConstants = "DEBUG;TRACE"
DocumentationFile = ""
DebugSymbols = "true"
FileAlignment = "4096"
IncrementalBuild = "true"
Optimize = "false"
OutputPath = "bin\Debug\"
RegisterForComInterop = "false"
RemoveIntegerChecks = "false"
TreatWarningsAsErrors = "false"
WarningLevel = "4"
/>
<Config
Name = "Release"
AllowUnsafeBlocks = "false"
BaseAddress = "285212672"
CheckForOverflowUnderflow = "false"
ConfigurationOverrideFile = ""
DefineConstants = "TRACE"
DocumentationFile = ""
DebugSymbols = "false"
FileAlignment = "4096"
IncrementalBuild = "false"
Optimize = "true"
OutputPath = "bin\Release\"
RegisterForComInterop = "false"
RemoveIntegerChecks = "false"
TreatWarningsAsErrors = "false"
WarningLevel = "4"
/>
</Settings>
<References>
<Reference
Name = "System"
AssemblyName = "System"
HintPath = "..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.dll"
/>
<Reference
Name = "System.Data"
AssemblyName = "System.Data"
HintPath = "..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.Data.dll"
/>
<Reference
Name = "System.XML"
AssemblyName = "System.Xml"
HintPath = "..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.XML.dll"
/>
<Reference
Name = "System.Windows.Forms"
AssemblyName = "System.Windows.Forms"
HintPath = "..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.Windows.Forms.dll"
/>
<Reference
Name = "System.Drawing"
AssemblyName = "System.Drawing"
HintPath = "..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.Drawing.dll"
/>
<Reference
Name = "IK.VM.NET"
Project = "{F5C7B588-0403-4AF2-A4DE-5697DE21BC2C}"
Package = "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"
/>
<Reference
Name = "classpath"
AssemblyName = "classpath"
HintPath = "..\classpath\classpath.dll"
/>
</References>
</Build>
<Files>
<Include>
<File
RelPath = "AssemblyInfo.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "toolkit.cs"
SubType = "Code"
BuildAction = "Compile"
/>
</Include>
</Files>
</CSHARP>
</VisualStudioProject>

850
awt/toolkit.cs Normal file
Просмотреть файл

@ -0,0 +1,850 @@
/*
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
*/
using System;
using System.Threading;
using System.Windows.Forms;
using System.Drawing;
using System.ComponentModel;
using java.awt.datatransfer;
using java.awt.image;
using java.awt.peer;
using java.net;
using java.util;
namespace ikvm.awt
{
delegate void SetVoid();
delegate void SetBool(bool b);
delegate void SetXYWH(int x, int y, int w, int h);
delegate void SetString(string s);
delegate string GetString();
delegate void SetStringInt(string s, int i);
public class NetToolkit : java.awt.Toolkit
{
private static java.awt.EventQueue eventQueue = new java.awt.EventQueue();
private static Form bogusForm;
private static Delegate createControlInstance;
private delegate Control CreateControlInstanceDelegate(Type type);
private static void MessageLoop()
{
createControlInstance = new CreateControlInstanceDelegate(CreateControlImpl);
Form form = new Form();
form.CreateControl();
// HACK I have no idea why this line is necessary...
IntPtr p = form.Handle;
bogusForm = form;
Application.Run();
}
private static Control CreateControlImpl(Type type)
{
Control control = (Control)Activator.CreateInstance(type);
control.CreateControl();
// HACK here we go again...
IntPtr p = control.Handle;
return control;
}
internal static Control CreateControl(Type type)
{
return (Control)bogusForm.Invoke(createControlInstance, new object[] { type });
}
public NetToolkit()
{
lock(typeof(NetToolkit))
{
if(bogusForm != null)
{
throw new InvalidOperationException();
}
Thread thread = new Thread(new ThreadStart(MessageLoop));
thread.Start();
// TODO don't use polling...
while(bogusForm == null)
{
Thread.Sleep(1);
}
}
}
protected override java.awt.peer.ButtonPeer createButton(java.awt.Button target)
{
return new NetButtonPeer(target, (Button)CreateControl(typeof(Button)));
}
protected override java.awt.peer.TextFieldPeer createTextField(java.awt.TextField target)
{
return new NetTextFieldPeer(target, (TextBox)CreateControl(typeof(TextBox)));
}
protected override java.awt.peer.LabelPeer createLabel(java.awt.Label target)
{
throw new NotImplementedException();
}
protected override java.awt.peer.ListPeer createList(java.awt.List target)
{
throw new NotImplementedException();
}
protected override java.awt.peer.CheckboxPeer createCheckbox(java.awt.Checkbox target)
{
throw new NotImplementedException();
}
protected override java.awt.peer.ScrollbarPeer createScrollbar(java.awt.Scrollbar target)
{
throw new NotImplementedException();
}
protected override java.awt.peer.ScrollPanePeer createScrollPane(java.awt.ScrollPane target)
{
throw new NotImplementedException();
}
protected override java.awt.peer.TextAreaPeer createTextArea(java.awt.TextArea target)
{
return new NetTextAreaPeer(target, (TextBox)CreateControl(typeof(TextBox)));
}
protected override java.awt.peer.ChoicePeer createChoice(java.awt.Choice target)
{
throw new NotImplementedException();
}
protected override java.awt.peer.FramePeer createFrame(java.awt.Frame target)
{
return new NetFramePeer(target, (Form)CreateControl(typeof(Form)));
}
protected override java.awt.peer.CanvasPeer createCanvas(java.awt.Canvas target)
{
throw new NotImplementedException();
}
protected override java.awt.peer.PanelPeer createPanel(java.awt.Panel target)
{
return new NetPanelPeer(target, (ContainerControl)CreateControl(typeof(ContainerControl)));
}
protected override java.awt.peer.WindowPeer createWindow(java.awt.Window target)
{
throw new NotImplementedException();
}
protected override java.awt.peer.DialogPeer createDialog(java.awt.Dialog target)
{
throw new NotImplementedException();
}
protected override java.awt.peer.MenuBarPeer createMenuBar(java.awt.MenuBar target)
{
throw new NotImplementedException();
}
protected override java.awt.peer.MenuPeer createMenu(java.awt.Menu target)
{
throw new NotImplementedException();
}
protected override java.awt.peer.PopupMenuPeer createPopupMenu(java.awt.PopupMenu target)
{
throw new NotImplementedException();
}
protected override java.awt.peer.MenuItemPeer createMenuItem(java.awt.MenuItem target)
{
throw new NotImplementedException();
}
protected override java.awt.peer.FileDialogPeer createFileDialog(java.awt.FileDialog target)
{
throw new NotImplementedException();
}
protected override java.awt.peer.CheckboxMenuItemPeer createCheckboxMenuItem(java.awt.CheckboxMenuItem target)
{
throw new NotImplementedException();
}
protected override java.awt.peer.FontPeer getFontPeer(string name, int style)
{
throw new NotImplementedException();
}
public override java.awt.Dimension getScreenSize()
{
throw new NotImplementedException();
}
public override int getScreenResolution()
{
throw new NotImplementedException();
}
public override ColorModel getColorModel()
{
throw new NotImplementedException();
}
public override string[] getFontList()
{
throw new NotImplementedException();
}
public override java.awt.FontMetrics getFontMetrics(java.awt.Font font)
{
throw new NotImplementedException();
}
public override void sync()
{
throw new NotImplementedException();
}
public override java.awt.Image getImage(string filename)
{
throw new NotImplementedException();
}
public override java.awt.Image getImage(URL url)
{
throw new NotImplementedException();
}
public override java.awt.Image createImage(string filename)
{
throw new NotImplementedException();
}
public override java.awt.Image createImage(URL url)
{
throw new NotImplementedException();
}
public override bool prepareImage(java.awt.Image image,
int width,
int height,
java.awt.image.ImageObserver observer)
{
throw new NotImplementedException();
}
public override int checkImage(java.awt.Image image,
int width,
int height,
java.awt.image.ImageObserver observer)
{
throw new NotImplementedException();
}
public override java.awt.Image createImage(java.awt.image.ImageProducer producer)
{
throw new NotImplementedException();
}
public override java.awt.Image createImage(sbyte[] imagedata,
int imageoffset,
int imagelength)
{
throw new NotImplementedException();
}
public override java.awt.PrintJob getPrintJob(java.awt.Frame frame,
string jobtitle,
Properties props)
{
throw new NotImplementedException();
}
public override void beep()
{
throw new NotImplementedException();
}
public override java.awt.datatransfer.Clipboard getSystemClipboard()
{
throw new NotImplementedException();
}
protected override java.awt.EventQueue getSystemEventQueueImpl()
{
return eventQueue;
}
public override java.awt.dnd.peer.DragSourceContextPeer createDragSourceContextPeer(java.awt.dnd.DragGestureEvent dge)
{
throw new NotImplementedException();
}
public override Map mapInputMethodHighlight(java.awt.im.InputMethodHighlight highlight)
{
throw new NotImplementedException();
}
}
class NetComponentPeer : ComponentPeer
{
internal readonly java.awt.Component component;
internal readonly Control control;
public NetComponentPeer(java.awt.Component component, Control control)
{
this.control = control;
this.component = component;
java.awt.Container parent = component.getParent();
if(parent != null)
{
control.Parent = ((NetComponentPeer)parent.getPeer()).control;
}
setEnabled(component.isEnabled());
component.invalidate();
//setBounds(component.getX(), component.getY(), component.getWidth(), component.getHeight());
control.Invoke(new SetVoid(Setup));
}
private void Setup()
{
// TODO we really only should hook these events when they are needed...
control.KeyDown += new KeyEventHandler(OnKeyDown);
control.KeyUp += new KeyEventHandler(OnKeyUp);
control.KeyPress += new KeyPressEventHandler(OnKeyPress);
}
private static int MapKeyCode(Keys key)
{
switch(key)
{
default:
return (int)key;
}
}
protected virtual void OnKeyDown(object sender, KeyEventArgs e)
{
// TODO set all this stuff...
long when = 0;
int modifiers = 0;
int keyCode = MapKeyCode(e.KeyCode);
char keyChar = ' ';
int keyLocation = 0;
postEvent(new java.awt.@event.KeyEvent(component, java.awt.@event.KeyEvent.KEY_PRESSED, when, modifiers, keyCode, keyChar, keyLocation));
}
protected virtual void OnKeyUp(object sender, KeyEventArgs e)
{
// TODO set all this stuff...
long when = 0;
int modifiers = 0;
int keyCode = MapKeyCode(e.KeyCode);
char keyChar = ' ';
int keyLocation = 0;
postEvent(new java.awt.@event.KeyEvent(component, java.awt.@event.KeyEvent.KEY_RELEASED, when, modifiers, keyCode, keyChar, keyLocation));
}
protected virtual void OnKeyPress(object sender, KeyPressEventArgs e)
{
// TODO set all this stuff...
long when = 0;
int modifiers = 0;
int keyCode = 0;
char keyChar = e.KeyChar;
int keyLocation = 0;
postEvent(new java.awt.@event.KeyEvent(component, java.awt.@event.KeyEvent.KEY_TYPED, when, modifiers, keyCode, keyChar, keyLocation));
}
protected void postEvent(java.awt.AWTEvent evt)
{
getToolkit().getSystemEventQueue().postEvent(evt);
}
public int checkImage(java.awt.Image img, int width, int height, java.awt.image.ImageObserver ob)
{
throw new NotImplementedException();
}
public java.awt.Image createImage(java.awt.image.ImageProducer prod)
{
throw new NotImplementedException();
}
public java.awt.Image createImage(int width, int height)
{
throw new NotImplementedException();
}
public void disable()
{
throw new NotImplementedException();
}
public void dispose()
{
throw new NotImplementedException();
}
public void enable()
{
throw new NotImplementedException();
}
public ColorModel getColorModel()
{
throw new NotImplementedException();
}
public java.awt.FontMetrics getFontMetrics(java.awt.Font f)
{
throw new NotImplementedException();
}
public java.awt.Graphics getGraphics()
{
throw new NotImplementedException();
}
public java.awt.Point getLocationOnScreen()
{
throw new NotImplementedException();
}
public java.awt.Dimension getMinimumSize()
{
throw new NotImplementedException();
}
public virtual java.awt.Dimension getPreferredSize()
{
Console.WriteLine("NOTE: NetComponentPeer.getPreferredSize not implemented");
return new java.awt.Dimension(0, 0);
}
public java.awt.Toolkit getToolkit()
{
return java.awt.Toolkit.getDefaultToolkit();
}
public void handleEvent(java.awt.AWTEvent e)
{
Console.WriteLine("NOTE: NetComponentPeer.handleEvent not implemented");
}
public void hide()
{
throw new NotImplementedException();
}
public bool isFocusTraversable()
{
throw new NotImplementedException();
}
public java.awt.Dimension minimumSize()
{
throw new NotImplementedException();
}
public java.awt.Dimension preferredSize()
{
Console.WriteLine("NOTE: NetComponentPeer.preferredSize not implemented");
return new java.awt.Dimension(0, 0);
}
public void paint(java.awt.Graphics graphics)
{
throw new NotImplementedException();
}
public bool prepareImage(java.awt.Image img, int width, int height, ImageObserver ob)
{
throw new NotImplementedException();
}
public void print(java.awt.Graphics graphics)
{
throw new NotImplementedException();
}
public void repaint(long tm, int x, int y, int width, int height)
{
throw new NotImplementedException();
}
public void requestFocus()
{
throw new NotImplementedException();
}
public void reshape(int x, int y, int width, int height)
{
throw new NotImplementedException();
}
public void setBackground(java.awt.Color color)
{
throw new NotImplementedException();
}
private void setBoundsImpl(int x, int y, int width, int height)
{
control.SetBounds(x, y, width, height);
}
public void setBounds(int x, int y, int width, int height)
{
control.Invoke(new SetXYWH(setBoundsImpl), new object[] { x, y, width, height });
}
public void setCursor(java.awt.Cursor cursor)
{
throw new NotImplementedException();
}
private void setEnabledImpl(bool enabled)
{
control.Enabled = enabled;
}
public void setEnabled(bool enabled)
{
control.Invoke(new SetBool(setEnabledImpl), new object[] { enabled });
}
public void setFont(java.awt.Font font)
{
throw new NotImplementedException();
}
public void setForeground(java.awt.Color color)
{
throw new NotImplementedException();
}
private void setVisibleImpl(bool visible)
{
control.Visible = visible;
}
public void setVisible(bool visible)
{
control.Invoke(new SetBool(setVisibleImpl), new object[] { visible });
}
public void show()
{
throw new NotImplementedException();
}
public java.awt.GraphicsConfiguration getGraphicsConfiguration()
{
throw new NotImplementedException();
}
public void setEventMask (long mask)
{
Console.WriteLine("NOTE: NetComponentPeer.setEventMask not implemented");
}
}
class NetButtonPeer : NetComponentPeer, ButtonPeer
{
public NetButtonPeer(java.awt.Button awtbutton, Button button)
: base(awtbutton, button)
{
setLabel(awtbutton.getLabel());
control.Invoke(new SetVoid(Setup));
}
private void Setup()
{
((Button)control).Click += new EventHandler(OnClick);
}
private void OnClick(object sender, EventArgs e)
{
// TODO set all these properties correctly
string cmd = "";
long when = 0;
int modifiers = 0;
postEvent(new java.awt.@event.ActionEvent(component, java.awt.@event.ActionEvent.ACTION_PERFORMED, cmd, when, modifiers));
}
private void setLabelImpl(string label)
{
control.Text = label;
}
public void setLabel(string label)
{
control.Invoke(new SetString(setLabelImpl), new object[] { label });
}
public override java.awt.Dimension getPreferredSize()
{
// TODO get the size from somewhere...
return new java.awt.Dimension(80, 15);
}
}
class NetTextComponentPeer : NetComponentPeer, TextComponentPeer
{
public NetTextComponentPeer(java.awt.TextComponent textComponent, TextBox textBox)
: base(textComponent, textBox)
{
}
protected override void OnKeyPress(object sender, KeyPressEventArgs e)
{
base.OnKeyPress(sender, e);
// TODO for TextAreas this probably isn't the right behaviour
if(e.KeyChar == '\r')
{
// TODO set all these properties correctly
string cmd = "";
long when = 0;
int modifiers = 0;
postEvent(new java.awt.@event.ActionEvent(component, java.awt.@event.ActionEvent.ACTION_PERFORMED, cmd, when, modifiers));
}
}
public int getSelectionEnd()
{
throw new NotImplementedException();
}
public int getSelectionStart()
{
throw new NotImplementedException();
}
private string getTextImpl()
{
return control.Text;
}
public string getText()
{
return (string)control.Invoke(new GetString(getTextImpl));
}
private void setTextImpl(string text)
{
control.Text = text;
}
public void setText(string text)
{
control.Invoke(new SetString(setTextImpl), new object[] { text });
}
public void select(int start_pos, int end_pos)
{
throw new NotImplementedException();
}
public void setEditable(bool editable)
{
throw new NotImplementedException();
}
public int getCaretPosition()
{
throw new NotImplementedException();
}
public void setCaretPosition(int pos)
{
throw new NotImplementedException();
}
}
class NetTextFieldPeer : NetTextComponentPeer, TextFieldPeer
{
public NetTextFieldPeer(java.awt.TextField textField, TextBox textBox)
: base(textField, textBox)
{
}
public java.awt.Dimension minimumSize(int len)
{
throw new NotImplementedException();
}
public java.awt.Dimension preferredSize(int len)
{
throw new NotImplementedException();
}
public java.awt.Dimension getMinimumSize(int len)
{
throw new NotImplementedException();
}
public java.awt.Dimension getPreferredSize(int len)
{
TextBox b = (TextBox)control;
// TODO use control.Invoke
return new java.awt.Dimension(200, b.PreferredHeight);
}
public void setEchoChar(char echo_char)
{
throw new NotImplementedException();
}
public void setEchoCharacter(char echo_char)
{
throw new NotImplementedException();
}
}
class NetTextAreaPeer : NetTextComponentPeer, TextAreaPeer
{
public NetTextAreaPeer(java.awt.TextArea textArea, TextBox textBox)
: base(textArea, textBox)
{
control.Invoke(new SetVoid(Setup));
}
private void Setup()
{
((TextBox)control).ReadOnly = !((java.awt.TextArea)component).isEditable();
((TextBox)control).WordWrap = false;
((TextBox)control).ScrollBars = ScrollBars.Both;
((TextBox)control).Multiline = true;
}
private void insertImpl(string text, int pos)
{
((TextBox)control).Text = ((TextBox)control).Text.Insert(pos, text);
}
public void insert(string text, int pos)
{
control.Invoke(new SetStringInt(insertImpl), new Object[] { text, pos });
}
public void insertText(string text, int pos)
{
throw new NotImplementedException();
}
public java.awt.Dimension minimumSize(int rows, int cols)
{
throw new NotImplementedException();
}
public java.awt.Dimension getMinimumSize(int rows, int cols)
{
throw new NotImplementedException();
}
public java.awt.Dimension preferredSize(int rows, int cols)
{
throw new NotImplementedException();
}
public java.awt.Dimension getPreferredSize(int rows, int cols)
{
Console.WriteLine("NOTE: NetTextAreaPeer.getPreferredSize not implemented");
return new java.awt.Dimension(10 * cols, 15 * rows);
}
public void replaceRange(string text, int start_pos, int end_pos)
{
throw new NotImplementedException();
}
public void replaceText(string text, int start_pos, int end_pos)
{
throw new NotImplementedException();
}
}
class NetContainerPeer : NetComponentPeer, ContainerPeer
{
public NetContainerPeer(java.awt.Container awtcontainer, ContainerControl container)
: base(awtcontainer, container)
{
}
public java.awt.Insets insets()
{
throw new NotImplementedException();
}
public virtual java.awt.Insets getInsets()
{
Console.WriteLine("NOTE: NetContainerPeer.getInsets not implemented");
return new java.awt.Insets(0, 0, 0, 0);
}
public void beginValidate()
{
Console.WriteLine("NOTE: NetContainerPeer.beginValidate not implemented");
}
public void endValidate()
{
Console.WriteLine("NOTE: NetContainerPeer.endValidate not implemented");
}
}
class NetPanelPeer : NetContainerPeer, PanelPeer
{
public NetPanelPeer(java.awt.Panel panel, ContainerControl container)
: base(panel, container)
{
}
}
class NetWindowPeer : NetContainerPeer, WindowPeer
{
public NetWindowPeer(java.awt.Window window, Form form)
: base(window, form)
{
}
public void toBack()
{
throw new NotImplementedException();
}
public void toFront()
{
Console.WriteLine("NOTE: NetWindowPeer.toFront not implemented");
}
}
class NetFramePeer : NetWindowPeer, FramePeer
{
public NetFramePeer(java.awt.Frame frame, Form form)
: base(frame, form)
{
setTitle(frame.getTitle());
control.Invoke(new SetVoid(Setup));
}
private void Setup()
{
Form form = (Form)control;
form.Resize += new EventHandler(Resize);
form.Closing += new CancelEventHandler(Closing);
}
private void Closing(object sender, CancelEventArgs e)
{
e.Cancel = true;
postEvent(new java.awt.@event.WindowEvent((java.awt.Window)component, java.awt.@event.WindowEvent.WINDOW_CLOSING));
}
private void Resize(object sender, EventArgs e)
{
// TODO I have no clue what I should do here...
Rectangle r = control.Bounds;
component.setBounds(r.X, r.Y, r.Width, r.Height);
component.invalidate();
component.validate();
postEvent(new java.awt.@event.ComponentEvent(component, java.awt.@event.ComponentEvent.COMPONENT_RESIZED));
}
public void setIconImage(java.awt.Image image)
{
throw new NotImplementedException();
}
public void setMenuBar(java.awt.MenuBar mb)
{
throw new NotImplementedException();
}
public void setResizable(bool resizable)
{
throw new NotImplementedException();
}
private void setTitleImpl(string title)
{
control.Text = title;
}
public void setTitle(string title)
{
control.Invoke(new SetString(setTitleImpl), new object[] { title });
}
public override java.awt.Insets getInsets()
{
// NOTE that we're not returning the "real" insets, but the result is equivalent (I think)
// and it doesn't require me to remap the client coordinates
Rectangle client = control.ClientRectangle;
// TODO use control.Invoke
return new java.awt.Insets(0, 0, control.Height - client.Height, control.Width - client.Width);
}
}
}

Просмотреть файл

@ -0,0 +1,39 @@
# classpath.security
# Copyright (C) 2002 Free Software Foundation, Inc.
#
# This file is part of GNU Classpath.
#
# GNU Classpath is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# GNU Classpath is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GNU Classpath; see the file COPYING. If not, write to the
# Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# 02111-1307 USA.
#
# Linking this library statically or dynamically with other modules is
# making a combined work based on this library. Thus, the terms and
# conditions of the GNU General Public License cover the whole
# combination.
#
# As a special exception, the copyright holders of this library give you
# permission to link this library with independent modules to produce an
# executable, regardless of the license terms of these independent
# modules, and to copy and distribute the resulting executable under
# terms of your choice, provided that you also meet, for each linked
# independent module, the terms and conditions of the license of that
# module. An independent module is a module which is not derived from
# or based on this library. If you modify this library, you may extend
# this exception to your version of the library, but you are not
# obligated to do so. If you do not wish to do so, delete this
# exception statement from your version.
security.provider.1=gnu.java.security.provider.Gnu

Двоичные данные
classpath/System.Xml.jar Normal file

Двоичный файл не отображается.

Двоичные данные
classpath/System.jar Normal file

Двоичный файл не отображается.

1488
classpath/allsources.lst Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

33
classpath/classpath.build Normal file
Просмотреть файл

@ -0,0 +1,33 @@
<?xml version="1.0"?>
<project name="classpath.dll" default="classpath.dll">
<property name="Classpath.dir" value="/classpath-0.04" />
<target name="jars">
<!-- TODO
<exec program="${nant.project.basedir}/../bin/netexp.exe" commandline="" />
-->
</target>
<target name="classes" depends="jars" description="Classpath + IK.VM.NET specifica Java classes">
<delete>
<fileset basedir="${Classpath.dir}">
<includes name="**.class"/>
</fileset>
</delete>
<delete>
<fileset basedir=".">
<includes name="**.class"/>
</fileset>
</delete>
<property name="classpath" value=".;${Classpath.dir};${Classpath.dir}/vm/reference;mscorlib.jar;System.jar" />
<exec program="jikes.exe" commandline="-classpath ${classpath} @allsources.lst"/>
</target>
<target name="classpath.dll" depends="classes">
<exec program="${nant.project.basedir}/../bin/ikvmc.exe" commandline="-nojni -out:classpath.dll -target:library -recurse:./*.class -recurse:${Classpath.dir}/*.class mscorlib.jar System.jar System.Xml.jar" />
<copy file="classpath.dll" tofile="../bin/classpath.dll.new" />
<exec program="peverify" commandline="../bin/classpath.dll.new" />
<copy file="classpath.dll" todir="../bin" />
<delete file="../bin/classpath.dll.new" />
</target>
</project>

Просмотреть файл

@ -0,0 +1,98 @@
/* gnu.classpath.Configuration
Copyright (C) 1998, 2001 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.classpath;
/**
* This file defines compile-time constants that can be accessed by
* java code. It is pre-processed by configure.
*/
public interface Configuration
{
// TODO
String CLASSPATH_HOME = "";
String CLASSPATH_VERSION = "";
/**
* The value of DEBUG is substituted according to whether the
* "--enable-debug" argument was passed to configure. Code
* which is made conditional based on the value of this flag - typically
* code that generates debugging output - will be removed by the optimizer
* in a non-debug build.
*/
boolean DEBUG = false;
/**
* The value of LOAD_LIBRARY is substituted according to whether the
* "--enable-load-library" or "--disable-load-library" argument was passed
* to configure. By default, configure should define this is as true.
* If set to false, loadLibrary() calls to load native function
* implementations, typically found in static initializers of classes
* which contain native functions, will be omitted. This is useful for
* runtimes which pre-link their native function implementations and do
* not require additional shared libraries to be loaded.
*/
boolean INIT_LOAD_LIBRARY = false;
/**
* Set to true if the VM provides a native method to implement
* Proxy.getProxyClass completely, including argument verification.
* If this is true, HAVE_NATIVE_GET_PROXY_DATA and
* HAVE_NATIVE_GENERATE_PROXY_CLASS should be false.
* @see java.lang.reflect.Proxy
*/
boolean HAVE_NATIVE_GET_PROXY_CLASS = false;
/**
* Set to true if the VM provides a native method to implement
* the first part of Proxy.getProxyClass: generation of the array
* of methods to convert, and verification of the arguments.
* If this is true, HAVE_NATIVE_GET_PROXY_CLASS should be false.
* @see java.lang.reflect.Proxy
*/
boolean HAVE_NATIVE_GET_PROXY_DATA = false;
/**
* Set to true if the VM provides a native method to implement
* the second part of Proxy.getProxyClass: conversion of an array of
* methods into an actual proxy class.
* If this is true, HAVE_NATIVE_GET_PROXY_CLASS should be false.
* @see java.lang.reflect.Proxy
*/
boolean HAVE_NATIVE_GENERATE_PROXY_CLASS = false;
}

Просмотреть файл

@ -0,0 +1,103 @@
/*
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 gnu.java.net.protocol.ikvmres;
import system.io.*;
import system.reflection.*;
import java.net.*;
import java.io.*;
import java.io.IOException;
class IkvmresURLConnection extends URLConnection
{
private InputStream inputStream;
IkvmresURLConnection(URL url)
{
super(url);
doOutput = false;
}
public void connect() throws IOException
{
if(!connected)
{
String assembly = url.getHost();
String resource = url.getFile();
// TODO error handling
FieldInfo fi = Assembly.Load(assembly).GetLoadedModules()[0].GetField(resource);
byte[] b = new byte[system.runtime.interopservices.Marshal.SizeOf(fi.get_FieldType())];
InitArray(b, fi);
inputStream = new ByteArrayInputStream(b);
connected = true;
}
}
private static native void InitArray(byte[] buf, FieldInfo field);
public InputStream getInputStream() throws IOException
{
if(!connected)
{
connect();
}
return inputStream;
}
public OutputStream getOutputStream() throws IOException
{
throw new IOException("resource URLs are read only");
}
public long getLastModified()
{
return -1;
}
public int getContentLength()
{
return -1;
}
}
public class Handler extends URLStreamHandler
{
protected URLConnection openConnection(URL url) throws IOException
{
return new IkvmresURLConnection(url);
}
protected void parseURL(URL url, String url_string, int start, int end)
{
int colon = url_string.indexOf(':', start);
String file = url_string.substring(start, colon);
String assembly = url_string.substring(colon + 1);
setURL(url, "ikvmres", assembly, 0, file, null);
}
protected String toExternalForm(URL url)
{
return "ikvmres:" + url.getFile() + ":" + url.getHost();
}
}

Просмотреть файл

@ -0,0 +1,316 @@
/*
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);
}

Просмотреть файл

@ -0,0 +1,249 @@
/*
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 java.io;
import system.Console;
import system.io.*;
public final class FileDescriptor
{
public static final FileDescriptor in = new FileDescriptor(Console.OpenStandardInput());
public static final FileDescriptor out = new FileDescriptor(Console.OpenStandardOutput());
public static final FileDescriptor err = new FileDescriptor(Console.OpenStandardError());
private Stream stream;
public FileDescriptor()
{
}
private FileDescriptor(Stream stream)
{
this.stream = stream;
}
public synchronized void sync() throws SyncFailedException
{
if(stream == null)
{
throw new SyncFailedException("The handle is invalid");
}
try
{
if(false) throw new system.io.IOException();
stream.Flush();
}
catch(system.io.IOException x)
{
throw new SyncFailedException(x.get_Message());
}
}
public synchronized boolean valid()
{
return stream != null;
}
synchronized void close() throws IOException
{
if(stream != null)
{
// HACK don't close stdin because that throws a NotSupportedException (bug in System.IO.__ConsoleStream)
if(stream != in.stream)
{
try
{
stream.Close();
if(false) throw new system.io.IOException();
}
catch(system.io.IOException x)
{
throw new IOException(x.get_Message());
}
}
stream = null;
}
}
private static String demanglePath(String path)
{
// HACK for some reason Java accepts: \c:\foo.txt
// I don't know what else, but for now lets just support this
if(path.length() > 3 && path.charAt(0) == '\\' && path.charAt(2) == ':')
{
path = path.substring(1);
}
return path;
}
static FileDescriptor open(String name, boolean append, boolean create, boolean read, boolean write) throws FileNotFoundException
{
try
{
if(false) throw new system.io.IOException();
if(false) throw new system.security.SecurityException();
FileStream fs = system.io.File.Open(demanglePath(name),
append ? FileMode.Append : (create ? FileMode.OpenOrCreate : FileMode.Open),
write ? (read ? FileAccess.ReadWrite : FileAccess.Write) : FileAccess.Read, FileShare.ReadWrite);
return new FileDescriptor(fs);
}
catch(system.security.SecurityException x1)
{
throw new SecurityException(x1.get_Message());
}
catch(system.io.IOException x2)
{
throw new FileNotFoundException(x2.get_Message());
}
// TODO map al the other exceptions as well...
}
synchronized long getFilePointer() throws IOException
{
if(stream == null)
{
throw new IOException();
}
try
{
if(false) throw new system.io.IOException();
return stream.get_Position();
}
catch(system.io.IOException x)
{
throw new IOException(x.get_Message());
}
// TODO map al the other exceptions as well...
}
synchronized long getLength() throws IOException
{
if(stream == null)
{
throw new IOException();
}
try
{
if(false) throw new system.io.IOException();
return stream.get_Length();
}
catch(system.io.IOException x)
{
throw new IOException(x.get_Message());
}
// TODO map al the other exceptions as well...
}
synchronized void setLength(long length) throws IOException
{
if(stream == null)
{
throw new IOException();
}
try
{
if(false) throw new system.io.IOException();
stream.SetLength(length);
}
catch(system.io.IOException x)
{
throw new IOException(x.get_Message());
}
// TODO map al the other exceptions as well...
}
synchronized void seek(long pos) throws IOException
{
if(stream == null)
{
throw new IOException();
}
try
{
if(false) throw new system.io.IOException();
stream.Seek(pos, SeekOrigin.Begin);
}
catch(system.io.IOException x)
{
throw new IOException(x.get_Message());
}
// TODO map al the other exceptions as well...
}
synchronized int read(byte[] buf, int offset, int length) throws IOException
{
if(stream == null)
{
throw new IOException();
}
try
{
if(false) throw new system.io.IOException();
return stream.Read(buf, offset, length);
}
catch(system.io.IOException x)
{
throw new IOException(x.get_Message());
}
// TODO map al the other exceptions as well...
}
synchronized void write(byte[] buf, int offset, int length) throws IOException
{
if(stream == null)
{
throw new IOException();
}
try
{
if(false) throw new system.io.IOException();
stream.Write(buf, offset, length);
}
catch(system.io.IOException x)
{
throw new IOException(x.get_Message());
}
// TODO map al the other exceptions as well...
}
synchronized long skip(long n) throws IOException
{
if(stream == null)
{
throw new IOException();
}
try
{
if(false) throw new system.io.IOException();
// TODO this is broken, because non-seekable streams should support skip as well...
// (and I don't think we should seek past EOF here)
stream.Seek(n, SeekOrigin.Current);
return n;
}
catch(system.io.IOException x)
{
throw new IOException(x.get_Message());
}
// TODO map al the other exceptions as well...
}
}

Просмотреть файл

@ -0,0 +1,396 @@
/* FileInputStream.java -- An input stream that reads from disk files.
Copyright (C) 1998 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.io;
import gnu.classpath.Configuration;
import java.nio.channels.FileChannel;
import gnu.java.nio.FileChannelImpl;
/**
* This class is a stream that reads its bytes from a file.
*
* @version 0.0
*
* @author Aaron M. Renn (arenn@urbanophile.com)
*/
public class FileInputStream extends InputStream
{
/*************************************************************************/
/*
* Class Variables and Initializers
*/
static
{
if (Configuration.INIT_LOAD_LIBRARY)
{
System.loadLibrary ("javaio");
}
}
/*************************************************************************/
/*
* Instance Variables
*/
/**
* This is the native file handle for the file this stream is reading from
*/
private FileDescriptor fd;
/*************************************************************************/
/*
* Constructors
*/
/**
* This method initializes a <code>FileInputStream</code> to read from the
* specified named file. A security check is first made to determine
* whether or not access to this file is allowed. This is done by
* calling the <code>checkRead()</code> method of the <code>SecurityManager</code>
* (if one exists) with the name of this file. An exception is thrown
* if reading is not allowed. If the file does not exist, an exception
* is also thrown.
*
* @param name The name of the file this stream should read from
*
* @exception SecurityException If read access to the file is not allowed
* @exception FileNotFoundException If the file does not exist.
*/
public
FileInputStream(String name) throws SecurityException, FileNotFoundException
{
this(new File(name));
}
/*************************************************************************/
/**
* This method initializes a <code>FileInputStream</code> to read from the
* specified <code>File</code> object. A security check is first made to determine
* whether or not access to this file is allowed. This is done by
* calling the <code>checkRead()</code> method of the <code>SecurityManager</code>
* (if one exists) with the name of this file. An exception is thrown
* if reading is not allowed. If the file does not exist, an exception
* is also thrown.
*
* @param file The <code>File</code> object this stream should read from
*
* @exception SecurityException If read access to the file is not allowed
* @exception FileNotFoundException If the file does not exist.
*/
public
FileInputStream(File file) throws SecurityException, FileNotFoundException
{
// Talk about the lazy man's way out. The File.exists() method does
// a security check so don't repeat it here.
if (!file.exists())
throw new FileNotFoundException(file.getName());
fd = FileDescriptor.open(file.getPath(), false, false, true, false);
}
/*************************************************************************/
/**
* This method initializes a <code>FileInputStream</code> to read from the
* specified <code>FileDescriptor</code> object. A security check is first made to
* determine whether or not access to this file is allowed. This is done by
* calling the <code>checkRead()</code> method of the <code>SecurityManager</code>
* (if one exists) with the specified <code>FileDescriptor</code> An exception is
* thrown if reading is not allowed.
*
* @param fd The <code>FileDescriptor</code> object this stream should read from
*
* @exception SecurityException If read access to the file is not allowed
*/
public
FileInputStream(FileDescriptor fd) throws SecurityException
{
// Hmmm, no other exception but this one to throw, but if the descriptor
// isn't valid, we surely don't have "permission" to read from it.
if (!fd.valid())
throw new SecurityException("Invalid FileDescriptor");
SecurityManager sm = System.getSecurityManager();
if (sm != null)
sm.checkRead(fd);
this.fd = fd;
}
/*************************************************************************/
/*
* Instance Methods
*/
/**
* This method returns a <code>FileDescriptor</code> object representing the
* underlying native file handle of the file this stream is reading
* from
*
* @return A <code>FileDescriptor</code> for this stream
*
* @exception IOException If an error occurs
*/
public final FileDescriptor
getFD() throws IOException
{
return fd;
}
/*************************************************************************/
/**
* This method returns the number of bytes that can be read from this
* stream before a read can block. A return of 0 indicates that blocking
* might (or might not) occur on the very next read attempt.
* <p>
* This method returns the number of unread bytes remaining in the file if
* the descriptor being read from is an actual file. If this method is
* reading from a ''special'' file such a the standard input, this method
* will return the appropriate value for the stream being read.
* <p>
* Be aware that reads on plain files that do not reside locally might
* possibly block even if this method says they should not. For example,
* a remote server might crash, preventing an NFS mounted file from being
* read.
*
* @return The number of bytes that can be read before blocking could occur
*
* @exception IOException If an error occurs
*/
public int
available() throws IOException
{
int retval = (int)(fd.getLength() - fd.getFilePointer());
if (retval <= 0)
return(0);
return(retval);
}
/*************************************************************************/
/**
* This method skips the specified number of bytes in the stream. It
* returns the actual number of bytes skipped, which may be less than the
* requested amount.
* <p>
* This method reads and discards bytes into a 256 byte array until the
* specified number of bytes were skipped or until either the end of stream
* is reached or a read attempt returns a short count. Subclasses can
* override this metho to provide a more efficient implementation where
* one exists.
*
* @param num_bytes The requested number of bytes to skip
*
* @return The actual number of bytes skipped.
*
* @exception IOException If an error occurs
*/
public long
skip(long num_bytes) throws IOException
{
if (num_bytes <= 0)
return(0);
if (num_bytes > available())
num_bytes = available();
long bytes_skipped = fd.skip(num_bytes);
return(bytes_skipped);
}
/*************************************************************************/
/**
* This method reads an unsigned byte from the input stream and returns it
* as an int in the range of 0-255. This method also will return -1 if
* the end of the stream has been reached.
* <p>
* This method will block until the byte can be read.
*
* @return The byte read or -1 if end of stream
*
* @exception IOException If an error occurs
*/
public int
read() throws IOException
{
byte[] buf = new byte[1];
int bytes_read = fd.read(buf, 0, buf.length);
if (bytes_read == 0)
return(-1);
if (bytes_read == -1)
return(-1);
return((buf[0] & 0xFF));
}
/*************************************************************************/
/**
* This method reads bytes from a stream and stores them into a caller
* supplied buffer. This method attempts to completely fill the buffer,
* but can return before doing so. The actual number of bytes read is
* returned as an int. A -1 is returned to indicate the end of the stream.
* <p>
* This method will block until some data can be read.
* <p>
* This method operates by calling an overloaded read method like so:
* <code>read(buf, 0, buf.length)</code>
*
* @param buf The buffer into which the bytes read will be stored.
*
* @return The number of bytes read or -1 if end of stream.
*
* @exception IOException If an error occurs.
*/
public int
read(byte[] buf) throws IOException
{
return(read(buf, 0, buf.length));
}
/*************************************************************************/
/**
* This method read bytes from a stream and stores them into a caller
* supplied buffer. It starts storing the data at index <code>offset</code> into
* the buffer and attempts to read <code>len</code> bytes. This method can
* return before reading the number of bytes requested. The actual number
* of bytes read is returned as an int. A -1 is returned to indicate the
* end of the stream.
* <p>
* This method will block until some data can be read.
*
* @param buf The array into which the bytes read should be stored
* @param offset The offset into the array to start storing bytes
* @param len The requested number of bytes to read
*
* @return The actual number of bytes read, or -1 if end of stream.
*
* @exception IOException If an error occurs.
*/
public int
read(byte[] buf, int offset, int len) throws IOException
{
if (len == 0)
return(0);
int bytes_read = fd.read(buf, offset, len);
if (bytes_read == 0)
return(-1);
if (bytes_read == -1)
return(-1);
return(bytes_read);
}
/*************************************************************************/
/**
* This method closes the stream. Any futher attempts to read from the
* stream will likely generate an IOException since the underlying file
* will be closed.
*
* @exception IOException If an error occurs.
*/
public void
close() throws IOException
{
fd.close();
}
/*************************************************************************/
/**
* This method ensures that the underlying file is closed when this object
* is garbage collected. Since there is a system dependent limit on how
* many files a single process can have open, it is a good idea to close
* streams when they are no longer needed rather than waiting for garbage
* collectio to automatically close them.
*
* @exception IOException If an error occurs
*/
protected void
finalize() throws IOException
{
if(fd != null)
{
close();
}
}
/*************************************************************************/
/**
* This method creates a java.nio.channels.FileChannel.
* Nio does not allow one to create a file channel directly.
* A file channel must be created by first creating an instance of
* Input/Output/RandomAccessFile and invoking the getChannel() method on it.
*/
private FileChannel ch; /* cached associated file-channel */
public FileChannel
getChannel()
{
synchronized (this)
{
// if (ch == null)
// ch = new gnu.java.nio.FileChannelImpl(native_fd,
// this);
}
return ch;
}
} // class FileInputStream

Просмотреть файл

@ -0,0 +1,339 @@
/* FileOutputStream.java -- Writes to a file on disk.
Copyright (C) 1998, 2001 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.io;
import gnu.classpath.Configuration;
import java.nio.channels.FileChannel;
import gnu.java.nio.FileChannelImpl;
/**
* This classes allows a stream of data to be written to a disk file or
* any open <code>FileDescriptor</code>.
*
* @version 0.0
*
* @author Aaron M. Renn (arenn@urbanophile.com)
*/
public class FileOutputStream extends OutputStream
{
/*************************************************************************/
/*
* Class Variables and Initializers
*/
static
{
if (Configuration.INIT_LOAD_LIBRARY)
{
System.loadLibrary ("javaio");
}
}
/*************************************************************************/
/*
* Instance Variables
*/
/**
* This is the native file handle
*/
private FileDescriptor fd;
/*************************************************************************/
/*
* Constructors
*/
/**
* This method initializes a <code>FileOutputStream</code> object to write
* to the named file. The file is created if it does not exist, and
* the bytes written are written starting at the beginning of the file.
* <p>
* Before opening a file, a security check is performed by calling the
* <code>checkWrite</code> method of the <code>SecurityManager</code> (if
* one exists) with the name of the file to be opened. An exception is
* thrown if writing is not allowed.
*
* @param name The name of the file this stream should write to
*
* @exception SecurityException If write access to the file is not allowed
* @exception IOException If a non-security error occurs
*/
public
FileOutputStream(String name) throws SecurityException, IOException
{
this(name, false);
}
/*************************************************************************/
/**
* This method initializes a <code>FileOutputStream</code> object to write
* to the specified <code>File</code> object. The file is created if it
* does not exist, and the bytes written are written starting at the
* beginning of the file.
* <p>
* Before opening a file, a security check is performed by calling the
* <code>checkWrite</code> method of the <code>SecurityManager</code> (if
* one exists) with the name of the file to be opened. An exception is
* thrown if writing is not allowed.
*
* @param file The <code>File</code> object this stream should write to
*
* @exception SecurityException If write access to the file is not allowed
* @exception IOException If a non-security error occurs
*/
public
FileOutputStream(File file) throws SecurityException, IOException
{
this(file.getPath(), false);
}
/*************************************************************************/
/**
* This method initializes a <code>FileOutputStream</code> object to write
* to the named file. The file is created if it does not exist, and
* the bytes written are written starting at the beginning of the file if
* the <code>append</code> argument is <code>false</code> or at the end
* of the file if the <code>append</code> argument is true.
* <p>
* Before opening a file, a security check is performed by calling the
* <code>checkWrite</code> method of the <code>SecurityManager</code> (if
* one exists) with the name of the file to be opened. An exception is
* thrown if writing is not allowed.
*
* @param name The name of the file this stream should write to
* @param append <code>true</code> to append bytes to the end of the file, or <code>false</code> to write bytes to the beginning
*
* @exception SecurityException If write access to the file is not allowed
* @exception IOException If a non-security error occurs
*/
public
FileOutputStream(String name, boolean append) throws SecurityException,
IOException
{
SecurityManager sm = System.getSecurityManager();
if (sm != null)
{
// try
// {
sm.checkWrite(name);
// }
// catch(AccessControlException e)
// {
// throw new SecurityException(e.getMessage());
// }
}
fd = FileDescriptor.open((new File(name)).getAbsolutePath(), append, true, false, true);
}
/*************************************************************************/
/**
* This method initializes a <code>FileOutputStream</code> object to write
* to the file represented by the specified <code>FileDescriptor</code>
* object. This method does not create any underlying disk file or
* reposition the file pointer of the given descriptor. It assumes that
* this descriptor is ready for writing as is.
* <p>
* Before opening a file, a security check is performed by calling the
* <code>checkWrite</code> method of the <code>SecurityManager</code> (if
* one exists) with the specified <code>FileDescriptor</code> as an argument.
* An exception is thrown if writing is not allowed.
*
* @param file The <code>FileDescriptor</code> this stream should write to
*
* @exception SecurityException If write access to the file is not allowed
*/
public
FileOutputStream(FileDescriptor fd) throws SecurityException
{
// Hmm, no other exception but this one to throw, but if the descriptor
// isn't valid, we surely don't have "permission" to write to it.
if (!fd.valid())
throw new SecurityException("Invalid FileDescriptor");
SecurityManager sm = System.getSecurityManager();
if (sm != null)
{
// try
// {
// sm.checkWrite(fd);
// }
// catch(AccessControlException e)
// {
// throw new SecurityException(e.getMessage());
// }
}
this.fd = fd;
}
/*************************************************************************/
/**
* This method returns a <code>FileDescriptor</code> object representing
* the file that is currently being written to
*
* @return A <code>FileDescriptor</code> object for this stream
*
* @exception IOException If an error occurs
*/
public final FileDescriptor
getFD() throws IOException
{
return fd;
}
/*************************************************************************/
/**
* This method writes a single byte of data to the file.
*
* @param b The byte of data to write, passed as an <code>int</code>
*
* @exception IOException If an error occurs
*/
public void
write(int b) throws IOException
{
byte[] buf = new byte[1];
buf[0] = (byte)(b & 0xFF);
fd.write(buf, 0, buf.length);
}
/*************************************************************************/
/**
* This method writes all the bytes in the specified array to the
* file.
*
* @param buf The array of bytes to write to the file
*
* @exception IOException If an error occurs
*/
public void
write(byte[] buf) throws IOException
{
fd.write(buf, 0, buf.length);
}
/*************************************************************************/
/**
* This method writes <code>len</code> bytes from the byte array
* <code>buf</code> to the file starting at index <code>offset</code>.
*
* @param buf The array of bytes to write to the file
* @param offset The offset into the array to start writing bytes from
* @param len The number of bytes to write to the file
*
* @exception IOException If an error occurs
*/
public void
write(byte[] buf, int offset, int len) throws IOException
{
fd.write(buf, offset, len);
}
/*************************************************************************/
/**
* This method closes the underlying file. Any further attempts to
* write to this stream will likely generate an exception since the
* file is closed.
*
* @exception IOException If an error occurs
*/
public void
close() throws IOException
{
fd.close();
}
/*************************************************************************/
/**
* This method closes the stream when this object is being garbage
* collected.
*
* @exception IOException If an error occurs (ignored by the Java runtime)
*/
protected void
finalize() throws IOException
{
if(fd != null)
{
close();
}
}
/*************************************************************************/
/**
* This method creates a java.nio.channels.FileChannel.
* Nio does not allow one to create a file channel directly.
* A file channel must be created by first creating an instance of
* Input/Output/RandomAccessFile and invoking the getChannel() method on it.
*/
private FileChannel ch; /* cached associated file-channel */
public FileChannel
getChannel()
{
synchronized (this)
{
// if (ch == null)
// ch = new gnu.java.nio.FileChannelImpl(native_fd,
// this);
}
return ch;
}
} // class FileOutputStream

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,271 @@
/* VMClassLoader.java -- Reference implementation of native interface
required by ClassLoader
Copyright (C) 1998, 2001, 2002 Free Software Foundation
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.lang;
import java.security.ProtectionDomain;
import java.net.URL;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Map;
import java.util.HashMap;
import system.*;
import system.reflection.*;
/**
* java.lang.VMClassLoader is a package-private helper for VMs to implement
* on behalf of java.lang.ClassLoader.
*
* @author John Keiser
* @author Mark Wielaard <mark@klomp.org>
* @author Eric Blake <ebb9@email.byu.edu>
*/
final class VMClassLoader
{
/**
* Helper to define a class using a string of bytes. This assumes that
* the security checks have already been performed, if necessary.
* <strong>This method will be removed in a future version of GNU
* Classpath</strong>.
*
* @param name the name to give the class, or null if unknown
* @param data the data representing the classfile, in classfile format
* @param offset the offset into the data where the classfile starts
* @param len the length of the classfile data in the array
* @return the class that was defined
* @throws ClassFormatError if data is not in proper classfile format
* @deprecated Implement
* {@link #defineClass(ClassLoader, String, byte[], int, int, ProtectionDomain)}
* instead.
*/
static final Class defineClass(ClassLoader cl, String name, byte[] data, int offset, int len) throws ClassFormatError
{
return defineClass(cl, name, data, offset, len, null);
}
/**
* Helper to define a class using a string of bytes. This assumes that
* the security checks have already been performed, if necessary.
*
* <strong>For backward compatibility, this just ignores the protection
* domain; that is the wrong behavior, and you should directly implement
* this method natively if you can.</strong>
*
* @param name the name to give the class, or null if unknown
* @param data the data representing the classfile, in classfile format
* @param offset the offset into the data where the classfile starts
* @param len the length of the classfile data in the array
* @param pd the protection domain
* @return the class that was defined
* @throws ClassFormatError if data is not in proper classfile format
*/
static final native Class defineClass(ClassLoader cl, String name, byte[] data, int offset, int len, ProtectionDomain pd)
throws ClassFormatError;
/**
* Helper to resolve all references to other classes from this class.
*
* @param c the class to resolve
*/
static final void resolveClass(Class c)
{
// TODO
}
/**
* Helper to load a class from the bootstrap class loader.
*
* @param name the class name to load
* @param resolve whether to resolve it
* @return the class, loaded by the bootstrap classloader
*/
static Class loadClass(String name, boolean resolve) throws ClassNotFoundException
{
Class c = Class.loadBootstrapClass(name, false);
if(c == null)
{
throw new ClassNotFoundException(name);
}
return c;
}
/**
* Helper to load a resource from the bootstrap class loader.
*
* XXX - Not implemented yet; this requires native help.
*
* @param name the resource to find
* @return the URL to the resource
*/
static URL getResource(String name)
{
try
{
Assembly assembly = findResourceAssembly(name);
if(assembly != null)
{
return new URL("ikvmres:" + name + ":" + assembly.get_FullName());
}
}
catch(java.net.MalformedURLException x)
{
}
return null;
}
private static native Assembly findResourceAssembly(String name);
/**
* Helper to get a list of resources from the bootstrap class loader.
*
* XXX - Not implemented yet; this requires native help.
*
* @param name the resource to find
* @return an enumeration of resources
* @throws IOException if one occurs
*/
static Enumeration getResources(String name) throws IOException
{
System.out.println("*** VMClassLoader.getResources: " + name);
// TODO
return new java.util.Vector(0).elements();
//return ClassLoader.getSystemResources(name);
}
/**
* Helper to get a package from the bootstrap class loader. The default
* implementation of returning null may be adequate, or you may decide
* that this needs some native help.
*
* @param name the name to find
* @return the named package, if it exists
*/
static Package getPackage(String name)
{
return null;
}
/**
* Helper to get all packages from the bootstrap class loader. The default
* implementation of returning an empty array may be adequate, or you may
* decide that this needs some native help.
*
* @return all named packages, if any exist
*/
static Package[] getPackages()
{
return new Package[0];
}
/**
* Helper for java.lang.Integer, Byte, etc to get the TYPE class
* at initialization time. The type code is one of the chars that
* represents the primitive type as in JNI.
*
* <ul>
* <li>'Z' - boolean</li>
* <li>'B' - byte</li>
* <li>'C' - char</li>
* <li>'D' - double</li>
* <li>'F' - float</li>
* <li>'I' - int</li>
* <li>'J' - long</li>
* <li>'S' - short</li>
* <li>'V' - void</li>
* </ul>
*
* Note that this is currently a java version that converts the type code
* to a string and calls the native <code>getPrimitiveClass(String)</code>
* method for backwards compatibility with VMs that used old versions of
* GNU Classpath. Please replace this method with a native method
* <code>final static native Class getPrimitiveClass(char type);</code>
* if your VM supports it. <strong>The java version of this method and
* the String version of this method will disappear in a future version
* of GNU Classpath</strong>.
*
* @param type the primitive type
* @return a "bogus" class representing the primitive type
*/
static final Class getPrimitiveClass(char type)
{
return Class.getClassFromType(getPrimitiveType(type));
}
private static native system.Type getPrimitiveType(char type);
/**
* The system default for assertion status. This is used for all system
* classes (those with a null ClassLoader), as well as the initial value for
* every ClassLoader's default assertion status.
*
* XXX - Not implemented yet; this requires native help.
*
* @return the system-wide default assertion status
*/
static final boolean defaultAssertionStatus()
{
return true;
}
/**
* The system default for package assertion status. This is used for all
* ClassLoader's packageAssertionStatus defaults. It must be a map of
* package names to Boolean.TRUE or Boolean.FALSE, with the unnamed package
* represented as a null key.
*
* XXX - Not implemented yet; this requires native help.
*
* @return a (read-only) map for the default packageAssertionStatus
*/
static final Map packageAssertionStatus()
{
return new HashMap();
}
/**
* The system default for class assertion status. This is used for all
* ClassLoader's classAssertionStatus defaults. It must be a map of
* class names to Boolean.TRUE or Boolean.FALSE
*
* XXX - Not implemented yet; this requires native help.
*
* @return a (read-only) map for the default classAssertionStatus
*/
static final Map classAssertionStatus()
{
return new HashMap();
}
}

Просмотреть файл

@ -0,0 +1,282 @@
/* java.lang.reflect.Constructor - reflection of Java constructors
Copyright (C) 1998, 2001 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.lang.reflect;
import system.*;
import system.reflection.*;
/**
* The Constructor class represents a constructor of a class. It also allows
* dynamic creation of an object, via reflection. Invocation on Constructor
* objects knows how to do widening conversions, but throws
* {@link IllegalArgumentException} if a narrowing conversion would be
* necessary. You can query for information on this Constructor regardless
* of location, but construction access may be limited by Java language
* access controls. If you can't do it in the compiler, you can't normally
* do it here either.<p>
*
* <B>Note:</B> This class returns and accepts types as Classes, even
* primitive types; there are Class types defined that represent each
* different primitive type. They are <code>java.lang.Boolean.TYPE,
* java.lang.Byte.TYPE,</code>, also available as <code>boolean.class,
* byte.class</code>, etc. These are not to be confused with the
* classes <code>java.lang.Boolean, java.lang.Byte</code>, etc., which are
* real classes.<p>
*
* Also note that this is not a serializable class. It is entirely feasible
* to make it serializable using the Externalizable interface, but this is
* on Sun, not me.
*
* @author John Keiser
* @author Eric Blake <ebb9@email.byu.edu>
* @see Member
* @see Class
* @see java.lang.Class#getConstructor(Object[])
* @see java.lang.Class#getDeclaredConstructor(Object[])
* @see java.lang.Class#getConstructors()
* @see java.lang.Class#getDeclaredConstructors()
* @since 1.1
* @status updated to 1.4
*/
public final class Constructor
extends AccessibleObject implements Member
{
private Class clazz;
private Object methodCookie;
/**
* This class is instantiated by java.lang.Class
*/
// TODO this constructor shouldn't be public (but it needs to be accessible to java.lang.Class)
public Constructor(Class declaringClass, Object methodCookie)
{
this.clazz = declaringClass;
this.methodCookie = methodCookie;
}
/**
* Gets the class that declared this constructor.
* @return the class that declared this member
*/
public Class getDeclaringClass()
{
return clazz;
}
/**
* Gets the name of this constructor (the non-qualified name of the class
* it was declared in).
* @return the name of this constructor
*/
public String getName()
{
return Method.GetName(methodCookie);
}
/**
* Gets the modifiers this constructor uses. Use the <code>Modifier</code>
* class to interpret the values. A constructor can only have a subset of the
* following modifiers: public, private, protected.
*
* @return an integer representing the modifiers to this Member
* @see Modifier
*/
public int getModifiers()
{
return Method.GetModifiers(methodCookie);
}
/**
* Get the parameter list for this constructor, in declaration order. If the
* constructor takes no parameters, returns a 0-length array (not null).
*
* @return a list of the types of the constructor's parameters
*/
public Class[] getParameterTypes()
{
Object[] params = Method.GetParameterTypes(methodCookie);
Class[] paramsClass = new Class[params.length];
System.arraycopy(params, 0, paramsClass, 0, params.length);
return paramsClass;
}
/**
* Get the exception types this constructor says it throws, in no particular
* order. If the constructor has no throws clause, returns a 0-length array
* (not null).
*
* @return a list of the types in the constructor's throws clause
*/
public Class[] getExceptionTypes()
{
Object[] ex = Method.GetExceptionTypes(methodCookie);
Class[] exc = new Class[ex.length];
System.arraycopy(ex, 0, exc, 0, ex.length);
return exc;
}
/**
* Compare two objects to see if they are semantically equivalent.
* Two Constructors are semantically equivalent if they have the same
* declaring class and the same parameter list. This ignores different
* exception clauses, but since you can't create a Method except through the
* VM, this is just the == relation.
*
* @param o the object to compare to
* @return <code>true</code> if they are equal; <code>false</code> if not.
*/
public boolean equals(Object o)
{
if(o instanceof ConstructorInfo)
{
return methodCookie == ((Constructor)o).methodCookie;
}
return false;
}
/**
* Get the hash code for the Constructor. The Constructor hash code is the
* hash code of the declaring class's name.
*
* @return the hash code for the object
*/
public int hashCode()
{
return getDeclaringClass().getName().hashCode();
}
/**
* Get a String representation of the Constructor. A Constructor's String
* representation is "&lt;modifier&gt; &lt;classname&gt;(&lt;paramtypes&gt;)
* throws &lt;exceptions&gt;", where everything after ')' is omitted if
* there are no exceptions.<br> Example:
* <code>public java.io.FileInputStream(java.lang.Runnable)
* throws java.io.FileNotFoundException</code>
*
* @return the String representation of the Constructor
*/
public String toString()
{
StringBuffer sb = new StringBuffer();
Modifier.toString(getModifiers(), sb).append(' ');
sb.append(getDeclaringClass().getName()).append('(');
Class[] c = getParameterTypes();
if (c.length > 0)
{
sb.append(c[0].getName());
for (int i = 1; i < c.length; i++)
sb.append(',').append(c[i].getName());
}
sb.append(')');
c = getExceptionTypes();
if (c.length > 0)
{
sb.append(" throws ").append(c[0].getName());
for (int i = 1; i < c.length; i++)
sb.append(',').append(c[i].getName());
}
return sb.toString();
}
/**
* Create a new instance by invoking the constructor. Arguments are
* automatically unwrapped and widened, if needed.<p>
*
* If this class is abstract, you will get an
* <code>InstantiationException</code>. If the constructor takes 0
* arguments, you may use null or a 0-length array for <code>args</code>.<p>
*
* If this Constructor enforces access control, your runtime context is
* evaluated, and you may have an <code>IllegalAccessException</code> if
* you could not create this object in similar compiled code. If the class
* is uninitialized, you trigger class initialization, which may end in a
* <code>ExceptionInInitializerError</code>.<p>
*
* Then, the constructor is invoked. If it completes normally, the return
* value will be the new object. If it completes abruptly, the exception is
* wrapped in an <code>InvocationTargetException</code>.
*
* @param args the arguments to the constructor
* @return the newly created object
* @throws IllegalAccessException if the constructor could not normally be
* called by the Java code (i.e. it is not public)
* @throws IllegalArgumentException if the number of arguments is incorrect;
* or if the arguments types are wrong even with a widening
* conversion
* @throws InstantiationException if the class is abstract
* @throws InvocationTargetException if the constructor throws an exception
* @throws ExceptionInInitializerError if construction triggered class
* initialization, which then failed
*/
public Object newInstance(Object args[])
throws InstantiationException, IllegalAccessException,
InvocationTargetException
{
return Method.Invoke(methodCookie, null, args);
/*
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);
}
catch(MemberAccessException x1)
{
throw new IllegalAccessException(x1.get_Message());
}
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;
}
*/
}
}

Просмотреть файл

@ -0,0 +1,646 @@
/* java.lang.reflect.Field - reflection of Java fields
Copyright (C) 1998, 2001 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.lang.reflect;
/**
* The Field class represents a member variable of a class. It also allows
* dynamic access to a member, via reflection. This works for both
* static and instance fields. Operations on Field objects know how to
* do widening conversions, but throw {@link IllegalArgumentException} if
* a narrowing conversion would be necessary. You can query for information
* on this Field regardless of location, but get and set access may be limited
* by Java language access controls. If you can't do it in the compiler, you
* can't normally do it here either.<p>
*
* <B>Note:</B> This class returns and accepts types as Classes, even
* primitive types; there are Class types defined that represent each
* different primitive type. They are <code>java.lang.Boolean.TYPE,
* java.lang.Byte.TYPE,</code>, also available as <code>boolean.class,
* byte.class</code>, etc. These are not to be confused with the
* classes <code>java.lang.Boolean, java.lang.Byte</code>, etc., which are
* real classes.<p>
*
* Also note that this is not a serializable class. It is entirely feasible
* to make it serializable using the Externalizable interface, but this is
* on Sun, not me.
*
* @author John Keiser
* @author Eric Blake <ebb9@email.byu.edu>
* @see Member
* @see Class
* @see Class#getField(String)
* @see Class#getDeclaredField(String)
* @see Class#getFields()
* @see Class#getDeclaredFields()
* @since 1.1
* @status updated to 1.4
*/
public final class Field extends AccessibleObject implements Member
{
private Class declaringClass;
private Object fieldCookie;
/**
* This class is uninstantiable except natively.
*/
public Field(Class declaringClass, Object fieldCookie)
{
this.declaringClass = declaringClass;
this.fieldCookie = fieldCookie;
}
/**
* Gets the class that declared this field, or the class where this field
* is a non-inherited member.
* @return the class that declared this member
*/
public Class getDeclaringClass()
{
return declaringClass;
}
/**
* Gets the name of this field.
* @return the name of this field
*/
public String getName()
{
return GetName(fieldCookie);
}
private static native String GetName(Object fieldCookie);
/**
* Gets the modifiers this field uses. Use the <code>Modifier</code>
* class to interpret the values. A field can only have a subset of the
* following modifiers: public, private, protected, static, final,
* transient, and volatile.
*
* @return an integer representing the modifiers to this Member
* @see Modifier
*/
public int getModifiers()
{
return GetModifiers(fieldCookie);
}
private static native int GetModifiers(Object fieldCookie);
/**
* Gets the type of this field.
* @return the type of this field
*/
public Class getType()
{
return (Class)GetFieldType(fieldCookie);
}
private static native Object GetFieldType(Object fieldCookie);
/**
* Compare two objects to see if they are semantically equivalent.
* Two Fields are semantically equivalent if they have the same declaring
* class, name, and type. Since you can't creat a Field except through
* the VM, this is just the == relation.
*
* @param o the object to compare to
* @return <code>true</code> if they are equal; <code>false</code> if not
*/
public boolean equals(Object o)
{
if(o instanceof Field)
{
return fieldCookie == ((Field)o).fieldCookie;
}
return false;
}
/**
* Get the hash code for the Field. The Field hash code is the hash code
* of its name XOR'd with the hash code of its class name.
*
* @return the hash code for the object.
*/
public int hashCode()
{
return getDeclaringClass().getName().hashCode() ^ getName().hashCode();
}
/**
* Get a String representation of the Field. A Field's String
* representation is "&lt;modifiers&gt; &lt;type&gt;
* &lt;class&gt;.&lt;fieldname&gt;".<br> Example:
* <code>public transient boolean gnu.parse.Parser.parseComplete</code>
*
* @return the String representation of the Field
*/
public String toString()
{
StringBuffer sb = new StringBuffer();
Modifier.toString(getModifiers(), sb).append(' ');
sb.append(getType().getName()).append(' ');
sb.append(getDeclaringClass().getName()).append('.');
sb.append(getName());
return sb.toString();
}
/**
* Get the value of this Field. If it is primitive, it will be wrapped
* in the appropriate wrapper type (boolean = java.lang.Boolean).<p>
*
* If the field is static, <code>o</code> will be ignored. Otherwise, if
* <code>o</code> is null, you get a <code>NullPointerException</code>,
* and if it is incompatible with the declaring class of the field, you
* get an <code>IllegalArgumentException</code>.<p>
*
* Next, if this Field enforces access control, your runtime context is
* evaluated, and you may have an <code>IllegalAccessException</code> if
* you could not access this field in similar compiled code. If the field
* is static, and its class is uninitialized, you trigger class
* initialization, which may end in a
* <code>ExceptionInInitializerError</code>.<p>
*
* Finally, the field is accessed, and primitives are wrapped (but not
* necessarily in new objects). This method accesses the field of the
* declaring class, even if the instance passed in belongs to a subclass
* which declares another field to hide this one.
*
* @param o the object to get the value of this Field from
* @return the value of the Field
* @throws IllegalAccessException if you could not normally access this field
* (i.e. it is not public)
* @throws IllegalArgumentException if <code>o</code> is not an instance of
* the class or interface declaring this field
* @throws NullPointerException if <code>o</code> is null and this field
* requires an instance
* @throws ExceptionInInitializerError if accessing a static field triggered
* class initialization, which then failed
* @see #getBoolean(Object)
* @see #getByte(Object)
* @see #getChar(Object)
* @see #getShort(Object)
* @see #getInt(Object)
* @see #getLong(Object)
* @see #getFloat(Object)
* @see #getDouble(Object)
*/
public Object get(Object o)
throws IllegalAccessException
{
return GetValue(fieldCookie, o);
}
private static native Object GetValue(Object fieldCookie, Object o);
/**
* Get the value of this boolean Field. If the field is static,
* <code>o</code> will be ignored.
*
* @param o the object to get the value of this Field from
* @return the value of the Field
* @throws IllegalAccessException if you could not normally access this field
* (i.e. it is not public)
* @throws IllegalArgumentException if this is not a boolean field of
* <code>o</code>, or if <code>o</code> is not an instance of the
* declaring class of this field
* @throws NullPointerException if <code>o</code> is null and this field
* requires an instance
* @throws ExceptionInInitializerError if accessing a static field triggered
* class initialization, which then failed
* @see #get(Object)
*/
public boolean getBoolean(Object o)
throws IllegalAccessException
{
return ((Boolean)get(o)).booleanValue();
}
/**
* Get the value of this byte Field. If the field is static,
* <code>o</code> will be ignored.
*
* @param o the object to get the value of this Field from
* @return the value of the Field
* @throws IllegalAccessException if you could not normally access this field
* (i.e. it is not public)
* @throws IllegalArgumentException if this is not a byte field of
* <code>o</code>, or if <code>o</code> is not an instance of the
* declaring class of this field
* @throws NullPointerException if <code>o</code> is null and this field
* requires an instance
* @throws ExceptionInInitializerError if accessing a static field triggered
* class initialization, which then failed
* @see #get(Object)
*/
public byte getByte(Object o)
throws IllegalAccessException
{
return ((Byte)get(o)).byteValue();
}
/**
* Get the value of this Field as a char. If the field is static,
* <code>o</code> will be ignored.
*
* @throws IllegalAccessException if you could not normally access this field
* (i.e. it is not public)
* @throws IllegalArgumentException if this is not a char field of
* <code>o</code>, or if <code>o</code> is not an instance
* of the declaring class of this field
* @throws NullPointerException if <code>o</code> is null and this field
* requires an instance
* @throws ExceptionInInitializerError if accessing a static field triggered
* class initialization, which then failed
* @see #get(Object)
*/
public char getChar(Object o)
throws IllegalAccessException
{
return ((Character)get(o)).charValue();
}
/**
* Get the value of this Field as a short. If the field is static,
* <code>o</code> will be ignored.
*
* @param o the object to get the value of this Field from
* @return the value of the Field
* @throws IllegalAccessException if you could not normally access this field
* (i.e. it is not public)
* @throws IllegalArgumentException if this is not a byte or short
* field of <code>o</code>, or if <code>o</code> is not an instance
* of the declaring class of this field
* @throws NullPointerException if <code>o</code> is null and this field
* requires an instance
* @throws ExceptionInInitializerError if accessing a static field triggered
* class initialization, which then failed
* @see #get(Object)
*/
public short getShort(Object o)
throws IllegalAccessException
{
return ((Short)get(o)).shortValue();
}
/**
* Get the value of this Field as an int. If the field is static,
* <code>o</code> will be ignored.
*
* @param o the object to get the value of this Field from
* @return the value of the Field
* @throws IllegalAccessException if you could not normally access this field
* (i.e. it is not public)
* @throws IllegalArgumentException if this is not a byte, short, char, or
* int field of <code>o</code>, or if <code>o</code> is not an
* instance of the declaring class of this field
* @throws NullPointerException if <code>o</code> is null and this field
* requires an instance
* @throws ExceptionInInitializerError if accessing a static field triggered
* class initialization, which then failed
* @see #get(Object)
*/
public int getInt(Object o)
throws IllegalAccessException
{
return ((Integer)get(o)).intValue();
}
/**
* Get the value of this Field as a long. If the field is static,
* <code>o</code> will be ignored.
*
* @param o the object to get the value of this Field from
* @return the value of the Field
* @throws IllegalAccessException if you could not normally access this field
* (i.e. it is not public)
* @throws IllegalArgumentException if this is not a byte, short, char, int,
* or long field of <code>o</code>, or if <code>o</code> is not an
* instance of the declaring class of this field
* @throws NullPointerException if <code>o</code> is null and this field
* requires an instance
* @throws ExceptionInInitializerError if accessing a static field triggered
* class initialization, which then failed
* @see #get(Object)
*/
public long getLong(Object o)
throws IllegalAccessException
{
return ((Long)get(o)).longValue();
}
/**
* Get the value of this Field as a float. If the field is static,
* <code>o</code> will be ignored.
*
* @param o the object to get the value of this Field from
* @return the value of the Field
* @throws IllegalAccessException if you could not normally access this field
* (i.e. it is not public)
* @throws IllegalArgumentException if this is not a byte, short, char, int,
* long, or float field of <code>o</code>, or if <code>o</code> is
* not an instance of the declaring class of this field
* @throws NullPointerException if <code>o</code> is null and this field
* requires an instance
* @throws ExceptionInInitializerError if accessing a static field triggered
* class initialization, which then failed
* @see #get(Object)
*/
public float getFloat(Object o)
throws IllegalAccessException
{
return ((Float)get(o)).floatValue();
}
/**
* Get the value of this Field as a double. If the field is static,
* <code>o</code> will be ignored.
*
* @param o the object to get the value of this Field from
* @return the value of the Field
* @throws IllegalAccessException if you could not normally access this field
* (i.e. it is not public)
* @throws IllegalArgumentException if this is not a byte, short, char, int,
* long, float, or double field of <code>o</code>, or if
* <code>o</code> is not an instance of the declaring class of this
* field
* @throws NullPointerException if <code>o</code> is null and this field
* requires an instance
* @throws ExceptionInInitializerError if accessing a static field triggered
* class initialization, which then failed
* @see #get(Object)
*/
public double getDouble(Object o)
throws IllegalAccessException
{
return ((Double)get(o)).doubleValue();
}
/**
* Set the value of this Field. If it is a primitive field, the value
* will be unwrapped from the passed object (boolean = java.lang.Boolean).<p>
*
* If the field is static, <code>o</code> will be ignored. Otherwise, if
* <code>o</code> is null, you get a <code>NullPointerException</code>,
* and if it is incompatible with the declaring class of the field, you
* get an <code>IllegalArgumentException</code>.<p>
*
* Next, if this Field enforces access control, your runtime context is
* evaluated, and you may have an <code>IllegalAccessException</code> if
* you could not access this field in similar compiled code. This also
* occurs whether or not there is access control if the field is final.
* If the field is primitive, and unwrapping your argument fails, you will
* get an <code>IllegalArgumentException</code>; likewise, this error
* happens if <code>value</code> cannot be cast to the correct object type.
* If the field is static, and its class is uninitialized, you trigger class
* initialization, which may end in a
* <code>ExceptionInInitializerError</code>.<p>
*
* Finally, the field is set with the widened value. This method accesses
* the field of the declaring class, even if the instance passed in belongs
* to a subclass which declares another field to hide this one.
*
* @param o the object to set this Field on
* @param value the value to set this Field to
* @throws IllegalAccessException if you could not normally access this field
* (i.e. it is not public)
* @throws IllegalArgumentException if <code>value</code> cannot be
* converted by a widening conversion to the underlying type of
* the Field, or if <code>o</code> is not an instance of the class
* declaring this field
* @throws NullPointerException if <code>o</code> is null and this field
* requires an instance
* @throws ExceptionInInitializerError if accessing a static field triggered
* class initialization, which then failed
* @see #setBoolean(Object, boolean)
* @see #setByte(Object, byte)
* @see #setChar(Object, char)
* @see #setShort(Object, short)
* @see #setInt(Object, int)
* @see #setLong(Object, long)
* @see #setFloat(Object, float)
* @see #setDouble(Object, double)
*/
public void set(Object o, Object value)
throws IllegalAccessException
{
SetValue(fieldCookie, o, value);
}
private static native void SetValue(Object fieldCookie, Object o, Object value);
/**
* Set this boolean Field. If the field is static, <code>o</code> will be
* ignored.
*
* @param o the object to set this Field on
* @param value the value to set this Field to
* @throws IllegalAccessException if you could not normally access this field
* (i.e. it is not public)
* @throws IllegalArgumentException if this is not a boolean field, or if
* <code>o</code> is not an instance of the class declaring this
* field
* @throws NullPointerException if <code>o</code> is null and this field
* requires an instance
* @throws ExceptionInInitializerError if accessing a static field triggered
* class initialization, which then failed
* @see #set(Object, Object)
*/
public void setBoolean(Object o, boolean value)
throws IllegalAccessException
{
set(o, new Boolean(value));
}
/**
* Set this byte Field. If the field is static, <code>o</code> will be
* ignored.
*
* @param o the object to set this Field on
* @param value the value to set this Field to
* @throws IllegalAccessException if you could not normally access this field
* (i.e. it is not public)
* @throws IllegalArgumentException if this is not a byte, short, int, long,
* float, or double field, or if <code>o</code> is not an instance
* of the class declaring this field
* @throws NullPointerException if <code>o</code> is null and this field
* requires an instance
* @throws ExceptionInInitializerError if accessing a static field triggered
* class initialization, which then failed
* @see #set(Object, Object)
*/
public void setByte(Object o, byte value)
throws IllegalAccessException
{
set(o, new Byte(value));
}
/**
* Set this char Field. If the field is static, <code>o</code> will be
* ignored.
*
* @param o the object to set this Field on
* @param value the value to set this Field to
* @throws IllegalAccessException if you could not normally access this field
* (i.e. it is not public)
* @throws IllegalArgumentException if this is not a char, int, long,
* float, or double field, or if <code>o</code> is not an instance
* of the class declaring this field
* @throws NullPointerException if <code>o</code> is null and this field
* requires an instance
* @throws ExceptionInInitializerError if accessing a static field triggered
* class initialization, which then failed
* @see #set(Object, Object)
*/
public void setChar(Object o, char value)
throws IllegalAccessException
{
set(o, new Character(value));
}
/**
* Set this short Field. If the field is static, <code>o</code> will be
* ignored.
*
* @param o the object to set this Field on
* @param value the value to set this Field to
* @throws IllegalAccessException if you could not normally access this field
* (i.e. it is not public)
* @throws IllegalArgumentException if this is not a short, int, long,
* float, or double field, or if <code>o</code> is not an instance
* of the class declaring this field
* @throws NullPointerException if <code>o</code> is null and this field
* requires an instance
* @throws ExceptionInInitializerError if accessing a static field triggered
* class initialization, which then failed
* @see #set(Object, Object)
*/
public void setShort(Object o, short value)
throws IllegalAccessException
{
set(o, new Short(value));
}
/**
* Set this int Field. If the field is static, <code>o</code> will be
* ignored.
*
* @param o the object to set this Field on
* @param value the value to set this Field to
* @throws IllegalAccessException if you could not normally access this field
* (i.e. it is not public)
* @throws IllegalArgumentException if this is not an int, long, float, or
* double field, or if <code>o</code> is not an instance of the
* class declaring this field
* @throws NullPointerException if <code>o</code> is null and this field
* requires an instance
* @throws ExceptionInInitializerError if accessing a static field triggered
* class initialization, which then failed
* @see #set(Object, Object)
*/
public void setInt(Object o, int value)
throws IllegalAccessException
{
set(o, new Integer(value));
}
/**
* Set this long Field. If the field is static, <code>o</code> will be
* ignored.
*
* @param o the object to set this Field on
* @param value the value to set this Field to
* @throws IllegalAccessException if you could not normally access this field
* (i.e. it is not public)
* @throws IllegalArgumentException if this is not a long, float, or double
* field, or if <code>o</code> is not an instance of the class
* declaring this field
* @throws NullPointerException if <code>o</code> is null and this field
* requires an instance
* @throws ExceptionInInitializerError if accessing a static field triggered
* class initialization, which then failed
* @see #set(Object, Object)
*/
public void setLong(Object o, long value)
throws IllegalAccessException
{
set(o, new Long(value));
}
/**
* Set this float Field. If the field is static, <code>o</code> will be
* ignored.
*
* @param o the object to set this Field on
* @param value the value to set this Field to
* @throws IllegalAccessException if you could not normally access this field
* (i.e. it is not public)
* @throws IllegalArgumentException if this is not a float or long field, or
* if <code>o</code> is not an instance of the class declaring this
* field
* @throws NullPointerException if <code>o</code> is null and this field
* requires an instance
* @throws ExceptionInInitializerError if accessing a static field triggered
* class initialization, which then failed
* @see #set(Object, Object)
*/
public void setFloat(Object o, float value)
throws IllegalAccessException
{
set(o, new Float(value));
}
/**
* Set this double Field. If the field is static, <code>o</code> will be
* ignored.
*
* @param o the object to set this Field on
* @param value the value to set this Field to
* @throws IllegalAccessException if you could not normally access this field
* (i.e. it is not public)
* @throws IllegalArgumentException if this is not a double field, or if
* <code>o</code> is not an instance of the class declaring this
* field
* @throws NullPointerException if <code>o</code> is null and this field
* requires an instance
* @throws ExceptionInInitializerError if accessing a static field triggered
* class initialization, which then failed
* @see #set(Object, Object)
*/
public void setDouble(Object o, double value)
throws IllegalAccessException
{
set(o, new Double(value));
}
}

Просмотреть файл

@ -0,0 +1,376 @@
/* java.lang.reflect.Method - reflection of Java methods
Copyright (C) 1998, 2001, 2002 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.lang.reflect;
import system.*;
import system.reflection.*;
/**
* The Method class represents a member method of a class. It also allows
* dynamic invocation, via reflection. This works for both static and
* instance methods. Invocation on Method objects knows how to do
* widening conversions, but throws {@link IllegalArgumentException} if
* a narrowing conversion would be necessary. You can query for information
* on this Method regardless of location, but invocation access may be limited
* by Java language access controls. If you can't do it in the compiler, you
* can't normally do it here either.<p>
*
* <B>Note:</B> This class returns and accepts types as Classes, even
* primitive types; there are Class types defined that represent each
* different primitive type. They are <code>java.lang.Boolean.TYPE,
* java.lang.Byte.TYPE,</code>, also available as <code>boolean.class,
* byte.class</code>, etc. These are not to be confused with the
* classes <code>java.lang.Boolean, java.lang.Byte</code>, etc., which are
* real classes.<p>
*
* Also note that this is not a serializable class. It is entirely feasible
* to make it serializable using the Externalizable interface, but this is
* on Sun, not me.
*
* @author John Keiser
* @author Eric Blake <ebb9@email.byu.edu>
* @see Member
* @see Class
* @see java.lang.Class#getMethod(String,Object[])
* @see java.lang.Class#getDeclaredMethod(String,Object[])
* @see java.lang.Class#getMethods()
* @see java.lang.Class#getDeclaredMethods()
* @since 1.1
* @status updated to 1.4
*/
public final class Method extends AccessibleObject implements Member
{
private Class declaringClass;
private Object methodCookie;
/**
* This class is uninstantiable.
*/
public Method(Class declaringClass, Object methodCookie)
{
this.declaringClass = declaringClass;
this.methodCookie = methodCookie;
}
/**
* Gets the class that declared this method, or the class where this method
* is a non-inherited member.
* @return the class that declared this member
*/
public Class getDeclaringClass()
{
return declaringClass;
}
/**
* Gets the name of this method.
* @return the name of this method
*/
public String getName()
{
return GetName(methodCookie);
}
static native String GetName(Object methodCookie);
/**
* Gets the modifiers this method uses. Use the <code>Modifier</code>
* class to interpret the values. A method can only have a subset of the
* following modifiers: public, private, protected, abstract, static,
* final, synchronized, native, and strictfp.
*
* @return an integer representing the modifiers to this Member
* @see Modifier
*/
public int getModifiers()
{
return GetModifiers(methodCookie);
}
static native int GetModifiers(Object methodCookie);
/**
* Gets the return type of this method.
* @return the type of this method
*/
public Class getReturnType()
{
return (Class)GetReturnType(methodCookie);
}
static native Object GetReturnType(Object methodCookie);
/**
* Get the parameter list for this method, in declaration order. If the
* method takes no parameters, returns a 0-length array (not null).
*
* @return a list of the types of the method's parameters
*/
public Class[] getParameterTypes()
{
Object[] params = GetParameterTypes(methodCookie);
Class[] paramsClass = new Class[params.length];
System.arraycopy(params, 0, paramsClass, 0, params.length);
return paramsClass;
}
static native Object[] GetParameterTypes(Object methodCookie);
/**
* Get the exception types this method says it throws, in no particular
* order. If the method has no throws clause, returns a 0-length array
* (not null).
*
* @return a list of the types in the method's throws clause
*/
public Class[] getExceptionTypes()
{
Object[] ex = GetExceptionTypes(methodCookie);
Class[] exc = new Class[ex.length];
System.arraycopy(ex, 0, exc, 0, ex.length);
return exc;
}
static native Object[] GetExceptionTypes(Object methodCookie);
/**
* Compare two objects to see if they are semantically equivalent.
* Two Methods are semantically equivalent if they have the same declaring
* class, name, and parameter list. This ignores different exception
* clauses or return types.
*
* @param o the object to compare to
* @return <code>true</code> if they are equal; <code>false</code> if not
*/
public boolean equals(Object o)
{
// Implementation note:
// The following is a correct but possibly slow implementation.
//
// This class has a private field 'slot' that could be used by
// the VM implementation to "link" a particular method to a Class.
// In that case equals could be simply implemented as:
//
// if (o instanceof Method)
// {
// Method m = (Method)o;
// return m.declaringClass == this.declaringClass
// && m.slot == this.slot;
// }
// return false;
//
// If a VM uses the Method class as their native/internal representation
// then just using the following would be optimal:
//
// return return this == o;
//
if (!(o instanceof Method))
return false;
Method m = (Method)o;
if(!getName().equals(m.getName()))
return false;
if(declaringClass != m.declaringClass)
return false;
Class[] params1 = getParameterTypes();
Class[] params2 = m.getParameterTypes();
if(params1.length != params2.length)
return false;
for(int i = 0; i < params1.length; i++)
if(params1[i] != params2[i])
return false;
return true;
}
/**
* Get the hash code for the Method. The Method hash code is the hash code
* of its name XOR'd with the hash code of its class name.
*
* @return the hash code for the object
*/
public int hashCode()
{
return getDeclaringClass().getName().hashCode() ^ getName().hashCode();
}
/**
* Get a String representation of the Method. A Method's String
* representation is "&lt;modifiers&gt; &lt;returntype&gt;
* &lt;methodname&gt;(&lt;paramtypes&gt;) throws &lt;exceptions&gt;", where
* everything after ')' is omitted if there are no exceptions.<br> Example:
* <code>public static int run(java.lang.Runnable,int)</code>
*
* @return the String representation of the Method
*/
public String toString()
{
StringBuffer sb = new StringBuffer();
Modifier.toString(getModifiers(), sb).append(' ');
sb.append(getReturnType().getName()).append(' ');
sb.append(getDeclaringClass().getName()).append('.');
sb.append(getName()).append('(');
Class[] c = getParameterTypes();
if (c.length > 0)
{
sb.append(c[0].getName());
for (int i = 1; i < c.length; i++)
sb.append(',').append(c[i].getName());
}
sb.append(')');
c = getExceptionTypes();
if (c.length > 0)
{
sb.append(" throws ").append(c[0].getName());
for (int i = 1; i < c.length; i++)
sb.append(',').append(c[i].getName());
}
return sb.toString();
}
/**
* Invoke the method. Arguments are automatically unwrapped and widened,
* and the result is automatically wrapped, if needed.<p>
*
* If the method is static, <code>o</code> will be ignored. Otherwise,
* the method uses dynamic lookup as described in JLS 15.12.4.4. You cannot
* mimic the behavior of nonvirtual lookup (as in super.foo()). This means
* you will get a <code>NullPointerException</code> if <code>o</code> is
* null, and an <code>IllegalArgumentException</code> if it is incompatible
* with the declaring class of the method. If the method takes 0 arguments,
* you may use null or a 0-length array for <code>args</code>.<p>
*
* Next, if this Method enforces access control, your runtime context is
* evaluated, and you may have an <code>IllegalAccessException</code> if
* you could not acces this method in similar compiled code. If the method
* is static, and its class is uninitialized, you trigger class
* initialization, which may end in a
* <code>ExceptionInInitializerError</code>.<p>
*
* Finally, the method is invoked. If it completes normally, the return value
* will be null for a void method, a wrapped object for a primitive return
* method, or the actual return of an Object method. If it completes
* abruptly, the exception is wrapped in an
* <code>InvocationTargetException</code>.
*
* @param o the object to invoke the method on
* @param args the arguments to the method
* @return the return value of the method, wrapped in the appropriate
* wrapper if it is primitive
* @throws IllegalAccessException if the method could not normally be called
* by the Java code (i.e. it is not public)
* @throws IllegalArgumentException if the number of arguments is incorrect;
* if the arguments types are wrong even with a widening conversion;
* or if <code>o</code> is not an instance of the class or interface
* declaring this method
* @throws InvocationTargetException if the method throws an exception
* @throws NullPointerException if <code>o</code> is null and this field
* requires an instance
* @throws ExceptionInInitializerError if accessing a static method triggered
* class initialization, which then failed
*/
public Object invoke(Object o, Object[] args)
throws IllegalAccessException, InvocationTargetException
{
// TODO
return Invoke(methodCookie, o, args);
/*
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;
}
catch(MemberAccessException x1)
{
throw new IllegalAccessException(x1.get_Message());
}
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);
}

Просмотреть файл

@ -0,0 +1,312 @@
/* PlainDatagramSocketImpl.java -- Default DatagramSocket implementation
Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.net;
import java.io.IOException;
import system.net.*;
import system.net.sockets.*;
/**
* This is the default socket implementation for datagram sockets.
* It makes native calls to C routines that implement BSD style
* SOCK_DGRAM sockets in the AF_INET family.
*
* @version 0.1
*
* @author Aaron M. Renn (arenn@urbanophile.com)
*/
public class PlainDatagramSocketImpl extends DatagramSocketImpl
{
/*
* Static Variables
*/
/**
* Option id for the IP_TTL (time to live) value.
*/
private static final int IP_TTL = 0x1E61; // 7777
/*
* Instance Variables
*/
/**
* This is the actual underlying socket
*/
private UdpClient socket;
/*************************************************************************/
/*
* Constructors
*/
/**
* Default do nothing constructor
*/
public PlainDatagramSocketImpl()
{
}
/*************************************************************************/
/*
* Instance Methods
*/
/**
* Creates a new datagram socket
*
* @exception SocketException If an error occurs
*/
protected void create() throws SocketException
{
}
/*************************************************************************/
/**
* Closes the socket
*/
protected void close()
{
socket.Close();
}
/*************************************************************************/
/**
* Binds this socket to a particular port and interface
*
* @param port The port to bind to
* @param addr The address to bind to
*
* @exception SocketException If an error occurs
*/
protected void bind(int port, InetAddress addr) throws SocketException
{
// TODO error handling
socket = new UdpClient(new IPEndPoint(PlainSocketImpl.getAddressFromInetAddress(addr), port));
}
/*************************************************************************/
/**
* Sends a packet of data to a remote host
*
* @param packet The packet to send
*
* @exception IOException If an error occurs
*/
protected void send(DatagramPacket packet) throws IOException
{
// TODO error handling
int len = packet.getLength();
if(socket.Send(packet.getData(), len, new IPEndPoint(PlainSocketImpl.getAddressFromInetAddress(packet.getAddress()), packet.getPort())) != len)
{
// TODO
throw new IOException();
}
}
/*************************************************************************/
/**
* What does this method really do?
*/
protected int peek(InetAddress addr) throws IOException
{
throw new IOException("Not Implemented Yet");
}
/*************************************************************************/
/**
* Receives a UDP packet from the network
*
* @param packet The packet to fill in with the data received
*
* @exception IOException IOException If an error occurs
*/
protected native void receive(DatagramPacket packet) throws IOException;
/*************************************************************************/
/**
* Joins a multicast group
*
* @param addr The group to join
*
* @exception IOException If an error occurs
*/
protected void join(InetAddress addr) throws IOException
{
System.out.println("PlainDatagramSocketImpl.join not implemented");
throw new IOException("join not implemented");
}
/*************************************************************************/
/**
* Leaves a multicast group
*
* @param addr The group to leave
*
* @exception IOException If an error occurs
*/
protected void leave(InetAddress addr) throws IOException
{
System.out.println("PlainDatagramSocketImpl.leave not implemented");
throw new IOException("leave not implemented");
}
/*************************************************************************/
/**
* Gets the Time to Live value for the socket
*
* @return The TTL value
*
* @exception IOException If an error occurs
*/
protected byte getTTL() throws IOException
{
Object obj = getOption(IP_TTL);
if (!(obj instanceof Integer))
throw new IOException("Internal Error");
return(((Integer)obj).byteValue());
}
/*************************************************************************/
/**
* Sets the Time to Live value for the socket
*
* @param ttl The new TTL value
*
* @exception IOException If an error occurs
*/
protected void setTTL(byte ttl) throws IOException
{
setOption(IP_TTL, new Integer(ttl));
}
/*************************************************************************/
/**
* Gets the Time to Live value for the socket
*
* @return The TTL value
*
* @exception IOException If an error occurs
*/
protected int getTimeToLive() throws IOException
{
Object obj = getOption(IP_TTL);
if (!(obj instanceof Integer))
throw new IOException("Internal Error");
return(((Integer)obj).intValue());
}
/*************************************************************************/
/**
* Sets the Time to Live value for the socket
*
* @param ttl The new TTL value
*
* @exception IOException If an error occurs
*/
protected void setTimeToLive(int ttl) throws IOException
{
setOption(IP_TTL, new Integer(ttl));
}
/*************************************************************************/
/**
* Retrieves the value of an option on the socket
*
* @param option_id The identifier of the option to retrieve
*
* @return The value of the option
*
* @exception SocketException If an error occurs
*/
public Object getOption(int option_id) throws SocketException
{
// TODO
return null;
}
/*************************************************************************/
/**
* Sets the value of an option on the socket
*
* @param option_id The identifier of the option to set
* @param val The value of the option to set
*
* @exception SocketException If an error occurs
*/
public void setOption(int option_id, Object val) throws SocketException
{
// TODO
}
public int peekData(DatagramPacket packet)
{
throw new InternalError ("PlainDatagramSocketImpl::peekData is not implemented");
}
public void joinGroup(SocketAddress address, NetworkInterface netIf)
{
throw new InternalError ("PlainDatagramSocketImpl::joinGroup is not implemented");
}
public void leaveGroup(SocketAddress address, NetworkInterface netIf)
{
throw new InternalError ("PlainDatagramSocketImpl::leaveGroup is not implemented");
}
} // class PlainDatagramSocketImpl

Просмотреть файл

@ -0,0 +1,327 @@
/* PlainSocketImpl.java -- Default socket implementation
Copyright (C) 1998, 1999 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.net;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import system.net.*;
import system.net.sockets.*;
/**
* Unless the application installs its own SocketImplFactory, this is the
* default socket implemetation that will be used. It simply uses a
* combination of Java and native routines to implement standard BSD
* style sockets of family AF_INET and types SOCK_STREAM and SOCK_DGRAM
*
* @version 0.1
*
* @author Aaron M. Renn (arenn@urbanophile.com)
*/
class PlainSocketImpl extends SocketImpl
{
/**
* This is the native file descriptor for this socket
*/
private system.net.sockets.Socket socket;
/**
* Default do nothing constructor
*/
public PlainSocketImpl()
{
}
/**
* Accepts a new connection on this socket and returns in in the
* passed in SocketImpl.
*
* @param impl The SocketImpl object to accept this connection.
*/
protected void accept(SocketImpl impl) throws IOException
{
// TODO catch .NET exceptions
system.net.sockets.Socket accept = socket.Accept();
((PlainSocketImpl)impl).socket = accept;
IPEndPoint remoteEndPoint = ((IPEndPoint)accept.get_RemoteEndPoint());
long remoteIP = remoteEndPoint.get_Address().get_Address();
String remote = (remoteIP & 0xff) + "." + ((remoteIP >> 8) & 0xff) + "." + ((remoteIP >> 16) & 0xff) + "." + ((remoteIP >> 24) & 0xff);
impl.address = InetAddress.getByName(remote);
impl.port = remoteEndPoint.get_Port();
impl.localport = ((IPEndPoint)accept.get_LocalEndPoint()).get_Port();
}
/**
* Returns the number of bytes that the caller can read from this socket
* without blocking.
*
* @return The number of readable bytes before blocking
*
* @exception IOException If an error occurs
*/
protected int available() throws IOException
{
// TODO catch .NET exceptions
return socket.get_Available();
}
/**
* Binds to the specified port on the specified addr. Note that this addr
* must represent a local IP address. **** How bind to INADDR_ANY? ****
*
* @param addr The address to bind to
* @param port The port number to bind to
*
* @exception IOException If an error occurs
*/
protected void bind(InetAddress addr, int port) throws IOException
{
// TODO catch .NET exceptions
socket.Bind(new IPEndPoint(getAddressFromInetAddress(addr), port));
}
static int getAddressFromInetAddress(InetAddress addr)
{
byte[] b = addr.getAddress();
return ((b[3] & 0xff) << 24) + ((b[2] & 0xff) << 16) + ((b[1] & 0xff) << 8) + (b[0] & 0xff);
}
/**
* Closes the socket. This will cause any InputStream or OutputStream
* objects for this Socket to be closed as well.
* <p>
* Note that if the SO_LINGER option is set on this socket, then the
* operation could block.
*
* @exception IOException If an error occurs
*/
protected void close() throws IOException
{
// TODO catch .NET exceptions
socket.Close();
}
/**
* Connects to the remote address and port specified as arguments.
*
* @param addr The remote address to connect to
* @param port The remote port to connect to
*
* @exception IOException If an error occurs
*/
protected void connect(InetAddress addr, int port) throws IOException
{
// TODO error handling
socket.Connect(new IPEndPoint(getAddressFromInetAddress(addr), port));
}
/**
* Connects to the remote hostname and port specified as arguments.
*
* @param hostname The remote hostname to connect to
* @param port The remote port to connect to
*
* @exception IOException If an error occurs
*/
protected void connect(String hostname, int port) throws IOException
{
// TODO error handling
InetAddress addr = InetAddress.getByName(hostname);
connect(addr, port);
}
/**
* Creates a new socket that is not bound to any local address/port and
* is not connected to any remote address/port. This will be created as
* a stream socket if the stream parameter is true, or a datagram socket
* if the stream parameter is false.
*
* @param stream true for a stream socket, false for a datagram socket
*/
protected void create(boolean stream) throws IOException
{
// TODO error handling
if(!stream)
{
// TODO
System.out.println("NOTE: PlainSocketImpl.create(false) not implemented");
throw new IOException("PlainSocketImpl.create(false) not implemented");
}
socket = new system.net.sockets.Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
}
/**
* Starts listening for connections on a socket. The queuelen parameter
* is how many pending connections will queue up waiting to be serviced
* before being accept'ed. If the queue of pending requests exceeds this
* number, additional connections will be refused.
*
* @param queuelen The length of the pending connection queue
*
* @exception IOException If an error occurs
*/
protected void listen(int queuelen) throws IOException
{
// TODO error handling
socket.Listen(queuelen);
localport = ((IPEndPoint)socket.get_LocalEndPoint()).get_Port();
}
/**
* Internal method used by SocketInputStream for reading data from
* the connection. Reads up to len bytes of data into the buffer
* buf starting at offset bytes into the buffer.
*
* @return The actual number of bytes read or -1 if end of stream.
*
* @exception IOException If an error occurs
*/
protected int read(byte[] buf, int offset, int len) throws IOException
{
// TODO error handling
return socket.Receive(buf, offset, len, SocketFlags.None);
}
/**
* Internal method used by SocketOuputStream for writing data to
* the connection. Writes up to len bytes of data from the buffer
* buf starting at offset bytes into the buffer.
*
* @exception IOException If an error occurs
*/
protected void write(byte[] buf, int offset, int len) throws IOException
{
// TODO error handling
socket.Send(buf, offset, len, SocketFlags.None);
}
/**
* Sets the specified option on a socket to the passed in object. For
* options that take an integer argument, the passed in object is an
* Integer. The option_id parameter is one of the defined constants in
* this interface.
*
* @param option_id The identifier of the option
* @param val The value to set the option to
*
* @exception SocketException If an error occurs
*/
public void setOption(int option_id, Object val) throws SocketException
{
switch(option_id)
{
case 0x1006:
// TODO set the timeout
return;
}
// TODO
System.out.println("setOption: " + option_id);
}
/**
* Returns the current setting of the specified option. The Object returned
* will be an Integer for options that have integer values. The option_id
* is one of the defined constants in this interface.
*
* @param option_id The option identifier
*
* @return The current value of the option
*
* @exception SocketException If an error occurs
*/
public Object getOption(int option_id) throws SocketException
{
switch(option_id)
{
case 0x1006:
// TODO get the timeout from somewhere
return new Integer(0);
}
// TODO
System.out.println("getOption: " + option_id);
return null;
}
/**
* Returns an InputStream object for reading from this socket. This will
* be an instance of SocketInputStream.
*
* @return An InputStream
*
* @exception IOException If an error occurs
*/
protected InputStream getInputStream() throws IOException
{
return new SocketInputStream(this);
}
/**
* Returns an OutputStream object for writing to this socket. This will
* be an instance of SocketOutputStream.
*
* @return An OutputStream
*
* @exception IOException If an error occurs
*/
protected OutputStream getOutputStream() throws IOException
{
return new SocketOutputStream(this);
}
public void connect(SocketAddress address, int timeout)
{
throw new InternalError ("PlainSocketImpl::connect not implemented");
}
public void sendUrgentData(int data)
{
throw new InternalError ("PlainSocketImpl::sendUrgentData not implemented");
}
public void shutdownInput()
{
throw new InternalError ("PlainSocketImpl::shutdownInput not implemented");
}
public void shutdownOutput()
{
throw new InternalError ("PlainSocketImpl::shutdownOutput not implemented");
}
} // class PlainSocketImpl

Двоичные данные
classpath/mscorlib.jar Normal file

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1,66 @@
/*
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 sun.misc;
import system.WeakReference;
public abstract class Ref
{
private WeakReference weakRef = new WeakReference(null);
public Object get()
{
Object p = weakRef.get_Target();
if(p == null)
{
synchronized(this)
{
if((p = weakRef.get_Target()) == null)
{
p = reconstitute();
weakRef.set_Target(p);
}
}
}
return p;
}
public abstract Object reconstitute();
public void flush()
{
weakRef.set_Target(null);
}
public void setThing(Object thing)
{
weakRef.set_Target(thing);
}
public Object check()
{
return weakRef.get_Target();
}
}

19
ikvm.build Normal file
Просмотреть файл

@ -0,0 +1,19 @@
<?xml version="1.0"?>
<project name="ikvm" default="all">
<!--
NOTE because of the circular dependencies, we don't use NAnt dependencies,
but some predefined order, that hopefully makes sense.
Please note that, because of the circular dependencies, the BIN directory
needs to contain the IK.VM.NET.dll and classpath.dll binaries, before the project
can be built.
-->
<target name="all">
<nant buildfile="ikvmc/ikvmc.build" />
<nant buildfile="netexp/netexp.build" />
<nant buildfile="ik.vm.jni/ik.vm.jni.build" />
<nant buildfile="ik.vm.net/ik.vm.net.build" />
<nant buildfile="classpath/classpath.build" />
<nant buildfile="ikvm/ikvm.build" />
<nant buildfile="awt/awt.build" />
</target>
</project>

51
ikvm.sln Normal file
Просмотреть файл

@ -0,0 +1,51 @@
Microsoft Visual Studio Solution File, Format Version 7.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IK.VM.NET", "IK.VM.NET\IK.VM.NET.csproj", "{F5C7B588-0403-4AF2-A4DE-5697DE21BC2C}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "IK.VM.JNI", "IK.VM.JNI\IK.VM.JNI.vcproj", "{4D400F9D-68A1-4066-95F6-85AF0E58B710}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ikvm", "ikvm\ikvm.csproj", "{4FBAFF23-1E48-4977-8C50-30F87E70A8B5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "netexp", "netexp\netexp.csproj", "{D2A9434D-59E4-43E9-8D9C-332AA138CEAD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ikvmc", "ikvmc\ikvmc.csproj", "{4CA3F3DF-D2B7-4FA2-874C-BFC4B04286A2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "awt", "awt\awt.csproj", "{E00A0FA2-1FD7-4DD9-8C06-7202CE366102}"
EndProject
Global
GlobalSection(SolutionConfiguration) = preSolution
ConfigName.0 = Debug
ConfigName.1 = Release
EndGlobalSection
GlobalSection(ProjectDependencies) = postSolution
EndGlobalSection
GlobalSection(ProjectConfiguration) = postSolution
{F5C7B588-0403-4AF2-A4DE-5697DE21BC2C}.Debug.ActiveCfg = Debug|.NET
{F5C7B588-0403-4AF2-A4DE-5697DE21BC2C}.Debug.Build.0 = Debug|.NET
{F5C7B588-0403-4AF2-A4DE-5697DE21BC2C}.Release.ActiveCfg = Release|.NET
{F5C7B588-0403-4AF2-A4DE-5697DE21BC2C}.Release.Build.0 = Release|.NET
{4D400F9D-68A1-4066-95F6-85AF0E58B710}.Debug.ActiveCfg = Debug|Win32
{4D400F9D-68A1-4066-95F6-85AF0E58B710}.Debug.Build.0 = Debug|Win32
{4D400F9D-68A1-4066-95F6-85AF0E58B710}.Release.ActiveCfg = Release|Win32
{4D400F9D-68A1-4066-95F6-85AF0E58B710}.Release.Build.0 = Release|Win32
{4FBAFF23-1E48-4977-8C50-30F87E70A8B5}.Debug.ActiveCfg = Debug|.NET
{4FBAFF23-1E48-4977-8C50-30F87E70A8B5}.Debug.Build.0 = Debug|.NET
{4FBAFF23-1E48-4977-8C50-30F87E70A8B5}.Release.ActiveCfg = Release|.NET
{4FBAFF23-1E48-4977-8C50-30F87E70A8B5}.Release.Build.0 = Release|.NET
{D2A9434D-59E4-43E9-8D9C-332AA138CEAD}.Debug.ActiveCfg = Debug|.NET
{D2A9434D-59E4-43E9-8D9C-332AA138CEAD}.Debug.Build.0 = Debug|.NET
{D2A9434D-59E4-43E9-8D9C-332AA138CEAD}.Release.ActiveCfg = Release|.NET
{D2A9434D-59E4-43E9-8D9C-332AA138CEAD}.Release.Build.0 = Release|.NET
{4CA3F3DF-D2B7-4FA2-874C-BFC4B04286A2}.Debug.ActiveCfg = Debug|.NET
{4CA3F3DF-D2B7-4FA2-874C-BFC4B04286A2}.Debug.Build.0 = Debug|.NET
{4CA3F3DF-D2B7-4FA2-874C-BFC4B04286A2}.Release.ActiveCfg = Release|.NET
{4CA3F3DF-D2B7-4FA2-874C-BFC4B04286A2}.Release.Build.0 = Release|.NET
{E00A0FA2-1FD7-4DD9-8C06-7202CE366102}.Debug.ActiveCfg = Debug|.NET
{E00A0FA2-1FD7-4DD9-8C06-7202CE366102}.Debug.Build.0 = Debug|.NET
{E00A0FA2-1FD7-4DD9-8C06-7202CE366102}.Release.ActiveCfg = Release|.NET
{E00A0FA2-1FD7-4DD9-8C06-7202CE366102}.Release.Build.0 = Release|.NET
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
EndGlobalSection
GlobalSection(ExtensibilityAddIns) = postSolution
EndGlobalSection
EndGlobal

81
ikvm/AssemblyInfo.cs Normal file
Просмотреть файл

@ -0,0 +1,81 @@
/*
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
*/
using System.Reflection;
using System.Runtime.CompilerServices;
//
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
//
[assembly: AssemblyTitle("")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
//
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("1.0.*")]
//
// In order to sign your assembly you must specify a key to use. Refer to the
// Microsoft .NET Framework documentation for more information on assembly signing.
//
// Use the attributes below to control which key is used for signing.
//
// Notes:
// (*) If no key is specified, the assembly is not signed.
// (*) KeyName refers to a key that has been installed in the Crypto Service
// Provider (CSP) on your machine. KeyFile refers to a file which contains
// a key.
// (*) If the KeyFile and the KeyName values are both specified, the
// following processing occurs:
// (1) If the KeyName can be found in the CSP, that key is used.
// (2) If the KeyName does not exist and the KeyFile does exist, the key
// in the KeyFile is installed into the CSP and used.
// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
// When specifying the KeyFile, the location of the KeyFile should be
// relative to the project output directory which is
// %Project Directory%\obj\<configuration>. For example, if your KeyFile is
// located in the project directory, you would specify the AssemblyKeyFile
// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
// documentation for more information on this.
//
[assembly: AssemblyDelaySign(false)]
[assembly: AssemblyKeyFile("")]
[assembly: AssemblyKeyName("")]

Просмотреть файл

@ -0,0 +1,39 @@
# classpath.security
# Copyright (C) 2002 Free Software Foundation, Inc.
#
# This file is part of GNU Classpath.
#
# GNU Classpath is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# GNU Classpath is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GNU Classpath; see the file COPYING. If not, write to the
# Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# 02111-1307 USA.
#
# Linking this library statically or dynamically with other modules is
# making a combined work based on this library. Thus, the terms and
# conditions of the GNU General Public License cover the whole
# combination.
#
# As a special exception, the copyright holders of this library give you
# permission to link this library with independent modules to produce an
# executable, regardless of the license terms of these independent
# modules, and to copy and distribute the resulting executable under
# terms of your choice, provided that you also meet, for each linked
# independent module, the terms and conditions of the license of that
# module. An independent module is a module which is not derived from
# or based on this library. If you modify this library, you may extend
# this exception to your version of the library, but you are not
# obligated to do so. If you do not wish to do so, delete this
# exception statement from your version.
security.provider.1=gnu.java.security.provider.Gnu

Просмотреть файл

@ -0,0 +1,39 @@
# classpath.security
# Copyright (C) 2002 Free Software Foundation, Inc.
#
# This file is part of GNU Classpath.
#
# GNU Classpath is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# GNU Classpath is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GNU Classpath; see the file COPYING. If not, write to the
# Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# 02111-1307 USA.
#
# Linking this library statically or dynamically with other modules is
# making a combined work based on this library. Thus, the terms and
# conditions of the GNU General Public License cover the whole
# combination.
#
# As a special exception, the copyright holders of this library give you
# permission to link this library with independent modules to produce an
# executable, regardless of the license terms of these independent
# modules, and to copy and distribute the resulting executable under
# terms of your choice, provided that you also meet, for each linked
# independent module, the terms and conditions of the license of that
# module. An independent module is a module which is not derived from
# or based on this library. If you modify this library, you may extend
# this exception to your version of the library, but you are not
# obligated to do so. If you do not wish to do so, delete this
# exception statement from your version.
security.provider.1=gnu.java.security.provider.Gnu

14
ikvm/ikvm.build Normal file
Просмотреть файл

@ -0,0 +1,14 @@
<?xml version="1.0"?>
<project name="ikvm" default="ikvm">
<target name="ikvm">
<csc target="exe" output="../bin/ikvm.exe">
<sources>
<includes name="*.cs" />
</sources>
<references>
<includes name="../bin/classpath.dll" asis="true" />
<includes name="../bin/IK.VM.NET.dll" asis="true" />
</references>
</csc>
</target>
</project>

103
ikvm/ikvm.csproj Normal file
Просмотреть файл

@ -0,0 +1,103 @@
<VisualStudioProject>
<CSHARP
ProjectType = "Local"
ProductVersion = "7.0.9466"
SchemaVersion = "1.0"
ProjectGuid = "{4FBAFF23-1E48-4977-8C50-30F87E70A8B5}"
>
<Build>
<Settings
ApplicationIcon = ""
AssemblyKeyContainerName = ""
AssemblyName = "ikvm"
AssemblyOriginatorKeyFile = ""
DefaultClientScript = "JScript"
DefaultHTMLPageLayout = "Grid"
DefaultTargetSchema = "IE50"
DelaySign = "false"
OutputType = "Exe"
RootNamespace = "ikvm"
StartupObject = ""
>
<Config
Name = "Debug"
AllowUnsafeBlocks = "false"
BaseAddress = "285212672"
CheckForOverflowUnderflow = "false"
ConfigurationOverrideFile = ""
DefineConstants = "DEBUG;TRACE"
DocumentationFile = ""
DebugSymbols = "true"
FileAlignment = "4096"
IncrementalBuild = "true"
Optimize = "false"
OutputPath = "bin\Debug\"
RegisterForComInterop = "false"
RemoveIntegerChecks = "false"
TreatWarningsAsErrors = "false"
WarningLevel = "4"
/>
<Config
Name = "Release"
AllowUnsafeBlocks = "false"
BaseAddress = "285212672"
CheckForOverflowUnderflow = "false"
ConfigurationOverrideFile = ""
DefineConstants = "TRACE"
DocumentationFile = ""
DebugSymbols = "true"
FileAlignment = "4096"
IncrementalBuild = "false"
Optimize = "true"
OutputPath = "bin\Release\"
RegisterForComInterop = "false"
RemoveIntegerChecks = "false"
TreatWarningsAsErrors = "false"
WarningLevel = "4"
/>
</Settings>
<References>
<Reference
Name = "System"
AssemblyName = "System"
HintPath = "..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.dll"
/>
<Reference
Name = "System.Data"
AssemblyName = "System.Data"
HintPath = "..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.Data.dll"
/>
<Reference
Name = "System.XML"
AssemblyName = "System.Xml"
HintPath = "..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.XML.dll"
/>
<Reference
Name = "IK.VM.NET"
Project = "{F5C7B588-0403-4AF2-A4DE-5697DE21BC2C}"
Package = "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"
/>
<Reference
Name = "classpath"
AssemblyName = "classpath"
HintPath = "..\bin\classpath.dll"
/>
</References>
</Build>
<Files>
<Include>
<File
RelPath = "AssemblyInfo.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "starter.cs"
SubType = "Code"
BuildAction = "Compile"
/>
</Include>
</Files>
</CSHARP>
</VisualStudioProject>

249
ikvm/starter.cs Normal file
Просмотреть файл

@ -0,0 +1,249 @@
/*
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
*/
using System;
using System.IO;
using System.Reflection;
using System.Reflection.Emit;
using System.Collections;
using java.lang.reflect;
using java.net;
using java.util.jar;
using java.io;
public class Starter
{
private class Timer
{
private static Timer t;
private DateTime now = DateTime.Now;
internal Timer()
{
t = this;
}
~Timer()
{
Console.WriteLine(DateTime.Now - now);
}
}
private class ExtClassLoader : URLClassLoader
{
private static URL[] GetClassPath()
{
string classpath = java.lang.System.getProperty("java.ext.dirs", "");
string[] s = classpath.Split(';');
ArrayList jars = new ArrayList();
for(int i = 0; i < s.Length; i++)
{
try
{
string[] files = Directory.GetFiles(s[i]);
for(int j = 0; j < files.Length; j++)
{
jars.Add(new java.io.File(files[j]).toURL());
}
}
catch(ArgumentException)
{
// ignore any malformed components
}
}
return (URL[])jars.ToArray(typeof(URL));
}
internal ExtClassLoader(java.lang.ClassLoader parent)
: base(GetClassPath(), parent)
{
}
}
public class AppClassLoader : URLClassLoader
{
private static URL[] GetClassPath()
{
string classpath = java.lang.System.getProperty("java.class.path", ".");
string[] s = classpath.Split(';');
URL[] urls = new URL[s.Length];
for(int i = 0; i < urls.Length; i++)
{
// TODO non-existing file/dir is treated as current directory, this obviously isn't correct
urls[i] = new java.io.File(s[i]).toURL();
}
return urls;
}
public AppClassLoader(java.lang.ClassLoader parent)
: base(GetClassPath(), new ExtClassLoader(parent))
{
}
}
[StackTraceInfo(Hidden = true, EatFrames = 1)]
[STAThread] // NOTE this is here because otherwise SWT's RegisterDragDrop (a COM thing) doesn't work
static int Main(string[] args)
{
System.Threading.Thread.CurrentThread.Name = "main";
bool jar = false;
bool saveAssembly = false;
string mainClass = null;
string[] vmargs = null;
for(int i = 0; i < args.Length; i++)
{
if(args[i][0] == '-')
{
if(args[i] == "-help")
{
break;
}
else if(args[i] == "-save")
{
saveAssembly = true;
}
else if(args[i] == "-time")
{
new Timer();
}
else if(args[i] == "-jar")
{
jar = true;
}
else if(args[i].StartsWith("-D"))
{
string[] keyvalue = args[i].Substring(2).Split('=');
if(keyvalue.Length != 2)
{
keyvalue = new string[] { keyvalue[0], "" };
}
java.lang.System.setProperty(keyvalue[0], keyvalue[1]);
}
else if(args[i] == "-cp" || args[i] == "-classpath")
{
java.lang.System.setProperty("java.class.path", args[++i]);
}
else
{
Console.Error.WriteLine("{0}: illegal argument", args[i]);
break;
}
}
else
{
mainClass = args[i];
vmargs = new string[args.Length - (i + 1)];
System.Array.Copy(args, i + 1, vmargs, 0, vmargs.Length);
break;
}
}
if(mainClass == null)
{
Console.Error.WriteLine("usage: ikvm [-options] <class> [args...]");
Console.Error.WriteLine(" (to execute a class)");
Console.Error.WriteLine(" or ikvm -jar [-options] <jarfile> [args...]");
Console.Error.WriteLine(" (to execute a jar file)");
Console.Error.WriteLine();
Console.Error.WriteLine("where options include:");
Console.Error.WriteLine(" -help Display this message");
Console.Error.WriteLine(" -cp -classpath <directories and zip/jar files separated by ;>");
Console.Error.WriteLine(" set search path for application classes and resources");
Console.Error.WriteLine(" -save Save the generated assembly (for debugging)");
Console.Error.WriteLine(" -time Time the execution");
Console.Error.WriteLine(" -D<name>=<value> Set a system property");
return 1;
}
try
{
// HACK we take our own assembly location as the location of classpath (this is used by the Security infrastructure
// to find the classpath.security file)
java.lang.System.setProperty("gnu.classpath.home", new System.IO.FileInfo(Assembly.GetExecutingAssembly().Location).DirectoryName);
if(jar)
{
// TODO if there is no classpath, we're adding the current directory, but is this correct when running a jar?
java.lang.System.setProperty("java.class.path", mainClass + ";" + java.lang.System.getProperty("java.class.path"));
JarFile jf = new JarFile(mainClass);
try
{
// TODO use Attributes.Name.MAIN_CLASS (we don't support inner classes at the moment)
mainClass = jf.getManifest().getMainAttributes().getValue("Main-Class");
}
finally
{
jf.close();
}
if(mainClass == null)
{
Console.Error.WriteLine("Manifest doesn't contain a Main-Class.");
return 1;
}
}
// NOTE we should use the default systemclassloader (gnu.java.lang.SystemClassLoader),
// but at the moment it is broken (doesn't implement findClass())
java.lang.System.setProperty("java.system.class.loader", typeof(AppClassLoader).AssemblyQualifiedName);
java.lang.ClassLoader loader = java.lang.ClassLoader.getSystemClassLoader();
java.lang.Class clazz = loader.loadClass(mainClass);
Method method = clazz.getMethod("main", new java.lang.Class[] { java.lang.Class.getClassFromType(typeof(string[])) });
if(!Modifier.isPublic(method.getModifiers()))
{
Console.Error.WriteLine("Main method not public.");
return 1;
}
try
{
try
{
method.invoke(null, new object[] { vmargs });
}
finally
{
if(saveAssembly)
{
// TODO it would be nice to wait for other threads to exit
// TODO consider using a Shutdown hook!
JVM.SaveDebugImage(clazz);
saveAssembly = false;
}
}
}
catch(InvocationTargetException x)
{
throw x.getCause();
}
if(saveAssembly)
{
// TODO it would be nice to wait for other threads to exit
// TODO consider using a Shutdown hook!
JVM.SaveDebugImage(clazz);
}
return 0;
}
catch(System.Exception x)
{
java.lang.Thread thread = java.lang.Thread.currentThread();
thread.getThreadGroup().uncaughtException(thread, ExceptionHelper.MapExceptionFast(x));
return 1;
}
}
}

81
ikvmc/AssemblyInfo.cs Normal file
Просмотреть файл

@ -0,0 +1,81 @@
/*
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
*/
using System.Reflection;
using System.Runtime.CompilerServices;
//
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
//
[assembly: AssemblyTitle("")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
//
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("1.0.*")]
//
// In order to sign your assembly you must specify a key to use. Refer to the
// Microsoft .NET Framework documentation for more information on assembly signing.
//
// Use the attributes below to control which key is used for signing.
//
// Notes:
// (*) If no key is specified, the assembly is not signed.
// (*) KeyName refers to a key that has been installed in the Crypto Service
// Provider (CSP) on your machine. KeyFile refers to a file which contains
// a key.
// (*) If the KeyFile and the KeyName values are both specified, the
// following processing occurs:
// (1) If the KeyName can be found in the CSP, that key is used.
// (2) If the KeyName does not exist and the KeyFile does exist, the key
// in the KeyFile is installed into the CSP and used.
// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
// When specifying the KeyFile, the location of the KeyFile should be
// relative to the project output directory which is
// %Project Directory%\obj\<configuration>. For example, if your KeyFile is
// located in the project directory, you would specify the AssemblyKeyFile
// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
// documentation for more information on this.
//
[assembly: AssemblyDelaySign(false)]
[assembly: AssemblyKeyFile("")]
[assembly: AssemblyKeyName("")]

244
ikvmc/Compiler.cs Normal file
Просмотреть файл

@ -0,0 +1,244 @@
/*
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
*/
using System;
using System.Collections;
using System.IO;
using System.Reflection;
using java.io;
using java.util.zip;
class Compiler : MarshalByRefObject
{
private static ArrayList GetArgs(string[] args)
{
ArrayList arglist = new ArrayList();
foreach(string s in args)
{
if(s.StartsWith("@"))
{
using(StreamReader sr = new StreamReader(s.Substring(1)))
{
string line;
while((line = sr.ReadLine()) != null)
{
arglist.Add(line);
}
}
}
else
{
arglist.Add(s);
}
}
return arglist;
}
static int Main(string[] args)
{
System.Reflection.Emit.PEFileKinds target = System.Reflection.Emit.PEFileKinds.ConsoleApplication;
string assemblyname = null;
string outputfile = null;
string main = null;
bool nojni = false;
ArrayList references = new ArrayList();
ArrayList arglist = GetArgs(args);
if(arglist.Count == 0)
{
Console.Error.WriteLine("usage: ikvmc [-options] <classOrJar1> ... <classOrJarN>");
Console.Error.WriteLine();
Console.Error.WriteLine("options:");
Console.Error.WriteLine(" -out:<outputfile> Required");
Console.Error.WriteLine(" -assembly:<outputfile> Optionally used to specify assembly name");
Console.Error.WriteLine(" -target:exe Build a console executable");
Console.Error.WriteLine(" -target:winexe Build a windows executable");
Console.Error.WriteLine(" -target:library Build a library");
Console.Error.WriteLine(" -main:<class> Required (for executables)");
Console.Error.WriteLine(" -reference:<path> Reference an assembly");
Console.Error.WriteLine(" -recurse:<filespec> Recurse directory and include matching files");
Console.Error.WriteLine(" -nojni Do not generate JNI stub for native methods");
return 1;
}
ArrayList classes = new ArrayList();
Hashtable resources = new Hashtable();
foreach(string s in arglist)
{
if(s[0] == '-')
{
if(s.StartsWith("-out:"))
{
outputfile = s.Substring(5);
}
else if(s.StartsWith("-assembly:"))
{
assemblyname = s.Substring(10);
}
else if(s.StartsWith("-target:"))
{
switch(s)
{
case "-target:exe":
target = System.Reflection.Emit.PEFileKinds.ConsoleApplication;
break;
case "-target:winexe":
target = System.Reflection.Emit.PEFileKinds.WindowApplication;
break;
case "-target:library":
target = System.Reflection.Emit.PEFileKinds.Dll;
break;
}
}
else if(s.StartsWith("-main:"))
{
main = s.Substring(6);
}
else if(s.StartsWith("-reference:"))
{
references.Add(s.Substring(11));
}
else if(s.StartsWith("-recurse:"))
{
string spec = s.Substring(9);
Recurse(classes, resources, new DirectoryInfo(Path.GetDirectoryName(spec)), Path.GetFileName(spec));
}
else if(s == "-nojni")
{
nojni = true;
}
else
{
Console.Error.WriteLine("Warning: Unrecognized option: {0}", s);
}
}
else
{
ProcessFile(classes, resources, s);
}
}
if(outputfile == null)
{
Console.Error.WriteLine("Error: -out:<outputfile> must be specified");
return 1;
}
if(assemblyname == null)
{
int idx = outputfile.LastIndexOf('.');
if(idx > 0)
{
assemblyname = outputfile.Substring(0, idx);
}
else
{
assemblyname = outputfile;
}
}
if(target != System.Reflection.Emit.PEFileKinds.Dll && main == null)
{
Console.Error.WriteLine("Error: -main:<class> must be specified when creating an executable");
return 1;
}
// HACK since we use Classpath's zip code, our VM is already running in this AppDomain, which means that
// it cannot be (ab)used to statically compile anymore, so we create a new AppDomain to run the compile in.
Compiler c = (Compiler)AppDomain.CreateDomain("Compiler").CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().FullName, "Compiler");
return c.Compile(outputfile, assemblyname, main, target, (byte[][])classes.ToArray(typeof(byte[])), (string[])references.ToArray(typeof(string)), nojni, resources);
}
private static void ProcessFile(ArrayList classes, Hashtable resources, string file)
{
if(file.ToLower().EndsWith(".class"))
{
using(FileStream fs = new FileStream(file, FileMode.Open))
{
byte[] b = new byte[fs.Length];
fs.Read(b, 0, b.Length);
classes.Add(b);
}
}
else if(file.ToLower().EndsWith(".jar") || file.ToLower().EndsWith(".zip"))
{
ZipFile zf = new ZipFile(file);
java.util.Enumeration e = zf.entries();
while(e.hasMoreElements())
{
ZipEntry ze = (ZipEntry)e.nextElement();
if(ze.getName().ToLower().EndsWith(".class"))
{
sbyte[] sbuf = new sbyte[ze.getSize()];
DataInputStream dis = new DataInputStream(zf.getInputStream(ze));
dis.readFully(sbuf);
dis.close();
byte[] buf = new byte[sbuf.Length];
for(int i = 0; i < buf.Length; i++)
{
buf[i] = (byte)sbuf[i];
}
classes.Add(buf);
}
else
{
// if it's not a class, we treat it as a resource
sbyte[] sbuf = new sbyte[ze.getSize()];
DataInputStream dis = new DataInputStream(zf.getInputStream(ze));
dis.readFully(sbuf);
dis.close();
byte[] buf = new byte[sbuf.Length];
for(int i = 0; i < buf.Length; i++)
{
buf[i] = (byte)sbuf[i];
}
resources.Add(ze.getName(), buf);
}
}
}
else
{
Console.Error.WriteLine("Warning: Unknown file type: {0}", file);
}
}
private static void Recurse(ArrayList classes, Hashtable resources, DirectoryInfo dir, string spec)
{
foreach(FileInfo file in dir.GetFiles(spec))
{
ProcessFile(classes, resources, file.FullName);
}
foreach(DirectoryInfo sub in dir.GetDirectories())
{
Recurse(classes, resources, sub, spec);
}
}
public int Compile(string fileName, string assemblyName, string mainClass, System.Reflection.Emit.PEFileKinds target, byte[][] classes, string[] references, bool nojni, Hashtable resources)
{
try
{
JVM.Compile(fileName, assemblyName, mainClass, target, classes, references, nojni, resources);
return 0;
}
catch(Exception x)
{
Console.Error.WriteLine(x);
return 1;
}
}
}

Просмотреть файл

@ -0,0 +1,4 @@
Compiling class files (1)
Constructing compiler
Loading remapped types
Parsing class files

14
ikvmc/ikvmc.build Normal file
Просмотреть файл

@ -0,0 +1,14 @@
<?xml version="1.0"?>
<project name="ikvmc" default="ikvmc">
<target name="ikvmc">
<csc target="exe" output="../bin/ikvmc.exe">
<sources>
<includes name="*.cs" />
</sources>
<references>
<includes name="../bin/classpath.dll" asis="true" />
<includes name="../bin/ik.vm.net.dll" asis="true" />
</references>
</csc>
</target>
</project>

103
ikvmc/ikvmc.csproj Normal file
Просмотреть файл

@ -0,0 +1,103 @@
<VisualStudioProject>
<CSHARP
ProjectType = "Local"
ProductVersion = "7.0.9466"
SchemaVersion = "1.0"
ProjectGuid = "{4CA3F3DF-D2B7-4FA2-874C-BFC4B04286A2}"
>
<Build>
<Settings
ApplicationIcon = ""
AssemblyKeyContainerName = ""
AssemblyName = "ikvmc"
AssemblyOriginatorKeyFile = ""
DefaultClientScript = "JScript"
DefaultHTMLPageLayout = "Grid"
DefaultTargetSchema = "IE50"
DelaySign = "false"
OutputType = "Exe"
RootNamespace = "ikvmc"
StartupObject = ""
>
<Config
Name = "Debug"
AllowUnsafeBlocks = "false"
BaseAddress = "285212672"
CheckForOverflowUnderflow = "false"
ConfigurationOverrideFile = ""
DefineConstants = "DEBUG;TRACE"
DocumentationFile = ""
DebugSymbols = "true"
FileAlignment = "4096"
IncrementalBuild = "true"
Optimize = "false"
OutputPath = "bin\Debug\"
RegisterForComInterop = "false"
RemoveIntegerChecks = "false"
TreatWarningsAsErrors = "false"
WarningLevel = "4"
/>
<Config
Name = "Release"
AllowUnsafeBlocks = "false"
BaseAddress = "285212672"
CheckForOverflowUnderflow = "false"
ConfigurationOverrideFile = ""
DefineConstants = "TRACE"
DocumentationFile = ""
DebugSymbols = "true"
FileAlignment = "4096"
IncrementalBuild = "false"
Optimize = "true"
OutputPath = "bin\Release\"
RegisterForComInterop = "false"
RemoveIntegerChecks = "false"
TreatWarningsAsErrors = "false"
WarningLevel = "4"
/>
</Settings>
<References>
<Reference
Name = "System"
AssemblyName = "System"
HintPath = "..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.dll"
/>
<Reference
Name = "System.Data"
AssemblyName = "System.Data"
HintPath = "..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.Data.dll"
/>
<Reference
Name = "System.XML"
AssemblyName = "System.Xml"
HintPath = "..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.XML.dll"
/>
<Reference
Name = "IK.VM.NET"
Project = "{F5C7B588-0403-4AF2-A4DE-5697DE21BC2C}"
Package = "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"
/>
<Reference
Name = "classpath"
AssemblyName = "classpath"
HintPath = "..\classpath\classpath.dll"
/>
</References>
</Build>
<Files>
<Include>
<File
RelPath = "AssemblyInfo.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "Compiler.cs"
SubType = "Code"
BuildAction = "Compile"
/>
</Include>
</Files>
</CSHARP>
</VisualStudioProject>

81
netexp/AssemblyInfo.cs Normal file
Просмотреть файл

@ -0,0 +1,81 @@
/*
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
*/
using System.Reflection;
using System.Runtime.CompilerServices;
//
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
//
[assembly: AssemblyTitle("")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
//
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("1.0.*")]
//
// In order to sign your assembly you must specify a key to use. Refer to the
// Microsoft .NET Framework documentation for more information on assembly signing.
//
// Use the attributes below to control which key is used for signing.
//
// Notes:
// (*) If no key is specified, the assembly is not signed.
// (*) KeyName refers to a key that has been installed in the Crypto Service
// Provider (CSP) on your machine. KeyFile refers to a file which contains
// a key.
// (*) If the KeyFile and the KeyName values are both specified, the
// following processing occurs:
// (1) If the KeyName can be found in the CSP, that key is used.
// (2) If the KeyName does not exist and the KeyFile does exist, the key
// in the KeyFile is installed into the CSP and used.
// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
// When specifying the KeyFile, the location of the KeyFile should be
// relative to the project output directory which is
// %Project Directory%\obj\<configuration>. For example, if your KeyFile is
// located in the project directory, you would specify the AssemblyKeyFile
// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
// documentation for more information on this.
//
[assembly: AssemblyDelaySign(false)]
[assembly: AssemblyKeyFile("")]
[assembly: AssemblyKeyName("")]

632
netexp/ClassFileWriter.cs Normal file
Просмотреть файл

@ -0,0 +1,632 @@
/*
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
*/
using System;
using System.IO;
using System.Collections;
class BigEndianStream
{
private Stream stream;
public BigEndianStream(Stream stream)
{
this.stream = stream;
}
public void WriteUInt16(ushort s)
{
stream.WriteByte((byte)(s >> 8));
stream.WriteByte((byte)s);
}
public void WriteUInt32(uint u)
{
stream.WriteByte((byte)(u >> 24));
stream.WriteByte((byte)(u >> 16));
stream.WriteByte((byte)(u >> 8));
stream.WriteByte((byte)u);
}
public void WriteInt64(long l)
{
WriteUInt32((uint)(l >> 32));
WriteUInt32((uint)l);
}
public void WriteFloat(float f)
{
WriteUInt32(BitConverter.ToUInt32(BitConverter.GetBytes(f), 0));
}
public void WriteDouble(double d)
{
WriteInt64(BitConverter.ToInt64(BitConverter.GetBytes(d), 0));
}
public void WriteByte(byte b)
{
stream.WriteByte(b);
}
public void WriteUtf8(string str)
{
byte[] buf = new byte[str.Length * 3 + 1];
int j = 0;
for(int i = 0, e = str.Length; i < e; i++)
{
char ch = str[i];
if ((ch != 0) && (ch <=0x7f))
{
buf[j++] = (byte)ch;
}
else if (ch <= 0x7FF)
{
/* 11 bits or less. */
byte high_five = (byte)(ch >> 6);
byte low_six = (byte)(ch & 0x3F);
buf[j++] = (byte)(high_five | 0xC0); /* 110xxxxx */
buf[j++] = (byte)(low_six | 0x80); /* 10xxxxxx */
}
else
{
/* possibly full 16 bits. */
byte high_four = (byte)(ch >> 12);
byte mid_six = (byte)((ch >> 6) & 0x3F);
byte low_six = (byte)(ch & 0x3f);
buf[j++] = (byte)(high_four | 0xE0); /* 1110xxxx */
buf[j++] = (byte)(mid_six | 0x80); /* 10xxxxxx */
buf[j++] = (byte)(low_six | 0x80); /* 10xxxxxx*/
}
}
WriteUInt16((ushort)j);
stream.Write(buf, 0, j);
}
}
enum Constant
{
Utf8 = 1,
Integer = 3,
Float = 4,
Long = 5,
Double = 6,
Class = 7,
String = 8,
Fieldref = 9,
Methodref = 10,
InterfaceMethodref = 11,
NameAndType = 12
}
abstract class ConstantPoolItem
{
public abstract void Write(BigEndianStream bes);
}
class ConstantPoolItemClass : ConstantPoolItem
{
private ushort name_index;
public ConstantPoolItemClass(ushort name_index)
{
this.name_index = name_index;
}
public override int GetHashCode()
{
return name_index;
}
public override bool Equals(object o)
{
if(o != null && o.GetType() == typeof(ConstantPoolItemClass))
{
return ((ConstantPoolItemClass)o).name_index == name_index;
}
return false;
}
public override void Write(BigEndianStream bes)
{
bes.WriteByte((byte)Constant.Class);
bes.WriteUInt16(name_index);
}
}
class ConstantPoolItemUtf8 : ConstantPoolItem
{
private string str;
public ConstantPoolItemUtf8(string str)
{
this.str = str;
}
public override int GetHashCode()
{
return str.GetHashCode();
}
public override bool Equals(object o)
{
if(o != null && o.GetType() == typeof(ConstantPoolItemUtf8))
{
return ((ConstantPoolItemUtf8)o).str == str;
}
return false;
}
public override void Write(BigEndianStream bes)
{
bes.WriteByte((byte)Constant.Utf8);
bes.WriteUtf8(str);
}
}
class ConstantPoolItemInt : ConstantPoolItem
{
private int v;
public ConstantPoolItemInt(int v)
{
this.v = v;
}
public override int GetHashCode()
{
return v;
}
public override bool Equals(object o)
{
if(o != null && o.GetType() == typeof(ConstantPoolItemInt))
{
return ((ConstantPoolItemInt)o).v == v;
}
return false;
}
public override void Write(BigEndianStream bes)
{
bes.WriteByte((byte)Constant.Integer);
bes.WriteUInt32((uint)v);
}
}
class ConstantPoolItemLong : ConstantPoolItem
{
private long v;
public ConstantPoolItemLong(long v)
{
this.v = v;
}
public override int GetHashCode()
{
return (int)v;
}
public override bool Equals(object o)
{
if(o != null && o.GetType() == typeof(ConstantPoolItemLong))
{
return ((ConstantPoolItemLong)o).v == v;
}
return false;
}
public override void Write(BigEndianStream bes)
{
bes.WriteByte((byte)Constant.Long);
bes.WriteInt64(v);
}
}
class ConstantPoolItemFloat : ConstantPoolItem
{
private float v;
public ConstantPoolItemFloat(float v)
{
this.v = v;
}
public override int GetHashCode()
{
return BitConverter.ToInt32(BitConverter.GetBytes(v), 0);
}
public override bool Equals(object o)
{
if(o != null && o.GetType() == typeof(ConstantPoolItemFloat))
{
return ((ConstantPoolItemFloat)o).v == v;
}
return false;
}
public override void Write(BigEndianStream bes)
{
bes.WriteByte((byte)Constant.Float);
bes.WriteFloat(v);
}
}
class ConstantPoolItemDouble : ConstantPoolItem
{
private double v;
public ConstantPoolItemDouble(double v)
{
this.v = v;
}
public override int GetHashCode()
{
long l = BitConverter.DoubleToInt64Bits(v);
return ((int)l) ^ ((int)(l >> 32));
}
public override bool Equals(object o)
{
if(o != null && o.GetType() == typeof(ConstantPoolItemDouble))
{
return ((ConstantPoolItemDouble)o).v == v;
}
return false;
}
public override void Write(BigEndianStream bes)
{
bes.WriteByte((byte)Constant.Double);
bes.WriteDouble(v);
}
}
class ConstantPoolItemString : ConstantPoolItem
{
private ushort string_index;
public ConstantPoolItemString(ushort string_index)
{
this.string_index = string_index;
}
public override int GetHashCode()
{
return string_index;
}
public override bool Equals(object o)
{
if(o != null && o.GetType() == typeof(ConstantPoolItemString))
{
return ((ConstantPoolItemString)o).string_index == string_index;
}
return false;
}
public override void Write(BigEndianStream bes)
{
bes.WriteByte((byte)Constant.String);
bes.WriteUInt16(string_index);
}
}
class ClassFileAttribute
{
private ushort name_index;
public ClassFileAttribute(ushort name_index)
{
this.name_index = name_index;
}
public virtual void Write(BigEndianStream bes)
{
bes.WriteUInt16(name_index);
}
}
class ConstantValueAttribute : ClassFileAttribute
{
private ushort constant_index;
public ConstantValueAttribute(ushort name_index, ushort constant_index)
: base(name_index)
{
this.constant_index = constant_index;
}
public override void Write(BigEndianStream bes)
{
base.Write(bes);
bes.WriteUInt32(2);
bes.WriteUInt16(constant_index);
}
}
class StringAttribute : ClassFileAttribute
{
private ushort string_index;
public StringAttribute(ushort name_index, ushort string_index)
: base(name_index)
{
this.string_index = string_index;
}
public override void Write(BigEndianStream bes)
{
base.Write(bes);
bes.WriteUInt32(2);
bes.WriteUInt16(string_index);
}
}
class InnerClassesAttribute : ClassFileAttribute
{
private ClassFileWriter classFile;
private ArrayList classes = new ArrayList();
public InnerClassesAttribute(ClassFileWriter classFile)
: base(classFile.AddUtf8("InnerClasses"))
{
this.classFile = classFile;
}
public override void Write(BigEndianStream bes)
{
base.Write(bes);
bes.WriteUInt32((uint)(2 + 8 * classes.Count));
bes.WriteUInt16((ushort)classes.Count);
foreach(Item i in classes)
{
bes.WriteUInt16(i.inner_class_info_index);
bes.WriteUInt16(i.outer_class_info_index);
bes.WriteUInt16(i.inner_name_index);
bes.WriteUInt16(i.inner_class_access_flags);
}
}
private class Item
{
internal ushort inner_class_info_index;
internal ushort outer_class_info_index;
internal ushort inner_name_index;
internal ushort inner_class_access_flags;
}
public void Add(string inner, string outer, string name, ushort access)
{
Item i = new Item();
i.inner_class_info_index = classFile.AddClass(inner);
i.outer_class_info_index = classFile.AddClass(outer);
if(name != null)
{
i.inner_name_index = classFile.AddUtf8(name);
}
i.inner_class_access_flags = access;
classes.Add(i);
}
}
class FieldOrMethod
{
private Modifiers access_flags;
private ushort name_index;
private ushort descriptor_index;
private ArrayList attribs = new ArrayList();
public FieldOrMethod(Modifiers access_flags, ushort name_index, ushort descriptor_index)
{
this.access_flags = access_flags;
this.name_index = name_index;
this.descriptor_index = descriptor_index;
}
public void AddAttribute(ClassFileAttribute attrib)
{
attribs.Add(attrib);
}
public void Write(BigEndianStream bes)
{
bes.WriteUInt16((ushort)access_flags);
bes.WriteUInt16(name_index);
bes.WriteUInt16(descriptor_index);
bes.WriteUInt16((ushort)attribs.Count);
for(int i = 0; i < attribs.Count; i++)
{
((ClassFileAttribute)attribs[i]).Write(bes);
}
}
}
class ClassFileWriter
{
private ArrayList cplist = new ArrayList();
private Hashtable cphashtable = new Hashtable();
private ArrayList fields = new ArrayList();
private ArrayList methods = new ArrayList();
private ArrayList attribs = new ArrayList();
private Modifiers access_flags;
private ushort this_class;
private ushort super_class;
public ClassFileWriter(Modifiers mods, string name, string super)
{
cplist.Add(null);
access_flags = mods;
this_class = AddClass(name);
if(super != null)
{
super_class = AddClass(super);
}
}
private ushort Add(ConstantPoolItem cpi)
{
object index = cphashtable[cpi];
if(index == null)
{
index = (ushort)cplist.Add(cpi);
if(cpi is ConstantPoolItemDouble || cpi is ConstantPoolItemLong)
{
cplist.Add(null);
}
cphashtable[cpi] = index;
}
return (ushort)index;
}
public ushort AddUtf8(string str)
{
return Add(new ConstantPoolItemUtf8(str));
}
public ushort AddClass(string classname)
{
return Add(new ConstantPoolItemClass(AddUtf8(classname)));
}
private ushort AddInt(int i)
{
return Add(new ConstantPoolItemInt(i));
}
private ushort AddLong(long l)
{
return Add(new ConstantPoolItemLong(l));
}
private ushort AddFloat(float f)
{
return Add(new ConstantPoolItemFloat(f));
}
private ushort AddDouble(double d)
{
return Add(new ConstantPoolItemDouble(d));
}
private ushort AddString(string s)
{
return Add(new ConstantPoolItemString(AddUtf8(s)));
}
public FieldOrMethod AddMethod(Modifiers access, string name, string signature)
{
FieldOrMethod method = new FieldOrMethod(access, AddUtf8(name), AddUtf8(signature));
methods.Add(method);
return method;
}
public FieldOrMethod AddField(Modifiers access, string name, string signature, object constantValue)
{
FieldOrMethod field = new FieldOrMethod(access, AddUtf8(name), AddUtf8(signature));
if(constantValue != null)
{
ushort constantValueIndex;
if(constantValue is int)
{
constantValueIndex = AddInt((int)constantValue);
}
else if(constantValue is long)
{
constantValueIndex = AddLong((long)constantValue);
}
else if(constantValue is float)
{
constantValueIndex = AddFloat((float)constantValue);
}
else if(constantValue is double)
{
constantValueIndex = AddDouble((double)constantValue);
}
else if(constantValue is string)
{
constantValueIndex = AddString((string)constantValue);
}
else
{
throw new InvalidOperationException();
}
field.AddAttribute(new ConstantValueAttribute(AddUtf8("ConstantValue"), constantValueIndex));
}
fields.Add(field);
return field;
}
public void AddStringAttribute(string name, string value)
{
attribs.Add(new StringAttribute(AddUtf8(name), AddUtf8(value)));
}
public void AddAttribute(ClassFileAttribute attrib)
{
attribs.Add(attrib);
}
public void Write(Stream stream)
{
BigEndianStream bes = new BigEndianStream(stream);
bes.WriteUInt32(0xCAFEBABE);
bes.WriteUInt16((ushort)3);
bes.WriteUInt16((ushort)45);
bes.WriteUInt16((ushort)cplist.Count);
for(int i = 1; i < cplist.Count; i++)
{
ConstantPoolItem cpi = (ConstantPoolItem)cplist[i];
if(cpi != null)
{
cpi.Write(bes);
}
}
bes.WriteUInt16((ushort)access_flags);
bes.WriteUInt16(this_class);
bes.WriteUInt16(super_class);
// interfaces count
bes.WriteUInt16(0);
// fields count
bes.WriteUInt16((ushort)fields.Count);
for(int i = 0; i < fields.Count; i++)
{
((FieldOrMethod)fields[i]).Write(bes);
}
// methods count
bes.WriteUInt16((ushort)methods.Count);
for(int i = 0; i < methods.Count; i++)
{
((FieldOrMethod)methods[i]).Write(bes);
}
// attributes count
bes.WriteUInt16((ushort)attribs.Count);
for(int i = 0; i < attribs.Count; i++)
{
((ClassFileAttribute)attribs[i]).Write(bes);
}
}
}

474
netexp/NetExp.cs Normal file
Просмотреть файл

@ -0,0 +1,474 @@
/*
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
*/
using System;
using System.Reflection;
using System.IO;
using System.Text;
using System.Collections;
using java.util.zip;
using java.io;
public class NetExp
{
private static ZipOutputStream zipFile;
public static void Main(string[] args)
{
Assembly assembly = null;
if(new FileInfo(args[0]).Exists)
{
assembly = Assembly.LoadFrom(args[0]);
}
if(assembly == null)
{
Console.Error.WriteLine("Error: Assembly \"{0}\" not found", args[0]);
}
else
{
zipFile = new ZipOutputStream(new FileOutputStream(assembly.GetName().Name + ".jar"));
ProcessAssembly(assembly);
zipFile.close();
}
}
private static void ProcessAssembly(Assembly assembly)
{
object[] attribs = assembly.GetCustomAttributes(typeof(CLSCompliantAttribute), false);
bool assemblyIsCLSCompliant = true;
if(attribs.Length != 1)
{
assemblyIsCLSCompliant = false;
Console.Error.WriteLine("Warning: assembly has no (or multiple) CLS compliance attribute");
}
else if(!((CLSCompliantAttribute)attribs[0]).IsCompliant)
{
assemblyIsCLSCompliant = false;
Console.Error.WriteLine("Warning: assembly is marked as non-CLS compliant");
}
foreach(Type t in assembly.GetTypes())
{
bool typeIsCLSCompliant = true;
if(assemblyIsCLSCompliant)
{
attribs = t.GetCustomAttributes(typeof(CLSCompliantAttribute), false);
if(attribs.Length == 1)
{
typeIsCLSCompliant = ((CLSCompliantAttribute)attribs[0]).IsCompliant;
}
}
if(t.IsPublic && typeIsCLSCompliant)
{
ProcessType(t);
}
}
}
private static object UnwrapEnum(object o)
{
// is there a way to generically convert a boxed enum to its boxed underlying value?
Type underlyingType = Enum.GetUnderlyingType(o.GetType());
if(underlyingType == typeof(int))
{
o = (int)o;
}
else if(underlyingType == typeof(short))
{
o = (short)o;
}
else
{
throw new NotImplementedException(o.GetType().Name);
}
return o;
}
private static string ClassName(Type t)
{
if(t == typeof(object))
{
return "java/lang/Object";
}
else if(t == typeof(string))
{
return "java/lang/String";
}
string name = t.FullName;
int lastDot = name.LastIndexOf('.');
if(lastDot > 0)
{
name = name.Substring(0, lastDot).ToLower() + name.Substring(lastDot);
}
return name.Replace('.', '/');
}
// returns the mapped type in signature format (e.g. Ljava/lang/String;)
private static string SigType(Type t)
{
if(t.IsEnum)
{
t = Enum.GetUnderlyingType(t);
}
if(t == typeof(void))
{
return "V";
}
else if(t == typeof(byte) || t == typeof(sbyte))
{
return "B";
}
else if(t == typeof(bool))
{
return "Z";
}
else if(t == typeof(short) || t == typeof(ushort))
{
return "S";
}
else if(t == typeof(char))
{
return "C";
}
else if(t == typeof(int) || t == typeof(uint))
{
return "I";
}
else if(t == typeof(long) || t == typeof(ulong))
{
return "J";
}
else if(t == typeof(float))
{
return "F";
}
else if(t == typeof(double))
{
return "D";
}
else if(t == typeof(IntPtr))
{
// HACK
return "I";
}
else if(t.IsArray)
{
StringBuilder sb = new StringBuilder();
while(t.IsArray)
{
sb.Append('[');
t = t.GetElementType();
}
sb.Append(SigType(t));
return sb.ToString();
}
else if(!t.IsPrimitive)
{
return "L" + ClassName(t) + ";";
}
else
{
throw new NotImplementedException(t.FullName);
}
}
private static void ProcessType(Type type)
{
if(type == typeof(object) || type == typeof(string))
{
// special case for System.Object & System.String, don't emit those
return;
}
string name = ClassName(type);
string super;
if(type.BaseType == null)
{
// in .NET interfaces don't have a baseType, but in Java they "extend" java/lang/Object
super = "java/lang/Object";
}
else
{
if(type == typeof(Exception))
{
super = "java/lang/Throwable";
}
else
{
super = ClassName(type.BaseType);
}
}
Modifiers mods = Modifiers.Public | Modifiers.Super;
if(type.IsInterface)
{
mods |= Modifiers.Interface;
}
if(type.IsSealed)
{
mods |= Modifiers.Final;
}
if(type.IsAbstract)
{
mods |= Modifiers.Abstract;
}
ClassFileWriter f = new ClassFileWriter(mods, name, super);
f.AddStringAttribute("IK.VM.NET.Type", type.AssemblyQualifiedName);
FieldInfo[] fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
Hashtable clashtable = new Hashtable();
for(int i = 0; i < fields.Length; i++)
{
if(fields[i].IsPublic || fields[i].IsFamily)
{
object[] attribs = fields[i].GetCustomAttributes(typeof(CLSCompliantAttribute), false);
if(attribs.Length == 1 && !((CLSCompliantAttribute)attribs[0]).IsCompliant)
{
// skip non-CLS compliant field
}
else
{
ProcessField(type, f, fields[i], clashtable);
}
}
}
clashtable.Clear();
ConstructorInfo[] constructors = type.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
for(int i = 0; i < constructors.Length; i++)
{
if(constructors[i].IsPublic || constructors[i].IsFamily)
{
object[] attribs = constructors[i].GetCustomAttributes(typeof(CLSCompliantAttribute), false);
if(attribs.Length == 1 && !((CLSCompliantAttribute)attribs[0]).IsCompliant)
{
// skip non-CLS compliant field
}
else
{
ProcessMethod(type, f, constructors[i], clashtable);
}
}
}
MethodInfo[] methods = type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly);
for(int i = 0; i < methods.Length; i++)
{
if(methods[i].IsPublic || methods[i].IsFamily)
{
object[] attribs = methods[i].GetCustomAttributes(typeof(CLSCompliantAttribute), false);
if(attribs.Length == 1 && !((CLSCompliantAttribute)attribs[0]).IsCompliant)
{
// skip non-CLS compliant field
}
else
{
ProcessMethod(type, f, methods[i], clashtable);
}
}
}
// for delegates we have to construct the inner interface
if(type.IsSubclassOf(typeof(MulticastDelegate)))
{
InnerClassesAttribute innerclasses = new InnerClassesAttribute(f);
string outer = ClassName(type);
innerclasses.Add(outer + "$Method", outer, "Method", 0x209);
f.AddAttribute(innerclasses);
// now we construct the inner interface type
ClassFileWriter iface = new ClassFileWriter(Modifiers.Interface | Modifiers.Public, outer + "$Method", "java/lang/Object");
MethodInfo invoke = type.GetMethod("Invoke");
StringBuilder sb = new StringBuilder();
sb.Append('(');
ParameterInfo[] parameters = invoke.GetParameters();
for(int i = 0; i < parameters.Length; i++)
{
sb.Append(SigType(parameters[i].ParameterType));
}
sb.Append(')');
sb.Append(SigType(invoke.ReturnType));
// TODO IK.VM.NET.Sig must be set here as well
iface.AddMethod(Modifiers.Public | Modifiers.Abstract, "Invoke", sb.ToString());
innerclasses = new InnerClassesAttribute(iface);
innerclasses.Add(outer + "$Method", outer, "Method", 0x209);
iface.AddAttribute(innerclasses);
WriteClass(outer + "$Method.class", iface);
}
WriteClass(name + ".class", f);
}
private static void WriteClass(string name, ClassFileWriter c)
{
zipFile.putNextEntry(new ZipEntry(name));
MemoryStream s = new MemoryStream();
c.Write(s);
byte[] buf = s.ToArray();
sbyte[] sbuf = new sbyte[buf.Length];
for(int i = 0; i < buf.Length; i++)
{
sbuf[i] = (sbyte)buf[i];
}
zipFile.write(sbuf, 0, sbuf.Length);
}
private static void ProcessField(Type type, ClassFileWriter f, FieldInfo fi, Hashtable clashtable)
{
Modifiers access;
if(fi.IsPublic)
{
access = Modifiers.Public;
}
else
{
access = Modifiers.Protected;
}
object v = null;
if(fi.IsLiteral)
{
v = fi.GetValue(null);
if(v is Enum)
{
v = UnwrapEnum(v);
}
if(v is byte)
{
v = (int)(byte)v;
}
else if(v is char)
{
v = (int)(char)v;
}
else if(v is short)
{
v = (int)(short)v;
}
else if(v is bool)
{
v = ((bool)v) ? 1 : 0;
}
else if(v is int || v is long || v is float || v is double || v is string)
{
}
else
{
throw new NotImplementedException(v.GetType().FullName);
}
access |= Modifiers.Static | Modifiers.Final;
}
else
{
if(fi.IsInitOnly)
{
access |= Modifiers.Final;
}
if(fi.IsStatic)
{
access |= Modifiers.Static;
}
if(type.IsEnum)
{
// we don't want the value__ field
return;
}
}
string sig = SigType(fi.FieldType);
string key = fi.Name + sig;
if(clashtable.ContainsKey(key))
{
// TODO instead of skipping, we should mangle the name
Console.Error.WriteLine("Skipping field " + type.FullName + "." + fi.Name + " (type " + sig + ") because it clashes");
}
else
{
clashtable.Add(key, key);
f.AddField(access, fi.Name, sig, v);
}
}
private static void ProcessMethod(Type type, ClassFileWriter f, MethodBase mb, Hashtable clashtable)
{
Modifiers access = 0;
if(!mb.IsAbstract)
{
access = Modifiers.Native;
}
if(mb.IsPublic)
{
access |= Modifiers.Public;
}
else
{
access |= Modifiers.Protected;
}
if(mb.IsFinal || !mb.IsVirtual)
{
access |= Modifiers.Final;
}
if(mb.IsStatic)
{
access |= Modifiers.Static;
}
if(mb.IsAbstract)
{
access |= Modifiers.Abstract;
}
// special case for delegate constructors!
if(mb.IsConstructor && type.IsSubclassOf(typeof(MulticastDelegate)))
{
access &= ~Modifiers.Final;
f.AddMethod(access, "<init>", "(L" + ClassName(type) + "$Method;)V");
return;
}
// HACK the native signature is really is very lame way of storing the signature
// TODO only store it when it doesn't match the Java sig and split it into parts (instead of one giant string)
StringBuilder nativesig = new StringBuilder();
StringBuilder sb = new StringBuilder();
sb.Append('(');
ParameterInfo[] parameters = mb.GetParameters();
string sep = "";
for(int i = 0; i < parameters.Length; i++)
{
sb.Append(SigType(parameters[i].ParameterType));
nativesig.Append(sep).Append(parameters[i].ParameterType.AssemblyQualifiedName);
sep = "|";
}
sb.Append(')');
if(mb.IsConstructor)
{
// HACK constructors may not be final in Java
access &= ~Modifiers.Final;
sb.Append('V');
}
else
{
sb.Append(SigType(((MethodInfo)mb).ReturnType));
}
string name = mb.IsConstructor ? "<init>" : mb.Name;
string sig = sb.ToString();
string key = name + sig;
if(clashtable.ContainsKey(key))
{
// TODO instead of skipping, we should mangle the name
Console.Error.WriteLine("Skipping method " + type.FullName + "." + name + sig + " because it clashes");
}
else
{
clashtable.Add(key, key);
f.AddMethod(access, name, sig)
.AddAttribute(new StringAttribute(f.AddUtf8("IK.VM.NET.Sig"), f.AddUtf8(nativesig.ToString())));
}
}
}

14
netexp/netexp.build Normal file
Просмотреть файл

@ -0,0 +1,14 @@
<?xml version="1.0"?>
<project name="netexp" default="netexp">
<target name="netexp">
<csc target="exe" output="../bin/netexp.exe">
<sources>
<includes name="*.cs" />
</sources>
<references>
<includes name="../bin/classpath.dll" asis="true" />
<includes name="../bin/IK.VM.NET.dll" asis="true" />
</references>
</csc>
</target>
</project>

108
netexp/netexp.csproj Normal file
Просмотреть файл

@ -0,0 +1,108 @@
<VisualStudioProject>
<CSHARP
ProjectType = "Local"
ProductVersion = "7.0.9466"
SchemaVersion = "1.0"
ProjectGuid = "{D2A9434D-59E4-43E9-8D9C-332AA138CEAD}"
>
<Build>
<Settings
ApplicationIcon = ""
AssemblyKeyContainerName = ""
AssemblyName = "netexp"
AssemblyOriginatorKeyFile = ""
DefaultClientScript = "JScript"
DefaultHTMLPageLayout = "Grid"
DefaultTargetSchema = "IE50"
DelaySign = "false"
OutputType = "Exe"
RootNamespace = "netexp"
StartupObject = ""
>
<Config
Name = "Debug"
AllowUnsafeBlocks = "false"
BaseAddress = "285212672"
CheckForOverflowUnderflow = "false"
ConfigurationOverrideFile = ""
DefineConstants = "DEBUG;TRACE"
DocumentationFile = ""
DebugSymbols = "true"
FileAlignment = "4096"
IncrementalBuild = "true"
Optimize = "false"
OutputPath = "bin\Debug\"
RegisterForComInterop = "false"
RemoveIntegerChecks = "false"
TreatWarningsAsErrors = "false"
WarningLevel = "4"
/>
<Config
Name = "Release"
AllowUnsafeBlocks = "false"
BaseAddress = "285212672"
CheckForOverflowUnderflow = "false"
ConfigurationOverrideFile = ""
DefineConstants = "TRACE"
DocumentationFile = ""
DebugSymbols = "true"
FileAlignment = "4096"
IncrementalBuild = "false"
Optimize = "true"
OutputPath = "bin\Release\"
RegisterForComInterop = "false"
RemoveIntegerChecks = "false"
TreatWarningsAsErrors = "false"
WarningLevel = "4"
/>
</Settings>
<References>
<Reference
Name = "System"
AssemblyName = "System"
HintPath = "..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.dll"
/>
<Reference
Name = "System.Data"
AssemblyName = "System.Data"
HintPath = "..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.Data.dll"
/>
<Reference
Name = "System.XML"
AssemblyName = "System.Xml"
HintPath = "..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.XML.dll"
/>
<Reference
Name = "classpath"
AssemblyName = "classpath"
HintPath = "..\classpath\classpath.dll"
/>
<Reference
Name = "IK.VM.NET"
Project = "{F5C7B588-0403-4AF2-A4DE-5697DE21BC2C}"
Package = "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"
/>
</References>
</Build>
<Files>
<Include>
<File
RelPath = "AssemblyInfo.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "ClassFileWriter.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "NetExp.cs"
SubType = "Code"
BuildAction = "Compile"
/>
</Include>
</Files>
</CSHARP>
</VisualStudioProject>