зеркало из https://github.com/mono/ikvm-fork.git
Initial revision
This commit is contained in:
Коммит
59d175f020
|
@ -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("")];
|
||||
|
|
@ -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>
|
|
@ -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"
|
|
@ -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>
|
|
@ -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);
|
||||
}
|
|
@ -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)));
|
||||
}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -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);
|
||||
};
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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>
|
||||
|
|
@ -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 });
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -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>
|
|
@ -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>
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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("")]
|
|
@ -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>
|
|
@ -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>
|
||||
|
|
@ -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
|
Двоичный файл не отображается.
Двоичный файл не отображается.
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -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 "<modifier> <classname>(<paramtypes>)
|
||||
* throws <exceptions>", 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 "<modifiers> <type>
|
||||
* <class>.<fieldname>".<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 "<modifiers> <returntype>
|
||||
* <methodname>(<paramtypes>) throws <exceptions>", 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
|
Двоичный файл не отображается.
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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>
|
|
@ -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
|
|
@ -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
|
|
@ -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>
|
|
@ -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>
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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,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
|
|
@ -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>
|
|
@ -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>
|
||||
|
|
@ -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,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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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())));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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>
|
|
@ -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>
|
||||
|
Загрузка…
Ссылка в новой задаче