/* Copyright (C) 2007, 2008, 2009 Jeroen Frijters Copyright (C) 2009 Volker Berlin (i-net software) 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.Generic; using System.Globalization; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Serialization; using System.Text; using System.Threading; using System.Runtime.InteropServices; using StackFrame = System.Diagnostics.StackFrame; using StackTrace = System.Diagnostics.StackTrace; using SystemArray = System.Array; using SystemDouble = System.Double; using SystemTimeZone = System.TimeZone; using SystemThreadingThread = System.Threading.Thread; using SystemThreadingThreadInterruptedException = System.Threading.ThreadInterruptedException; using SystemThreadingThreadPriority = System.Threading.ThreadPriority; using IKVM.Internal; #if !FIRST_PASS using jlClass = java.lang.Class; using jlClassLoader = java.lang.ClassLoader; using jlArrayIndexOutOfBoundsException = java.lang.ArrayIndexOutOfBoundsException; using jlClassNotFoundException = java.lang.ClassNotFoundException; using jlException = java.lang.Exception; using jlIllegalAccessException = java.lang.IllegalAccessException; using jlIllegalArgumentException = java.lang.IllegalArgumentException; using jlInterruptedException = java.lang.InterruptedException; using jlInternalError = java.lang.InternalError; using jlNegativeArraySizeException = java.lang.NegativeArraySizeException; using jlNoClassDefFoundError = java.lang.NoClassDefFoundError; using jlNullPointerException = java.lang.NullPointerException; using jlRunnable = java.lang.Runnable; using jlRuntimeException = java.lang.RuntimeException; using jlSecurityManager = java.lang.SecurityManager; using jlStackTraceElement = java.lang.StackTraceElement; using jlSystem = java.lang.System; using jlThread = java.lang.Thread; using jlThreadDeath = java.lang.ThreadDeath; using jlThreadGroup = java.lang.ThreadGroup; using jlRuntimePermission = java.lang.RuntimePermission; using jlBoolean = java.lang.Boolean; using jlByte = java.lang.Byte; using jlShort = java.lang.Short; using jlCharacter = java.lang.Character; using jlInteger = java.lang.Integer; using jlFloat = java.lang.Float; using jlLong = java.lang.Long; using jlDouble = java.lang.Double; using jlVoid = java.lang.Void; using jlNumber = java.lang.Number; using jlrConstructor = java.lang.reflect.Constructor; using jlrMethod = java.lang.reflect.Method; using jlrField = java.lang.reflect.Field; using jlrModifier = java.lang.reflect.Modifier; using jlrAccessibleObject = java.lang.reflect.AccessibleObject; using jlrInvocationTargetException = java.lang.reflect.InvocationTargetException; using ProtectionDomain = java.security.ProtectionDomain; using srMethodAccessor = sun.reflect.MethodAccessor; using srConstructorAccessor = sun.reflect.ConstructorAccessor; using srFieldAccessor = sun.reflect.FieldAccessor; using srLangReflectAccess = sun.reflect.LangReflectAccess; using srReflection = sun.reflect.Reflection; using srReflectionFactory = sun.reflect.ReflectionFactory; using jnByteBuffer = java.nio.ByteBuffer; using StubGenerator = ikvm.@internal.stubgen.StubGenerator; using Annotation = java.lang.annotation.Annotation; using smJavaIOAccess = sun.misc.JavaIOAccess; using smLauncher = sun.misc.Launcher; using smSharedSecrets = sun.misc.SharedSecrets; using smVM = sun.misc.VM; using jiConsole = java.io.Console; using jiIOException = java.io.IOException; using jiFile = java.io.File; using jiObjectStreamField = java.io.ObjectStreamField; using jnCharset = java.nio.charset.Charset; using juProperties = java.util.Properties; using irUtil = ikvm.runtime.Util; using iiFieldReflectorBase = ikvm.@internal.FieldReflectorBase; using juzZipFile = java.util.zip.ZipFile; using juzZipEntry = java.util.zip.ZipEntry; using juEnumeration = java.util.Enumeration; using jiInputStream = java.io.InputStream; using jsAccessController = java.security.AccessController; using jsAccessControlContext = java.security.AccessControlContext; using jsPrivilegedAction = java.security.PrivilegedAction; using jsPrivilegedExceptionAction = java.security.PrivilegedExceptionAction; using jsPrivilegedActionException = java.security.PrivilegedActionException; using jnUnknownHostException = java.net.UnknownHostException; using jnInetAddress = java.net.InetAddress; using jnInet4Address = java.net.Inet4Address; using jnInet6Address = java.net.Inet6Address; using jnNetworkInterface = java.net.NetworkInterface; using jnInterfaceAddress = java.net.InterfaceAddress; using ssaGetPropertyAction = sun.security.action.GetPropertyAction; #endif namespace IKVM.Runtime { public static class Assertions { private static bool sysAsserts; private static bool userAsserts; private static OptionNode classes; private static OptionNode packages; private class OptionNode { internal readonly string name; internal readonly bool enabled; internal readonly OptionNode next; internal OptionNode(string name, bool enabled, OptionNode next) { this.name = name; this.enabled = enabled; this.next = next; } } private static void AddOption(string classOrPackage, bool enabled) { if (classOrPackage == null) { throw new ArgumentNullException("classOrPackage"); } if (classOrPackage.EndsWith("...")) { packages = new OptionNode(classOrPackage.Substring(0, classOrPackage.Length - 3), enabled, packages); } else { classes = new OptionNode(classOrPackage, enabled, classes); } } public static void EnableAssertions(string classOrPackage) { AddOption(classOrPackage, true); } public static void DisableAssertions(string classOrPackage) { AddOption(classOrPackage, false); } public static void EnableAssertions() { userAsserts = true; } public static void DisableAssertions() { userAsserts = false; } public static void EnableSystemAssertions() { sysAsserts = true; } public static void DisableSystemAssertions() { sysAsserts = false; } internal static bool IsEnabled(TypeWrapper tw) { string className = tw.Name; // match class name for (OptionNode n = classes; n != null; n = n.next) { if (n.name == className) { return n.enabled; } } // match package name if (packages != null) { int len = className.Length; while (len > 0 && className[--len] != '.') ; do { for (OptionNode n = packages; n != null; n = n.next) { if (String.Compare(n.name, 0, className, 0, len, false, System.Globalization.CultureInfo.InvariantCulture) == 0 && len == n.name.Length) { return n.enabled; } } while (len > 0 && className[--len] != '.') ; } while (len > 0); } return tw.GetClassLoader() == ClassLoaderWrapper.GetBootstrapClassLoader() ? sysAsserts : userAsserts; } private static int Count(OptionNode n) { int count = 0; while (n != null) { count++; n = n.next; } return count; } internal static object RetrieveDirectives() { #if FIRST_PASS return null; #else java.lang.AssertionStatusDirectives asd = new java.lang.AssertionStatusDirectives(); string[] arrStrings = new string[Count(classes)]; bool[] arrBools = new bool[arrStrings.Length]; OptionNode n = classes; for (int i = 0; i < arrStrings.Length; i++) { arrStrings[i] = n.name; arrBools[i] = n.enabled; n = n.next; } asd.classes = arrStrings; asd.classEnabled = arrBools; arrStrings = new string[Count(packages)]; arrBools = new bool[arrStrings.Length]; n = packages; for (int i = 0; i < arrStrings.Length; i++) { arrStrings[i] = n.name; arrBools[i] = n.enabled; n = n.next; } asd.packages = arrStrings; asd.packageEnabled = arrBools; asd.deflt = userAsserts; return asd; #endif } } } static class DynamicMethodUtils { internal static DynamicMethod Create(string name, Type owner, bool nonPublic, Type returnType, Type[] paramTypes) { try { if (owner.IsInterface) { // FXBUG interfaces aren't allowed as owners of dynamic methods return new DynamicMethod(name, MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, returnType, paramTypes, owner.Module, true); } else { return new DynamicMethod(name, returnType, paramTypes, owner); } } catch (System.Security.SecurityException) { if (nonPublic && !RestrictedMemberAccess) { // we don't have RestrictedMemberAccess, so we stick the dynamic method in our module and hope for the best // (i.e. that we're trying to access something with assembly access in an assembly that lets us) return new DynamicMethod(name, returnType, paramTypes, typeof(DynamicMethodUtils).Module); } // apparently we don't have full trust, so we try again with .NET 2.0 SP1 method // and we only request restrictSkipVisibility if it is required return new DynamicMethod(name, returnType, paramTypes, nonPublic); } } private static bool RestrictedMemberAccess { get { try { new System.Security.Permissions.ReflectionPermission(System.Security.Permissions.ReflectionPermissionFlag.RestrictedMemberAccess).Demand(); return true; } catch (System.Security.SecurityException) { return false; } } } } namespace IKVM.NativeCode.java { namespace io { static class Console { public static string encoding() { int cp = 437; try { cp = global::System.Console.InputEncoding.CodePage; } catch { } if (cp >= 874 && cp <= 950) { return "ms" + cp; } return "cp" + cp; } private const int STD_INPUT_HANDLE = -10; private const int ENABLE_ECHO_INPUT = 0x0004; [System.Runtime.InteropServices.DllImport("kernel32")] private static extern IntPtr GetStdHandle(int nStdHandle); [System.Runtime.InteropServices.DllImport("kernel32")] private static extern int GetConsoleMode(IntPtr hConsoleHandle, out int lpMode); [System.Runtime.InteropServices.DllImport("kernel32")] private static extern int SetConsoleMode(IntPtr hConsoleHandle, int dwMode); public static bool echo(bool on) { #if !FIRST_PASS // HACK the only way to get this to work is by p/invoking the Win32 APIs if (Environment.OSVersion.Platform == PlatformID.Win32NT) { IntPtr hStdIn = GetStdHandle(STD_INPUT_HANDLE); if (hStdIn.ToInt64() == 0 || hStdIn.ToInt64() == -1) { throw new global::java.io.IOException("The handle is invalid"); } int fdwMode; if (GetConsoleMode(hStdIn, out fdwMode) == 0) { throw new global::java.io.IOException("GetConsoleMode failed"); } bool old = (fdwMode & ENABLE_ECHO_INPUT) != 0; if (on) { fdwMode |= ENABLE_ECHO_INPUT; } else { fdwMode &= ~ENABLE_ECHO_INPUT; } if (SetConsoleMode(hStdIn, fdwMode) == 0) { throw new global::java.io.IOException("SetConsoleMode failed"); } return old; } #endif return true; } public static bool istty() { // The JDK returns false here if stdin or stdout (not stderr) is redirected to a file // or if there is no console associated with the current process. // The best we can do is to look at the KeyAvailable property, which // will throw an InvalidOperationException if stdin is redirected or not available try { return global::System.Console.KeyAvailable || true; } catch (InvalidOperationException) { return false; } } } static class FileDescriptor { public static System.IO.Stream open(String name, System.IO.FileMode fileMode, System.IO.FileAccess fileAccess) { if (VirtualFileSystem.IsVirtualFS(name)) { return VirtualFileSystem.Open(name, fileMode, fileAccess); } else { return new System.IO.FileStream(name, fileMode, fileAccess, System.IO.FileShare.ReadWrite, 1, false); } } } static class FileSystem { public static object getFileSystem() { #if FIRST_PASS return null; #else if (JVM.IsUnix) { return new global::java.io.UnixFileSystem(); } else { return new global::java.io.Win32FileSystem(); } #endif } } static class ObjectInputStream { public static void bytesToFloats(byte[] src, int srcpos, float[] dst, int dstpos, int nfloats) { IKVM.Runtime.FloatConverter converter = new IKVM.Runtime.FloatConverter(); for (int i = 0; i < nfloats; i++) { int v = src[srcpos++]; v = (v << 8) | src[srcpos++]; v = (v << 8) | src[srcpos++]; v = (v << 8) | src[srcpos++]; dst[dstpos++] = IKVM.Runtime.FloatConverter.ToFloat(v, ref converter); } } public static void bytesToDoubles(byte[] src, int srcpos, double[] dst, int dstpos, int ndoubles) { IKVM.Runtime.DoubleConverter converter = new IKVM.Runtime.DoubleConverter(); for (int i = 0; i < ndoubles; i++) { long v = src[srcpos++]; v = (v << 8) | src[srcpos++]; v = (v << 8) | src[srcpos++]; v = (v << 8) | src[srcpos++]; v = (v << 8) | src[srcpos++]; v = (v << 8) | src[srcpos++]; v = (v << 8) | src[srcpos++]; v = (v << 8) | src[srcpos++]; dst[dstpos++] = IKVM.Runtime.DoubleConverter.ToDouble(v, ref converter); } } public static object latestUserDefinedLoader() { // testing shows that it is cheaper the get the full stack trace and then look at a few frames than getting the frames individually StackTrace trace = new StackTrace(2, false); for (int i = 0; i < trace.FrameCount; i++) { StackFrame frame = trace.GetFrame(i); MethodBase method = frame.GetMethod(); if (method == null) { continue; } Type type = method.DeclaringType; if (type != null) { TypeWrapper tw = ClassLoaderWrapper.GetWrapperFromType(type); if (tw != null) { ClassLoaderWrapper classLoader = tw.GetClassLoader(); AssemblyClassLoader acl = classLoader as AssemblyClassLoader; if (acl == null || acl.GetAssembly(tw) != typeof(object).Assembly) { object javaClassLoader = classLoader.GetJavaClassLoader(); if (javaClassLoader != null) { return javaClassLoader; } } } } } return null; } } static class ObjectOutputStream { public static void floatsToBytes(float[] src, int srcpos, byte[] dst, int dstpos, int nfloats) { IKVM.Runtime.FloatConverter converter = new IKVM.Runtime.FloatConverter(); for (int i = 0; i < nfloats; i++) { int v = IKVM.Runtime.FloatConverter.ToInt(src[srcpos++], ref converter); dst[dstpos++] = (byte)(v >> 24); dst[dstpos++] = (byte)(v >> 16); dst[dstpos++] = (byte)(v >> 8); dst[dstpos++] = (byte)(v >> 0); } } public static void doublesToBytes(double[] src, int srcpos, byte[] dst, int dstpos, int ndoubles) { IKVM.Runtime.DoubleConverter converter = new IKVM.Runtime.DoubleConverter(); for (int i = 0; i < ndoubles; i++) { long v = IKVM.Runtime.DoubleConverter.ToLong(src[srcpos++], ref converter); dst[dstpos++] = (byte)(v >> 56); dst[dstpos++] = (byte)(v >> 48); dst[dstpos++] = (byte)(v >> 40); dst[dstpos++] = (byte)(v >> 32); dst[dstpos++] = (byte)(v >> 24); dst[dstpos++] = (byte)(v >> 16); dst[dstpos++] = (byte)(v >> 8); dst[dstpos++] = (byte)(v >> 0); } } } public static class IOHelpers { public static void WriteByte(byte[] buf, int offset, byte value) { buf[offset] = value; } public static void WriteBoolean(byte[] buf, int offset, bool value) { buf[offset] = value ? (byte)1 : (byte)0; } public static void WriteChar(byte[] buf, int offset, char value) { buf[offset + 0] = (byte)(value >> 8); buf[offset + 1] = (byte)(value >> 0); } public static void WriteShort(byte[] buf, int offset, short value) { buf[offset + 0] = (byte)(value >> 8); buf[offset + 1] = (byte)(value >> 0); } public static void WriteInt(byte[] buf, int offset, int value) { buf[offset + 0] = (byte)(value >> 24); buf[offset + 1] = (byte)(value >> 16); buf[offset + 2] = (byte)(value >> 8); buf[offset + 3] = (byte)(value >> 0); } public static void WriteFloat(byte[] buf, int offset, float value) { #if !FIRST_PASS global::java.io.Bits.putFloat(buf, offset, value); #endif } public static void WriteLong(byte[] buf, int offset, long value) { WriteInt(buf, offset, (int)(value >> 32)); WriteInt(buf, offset + 4, (int)value); } public static void WriteDouble(byte[] buf, int offset, double value) { #if !FIRST_PASS global::java.io.Bits.putDouble(buf, offset, value); #endif } public static byte ReadByte(byte[] buf, int offset) { return buf[offset]; } public static bool ReadBoolean(byte[] buf, int offset) { return buf[offset] != 0; } public static char ReadChar(byte[] buf, int offset) { return (char)((buf[offset] << 8) + buf[offset + 1]); } public static short ReadShort(byte[] buf, int offset) { return (short)((buf[offset] << 8) + buf[offset + 1]); } public static int ReadInt(byte[] buf, int offset) { return (buf[offset + 0] << 24) + (buf[offset + 1] << 16) + (buf[offset + 2] << 8) + (buf[offset + 3] << 0); } public static float ReadFloat(byte[] buf, int offset) { #if FIRST_PASS return 0; #else return jlFloat.intBitsToFloat(ReadInt(buf, offset)); #endif } public static long ReadLong(byte[] buf, int offset) { long hi = (uint)ReadInt(buf, offset); long lo = (uint)ReadInt(buf, offset + 4); return lo + (hi << 32); } public static double ReadDouble(byte[] buf, int offset) { #if FIRST_PASS return 0; #else return jlDouble.longBitsToDouble(ReadLong(buf, offset)); #endif } } static class ObjectStreamClass { private static bool runClassInit; public static void initNative() { #if !FIRST_PASS // HACK if we're being run from ikvmstub, don't run the static initializer runClassInit = !"true".Equals(ClassLoaderWrapper.DoPrivileged(new global::sun.security.action.GetPropertyAction("ikvm.stubgen.serialver"))); #endif } public static bool isDynamicTypeWrapper(object cl) { TypeWrapper wrapper = TypeWrapper.FromClass(cl); return !wrapper.IsFastClassLiteralSafe; } public static bool hasStaticInitializer(object cl) { TypeWrapper wrapper = TypeWrapper.FromClass(cl); try { wrapper.Finish(); } catch (RetargetableJavaException x) { throw x.ToJava(); } Type type = wrapper.TypeAsTBD; if (!type.IsArray && type.TypeInitializer != null) { if (runClassInit) { wrapper.RunClassInit(); } return !AttributeHelper.IsHideFromJava(type.TypeInitializer); } return false; } #if !FIRST_PASS private sealed class FastFieldReflector : iiFieldReflectorBase { private static readonly MethodInfo ReadByteMethod = typeof(IOHelpers).GetMethod("ReadByte"); private static readonly MethodInfo ReadBooleanMethod = typeof(IOHelpers).GetMethod("ReadBoolean"); private static readonly MethodInfo ReadCharMethod = typeof(IOHelpers).GetMethod("ReadChar"); private static readonly MethodInfo ReadShortMethod = typeof(IOHelpers).GetMethod("ReadShort"); private static readonly MethodInfo ReadIntMethod = typeof(IOHelpers).GetMethod("ReadInt"); private static readonly MethodInfo ReadFloatMethod = typeof(IOHelpers).GetMethod("ReadFloat"); private static readonly MethodInfo ReadLongMethod = typeof(IOHelpers).GetMethod("ReadLong"); private static readonly MethodInfo ReadDoubleMethod = typeof(IOHelpers).GetMethod("ReadDouble"); private static readonly MethodInfo WriteByteMethod = typeof(IOHelpers).GetMethod("WriteByte"); private static readonly MethodInfo WriteBooleanMethod = typeof(IOHelpers).GetMethod("WriteBoolean"); private static readonly MethodInfo WriteCharMethod = typeof(IOHelpers).GetMethod("WriteChar"); private static readonly MethodInfo WriteShortMethod = typeof(IOHelpers).GetMethod("WriteShort"); private static readonly MethodInfo WriteIntMethod = typeof(IOHelpers).GetMethod("WriteInt"); private static readonly MethodInfo WriteFloatMethod = typeof(IOHelpers).GetMethod("WriteFloat"); private static readonly MethodInfo WriteLongMethod = typeof(IOHelpers).GetMethod("WriteLong"); private static readonly MethodInfo WriteDoubleMethod = typeof(IOHelpers).GetMethod("WriteDouble"); private delegate void ObjFieldGetterSetter(object obj, object[] objarr); private delegate void PrimFieldGetterSetter(object obj, byte[] objarr); private static readonly ObjFieldGetterSetter objDummy = new ObjFieldGetterSetter(Dummy); private static readonly PrimFieldGetterSetter primDummy = new PrimFieldGetterSetter(Dummy); private jiObjectStreamField[] fields; private ObjFieldGetterSetter objFieldGetter; private PrimFieldGetterSetter primFieldGetter; private ObjFieldGetterSetter objFieldSetter; private PrimFieldGetterSetter primFieldSetter; private static void Dummy(object obj, object[] objarr) { } private static void Dummy(object obj, byte[] barr) { } internal FastFieldReflector(jiObjectStreamField[] fields) { this.fields = fields; TypeWrapper tw = null; foreach (jiObjectStreamField field in fields) { FieldWrapper fw = GetFieldWrapper(field); if (fw != null) { if (tw == null) { tw = fw.DeclaringType; } else if (tw != fw.DeclaringType) { // pre-condition is that all fields are from the same Type! throw new jlInternalError(); } } } if (tw == null) { objFieldGetter = objFieldSetter = objDummy; primFieldGetter = primFieldSetter = primDummy; } else { try { tw.Finish(); } catch (RetargetableJavaException x) { throw x.ToJava(); } DynamicMethod dmObjGetter = DynamicMethodUtils.Create("__", tw.TypeAsBaseType, true, null, new Type[] { typeof(object), typeof(object[]) }); DynamicMethod dmPrimGetter = DynamicMethodUtils.Create("__", tw.TypeAsBaseType, true, null, new Type[] { typeof(object), typeof(byte[]) }); DynamicMethod dmObjSetter = DynamicMethodUtils.Create("__", tw.TypeAsBaseType, true, null, new Type[] { typeof(object), typeof(object[]) }); DynamicMethod dmPrimSetter = DynamicMethodUtils.Create("__", tw.TypeAsBaseType, true, null, new Type[] { typeof(object), typeof(byte[]) }); CodeEmitter ilgenObjGetter = CodeEmitter.Create(dmObjGetter); CodeEmitter ilgenPrimGetter = CodeEmitter.Create(dmPrimGetter); CodeEmitter ilgenObjSetter = CodeEmitter.Create(dmObjSetter); CodeEmitter ilgenPrimSetter = CodeEmitter.Create(dmPrimSetter); // we want the getters to be verifiable (because writeObject can be used from partial trust), // so we create a local to hold the properly typed object reference LocalBuilder objGetterThis = ilgenObjGetter.DeclareLocal(tw.TypeAsBaseType); LocalBuilder primGetterThis = ilgenPrimGetter.DeclareLocal(tw.TypeAsBaseType); ilgenObjGetter.Emit(OpCodes.Ldarg_0); ilgenObjGetter.Emit(OpCodes.Castclass, tw.TypeAsBaseType); ilgenObjGetter.Emit(OpCodes.Stloc, objGetterThis); ilgenPrimGetter.Emit(OpCodes.Ldarg_0); ilgenPrimGetter.Emit(OpCodes.Castclass, tw.TypeAsBaseType); ilgenPrimGetter.Emit(OpCodes.Stloc, primGetterThis); foreach (jiObjectStreamField field in fields) { FieldWrapper fw = GetFieldWrapper(field); if (fw == null) { continue; } fw.ResolveField(); TypeWrapper fieldType = fw.FieldTypeWrapper; try { fieldType.Finish(); } catch (RetargetableJavaException x) { throw x.ToJava(); } if (fieldType.IsPrimitive) { // Getter ilgenPrimGetter.Emit(OpCodes.Ldarg_1); ilgenPrimGetter.Emit(OpCodes.Ldc_I4, field.getOffset()); ilgenPrimGetter.Emit(OpCodes.Ldloc, primGetterThis); fw.EmitGet(ilgenPrimGetter); if (fieldType == PrimitiveTypeWrapper.BYTE) { ilgenPrimGetter.Emit(OpCodes.Call, WriteByteMethod); } else if (fieldType == PrimitiveTypeWrapper.BOOLEAN) { ilgenPrimGetter.Emit(OpCodes.Call, WriteBooleanMethod); } else if (fieldType == PrimitiveTypeWrapper.CHAR) { ilgenPrimGetter.Emit(OpCodes.Call, WriteCharMethod); } else if (fieldType == PrimitiveTypeWrapper.SHORT) { ilgenPrimGetter.Emit(OpCodes.Call, WriteShortMethod); } else if (fieldType == PrimitiveTypeWrapper.INT) { ilgenPrimGetter.Emit(OpCodes.Call, WriteIntMethod); } else if (fieldType == PrimitiveTypeWrapper.FLOAT) { ilgenPrimGetter.Emit(OpCodes.Call, WriteFloatMethod); } else if (fieldType == PrimitiveTypeWrapper.LONG) { ilgenPrimGetter.Emit(OpCodes.Call, WriteLongMethod); } else if (fieldType == PrimitiveTypeWrapper.DOUBLE) { ilgenPrimGetter.Emit(OpCodes.Call, WriteDoubleMethod); } else { throw new jlInternalError(); } // Setter ilgenPrimSetter.Emit(OpCodes.Ldarg_0); ilgenPrimSetter.Emit(OpCodes.Castclass, tw.TypeAsBaseType); ilgenPrimSetter.Emit(OpCodes.Ldarg_1); ilgenPrimSetter.Emit(OpCodes.Ldc_I4, field.getOffset()); if (fieldType == PrimitiveTypeWrapper.BYTE) { ilgenPrimSetter.Emit(OpCodes.Call, ReadByteMethod); } else if (fieldType == PrimitiveTypeWrapper.BOOLEAN) { ilgenPrimSetter.Emit(OpCodes.Call, ReadBooleanMethod); } else if (fieldType == PrimitiveTypeWrapper.CHAR) { ilgenPrimSetter.Emit(OpCodes.Call, ReadCharMethod); } else if (fieldType == PrimitiveTypeWrapper.SHORT) { ilgenPrimSetter.Emit(OpCodes.Call, ReadShortMethod); } else if (fieldType == PrimitiveTypeWrapper.INT) { ilgenPrimSetter.Emit(OpCodes.Call, ReadIntMethod); } else if (fieldType == PrimitiveTypeWrapper.FLOAT) { ilgenPrimSetter.Emit(OpCodes.Call, ReadFloatMethod); } else if (fieldType == PrimitiveTypeWrapper.LONG) { ilgenPrimSetter.Emit(OpCodes.Call, ReadLongMethod); } else if (fieldType == PrimitiveTypeWrapper.DOUBLE) { ilgenPrimSetter.Emit(OpCodes.Call, ReadDoubleMethod); } else { throw new jlInternalError(); } fw.EmitSet(ilgenPrimSetter); } else { // Getter ilgenObjGetter.Emit(OpCodes.Ldarg_1); ilgenObjGetter.Emit(OpCodes.Ldc_I4, field.getOffset()); ilgenObjGetter.Emit(OpCodes.Ldloc, objGetterThis); fw.EmitGet(ilgenObjGetter); fw.FieldTypeWrapper.EmitConvSignatureTypeToStackType(ilgenObjGetter); ilgenObjGetter.Emit(OpCodes.Stelem_Ref); // Setter ilgenObjSetter.Emit(OpCodes.Ldarg_0); ilgenObjSetter.Emit(OpCodes.Ldarg_1); ilgenObjSetter.Emit(OpCodes.Ldc_I4, field.getOffset()); ilgenObjSetter.Emit(OpCodes.Ldelem_Ref); fw.FieldTypeWrapper.EmitCheckcast(null, ilgenObjSetter); fw.FieldTypeWrapper.EmitConvStackTypeToSignatureType(ilgenObjSetter, null); fw.EmitSet(ilgenObjSetter); } } ilgenObjGetter.Emit(OpCodes.Ret); ilgenPrimGetter.Emit(OpCodes.Ret); ilgenObjSetter.Emit(OpCodes.Ret); ilgenPrimSetter.Emit(OpCodes.Ret); objFieldGetter = (ObjFieldGetterSetter)dmObjGetter.CreateDelegate(typeof(ObjFieldGetterSetter)); primFieldGetter = (PrimFieldGetterSetter)dmPrimGetter.CreateDelegate(typeof(PrimFieldGetterSetter)); objFieldSetter = (ObjFieldGetterSetter)dmObjSetter.CreateDelegate(typeof(ObjFieldGetterSetter)); primFieldSetter = (PrimFieldGetterSetter)dmPrimSetter.CreateDelegate(typeof(PrimFieldGetterSetter)); } } private static FieldWrapper GetFieldWrapper(jiObjectStreamField field) { jlrField f = field.getField(); return f == null ? null : FieldWrapper.FromField(f); } public override jiObjectStreamField[] getFields() { return fields; } public override void getObjFieldValues(object obj, object[] objarr) { objFieldGetter(obj, objarr); } public override void setObjFieldValues(object obj, object[] objarr) { objFieldSetter(obj, objarr); } public override void getPrimFieldValues(object obj, byte[] barr) { primFieldGetter(obj, barr); } public override void setPrimFieldValues(object obj, byte[] barr) { primFieldSetter(obj, barr); } } #endif // !FIRST_PASS public static object getFastFieldReflector(object fieldsObj) { #if FIRST_PASS return null; #else return new FastFieldReflector((jiObjectStreamField[])fieldsObj); #endif } } static class Win32FileSystem { internal const int ACCESS_READ = 0x04; const int ACCESS_WRITE = 0x02; const int ACCESS_EXECUTE = 0x01; public static string getDriveDirectory(object _this, int drive) { try { string path = ((char)('A' + (drive - 1))) + ":"; return System.IO.Path.GetFullPath(path).Substring(2); } catch (ArgumentException) { } catch (System.Security.SecurityException) { } catch (System.IO.PathTooLongException) { } return "\\"; } private static string CanonicalizePath(string path) { try { System.IO.FileInfo fi = new System.IO.FileInfo(path); if (fi.DirectoryName == null) { return path.Length > 1 && path[1] == ':' ? path.ToUpper() : path; } string dir = CanonicalizePath(fi.DirectoryName); string name = fi.Name; try { if (!VirtualFileSystem.IsVirtualFS(path)) { string[] arr = System.IO.Directory.GetFileSystemEntries(dir, name); if (arr.Length == 1) { name = arr[0]; } } } catch (System.UnauthorizedAccessException) { } catch (System.IO.IOException) { } return System.IO.Path.Combine(dir, name); } catch (System.UnauthorizedAccessException) { } catch (System.IO.IOException) { } catch (System.Security.SecurityException) { } catch (System.NotSupportedException) { } return path; } public static string canonicalize0(object _this, string path) { #if FIRST_PASS return null; #else try { // TODO there is still a known bug here. A dotted path component right after the root component // are not removed as they should be. E.g. "c:\..." => "C:\..." or "\\server\..." => IOException // Another know issue is that when running under Mono on Windows, the case names aren't converted // to the correct (on file system) casing. // // FXBUG we're appending the directory separator to work around an apparent .NET bug. // If we don't do this, "c:\j\." would be canonicalized to "C:\" int colon = path.IndexOf(':', 2); if (colon != -1) { return CanonicalizePath(path.Substring(0, colon) + System.IO.Path.DirectorySeparatorChar) + path.Substring(colon); } return CanonicalizePath(path + System.IO.Path.DirectorySeparatorChar); } catch (System.ArgumentException x) { throw new jiIOException(x.Message); } #endif } public static string canonicalizeWithPrefix0(object _this, string canonicalPrefix, string pathWithCanonicalPrefix) { return canonicalize0(_this, pathWithCanonicalPrefix); } private static string GetPathFromFile(object file) { #if FIRST_PASS return null; #else return ((jiFile)file).getPath(); #endif } public static int getBooleanAttributes(object _this, object f) { try { string path = GetPathFromFile(f); if (VirtualFileSystem.IsVirtualFS(path)) { return VirtualFileSystem.GetBooleanAttributes(path); } System.IO.FileAttributes attr = System.IO.File.GetAttributes(path); const int BA_EXISTS = 0x01; const int BA_REGULAR = 0x02; const int BA_DIRECTORY = 0x04; const int BA_HIDDEN = 0x08; int rv = BA_EXISTS; if ((attr & System.IO.FileAttributes.Directory) != 0) { rv |= BA_DIRECTORY; } else { rv |= BA_REGULAR; } if ((attr & System.IO.FileAttributes.Hidden) != 0) { rv |= BA_HIDDEN; } return rv; } catch (System.ArgumentException) { } catch (System.UnauthorizedAccessException) { } catch (System.Security.SecurityException) { } catch (System.NotSupportedException) { } catch (System.IO.IOException) { } return 0; } public static bool checkAccess(object _this, object f, int access) { string path = GetPathFromFile(f); if (VirtualFileSystem.IsVirtualFS(path)) { return VirtualFileSystem.CheckAccess(path, access); } bool ok = true; if ((access & (ACCESS_READ | ACCESS_EXECUTE)) != 0) { ok = false; try { // HACK if path refers to a directory, we always return true if (!System.IO.Directory.Exists(path)) { new System.IO.FileInfo(path).Open( System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.ReadWrite).Close(); } ok = true; } catch (System.Security.SecurityException) { } catch (System.ArgumentException) { } catch (System.UnauthorizedAccessException) { } catch (System.IO.IOException) { } catch (System.NotSupportedException) { } } if (ok && ((access & ACCESS_WRITE) != 0)) { ok = false; try { System.IO.FileInfo fileInfo = new System.IO.FileInfo(path); // Like the JDK we'll only look at the read-only attribute and not // the security permissions associated with the file or directory. ok = (fileInfo.Attributes & System.IO.FileAttributes.ReadOnly) == 0; } catch (System.Security.SecurityException) { } catch (System.ArgumentException) { } catch (System.UnauthorizedAccessException) { } catch (System.IO.IOException) { } catch (System.NotSupportedException) { } } return ok; } private static long DateTimeToJavaLongTime(System.DateTime datetime) { return (System.TimeZone.CurrentTimeZone.ToUniversalTime(datetime) - new System.DateTime(1970, 1, 1)).Ticks / 10000L; } private static System.DateTime JavaLongTimeToDateTime(long datetime) { return System.TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(new System.DateTime(1970, 1, 1).Ticks + datetime * 10000L)); } public static long getLastModifiedTime(object _this, object f) { try { return DateTimeToJavaLongTime(System.IO.File.GetLastWriteTime(GetPathFromFile(f))); } catch (System.UnauthorizedAccessException) { } catch (System.ArgumentException) { } catch (System.IO.IOException) { } catch (System.NotSupportedException) { } return 0; } public static long getLength(object _this, object f) { try { string path = GetPathFromFile(f); if (VirtualFileSystem.IsVirtualFS(path)) { return VirtualFileSystem.GetLength(path); } return new System.IO.FileInfo(path).Length; } catch (System.Security.SecurityException) { } catch (System.ArgumentException) { } catch (System.UnauthorizedAccessException) { } catch (System.IO.IOException) { } catch (System.NotSupportedException) { } return 0; } public static bool setPermission(object _this, object f, int access, bool enable, bool owneronly) { if ((access & ACCESS_WRITE) != 0) { try { System.IO.FileInfo file = new System.IO.FileInfo(GetPathFromFile(f)); if (enable) { file.Attributes &= ~System.IO.FileAttributes.ReadOnly; } else { file.Attributes |= System.IO.FileAttributes.ReadOnly; } return true; } catch (System.Security.SecurityException) { } catch (System.ArgumentException) { } catch (System.UnauthorizedAccessException) { } catch (System.IO.IOException) { } catch (System.NotSupportedException) { } return false; } return enable; } public static bool createFileExclusively(object _this, string path) { #if !FIRST_PASS try { System.IO.File.Open(path, System.IO.FileMode.CreateNew, System.IO.FileAccess.ReadWrite, System.IO.FileShare.None).Close(); return true; } catch (System.ArgumentException x) { throw new jiIOException(x.Message); } catch (System.IO.IOException x) { if (!System.IO.File.Exists(path) && !System.IO.Directory.Exists(path)) { throw new jiIOException(x.Message); } } catch (System.UnauthorizedAccessException x) { throw new jiIOException(x.Message); } catch (System.NotSupportedException x) { throw new jiIOException(x.Message); } #endif return false; } public static bool delete0(object _this, object f) { System.IO.FileSystemInfo fileInfo = null; try { string path = GetPathFromFile(f); if (System.IO.Directory.Exists(path)) { fileInfo = new System.IO.DirectoryInfo(path); } else if (System.IO.File.Exists(path)) { fileInfo = new System.IO.FileInfo(path); } else { return false; } // We need to be able to delete read-only files/dirs too, so we clear // the read-only attribute, if set. if ((fileInfo.Attributes & System.IO.FileAttributes.ReadOnly) != 0) { fileInfo.Attributes &= ~System.IO.FileAttributes.ReadOnly; } fileInfo.Delete(); return true; } catch (System.Security.SecurityException) { } catch (System.ArgumentException) { } catch (System.UnauthorizedAccessException) { } catch (System.IO.IOException) { } catch (System.NotSupportedException) { } return false; } public static string[] list(object _this, object f) { try { string path = GetPathFromFile(f); if (VirtualFileSystem.IsVirtualFS(path)) { return VirtualFileSystem.List(path); } string[] l = System.IO.Directory.GetFileSystemEntries(path); for (int i = 0; i < l.Length; i++) { int pos = l[i].LastIndexOf(System.IO.Path.DirectorySeparatorChar); if (pos >= 0) { l[i] = l[i].Substring(pos + 1); } } return l; } catch (System.ArgumentException) { } catch (System.IO.IOException) { } catch (System.UnauthorizedAccessException) { } catch (System.NotSupportedException) { } return null; } public static bool createDirectory(object _this, object f) { try { string path = GetPathFromFile(f); System.IO.DirectoryInfo parent = System.IO.Directory.GetParent(path); if (parent == null || !System.IO.Directory.Exists(parent.FullName) || System.IO.Directory.Exists(path)) { return false; } return System.IO.Directory.CreateDirectory(path) != null; } catch (System.Security.SecurityException) { } catch (System.ArgumentException) { } catch (System.UnauthorizedAccessException) { } catch (System.IO.IOException) { } catch (System.NotSupportedException) { } return false; } public static bool rename0(object _this, object f1, object f2) { try { new System.IO.FileInfo(GetPathFromFile(f1)).MoveTo(GetPathFromFile(f2)); return true; } catch (System.Security.SecurityException) { } catch (System.ArgumentException) { } catch (System.UnauthorizedAccessException) { } catch (System.IO.IOException) { } catch (System.NotSupportedException) { } return false; } public static bool setLastModifiedTime(object _this, object f, long time) { try { new System.IO.FileInfo(GetPathFromFile(f)).LastWriteTime = JavaLongTimeToDateTime(time); return true; } catch (System.Security.SecurityException) { } catch (System.ArgumentException) { } catch (System.UnauthorizedAccessException) { } catch (System.IO.IOException) { } catch (System.NotSupportedException) { } return false; } public static bool setReadOnly(object _this, object f) { try { System.IO.FileInfo fileInfo = new System.IO.FileInfo(GetPathFromFile(f)); fileInfo.Attributes |= System.IO.FileAttributes.ReadOnly; return true; } catch (System.Security.SecurityException) { } catch (System.ArgumentException) { } catch (System.UnauthorizedAccessException) { } catch (System.IO.IOException) { } catch (System.NotSupportedException) { } return false; } public static int listRoots0() { try { int drives = 0; foreach (string drive in System.IO.Directory.GetLogicalDrives()) { char c = Char.ToUpper(drive[0]); drives |= 1 << (c - 'A'); } return drives; } catch (System.IO.IOException) { } catch (System.UnauthorizedAccessException) { } return 0; } public static long getSpace0(object _this, object f, int t) { const int SPACE_TOTAL = 0; const int SPACE_FREE = 1; const int SPACE_USABLE = 2; long freeAvailable; long total; long totalFree; if (GetDiskFreeSpaceEx(GetPathFromFile(f), out freeAvailable, out total, out totalFree) != 0) { switch (t) { case SPACE_TOTAL: return total; case SPACE_FREE: return totalFree; case SPACE_USABLE: return freeAvailable; } } return 0; } [System.Runtime.InteropServices.DllImport("kernel32")] private static extern int GetDiskFreeSpaceEx(string directory, out long freeAvailable, out long total, out long totalFree); public static void initIDs() { } } static class UnixFileSystem { public static int getBooleanAttributes0(object _this, object f) { return Win32FileSystem.getBooleanAttributes(_this, f); } public static long getSpace(object _this, object f, int t) { // TODO return 0; } public static string getDriveDirectory(object _this, int drive) { return Win32FileSystem.getDriveDirectory(_this, drive); } public static string canonicalize0(object _this, string path) { return Win32FileSystem.canonicalize0(_this, path); } public static bool checkAccess(object _this, object f, int access) { return Win32FileSystem.checkAccess(_this, f, access); } public static long getLastModifiedTime(object _this, object f) { return Win32FileSystem.getLastModifiedTime(_this, f); } public static long getLength(object _this, object f) { return Win32FileSystem.getLength(_this, f); } public static bool setPermission(object _this, object f, int access, bool enable, bool owneronly) { // TODO consider using Mono.Posix return Win32FileSystem.setPermission(_this, f, access, enable, owneronly); } public static bool createFileExclusively(object _this, string path) { return Win32FileSystem.createFileExclusively(_this, path); } public static bool delete0(object _this, object f) { return Win32FileSystem.delete0(_this, f); } public static string[] list(object _this, object f) { return Win32FileSystem.list(_this, f); } public static bool createDirectory(object _this, object f) { return Win32FileSystem.createDirectory(_this, f); } public static bool rename0(object _this, object f1, object f2) { return Win32FileSystem.rename0(_this, f1, f2); } public static bool setLastModifiedTime(object _this, object f, long time) { return Win32FileSystem.setLastModifiedTime(_this, f, time); } public static bool setReadOnly(object _this, object f) { return Win32FileSystem.setReadOnly(_this, f); } public static void initIDs() { } } } namespace lang { namespace reflect { static class Array { #if FIRST_PASS public static int getLength(object arrayObj) { return 0; } public static object get(object arrayObj, int index) { return null; } public static bool getBoolean(object arrayObj, int index) { return false; } public static byte getByte(object arrayObj, int index) { return 0; } public static char getChar(object arrayObj, int index) { return '\u0000'; } public static short getShort(object arrayObj, int index) { return 0; } public static int getInt(object arrayObj, int index) { return 0; } public static float getFloat(object arrayObj, int index) { return 0; } public static long getLong(object arrayObj, int index) { return 0; } public static double getDouble(object arrayObj, int index) { return 0; } public static void set(object arrayObj, int index, object value) { } public static void setBoolean(object arrayObj, int index, bool value) { } public static void setByte(object arrayObj, int index, byte value) { } public static void setChar(object arrayObj, int index, char value) { } public static void setShort(object arrayObj, int index, short value) { } public static void setInt(object arrayObj, int index, int value) { } public static void setFloat(object arrayObj, int index, float value) { } public static void setLong(object arrayObj, int index, long value) { } public static void setDouble(object arrayObj, int index, double value) { } public static object newArray(object componentType, int length) { return null; } public static object multiNewArray(object componentType, int[] dimensions) { return null; } #else private static SystemArray CheckArray(object arrayObj) { if (arrayObj == null) { throw new jlNullPointerException(); } SystemArray arr = arrayObj as SystemArray; if (arr != null) { return arr; } throw new jlIllegalArgumentException("Argument is not an array"); } public static int getLength(object arrayObj) { return CheckArray(arrayObj).Length; } public static object get(object arrayObj, int index) { SystemArray arr = CheckArray(arrayObj); if (index < 0 || index >= arr.Length) { throw new jlArrayIndexOutOfBoundsException(); } // We need to look at the actual type here, because "is" or "as" // will convert enums to their underlying type and unsigned integral types // to their signed counter parts. Type type = arrayObj.GetType(); if (type == typeof(bool[])) { return jlBoolean.valueOf(((bool[])arr)[index]); } if (type == typeof(byte[])) { return jlByte.valueOf(((byte[])arr)[index]); } if (type == typeof(short[])) { return jlShort.valueOf(((short[])arr)[index]); } if (type == typeof(char[])) { return jlCharacter.valueOf(((char[])arr)[index]); } if (type == typeof(int[])) { return jlInteger.valueOf(((int[])arr)[index]); } if (type == typeof(float[])) { return jlFloat.valueOf(((float[])arr)[index]); } if (type == typeof(long[])) { return jlLong.valueOf(((long[])arr)[index]); } if (type == typeof(double[])) { return jlDouble.valueOf(((double[])arr)[index]); } return arr.GetValue(index); } public static bool getBoolean(object arrayObj, int index) { if (arrayObj == null) { throw new jlNullPointerException(); } bool[] arr = arrayObj as bool[]; if (arr != null) { if (index < 0 || index >= arr.Length) { throw new jlArrayIndexOutOfBoundsException(); } return arr[index]; } throw new jlIllegalArgumentException("argument type mismatch"); } public static byte getByte(object arrayObj, int index) { if (arrayObj == null) { throw new jlNullPointerException(); } byte[] arr = arrayObj as byte[]; if (arr != null) { if (index < 0 || index >= arr.Length) { throw new jlArrayIndexOutOfBoundsException(); } return arr[index]; } throw new jlIllegalArgumentException("argument type mismatch"); } public static char getChar(object arrayObj, int index) { if (arrayObj == null) { throw new jlNullPointerException(); } char[] arr = arrayObj as char[]; if (arr != null) { if (index < 0 || index >= arr.Length) { throw new jlArrayIndexOutOfBoundsException(); } return arr[index]; } throw new jlIllegalArgumentException("argument type mismatch"); } public static short getShort(object arrayObj, int index) { if (arrayObj == null) { throw new jlNullPointerException(); } short[] arr = arrayObj as short[]; if (arr != null) { if (index < 0 || index >= arr.Length) { throw new jlArrayIndexOutOfBoundsException(); } return arr[index]; } return (sbyte)getByte(arrayObj, index); } public static int getInt(object arrayObj, int index) { if (arrayObj == null) { throw new jlNullPointerException(); } int[] arr1 = arrayObj as int[]; if (arr1 != null) { if (index < 0 || index >= arr1.Length) { throw new jlArrayIndexOutOfBoundsException(); } return arr1[index]; } char[] arr2 = arrayObj as char[]; if (arr2 != null) { if (index < 0 || index >= arr2.Length) { throw new jlArrayIndexOutOfBoundsException(); } return arr2[index]; } return getShort(arrayObj, index); } public static float getFloat(object arrayObj, int index) { if (arrayObj == null) { throw new jlNullPointerException(); } float[] arr = arrayObj as float[]; if (arr != null) { if (index < 0 || index >= arr.Length) { throw new jlArrayIndexOutOfBoundsException(); } return arr[index]; } return getLong(arrayObj, index); } public static long getLong(object arrayObj, int index) { if (arrayObj == null) { throw new jlNullPointerException(); } long[] arr = arrayObj as long[]; if (arr != null) { if (index < 0 || index >= arr.Length) { throw new jlArrayIndexOutOfBoundsException(); } return arr[index]; } return getInt(arrayObj, index); } public static double getDouble(object arrayObj, int index) { if (arrayObj == null) { throw new jlNullPointerException(); } double[] arr = arrayObj as double[]; if (arr != null) { if (index < 0 || index >= arr.Length) { throw new jlArrayIndexOutOfBoundsException(); } return arr[index]; } return getFloat(arrayObj, index); } public static void set(object arrayObj, int index, object value) { if (arrayObj == null) { throw new jlNullPointerException(); } Type type = arrayObj.GetType(); if (type.IsArray && ClassLoaderWrapper.GetWrapperFromType(type.GetElementType()).IsPrimitive) { jlBoolean booleanValue = value as jlBoolean; if (booleanValue != null) { setBoolean(arrayObj, index, booleanValue.booleanValue()); return; } jlByte byteValue = value as jlByte; if (byteValue != null) { setByte(arrayObj, index, byteValue.byteValue()); return; } jlCharacter charValue = value as jlCharacter; if (charValue != null) { setChar(arrayObj, index, charValue.charValue()); return; } jlShort shortValue = value as jlShort; if (shortValue != null) { setShort(arrayObj, index, shortValue.shortValue()); return; } jlInteger intValue = value as jlInteger; if (intValue != null) { setInt(arrayObj, index, intValue.intValue()); return; } jlFloat floatValue = value as jlFloat; if (floatValue != null) { setFloat(arrayObj, index, floatValue.floatValue()); return; } jlLong longValue = value as jlLong; if (longValue != null) { setLong(arrayObj, index, longValue.longValue()); return; } jlDouble doubleValue = value as jlDouble; if (doubleValue != null) { setDouble(arrayObj, index, doubleValue.doubleValue()); return; } } try { CheckArray(arrayObj).SetValue(value, index); } catch (InvalidCastException) { throw new jlIllegalArgumentException("argument type mismatch"); } catch (IndexOutOfRangeException) { throw new jlArrayIndexOutOfBoundsException(); } } public static void setBoolean(object arrayObj, int index, bool value) { if (arrayObj == null) { throw new jlNullPointerException(); } bool[] arr = arrayObj as bool[]; if (arr != null) { if (index < 0 || index >= arr.Length) { throw new jlArrayIndexOutOfBoundsException(); } arr[index] = value; } else { throw new jlIllegalArgumentException("argument type mismatch"); } } public static void setByte(object arrayObj, int index, byte value) { if (arrayObj == null) { throw new jlNullPointerException(); } byte[] arr = arrayObj as byte[]; if (arr != null) { if (index < 0 || index >= arr.Length) { throw new jlArrayIndexOutOfBoundsException(); } arr[index] = value; } else { setShort(arrayObj, index, (sbyte)value); } } public static void setChar(object arrayObj, int index, char value) { if (arrayObj == null) { throw new jlNullPointerException(); } char[] arr = arrayObj as char[]; if (arr != null) { if (index < 0 || index >= arr.Length) { throw new jlArrayIndexOutOfBoundsException(); } arr[index] = value; } else { setInt(arrayObj, index, value); } } public static void setShort(object arrayObj, int index, short value) { if (arrayObj == null) { throw new jlNullPointerException(); } short[] arr = arrayObj as short[]; if (arr != null) { if (index < 0 || index >= arr.Length) { throw new jlArrayIndexOutOfBoundsException(); } arr[index] = value; } else { setInt(arrayObj, index, value); } } public static void setInt(object arrayObj, int index, int value) { if (arrayObj == null) { throw new jlNullPointerException(); } int[] arr = arrayObj as int[]; if (arr != null) { if (index < 0 || index >= arr.Length) { throw new jlArrayIndexOutOfBoundsException(); } arr[index] = value; } else { setLong(arrayObj, index, value); } } public static void setFloat(object arrayObj, int index, float value) { if (arrayObj == null) { throw new jlNullPointerException(); } float[] arr = arrayObj as float[]; if (arr != null) { if (index < 0 || index >= arr.Length) { throw new jlArrayIndexOutOfBoundsException(); } arr[index] = value; } else { setDouble(arrayObj, index, value); } } public static void setLong(object arrayObj, int index, long value) { if (arrayObj == null) { throw new jlNullPointerException(); } long[] arr = arrayObj as long[]; if (arr != null) { if (index < 0 || index >= arr.Length) { throw new jlArrayIndexOutOfBoundsException(); } arr[index] = value; } else { setFloat(arrayObj, index, value); } } public static void setDouble(object arrayObj, int index, double value) { if (arrayObj == null) { throw new jlNullPointerException(); } double[] arr = arrayObj as double[]; if (arr != null) { if (index < 0 || index >= arr.Length) { throw new jlArrayIndexOutOfBoundsException(); } arr[index] = value; } else { throw new jlIllegalArgumentException("argument type mismatch"); } } public static object newArray(object componentType, int length) { if (componentType == null) { throw new jlNullPointerException(); } if (componentType == jlVoid.TYPE) { throw new jlIllegalArgumentException(); } if (length < 0) { throw new jlNegativeArraySizeException(); } try { TypeWrapper wrapper = TypeWrapper.FromClass(componentType); wrapper.Finish(); object obj = SystemArray.CreateInstance(wrapper.TypeAsArrayType, length); if (wrapper.IsGhost || wrapper.IsGhostArray) { IKVM.Runtime.GhostTag.SetTag(obj, wrapper.MakeArrayType(1)); } return obj; } catch (RetargetableJavaException x) { throw x.ToJava(); } catch (NotSupportedException x) { // This happens when you try to create an array from TypedReference, ArgIterator, ByRef, // RuntimeArgumentHandle or an open generic type. throw new jlIllegalArgumentException(x.Message); } } public static object multiNewArray(object componentType, int[] dimensions) { if (componentType == null || dimensions == null) { throw new jlNullPointerException(); } if (componentType == jlVoid.TYPE) { throw new jlIllegalArgumentException(); } if (dimensions.Length == 0 || dimensions.Length > 255) { throw new jlIllegalArgumentException(); } try { TypeWrapper wrapper = TypeWrapper.FromClass(componentType).MakeArrayType(dimensions.Length); wrapper.Finish(); object obj = IKVM.Runtime.ByteCodeHelper.multianewarray(wrapper.TypeAsArrayType.TypeHandle, dimensions); if (wrapper.IsGhostArray) { IKVM.Runtime.GhostTag.SetTag(obj, wrapper); } return obj; } catch (RetargetableJavaException x) { throw x.ToJava(); } catch (NotSupportedException x) { // This happens when you try to create an array from TypedReference, ArgIterator, ByRef, // RuntimeArgumentHandle or an open generic type. throw new jlIllegalArgumentException(x.Message); } } #endif // FIRST_PASS } } static class Class { public static object forName0(string name, bool initialize, object loader) { #if FIRST_PASS return null; #else //Console.WriteLine("forName: " + name + ", loader = " + loader); TypeWrapper tw = null; if (name.IndexOf(',') > 0) { // we essentially require full trust before allowing arbitrary types to be loaded, // hence we do the "createClassLoader" permission check jlSecurityManager sm = jlSystem.getSecurityManager(); if (sm != null) sm.checkPermission(new jlRuntimePermission("createClassLoader")); Type type = Type.GetType(name); if (type != null) { tw = ClassLoaderWrapper.GetWrapperFromType(type); } if (tw == null) { throw new jlClassNotFoundException(name); } } else { try { ClassLoaderWrapper classLoaderWrapper = ClassLoaderWrapper.GetClassLoaderWrapper(loader); tw = classLoaderWrapper.LoadClassByDottedName(name); } catch (RetargetableJavaException x) { throw x.ToJava(); } } if (initialize && !tw.IsArray) { try { tw.Finish(); } catch (RetargetableJavaException x) { throw x.ToJava(); } tw.RunClassInit(); } return tw.ClassObject; #endif } public static bool isInstance(object thisClass, object obj) { return TypeWrapper.FromClass(thisClass).IsInstance(obj); } public static bool isAssignableFrom(object thisClass, object otherClass) { #if !FIRST_PASS if (otherClass == null) { throw new jlNullPointerException(); } #endif return TypeWrapper.FromClass(otherClass).IsAssignableTo(TypeWrapper.FromClass(thisClass)); } public static bool isInterface(object thisClass) { return TypeWrapper.FromClass(thisClass).IsInterface; } public static bool isArray(object thisClass) { return TypeWrapper.FromClass(thisClass).IsArray; } public static bool isPrimitive(object thisClass) { return TypeWrapper.FromClass(thisClass).IsPrimitive; } public static string getName0(object thisClass) { TypeWrapper tw = TypeWrapper.FromClass(thisClass); if (tw.IsPrimitive) { if (tw == PrimitiveTypeWrapper.BYTE) { return "byte"; } else if (tw == PrimitiveTypeWrapper.CHAR) { return "char"; } else if (tw == PrimitiveTypeWrapper.DOUBLE) { return "double"; } else if (tw == PrimitiveTypeWrapper.FLOAT) { return "float"; } else if (tw == PrimitiveTypeWrapper.INT) { return "int"; } else if (tw == PrimitiveTypeWrapper.LONG) { return "long"; } else if (tw == PrimitiveTypeWrapper.SHORT) { return "short"; } else if (tw == PrimitiveTypeWrapper.BOOLEAN) { return "boolean"; } else if (tw == PrimitiveTypeWrapper.VOID) { return "void"; } } return tw.Name; } public static string getSigName(object thisClass) { return TypeWrapper.FromClass(thisClass).SigName; } public static object getClassLoader0(object thisClass) { return TypeWrapper.FromClass(thisClass).GetClassLoader().GetJavaClassLoader(); } public static object getSuperclass(object thisClass) { TypeWrapper super = TypeWrapper.FromClass(thisClass).BaseTypeWrapper; return super != null ? super.ClassObject : null; } public static object getInterfaces(object thisClass) { #if FIRST_PASS return null; #else TypeWrapper[] ifaces = TypeWrapper.FromClass(thisClass).Interfaces; jlClass[] interfaces = new jlClass[ifaces.Length]; for (int i = 0; i < ifaces.Length; i++) { interfaces[i] = (jlClass)ifaces[i].ClassObject; } return interfaces; #endif } public static object getComponentType(object thisClass) { TypeWrapper tw = TypeWrapper.FromClass(thisClass); return tw.IsArray ? tw.ElementTypeWrapper.ClassObject : null; } public static int getModifiers(object thisClass) { // the 0x7FFF mask comes from JVM_ACC_WRITTEN_FLAGS in hotspot\src\share\vm\utilities\accessFlags.hpp // masking out ACC_SUPER comes from instanceKlass::compute_modifier_flags() in hotspot\src\share\vm\oops\instanceKlass.cpp const int mask = 0x7FFF & (int)~IKVM.Attributes.Modifiers.Super; return (int)TypeWrapper.FromClass(thisClass).ReflectiveModifiers & mask; } public static object[] getSigners(object thisClass) { #if FIRST_PASS return null; #else return ((jlClass)thisClass).signers; #endif } public static void setSigners(object thisClass, object[] signers) { #if !FIRST_PASS ((jlClass)thisClass).signers = signers; #endif } public static object[] getEnclosingMethod0(object thisClass) { TypeWrapper tw = TypeWrapper.FromClass(thisClass); string[] enc = tw.GetEnclosingMethod(); if (enc == null) { return null; } try { return new object[] { tw.GetClassLoader().LoadClassByDottedName(enc[0]).ClassObject, enc[1], enc[2] == null ? null : enc[2].Replace('.', '/') }; } catch (RetargetableJavaException x) { throw x.ToJava(); } } public static object getDeclaringClass(object thisClass) { try { TypeWrapper wrapper = TypeWrapper.FromClass(thisClass); wrapper.Finish(); TypeWrapper decl = wrapper.DeclaringTypeWrapper; if (decl == null) { return null; } if (!decl.IsAccessibleFrom(wrapper)) { throw new IllegalAccessError(string.Format("tried to access class {0} from class {1}", decl.Name, wrapper.Name)); } decl.Finish(); if (SystemArray.IndexOf(decl.InnerClasses, wrapper) == -1) { throw new IncompatibleClassChangeError(string.Format("{0} and {1} disagree on InnerClasses attribute", decl.Name, wrapper.Name)); } return decl.ClassObject; } catch (RetargetableJavaException x) { throw x.ToJava(); } } public static object getProtectionDomain0(object thisClass) { #if FIRST_PASS return null; #else TypeWrapper wrapper = TypeWrapper.FromClass(thisClass); while (wrapper.IsArray) { wrapper = wrapper.ElementTypeWrapper; } object pd = ((jlClass)wrapper.ClassObject).pd; if (pd == null) { // The protection domain for statically compiled code is created lazily (not at java.lang.Class creation time), // to work around boot strap issues. AssemblyClassLoader acl = wrapper.GetClassLoader() as AssemblyClassLoader; if (acl != null) { pd = acl.GetProtectionDomain(); } } return pd; #endif } public static void setProtectionDomain0(object thisClass, object pd) { #if !FIRST_PASS ((jlClass)thisClass).pd = (ProtectionDomain)pd; #endif } public static object getPrimitiveClass(string name) { // note that this method isn't used anymore (because it is an intrinsic (during core class library compilation)) // it still remains for compat because it might be invoked through reflection by evil code switch (name) { case "byte": return PrimitiveTypeWrapper.BYTE.ClassObject; case "char": return PrimitiveTypeWrapper.CHAR.ClassObject; case "double": return PrimitiveTypeWrapper.DOUBLE.ClassObject; case "float": return PrimitiveTypeWrapper.FLOAT.ClassObject; case "int": return PrimitiveTypeWrapper.INT.ClassObject; case "long": return PrimitiveTypeWrapper.LONG.ClassObject; case "short": return PrimitiveTypeWrapper.SHORT.ClassObject; case "boolean": return PrimitiveTypeWrapper.BOOLEAN.ClassObject; case "void": return PrimitiveTypeWrapper.VOID.ClassObject; default: throw new ArgumentException(name); } } public static string getGenericSignature(object thisClass) { string sig = TypeWrapper.FromClass(thisClass).GetGenericSignature(); if (sig == null) { return null; } return sig.Replace('.', '/'); } internal static object AnnotationsToMap(object[] objAnn) { #if FIRST_PASS return null; #else global::java.util.HashMap map = new global::java.util.HashMap(); if (objAnn != null) { foreach (object obj in objAnn) { Annotation a = obj as Annotation; if (a != null) { global::ikvm.@internal.AnnotationAttributeBase.freeze(a); map.put(a.annotationType(), a); } } } return map; #endif } public static object getDeclaredAnnotationsImpl(object thisClass) { #if FIRST_PASS return null; #else TypeWrapper wrapper = TypeWrapper.FromClass(thisClass); try { wrapper.Finish(); } catch (RetargetableJavaException x) { throw x.ToJava(); } return AnnotationsToMap(wrapper.GetDeclaredAnnotations()); #endif } public static object getDeclaredFields0(object thisClass, bool publicOnly) { #if FIRST_PASS return null; #else Profiler.Enter("Class.getDeclaredFields0"); try { TypeWrapper wrapper = TypeWrapper.FromClass(thisClass); // we need to finish the type otherwise all fields will not be in the field map yet wrapper.Finish(); FieldWrapper[] fields = wrapper.GetFields(); List list = new List(); for (int i = 0; i < fields.Length; i++) { if (fields[i].IsHideFromReflection) { // skip } else if (publicOnly && !fields[i].IsPublic) { // caller is only asking for public field, so we don't return this non-public field } else { fields[i].FieldTypeWrapper.EnsureLoadable(wrapper.GetClassLoader()); list.Add((jlrField)fields[i].ToField(false)); } } return list.ToArray(); } catch (RetargetableJavaException x) { throw x.ToJava(); } finally { Profiler.Leave("Class.getDeclaredFields0"); } #endif } public static object getDeclaredMethods0(object thisClass, bool publicOnly) { #if FIRST_PASS return null; #else Profiler.Enter("Class.getDeclaredMethods0"); try { TypeWrapper wrapper = TypeWrapper.FromClass(thisClass); wrapper.Finish(); if (wrapper.HasVerifyError) { // TODO we should get the message from somewhere throw new VerifyError(); } if (wrapper.HasClassFormatError) { // TODO we should get the message from somewhere throw new ClassFormatError(wrapper.Name); } // we need to look through the array for unloadable types, because we may not let them // escape into the 'wild' MethodWrapper[] methods = wrapper.GetMethods(); List list = new List(); for (int i = 0; i < methods.Length; i++) { // we don't want to expose "hideFromReflection" methods (one reason is that it would // mess up the serialVersionUID computation) if (!methods[i].IsHideFromReflection && methods[i].Name != "" && methods[i].Name != "" && (!publicOnly || methods[i].IsPublic)) { methods[i].ReturnType.EnsureLoadable(wrapper.GetClassLoader()); TypeWrapper[] args = methods[i].GetParameters(); for (int j = 0; j < args.Length; j++) { args[j].EnsureLoadable(wrapper.GetClassLoader()); } list.Add((jlrMethod)methods[i].ToMethodOrConstructor(false)); } } return list.ToArray(); } catch (RetargetableJavaException x) { throw x.ToJava(); } finally { Profiler.Leave("Class.getDeclaredMethods0"); } #endif } public static object getDeclaredConstructors0(object thisClass, bool publicOnly) { #if FIRST_PASS return null; #else Profiler.Enter("Class.getDeclaredConstructors0"); try { TypeWrapper wrapper = TypeWrapper.FromClass(thisClass); wrapper.Finish(); if (wrapper.HasVerifyError) { // TODO we should get the message from somewhere throw new VerifyError(); } if (wrapper.HasClassFormatError) { // TODO we should get the message from somewhere throw new ClassFormatError(wrapper.Name); } // we need to look through the array for unloadable types, because we may not let them // escape into the 'wild' MethodWrapper[] methods = wrapper.GetMethods(); List list = new List(); for (int i = 0; i < methods.Length; i++) { // we don't want to expose "hideFromReflection" methods (one reason is that it would // mess up the serialVersionUID computation) if (!methods[i].IsHideFromReflection && methods[i].Name == "" && (!publicOnly || methods[i].IsPublic)) { TypeWrapper[] args = methods[i].GetParameters(); for (int j = 0; j < args.Length; j++) { args[j].EnsureLoadable(wrapper.GetClassLoader()); } list.Add((jlrConstructor)methods[i].ToMethodOrConstructor(false)); } } return list.ToArray(); } catch (RetargetableJavaException x) { throw x.ToJava(); } finally { Profiler.Leave("Class.getDeclaredConstructors0"); } #endif } public static object getDeclaredClasses0(object thisClass) { #if FIRST_PASS return null; #else try { TypeWrapper wrapper = TypeWrapper.FromClass(thisClass); // NOTE to get at the InnerClasses we need to finish the type wrapper.Finish(); TypeWrapper[] wrappers = wrapper.InnerClasses; jlClass[] innerclasses = new jlClass[wrappers.Length]; for (int i = 0; i < innerclasses.Length; i++) { wrappers[i].Finish(); if (wrappers[i].IsUnloadable) { throw new jlNoClassDefFoundError(wrappers[i].Name); } if (!wrappers[i].IsAccessibleFrom(wrapper)) { throw new IllegalAccessError(string.Format("tried to access class {0} from class {1}", wrappers[i].Name, wrapper.Name)); } innerclasses[i] = (jlClass)wrappers[i].ClassObject; } return innerclasses; } catch (RetargetableJavaException x) { throw x.ToJava(); } #endif } public static bool desiredAssertionStatus0(object clazz) { return IKVM.Runtime.Assertions.IsEnabled(TypeWrapper.FromClass(clazz)); } } static class ClassLoader { #if !FIRST_PASS private static jlClassNotFoundException classNotFoundException; #endif public static object defineClass0(object thisClassLoader, string name, byte[] b, int off, int len, object pd) { return defineClass1(thisClassLoader, name, b, off, len, pd, null); } public static object defineClass1(object thisClassLoader, string name, byte[] b, int off, int len, object pd, string source) { // it appears the source argument is only used for trace messages in HotSpot. We'll just ignore it for now. Profiler.Enter("ClassLoader.defineClass"); try { try { ClassLoaderWrapper classLoaderWrapper = ClassLoaderWrapper.GetClassLoaderWrapper(thisClassLoader); ClassFileParseOptions cfp = ClassFileParseOptions.LineNumberTable; if (classLoaderWrapper.EmitDebugInfo) { cfp |= ClassFileParseOptions.LocalVariableTable; } ClassFile classFile = new ClassFile(b, off, len, name, cfp); if (name != null && classFile.Name != name) { #if !FIRST_PASS throw new jlNoClassDefFoundError(name + " (wrong name: " + classFile.Name + ")"); #endif } TypeWrapper type = classLoaderWrapper.DefineClass(classFile, pd); return type.ClassObject; } catch (RetargetableJavaException x) { throw x.ToJava(); } } finally { Profiler.Leave("ClassLoader.defineClass"); } } public static object defineClass2(object thisClassLoader, string name, object b, int off, int len, object pd, string source) { #if FIRST_PASS return null; #else jnByteBuffer bb = (jnByteBuffer)b; byte[] buf = new byte[bb.remaining()]; bb.get(buf); return defineClass1(thisClassLoader, name, buf, 0, buf.Length, pd, source); #endif } public static void resolveClass0(object thisClassLoader, object clazz) { // no-op } public static object findBootstrapClass(object thisClassLoader, string name) { #if FIRST_PASS return null; #else TypeWrapper tw; try { tw = ClassLoaderWrapper.GetBootstrapClassLoader().LoadClassByDottedNameFast(name); } catch (RetargetableJavaException x) { throw x.ToJava(); } if (tw == null) { // HACK for efficiency, we don't allocate a new exception here // (as this exception is thrown for *every* non-boot class that we load and // the exception is thrown away by our caller anyway) if (classNotFoundException == null) { jlClassNotFoundException ex = new jlClassNotFoundException(null, null); ex.setStackTrace(new jlStackTraceElement[] { new jlStackTraceElement("java.lang.ClassLoader", "findBootstrapClass", null, -2) }); classNotFoundException = ex; } throw classNotFoundException; } return tw.ClassObject; #endif } public static object findLoadedClass0(object thisClassLoader, string name) { ClassLoaderWrapper loader = ClassLoaderWrapper.GetClassLoaderWrapper(thisClassLoader); TypeWrapper tw = loader.GetLoadedClass(name); return tw != null ? tw.ClassObject : null; } internal static class NativeLibrary { public static void load(object thisNativeLibrary, string name) { #if !FIRST_PASS if (VirtualFileSystem.IsVirtualFS(name)) { // we fake success for native libraries loaded from VFS ((global::java.lang.ClassLoader.NativeLibrary)thisNativeLibrary).handle = -1; } else { doLoad(thisNativeLibrary, name); } #endif } #if !FIRST_PASS // we don't want to inline this method, because that would needlessly cause IKVM.Runtime.JNI.dll to be loaded when loading a fake native library from VFS [MethodImpl(MethodImplOptions.NoInlining)] private static void doLoad(object thisNativeLibrary, string name) { global::java.lang.ClassLoader.NativeLibrary lib = (global::java.lang.ClassLoader.NativeLibrary)thisNativeLibrary; lib.handle = IKVM.Runtime.JniHelper.LoadLibrary(name, TypeWrapper.FromClass(lib.fromClass).GetClassLoader()); } #endif public static long find(object thisNativeLibrary, string name) { // TODO throw new NotImplementedException(); } public static void unload(object thisNativeLibrary) { #if !FIRST_PASS global::java.lang.ClassLoader.NativeLibrary lib = (global::java.lang.ClassLoader.NativeLibrary)thisNativeLibrary; long handle = Interlocked.Exchange(ref lib.handle, 0); if (handle != 0) { IKVM.Runtime.JniHelper.UnloadLibrary(handle, TypeWrapper.FromClass(lib.fromClass).GetClassLoader()); } #endif } } public static object retrieveDirectives() { return IKVM.Runtime.Assertions.RetrieveDirectives(); } } static class Compiler { public static void initialize() { } public static void registerNatives() { } public static bool compileClass(object clazz) { return false; } public static bool compileClasses(string str) { return false; } public static object command(object any) { return null; } public static void enable() { } public static void disable() { } } static class Double { public static long doubleToRawLongBits(double value) { IKVM.Runtime.DoubleConverter converter = new IKVM.Runtime.DoubleConverter(); return IKVM.Runtime.DoubleConverter.ToLong(value, ref converter); } public static double longBitsToDouble(long bits) { IKVM.Runtime.DoubleConverter converter = new IKVM.Runtime.DoubleConverter(); return IKVM.Runtime.DoubleConverter.ToDouble(bits, ref converter); } } static class Float { public static int floatToRawIntBits(float value) { IKVM.Runtime.FloatConverter converter = new IKVM.Runtime.FloatConverter(); return IKVM.Runtime.FloatConverter.ToInt(value, ref converter); } public static float intBitsToFloat(int bits) { IKVM.Runtime.FloatConverter converter = new IKVM.Runtime.FloatConverter(); return IKVM.Runtime.FloatConverter.ToFloat(bits, ref converter); } } static class Package { public static string getSystemPackage0(string name) { // this method is not implemented because we redirect Package.getSystemPackage() to our implementation in LangHelper throw new NotImplementedException(); } public static string[] getSystemPackages0() { // this method is not implemented because we redirect Package.getSystemPackages() to our implementation in LangHelper throw new NotImplementedException(); } } static class ProcessEnvironment { public static string environmentBlock() { StringBuilder sb = new StringBuilder(); foreach (global::System.Collections.DictionaryEntry de in Environment.GetEnvironmentVariables()) { sb.Append(de.Key).Append('=').Append(de.Value).Append('\u0000'); } if (sb.Length == 0) { sb.Append('\u0000'); } sb.Append('\u0000'); return sb.ToString(); } } static class Runtime { public static int availableProcessors(object thisRuntime) { return Environment.ProcessorCount; } public static long freeMemory(object thisRuntime) { // TODO figure out if there is anything meaningful we can return here return 10 * 1024 * 1024; } public static long totalMemory(object thisRuntime) { // NOTE this really is a bogus number, but we have to return something return GC.GetTotalMemory(false) + freeMemory(thisRuntime); } public static long maxMemory(object thisRuntime) { // spec says: If there is no inherent limit then the value Long.MAX_VALUE will be returned. return Int64.MaxValue; } public static void gc(object thisRuntime) { GC.Collect(); } public static void traceInstructions(object thisRuntime, bool on) { } public static void traceMethodCalls(object thisRuntime, bool on) { } public static void runFinalization0() { GC.WaitForPendingFinalizers(); } } static class SecurityManager { // this field is set by code in the JNI assembly itself, // to prevent having to load the JNI assembly when it isn't used. internal static volatile Assembly jniAssembly; public static object getClassContext(object thisSecurityManager) { #if FIRST_PASS return null; #else List stack = new List(); StackTrace trace = new StackTrace(); for (int i = 0; i < trace.FrameCount; i++) { StackFrame frame = trace.GetFrame(i); MethodBase method = frame.GetMethod(); Type type = method.DeclaringType; // NOTE these checks should be the same as the ones in Reflection.getCallerClass if (IKVM.NativeCode.sun.reflect.Reflection.IsHideFromJava(method) || type == null || type.Assembly == typeof(object).Assembly || type.Assembly == typeof(SecurityManager).Assembly || type.Assembly == jniAssembly || type == typeof(jlrConstructor) || type == typeof(jlrMethod)) { continue; } if (type == typeof(jlSecurityManager)) { continue; } stack.Add((jlClass)ClassLoaderWrapper.GetWrapperFromType(type).ClassObject); } return stack.ToArray(); #endif } public static object currentClassLoader0(object thisSecurityManager) { object currentClass = currentLoadedClass0(thisSecurityManager); if (currentClass != null) { return TypeWrapper.FromClass(currentClass).GetClassLoader().GetJavaClassLoader(); } return null; } public static int classDepth(object thisSecurityManager, string name) { throw new NotImplementedException(); } public static int classLoaderDepth0(object thisSecurityManager) { throw new NotImplementedException(); } public static object currentLoadedClass0(object thisSecurityManager) { throw new NotImplementedException(); } } static class StrictMath { public static double sin(double d) { #if FIRST_PASS return 0; #else return global::ikvm.@internal.JMath.sin(d); #endif } public static double cos(double d) { #if FIRST_PASS return 0; #else return global::ikvm.@internal.JMath.cos(d); #endif } public static double tan(double d) { #if FIRST_PASS return 0; #else return global::ikvm.@internal.JMath.tan(d); #endif } public static double asin(double d) { #if FIRST_PASS return 0; #else return global::ikvm.@internal.JMath.asin(d); #endif } public static double acos(double d) { #if FIRST_PASS return 0; #else return global::ikvm.@internal.JMath.acos(d); #endif } public static double atan(double d) { #if FIRST_PASS return 0; #else return global::ikvm.@internal.JMath.atan(d); #endif } public static double exp(double d) { #if FIRST_PASS return 0; #else return global::ikvm.@internal.JMath.exp(d); #endif } public static double log(double d) { // FPU behavior is correct return Math.Log(d); } public static double log10(double d) { // FPU behavior is correct return Math.Log10(d); } public static double sqrt(double d) { // FPU behavior is correct return Math.Sqrt(d); } public static double cbrt(double d) { return Math.Pow(d, 1.0 / 3.0); } public static double IEEEremainder(double f1, double f2) { #if FIRST_PASS return 0; #else return global::ikvm.@internal.JMath.IEEEremainder(f1, f2); #endif } public static double ceil(double d) { #if FIRST_PASS return 0; #else return global::ikvm.@internal.JMath.ceil(d); #endif } public static double floor(double d) { #if FIRST_PASS return 0; #else return global::ikvm.@internal.JMath.floor(d); #endif } public static double atan2(double y, double x) { #if FIRST_PASS return 0; #else return global::ikvm.@internal.JMath.atan2(y, x); #endif } public static double pow(double x, double y) { #if FIRST_PASS return 0; #else return global::ikvm.@internal.JMath.pow(x, y); #endif } public static double sinh(double d) { return Math.Sinh(d); } public static double cosh(double d) { return Math.Cosh(d); } public static double tanh(double d) { return Math.Tanh(d); } public static double rint(double d) { #if FIRST_PASS return 0; #else return global::ikvm.@internal.JMath.rint(d); #endif } public static double hypot(double a, double b) { return a * a + b * b; } public static double expm1(double d) { return Math.Exp(d) - 1.0; } public static double log1p(double d) { return Math.Log(d + 1.0); } } static class System { public static void arraycopy(object src, int srcPos, object dest, int destPos, int length) { IKVM.Runtime.ByteCodeHelper.arraycopy(src, srcPos, dest, destPos, length); } } static class Thread { private static readonly object mainThreadGroup; #if !FIRST_PASS static Thread() { mainThreadGroup = new jlThreadGroup(jlThreadGroup.createRootGroup(), "main"); } #endif public static object getMainThreadGroup() { return mainThreadGroup; } // this is called from JniInterface.cs internal static void WaitUntilLastJniThread() { #if !FIRST_PASS int count = jlThread.currentThread().isDaemon() ? 0 : 1; while (Interlocked.CompareExchange(ref jlThread.nonDaemonCount[0], 0, 0) > count) { SystemThreadingThread.Sleep(1); } #endif } // this is called from JniInterface.cs internal static void AttachThreadFromJni(object threadGroup) { #if !FIRST_PASS if (threadGroup == null) { threadGroup = mainThreadGroup; } if (jlThread.current == null) { new jlThread((jlThreadGroup)threadGroup); } #endif } } static class VMThread { // this method is called from ikvm.runtime.Startup.exitMainThread() and from JNI public static void jniDetach() { #if !FIRST_PASS jlThread.currentThread().die(); #endif } } static class ProcessImpl { public static string mapVfsExecutable(string path) { if (VirtualFileSystem.IsVirtualFS(path)) { return VirtualFileSystem.MapExecutable(path); } return path; } } namespace reflect { static class Proxy { public static object defineClass0(object classLoader, string name, byte[] b, int off, int len) { return ClassLoader.defineClass1(classLoader, name, b, off, len, null, null); } } static class Field { public static object getDeclaredAnnotationsImpl(object thisField) { FieldWrapper fw = FieldWrapper.FromField(thisField); return Class.AnnotationsToMap(fw.DeclaringType.GetFieldAnnotations(fw)); } } static class Method { public static object getDeclaredAnnotationsImpl(object methodOrConstructor) { MethodWrapper mw = MethodWrapper.FromMethodOrConstructor(methodOrConstructor); return Class.AnnotationsToMap(mw.DeclaringType.GetMethodAnnotations(mw)); } public static object[][] getParameterAnnotationsImpl(object methodOrConstructor) { #if FIRST_PASS return null; #else MethodWrapper mw = MethodWrapper.FromMethodOrConstructor(methodOrConstructor); object[][] objAnn = mw.DeclaringType.GetParameterAnnotations(mw); if (objAnn == null) { return null; } Annotation[][] ann = new Annotation[objAnn.Length][]; for (int i = 0; i < ann.Length; i++) { List list = new List(); foreach (object obj in objAnn[i]) { Annotation a = obj as Annotation; if (a != null) { global::ikvm.@internal.AnnotationAttributeBase.freeze(a); list.Add(a); } } ann[i] = list.ToArray(); } return ann; #endif } public static object getDefaultValue(object thisMethod) { MethodWrapper mw = MethodWrapper.FromMethodOrConstructor(thisMethod); return mw.DeclaringType.GetAnnotationDefault(mw); } } } } namespace net { static class DatagramPacket { public static void init() { } } static class InetAddress { public static void init() { } #if !FIRST_PASS internal static jnInetAddress ConvertIPAddress(System.Net.IPAddress address, string hostname) { if (address.IsIPv6LinkLocal || address.IsIPv6SiteLocal) { return jnInet6Address.getByAddress(hostname, address.GetAddressBytes(), (int)address.ScopeId); } else { return jnInetAddress.getByAddress(hostname, address.GetAddressBytes()); } } #endif } static class InetAddressImplFactory { public static bool isIPv6Supported() { // TODO System.Net.Sockets.Socket.OSSupportsIPv6; return false; } } static class Inet4Address { public static void init() { } } static class Inet4AddressImpl { public static string getLocalHostName(object thisInet4AddressImpl) { #if FIRST_PASS return null; #else try { return System.Net.Dns.GetHostName(); } catch (System.Net.Sockets.SocketException x) { throw new jnUnknownHostException(x.Message); } #endif } public static object lookupAllHostAddr(object thisInet4AddressImpl, string hostname) { #if FIRST_PASS return null; #else try { System.Net.IPAddress[] addr = System.Net.Dns.GetHostAddresses(hostname); List addresses = new List(); for (int i = 0; i < addr.Length; i++) { byte[] b = addr[i].GetAddressBytes(); if (b.Length == 4) { addresses.Add(jnInetAddress.getByAddress(hostname, b)); } } return addresses.ToArray(); } catch (System.ArgumentException x) { throw new jnUnknownHostException(x.Message); } catch (System.Net.Sockets.SocketException x) { throw new jnUnknownHostException(x.Message); } #endif } public static string getHostByAddr(object thisInet4AddressImpl, byte[] addr) { #if FIRST_PASS return null; #else try { return System.Net.Dns.GetHostEntry(new System.Net.IPAddress(addr)).HostName; } catch (System.Net.Sockets.SocketException x) { throw new jnUnknownHostException(x.Message); } #endif } public static bool isReachable0(object thisInet4AddressImpl, byte[] addr, int timeout, byte[] ifaddr, int ttl) { // like the JDK, we don't use Ping, but we try a TCP connection to the echo port // (.NET 2.0 has a System.Net.NetworkInformation.Ping class, but that doesn't provide the option of binding to a specific interface) try { using (System.Net.Sockets.Socket sock = new System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp)) { if (ifaddr != null) { sock.Bind(new System.Net.IPEndPoint(((ifaddr[3] << 24) + (ifaddr[2] << 16) + (ifaddr[1] << 8) + ifaddr[0]) & 0xFFFFFFFFL, 0)); } if (ttl > 0) { sock.SetSocketOption(System.Net.Sockets.SocketOptionLevel.IP, System.Net.Sockets.SocketOptionName.IpTimeToLive, ttl); } System.Net.IPEndPoint ep = new System.Net.IPEndPoint(((addr[3] << 24) + (addr[2] << 16) + (addr[1] << 8) + addr[0]) & 0xFFFFFFFFL, 7); IAsyncResult res = sock.BeginConnect(ep, null, null); if (res.AsyncWaitHandle.WaitOne(timeout, false)) { try { sock.EndConnect(res); return true; } catch (System.Net.Sockets.SocketException x) { const int WSAECONNREFUSED = 10061; if (x.ErrorCode == WSAECONNREFUSED) { // we got back an explicit "connection refused", that means the host was reachable. return true; } } } } } catch (System.Net.Sockets.SocketException) { } return false; } } static class Inet6Address { public static void init() { } } static class Inet6AddressImpl { public static string getLocalHostName(object thisInet6AddressImpl) { #if FIRST_PASS return null; #else try { return System.Net.Dns.GetHostName(); } catch (System.Net.Sockets.SocketException x) { throw new jnUnknownHostException(x.Message); } #endif } public static object lookupAllHostAddr(object thisInet6AddressImpl, string hostname) { #if FIRST_PASS return null; #else try { System.Net.IPAddress[] addr = System.Net.Dns.GetHostAddresses(hostname); jnInetAddress[] addresses = new jnInetAddress[addr.Length]; for (int i = 0; i < addr.Length; i++) { addresses[i] = InetAddress.ConvertIPAddress(addr[i], hostname); } return addresses; } catch (System.ArgumentException x) { throw new jnUnknownHostException(x.Message); } catch (System.Net.Sockets.SocketException x) { throw new jnUnknownHostException(x.Message); } #endif } public static string getHostByAddr(object thisInet6AddressImpl, byte[] addr) { throw new NotImplementedException(); } public static bool isReachable0(object thisInet6AddressImpl, byte[] addr, int scope, int timeout, byte[] inf, int ttl, int if_scope) { throw new NotImplementedException(); } } static class NetworkInterface { #if !FIRST_PASS private static NetworkInterfaceInfo cache; private static DateTime cachedSince; #endif public static void init() { } #if !FIRST_PASS private class NetworkInterfaceInfo { internal System.Net.NetworkInformation.NetworkInterface[] dotnetInterfaces; internal jnNetworkInterface[] javaInterfaces; } private static NetworkInterfaceInfo GetInterfaces() { // Since many of the methods in java.net.NetworkInterface end up calling this method and the underlying stuff this is // based on isn't very quick either, we cache the array for a couple of seconds. if (cache != null && DateTime.UtcNow - cachedSince < new TimeSpan(0, 0, 5)) { return cache; } System.Net.NetworkInformation.NetworkInterface[] ifaces = System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces(); jnNetworkInterface[] ret = new jnNetworkInterface[ifaces.Length]; int eth = 0; int tr = 0; int fddi = 0; int lo = 0; int ppp = 0; int sl = 0; int net = 0; for (int i = 0; i < ifaces.Length; i++) { string name; switch (ifaces[i].NetworkInterfaceType) { case System.Net.NetworkInformation.NetworkInterfaceType.Ethernet: name = "eth" + eth++; break; case System.Net.NetworkInformation.NetworkInterfaceType.TokenRing: name = "tr" + tr++; break; case System.Net.NetworkInformation.NetworkInterfaceType.Fddi: name = "fddi" + fddi++; break; case System.Net.NetworkInformation.NetworkInterfaceType.Loopback: if (lo > 0) { continue; } name = "lo"; lo++; break; case System.Net.NetworkInformation.NetworkInterfaceType.Ppp: name = "ppp" + ppp++; break; case System.Net.NetworkInformation.NetworkInterfaceType.Slip: name = "sl" + sl++; break; default: name = "net" + net++; break; } System.Net.NetworkInformation.UnicastIPAddressInformationCollection uipaic = ifaces[i].GetIPProperties().UnicastAddresses; jnInetAddress[] addresses = new jnInetAddress[uipaic.Count]; for (int j = 0; j < addresses.Length; j++) { addresses[j] = InetAddress.ConvertIPAddress(uipaic[j].Address, null); } ret[i] = new jnNetworkInterface(name, i, addresses); // TODO should implement bindings ret[i]._set(ifaces[i].Description, new jnInterfaceAddress[0], new jnNetworkInterface[0]); } NetworkInterfaceInfo nii = new NetworkInterfaceInfo(); nii.dotnetInterfaces = ifaces; nii.javaInterfaces = ret; cache = nii; cachedSince = DateTime.UtcNow; return nii; } #endif public static object getByIndex(int index) { #if FIRST_PASS return null; #else jnNetworkInterface[] ifaces = GetInterfaces().javaInterfaces; if (index < 0 || index >= ifaces.Length) { return null; } return ifaces[index]; #endif } public static object getAll() { #if FIRST_PASS return null; #else return GetInterfaces().javaInterfaces; #endif } public static object getByName0(string name) { #if FIRST_PASS return null; #else foreach (jnNetworkInterface iface in GetInterfaces().javaInterfaces) { if (iface.getName() == name) { return iface; } } return null; #endif } public static object getByInetAddress0(object addr) { #if FIRST_PASS return null; #else foreach (jnNetworkInterface iface in GetInterfaces().javaInterfaces) { juEnumeration addresses = iface.getInetAddresses(); while (addresses.hasMoreElements()) { if (addresses.nextElement().Equals(addr)) { return iface; } } } return null; #endif } public static long getSubnet0(string name, int ind) { // this method is not used by the java code (!) return 0; } public static object getBroadcast0(string name, int ind) { // this method is not used by the java code (!) return null; } public static bool isUp0(string name, int ind) { #if FIRST_PASS return false; #else return GetInterfaces().dotnetInterfaces[ind].OperationalStatus == System.Net.NetworkInformation.OperationalStatus.Up; #endif } public static bool isLoopback0(string name, int ind) { #if FIRST_PASS return false; #else return GetInterfaces().dotnetInterfaces[ind].NetworkInterfaceType == System.Net.NetworkInformation.NetworkInterfaceType.Loopback; #endif } public static bool supportsMulticast0(string name, int ind) { #if FIRST_PASS return false; #else return GetInterfaces().dotnetInterfaces[ind].SupportsMulticast; #endif } public static bool isP2P0(string name, int ind) { #if FIRST_PASS return false; #else switch (GetInterfaces().dotnetInterfaces[ind].NetworkInterfaceType) { case System.Net.NetworkInformation.NetworkInterfaceType.Ppp: case System.Net.NetworkInformation.NetworkInterfaceType.Slip: return true; default: return false; } #endif } public static byte[] getMacAddr0(byte[] inAddr, string name, int ind) { #if FIRST_PASS return null; #else return GetInterfaces().dotnetInterfaces[ind].GetPhysicalAddress().GetAddressBytes(); #endif } public static int getMTU0(string name, int ind) { #if FIRST_PASS return 0; #else System.Net.NetworkInformation.IPv4InterfaceProperties props = GetInterfaces().dotnetInterfaces[ind].GetIPProperties().GetIPv4Properties(); return props == null ? -1 : props.Mtu; #endif } } } namespace nio { [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.LinkDemand, UnmanagedCode = true)] static class Bits { public static void copyFromByteArray(object src, long srcPos, long dstAddr, long length) { byte[] byteArray = src as byte[]; if (byteArray != null) { System.Runtime.InteropServices.Marshal.Copy(byteArray, (int)srcPos, (IntPtr)dstAddr, (int)length); return; } char[] charArray = src as char[]; if (charArray != null) { System.Runtime.InteropServices.Marshal.Copy(charArray, ((int)srcPos) >> 1, (IntPtr)dstAddr, ((int)length) >> 1); return; } short[] shortArray = src as short[]; if (shortArray != null) { System.Runtime.InteropServices.Marshal.Copy(shortArray, ((int)srcPos) >> 1, (IntPtr)dstAddr, ((int)length) >> 1); return; } int[] intArray = src as int[]; if (intArray != null) { System.Runtime.InteropServices.Marshal.Copy(intArray, ((int)srcPos) >> 2, (IntPtr)dstAddr, ((int)length) >> 2); return; } float[] floatArray = src as float[]; if (floatArray != null) { System.Runtime.InteropServices.Marshal.Copy(floatArray, ((int)srcPos) >> 2, (IntPtr)dstAddr, ((int)length) >> 2); return; } long[] longArray = src as long[]; if (longArray != null) { System.Runtime.InteropServices.Marshal.Copy(longArray, ((int)srcPos) >> 3, (IntPtr)dstAddr, ((int)length) >> 3); return; } double[] doubleArray = src as double[]; if (doubleArray != null) { System.Runtime.InteropServices.Marshal.Copy(doubleArray, ((int)srcPos) >> 3, (IntPtr)dstAddr, ((int)length) >> 3); return; } } public static void copyToByteArray(long srcAddr, object dst, long dstPos, long length) { byte[] byteArray = dst as byte[]; if (byteArray != null) { System.Runtime.InteropServices.Marshal.Copy((IntPtr)srcAddr, byteArray, (int)dstPos, (int)length); return; } char[] charArray = dst as char[]; if (charArray != null) { System.Runtime.InteropServices.Marshal.Copy((IntPtr)srcAddr, charArray, ((int)dstPos) >> 1, ((int)length) >> 1); return; } short[] shortArray = dst as short[]; if (shortArray != null) { System.Runtime.InteropServices.Marshal.Copy((IntPtr)srcAddr, shortArray, ((int)dstPos) >> 1, ((int)length) >> 1); return; } int[] intArray = dst as int[]; if (intArray != null) { System.Runtime.InteropServices.Marshal.Copy((IntPtr)srcAddr, intArray, ((int)dstPos) >> 2, ((int)length) >> 2); return; } float[] floatArray = dst as float[]; if (floatArray != null) { System.Runtime.InteropServices.Marshal.Copy((IntPtr)srcAddr, floatArray, ((int)dstPos) >> 2, ((int)length) >> 2); return; } long[] longArray = dst as long[]; if (longArray != null) { System.Runtime.InteropServices.Marshal.Copy((IntPtr)srcAddr, longArray, ((int)dstPos) >> 3, ((int)length) >> 3); return; } double[] doubleArray = dst as double[]; if (doubleArray != null) { System.Runtime.InteropServices.Marshal.Copy((IntPtr)srcAddr, doubleArray, ((int)dstPos) >> 3, ((int)length) >> 3); return; } } public static void copyFromShortArray(object src, long srcPos, long dstAddr, long length) { #if !FIRST_PASS short[] shortArray = src as short[]; if (shortArray != null) { int index = ((int)srcPos) >> 1; while (length > 0) { short v = jlShort.reverseBytes(shortArray[index++]); System.Runtime.InteropServices.Marshal.WriteInt16((IntPtr)dstAddr, v); dstAddr += 2; length -= 2; } } else { char[] charArray = (char[])src; int index = ((int)srcPos) >> 1; while (length > 0) { short v = jlShort.reverseBytes((short)charArray[index++]); System.Runtime.InteropServices.Marshal.WriteInt16((IntPtr)dstAddr, v); dstAddr += 2; length -= 2; } } #endif } public static void copyToShortArray(long srcAddr, object dst, long dstPos, long length) { #if !FIRST_PASS short[] shortArray = dst as short[]; if (shortArray != null) { int index = ((int)dstPos) >> 1; while (length > 0) { short v = System.Runtime.InteropServices.Marshal.ReadInt16((IntPtr)srcAddr); shortArray[index++] = jlShort.reverseBytes(v); srcAddr += 2; length -= 2; } } else { char[] charArray = (char[])dst; int index = ((int)dstPos) >> 1; while (length > 0) { short v = System.Runtime.InteropServices.Marshal.ReadInt16((IntPtr)srcAddr); charArray[index++] = (char)jlShort.reverseBytes(v); srcAddr += 2; length -= 2; } } #endif } public static void copyFromIntArray(object src, long srcPos, long dstAddr, long length) { #if !FIRST_PASS int[] intArray = src as int[]; if (intArray != null) { int index = ((int)srcPos) >> 2; while (length > 0) { int v = jlInteger.reverseBytes(intArray[index++]); System.Runtime.InteropServices.Marshal.WriteInt32((IntPtr)dstAddr, v); dstAddr += 4; length -= 4; } } else { float[] floatArray = (float[])src; int index = ((int)srcPos) >> 2; while (length > 0) { int v = jlInteger.reverseBytes(jlFloat.floatToRawIntBits(floatArray[index++])); System.Runtime.InteropServices.Marshal.WriteInt32((IntPtr)dstAddr, v); dstAddr += 4; length -= 4; } } #endif } public static void copyToIntArray(long srcAddr, object dst, long dstPos, long length) { #if !FIRST_PASS int[] intArray = dst as int[]; if (intArray != null) { int index = ((int)dstPos) >> 2; while (length > 0) { int v = System.Runtime.InteropServices.Marshal.ReadInt32((IntPtr)srcAddr); intArray[index++] = jlInteger.reverseBytes(v); srcAddr += 4; length -= 4; } } else { float[] floatArray = (float[])dst; int index = ((int)dstPos) >> 2; while (length > 0) { int v = System.Runtime.InteropServices.Marshal.ReadInt32((IntPtr)srcAddr); floatArray[index++] = jlFloat.intBitsToFloat(jlInteger.reverseBytes(v)); srcAddr += 4; length -= 4; } } #endif } public static void copyFromLongArray(object src, long srcPos, long dstAddr, long length) { #if !FIRST_PASS long[] longArray = src as long[]; if (longArray != null) { int index = ((int)srcPos) >> 3; while (length > 0) { long v = jlLong.reverseBytes(longArray[index++]); System.Runtime.InteropServices.Marshal.WriteInt64((IntPtr)dstAddr, v); dstAddr += 8; length -= 8; } } else { double[] doubleArray = (double[])src; int index = ((int)srcPos) >> 3; while (length > 0) { long v = jlLong.reverseBytes(BitConverter.DoubleToInt64Bits(doubleArray[index++])); System.Runtime.InteropServices.Marshal.WriteInt64((IntPtr)dstAddr, v); dstAddr += 8; length -= 8; } } #endif } public static void copyToLongArray(long srcAddr, object dst, long dstPos, long length) { #if !FIRST_PASS long[] longArray = dst as long[]; if (longArray != null) { int index = ((int)dstPos) >> 3; while (length > 0) { long v = System.Runtime.InteropServices.Marshal.ReadInt64((IntPtr)srcAddr); longArray[index++] = jlLong.reverseBytes(v); srcAddr += 8; length -= 8; } } else { double[] doubleArray = (double[])dst; int index = ((int)dstPos) >> 3; while (length > 0) { long v = System.Runtime.InteropServices.Marshal.ReadInt64((IntPtr)srcAddr); doubleArray[index++] = BitConverter.Int64BitsToDouble(jlLong.reverseBytes(v)); srcAddr += 8; length -= 8; } } #endif } } [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.LinkDemand, UnmanagedCode = true)] static class MappedByteBuffer { private static volatile int bogusField; public static bool isLoaded0(object thisMappedByteBuffer, long address, long length) { // on Windows, JDK simply returns false, so we can get away with that too. return false; } public static int load0(object thisMappedByteBuffer, long address, long length, int pageSize) { int bogus = bogusField; while (length > 0) { // touch a byte in every page bogus += System.Runtime.InteropServices.Marshal.ReadByte((IntPtr)address); length -= pageSize; address += pageSize; } // do a volatile store of the sum of the bytes to make sure the reads don't get optimized out bogusField = bogus; GC.KeepAlive(thisMappedByteBuffer); return 0; } public static void force0(object thisMappedByteBuffer, long address, long length) { if (JVM.IsUnix) { ikvm_msync((IntPtr)address, (int)length); GC.KeepAlive(thisMappedByteBuffer); } else { // according to the JDK sources, FlushViewOfFile can fail with an ERROR_LOCK_VIOLATION error, // so like the JDK, we retry up to three times if that happens. for (int i = 0; i < 3; i++) { if (FlushViewOfFile((IntPtr)address, (IntPtr)length) != 0) { GC.KeepAlive(thisMappedByteBuffer); return; } const int ERROR_LOCK_VIOLATION = 33; if (System.Runtime.InteropServices.Marshal.GetLastWin32Error() != ERROR_LOCK_VIOLATION) { break; } } #if !FIRST_PASS throw new jiIOException("Flush failed"); #endif } } [System.Runtime.InteropServices.DllImport("kernel32", SetLastError = true)] private static extern int FlushViewOfFile(IntPtr lpBaseAddress, IntPtr dwNumberOfBytesToFlush); [System.Runtime.InteropServices.DllImport("ikvm-native")] private static extern int ikvm_msync(IntPtr address, int size); } } namespace security { static class AccessController { public static object getStackAccessControlContext(object context, object callerID) { #if FIRST_PASS return null; #else object previous_protection_domain = null; object privileged_context = null; bool is_privileged = false; object protection_domain = null; StackTrace stack = new StackTrace(1); List array = new List(); for (int i = 0; i < stack.FrameCount; i++) { MethodBase method = stack.GetFrame(i).GetMethod(); if (method.DeclaringType == typeof(AccessController) && method.Name == "doPrivileged") { is_privileged = true; privileged_context = context; global::java.lang.Class caller = ((global::ikvm.@internal.CallerID)callerID).getCallerClass(); protection_domain = caller == null ? null : java.lang.Class.getProtectionDomain0(caller); } else { protection_domain = GetProtectionDomainFromType(method.DeclaringType); } if (previous_protection_domain != protection_domain && protection_domain != null) { previous_protection_domain = protection_domain; array.Add((ProtectionDomain)protection_domain); } if (is_privileged) { break; } } if (array.Count == 0) { if (is_privileged && privileged_context == null) { return null; } return CreateAccessControlContext(null, is_privileged, privileged_context); } return CreateAccessControlContext(array.ToArray(), is_privileged, privileged_context); #endif } #if !FIRST_PASS private static object CreateAccessControlContext(ProtectionDomain[] context, bool is_privileged, object privileged_context) { jsAccessControlContext acc = new jsAccessControlContext(context, is_privileged); acc._privilegedContext((jsAccessControlContext)privileged_context); return acc; } private static object GetProtectionDomainFromType(Type type) { if (type == null || type.Assembly == typeof(object).Assembly || type.Assembly == typeof(AccessController).Assembly || type.Assembly == java.lang.SecurityManager.jniAssembly || type.Assembly == typeof(jlThread).Assembly) { return null; } TypeWrapper tw = ClassLoaderWrapper.GetWrapperFromType(type); if (tw != null) { return java.lang.Class.getProtectionDomain0(tw.ClassObject); } return null; } #endif public static object getInheritedAccessControlContext() { #if FIRST_PASS return null; #else return jlThread.currentThread().inheritedAccessControlContext; #endif } } } namespace util { namespace logging { static class FileHandler { public static bool isSetUID() { // TODO return false; } } } namespace prefs { static class FileSystemPreferences { public static int chmod(string filename, int permission) { // TODO return 0; } public static int[] lockFile0(string filename, int permission, bool shared) { // TODO return new int[] { 1, 0 }; } public static int unlockFile0(int fd) { // TODO return 0; } } static class WindowsPreferences { // HACK we currently support only 16 handles at a time private static Microsoft.Win32.RegistryKey[] keys = new Microsoft.Win32.RegistryKey[16]; private static Microsoft.Win32.RegistryKey MapKey(int hKey) { switch (hKey) { case unchecked((int)0x80000001): return Microsoft.Win32.Registry.CurrentUser; case unchecked((int)0x80000002): return Microsoft.Win32.Registry.LocalMachine; default: return keys[hKey - 1]; } } private static int AllocHandle(Microsoft.Win32.RegistryKey key) { lock (keys) { if (key != null) { for (int i = 0; i < keys.Length; i++) { if (keys[i] == null) { keys[i] = key; return i + 1; } } } return 0; } } private static string BytesToString(byte[] bytes) { int len = bytes.Length; if (bytes[len - 1] == 0) { len--; } return Encoding.ASCII.GetString(bytes, 0, len); } private static byte[] StringToBytes(string str) { if (str.Length == 0 || str[str.Length - 1] != 0) { str += '\u0000'; } return Encoding.ASCII.GetBytes(str); } public static int[] WindowsRegOpenKey(int hKey, byte[] subKey, int securityMask) { bool writable = (securityMask & 0x30006) != 0; Microsoft.Win32.RegistryKey resultKey = null; int error = 0; try { resultKey = MapKey(hKey).OpenSubKey(BytesToString(subKey), writable); } catch (System.Security.SecurityException) { error = 5; } catch (UnauthorizedAccessException) { error = 5; } return new int[] { AllocHandle(resultKey), error }; } public static int WindowsRegCloseKey(int hKey) { keys[hKey - 1].Close(); lock (keys) { keys[hKey - 1] = null; } return 0; } public static int[] WindowsRegCreateKeyEx(int hKey, byte[] subKey) { Microsoft.Win32.RegistryKey resultKey = null; int error = 0; int disposition = -1; try { Microsoft.Win32.RegistryKey key = MapKey(hKey); string name = BytesToString(subKey); resultKey = key.OpenSubKey(name); disposition = 2; if (resultKey == null) { resultKey = key.CreateSubKey(name); disposition = 1; } } catch (System.Security.SecurityException) { error = 5; } catch (UnauthorizedAccessException) { error = 5; } return new int[] { AllocHandle(resultKey), error, disposition }; } public static int WindowsRegDeleteKey(int hKey, byte[] subKey) { try { MapKey(hKey).DeleteSubKey(BytesToString(subKey)); return 0; } catch (System.Security.SecurityException) { return 5; } } public static int WindowsRegFlushKey(int hKey) { MapKey(hKey).Flush(); return 0; } public static byte[] WindowsRegQueryValueEx(int hKey, byte[] valueName) { try { string value = MapKey(hKey).GetValue(BytesToString(valueName)) as string; if (value == null) { return null; } return StringToBytes(value); } catch (System.Security.SecurityException) { return null; } catch (UnauthorizedAccessException) { return null; } } public static int WindowsRegSetValueEx(int hKey, byte[] valueName, byte[] data) { if (valueName == null || data == null) { return -1; } try { MapKey(hKey).SetValue(BytesToString(valueName), BytesToString(data)); return 0; } catch (System.Security.SecurityException) { return 5; } catch (UnauthorizedAccessException) { return 5; } } public static int WindowsRegDeleteValue(int hKey, byte[] valueName) { try { MapKey(hKey).DeleteValue(BytesToString(valueName)); return 0; } catch (System.ArgumentException) { return 2; //ERROR_FILE_NOT_FOUND } catch (System.Security.SecurityException) { return 5; //ERROR_ACCESS_DENIED } catch (UnauthorizedAccessException) { return 5; //ERROR_ACCESS_DENIED } } public static int[] WindowsRegQueryInfoKey(int hKey) { int[] result = new int[5] { -1, -1, -1, -1, -1 }; try { Microsoft.Win32.RegistryKey key = MapKey(hKey); result[0] = key.SubKeyCount; result[1] = 0; result[2] = key.ValueCount; foreach (string s in key.GetSubKeyNames()) { result[3] = Math.Max(result[3], s.Length); } foreach (string s in key.GetValueNames()) { result[4] = Math.Max(result[4], s.Length); } } catch (System.Security.SecurityException) { result[1] = 5; } catch (UnauthorizedAccessException) { result[1] = 5; } return result; } public static byte[] WindowsRegEnumKeyEx(int hKey, int subKeyIndex, int maxKeyLength) { try { return StringToBytes(MapKey(hKey).GetSubKeyNames()[subKeyIndex]); } catch (System.Security.SecurityException) { return null; } catch (UnauthorizedAccessException) { return null; } } public static byte[] WindowsRegEnumValue(int hKey, int valueIndex, int maxValueNameLength) { try { return StringToBytes(MapKey(hKey).GetValueNames()[valueIndex]); } catch (System.Security.SecurityException) { return null; } catch (UnauthorizedAccessException) { return null; } } } } namespace jar { static class JarFile { public static string[] getMetaInfEntryNames(object thisJarFile) { #if FIRST_PASS return null; #else juzZipFile zf = (juzZipFile)thisJarFile; juEnumeration entries = zf.entries(); List list = null; while (entries.hasMoreElements()) { juzZipEntry entry = (juzZipEntry)entries.nextElement(); if (entry.getName().StartsWith("META-INF/", StringComparison.OrdinalIgnoreCase)) { if (list == null) { list = new List(); } list.Add(entry.getName()); } } return list == null ? null : list.ToArray(); #endif } } } static class TimeZone { public static string getSystemTimeZoneID(string javaHome, string country) { // HACK this is very lame and probably won't work on localized windows versions // (the switch was generated from the contents of $JAVA_HOME/lib/tzmappings) switch (SystemTimeZone.CurrentTimeZone.StandardName) { case "Romance": case "Romance Standard Time": return "Europe/Paris"; case "Warsaw": return "Europe/Warsaw"; case "Central Europe": case "Central Europe Standard Time": case "Prague Bratislava": return "Europe/Prague"; case "W. Central Africa Standard Time": return "Africa/Luanda"; case "FLE": case "FLE Standard Time": return "Europe/Helsinki"; case "GFT": case "GFT Standard Time": case "GTB": case "GTB Standard Time": return "Europe/Athens"; case "Israel": case "Israel Standard Time": return "Asia/Jerusalem"; case "Arab": case "Arab Standard Time": return "Asia/Riyadh"; case "Arabic Standard Time": return "Asia/Baghdad"; case "E. Africa": case "E. Africa Standard Time": return "Africa/Nairobi"; case "Saudi Arabia": case "Saudi Arabia Standard Time": return "Asia/Riyadh"; case "Iran": case "Iran Standard Time": return "Asia/Tehran"; case "Afghanistan": case "Afghanistan Standard Time": return "Asia/Kabul"; case "India": case "India Standard Time": return "Asia/Calcutta"; case "Myanmar Standard Time": return "Asia/Rangoon"; case "Nepal Standard Time": return "Asia/Katmandu"; case "Sri Lanka": case "Sri Lanka Standard Time": return "Asia/Colombo"; case "Beijing": case "China": case "China Standard Time": return "Asia/Shanghai"; case "AUS Central": case "AUS Central Standard Time": return "Australia/Darwin"; case "Cen. Australia": case "Cen. Australia Standard Time": return "Australia/Adelaide"; case "Vladivostok": case "Vladivostok Standard Time": return "Asia/Vladivostok"; case "West Pacific": case "West Pacific Standard Time": return "Pacific/Guam"; case "E. South America": case "E. South America Standard Time": return "America/Sao_Paulo"; case "Greenland Standard Time": return "America/Godthab"; case "Newfoundland": case "Newfoundland Standard Time": return "America/St_Johns"; case "Pacific SA": case "Pacific SA Standard Time": return "America/Santiago"; case "SA Western": case "SA Western Standard Time": return "America/Caracas"; case "SA Pacific": case "SA Pacific Standard Time": return "America/Bogota"; case "US Eastern": case "US Eastern Standard Time": return "America/Indianapolis"; case "Central America Standard Time": return "America/Regina"; case "Mexico": case "Mexico Standard Time": return "America/Mexico_City"; case "Canada Central": case "Canada Central Standard Time": return "America/Regina"; case "US Mountain": case "US Mountain Standard Time": return "America/Phoenix"; case "GMT": case "GMT Standard Time": return "Europe/London"; case "Ekaterinburg": case "Ekaterinburg Standard Time": return "Asia/Yekaterinburg"; case "West Asia": case "West Asia Standard Time": return "Asia/Karachi"; case "Central Asia": case "Central Asia Standard Time": return "Asia/Dhaka"; case "N. Central Asia Standard Time": return "Asia/Novosibirsk"; case "Bangkok": case "Bangkok Standard Time": return "Asia/Bangkok"; case "North Asia Standard Time": return "Asia/Krasnoyarsk"; case "SE Asia": case "SE Asia Standard Time": return "Asia/Bangkok"; case "North Asia East Standard Time": return "Asia/Ulaanbaatar"; case "Singapore": case "Singapore Standard Time": return "Asia/Singapore"; case "Taipei": case "Taipei Standard Time": return "Asia/Taipei"; case "W. Australia": case "W. Australia Standard Time": return "Australia/Perth"; case "Korea": case "Korea Standard Time": return "Asia/Seoul"; case "Tokyo": case "Tokyo Standard Time": return "Asia/Tokyo"; case "Yakutsk": case "Yakutsk Standard Time": return "Asia/Yakutsk"; case "Central European": case "Central European Standard Time": return "Europe/Belgrade"; case "W. Europe": case "W. Europe Standard Time": return "Europe/Berlin"; case "Tasmania": case "Tasmania Standard Time": return "Australia/Hobart"; case "AUS Eastern": case "AUS Eastern Standard Time": return "Australia/Sydney"; case "E. Australia": case "E. Australia Standard Time": return "Australia/Brisbane"; case "Sydney Standard Time": return "Australia/Sydney"; case "Central Pacific": case "Central Pacific Standard Time": return "Pacific/Guadalcanal"; case "Dateline": case "Dateline Standard Time": return "GMT-1200"; case "Fiji": case "Fiji Standard Time": return "Pacific/Fiji"; case "Samoa": case "Samoa Standard Time": return "Pacific/Apia"; case "Hawaiian": case "Hawaiian Standard Time": return "Pacific/Honolulu"; case "Alaskan": case "Alaskan Standard Time": return "America/Anchorage"; case "Pacific": case "Pacific Standard Time": return "America/Los_Angeles"; case "Mexico Standard Time 2": return "America/Chihuahua"; case "Mountain": case "Mountain Standard Time": return "America/Denver"; case "Central": case "Central Standard Time": return "America/Chicago"; case "Eastern": case "Eastern Standard Time": return "America/New_York"; case "E. Europe": case "E. Europe Standard Time": return "Europe/Minsk"; case "Egypt": case "Egypt Standard Time": return "Africa/Cairo"; case "South Africa": case "South Africa Standard Time": return "Africa/Harare"; case "Atlantic": case "Atlantic Standard Time": return "America/Halifax"; case "SA Eastern": case "SA Eastern Standard Time": return "America/Buenos_Aires"; case "Mid-Atlantic": case "Mid-Atlantic Standard Time": return "Atlantic/South_Georgia"; case "Azores": case "Azores Standard Time": return "Atlantic/Azores"; case "Cape Verde Standard Time": return "Atlantic/Cape_Verde"; case "Russian": case "Russian Standard Time": return "Europe/Moscow"; case "New Zealand": case "New Zealand Standard Time": return "Pacific/Auckland"; case "Tonga Standard Time": return "Pacific/Tongatapu"; case "Arabian": case "Arabian Standard Time": return "Asia/Muscat"; case "Caucasus": case "Caucasus Standard Time": return "Asia/Yerevan"; case "Greenwich": case "Greenwich Standard Time": return "GMT"; case "Central Brazilian Standard Time": return "America/Manaus"; case "Central Standard Time (Mexico)": return "America/Mexico_City"; case "Georgian Standard Time": return "Asia/Tbilisi"; case "Mountain Standard Time (Mexico)": return "America/Chihuahua"; case "Namibia Standard Time": return "Africa/Windhoek"; case "Pacific Standard Time (Mexico)": return "America/Tijuana"; case "Western Brazilian Standard Time": return "America/Rio_Branco"; case "Azerbaijan Standard Time": return "Asia/Baku"; case "Jordan Standard Time": return "Asia/Amman"; case "Middle East Standard Time": return "Asia/Beirut"; default: // this means fall back to GMT offset return null; } } public static string getSystemGMTOffsetID() { TimeSpan sp = SystemTimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now); int hours = sp.Hours; int mins = sp.Minutes; if (hours >= 0 && mins >= 0) { return String.Format("GMT+{0:D2}:{1:D2}", hours, mins); } else { return String.Format("GMT-{0:D2}:{1:D2}", -hours, -mins); } } } } } namespace IKVM.NativeCode.sun.awt { static class KeyboardFocusManagerPeerImpl { public static object getNativeFocusedWindow(){return null;} public static object getNativeFocusOwner(){return null;} public static void clearNativeGlobalFocusOwner(object activeWindow){ } } static class SunToolkit { public static void closeSplashScreen() { } } } namespace IKVM.NativeCode.sun.awt.shell { /// /// This class should use only on Windows that we can access shell32.dll /// static class Win32ShellFolder2 { private const uint SHGFI_LARGEICON = 0x0; private const uint SHGFI_SMALLICON = 0x1; private const uint SHGFI_ICON = 0x100; private const uint SHGFI_TYPENAME = 0x400; private const uint SHGFI_ATTRIBUTES = 0x800; private struct SHFILEINFO { public IntPtr hIcon; public IntPtr iIcon; public uint dwAttributes; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] public string szDisplayName; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)] public string szTypeName; }; [DllImport("msvcrt.dll", SetLastError = false)] static extern IntPtr memcpy(IntPtr dest, IntPtr src, int count); [DllImport("gdi32.dll")] static extern int GetDIBits(IntPtr hdc, IntPtr hbmp, uint uStartScan, uint cScanLines, int[] lpvBits, ref BITMAPINFO lpbmi, uint uUsage); [DllImport("gdi32.dll")] public static extern int BitBlt(IntPtr hdcDst, int xDst, int yDst, int w, int h, IntPtr hdcSrc, int xSrc, int ySrc, int rop); [DllImport("user32.dll")] public static extern IntPtr GetDC(IntPtr hwnd); [DllImport("gdi32.dll")] static extern int GetObject(IntPtr hgdiobj, int cbBuffer, ref BITMAPINFO lpvObject); [DllImport("gdi32.dll")] public static extern IntPtr CreateCompatibleDC(IntPtr hdc); [DllImport("user32.dll")] public static extern int ReleaseDC(IntPtr hwnd, IntPtr hdc); [DllImport("gdi32.dll")] static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int nWidth, int nHeight); [DllImport("gdi32.dll")] public static extern int DeleteDC(IntPtr hdc); [StructLayout(LayoutKind.Sequential)] struct ICONINFO { public bool fIcon; // Specifies whether this structure defines an icon or a cursor. A value of TRUE specifies // an icon; FALSE specifies a cursor. public Int32 xHotspot; // Specifies the x-coordinate of a cursor's hot spot. If this structure defines an icon, the hot // spot is always in the center of the icon, and this member is ignored. public Int32 yHotspot; // Specifies the y-coordinate of the cursor's hot spot. If this structure defines an icon, the hot // spot is always in the center of the icon, and this member is ignored. public IntPtr hbmMask; // (HBITMAP) Specifies the icon bitmask bitmap. If this structure defines a black and white icon, // this bitmask is formatted so that the upper half is the icon AND bitmask and the lower half is // the icon XOR bitmask. Under this condition, the height should be an even multiple of two. If // this structure defines a color icon, this mask only defines the AND bitmask of the icon. public IntPtr hbmColor; // (HBITMAP) Handle to the icon color bitmap. This member can be optional if this // structure defines a black and white icon. The AND bitmask of hbmMask is applied with the SRCAND // flag to the destination; subsequently, the color bitmap is applied (using XOR) to the // destination by using the SRCINVERT flag. } [DllImport("user32.dll")] static extern bool GetIconInfo(IntPtr hIcon, out ICONINFO piconinfo); [StructLayout(LayoutKind.Sequential)] public struct BITMAPINFO { public uint biSize; public int biWidth, biHeight; public short biPlanes, biBitCount; public uint biCompression, biSizeImage; public int biXPelsPerMeter, biYPelsPerMeter; public uint biClrUsed, biClrImportant; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)] public uint[] cols; } [DllImport("shell32.dll")] private static extern int FindExecutable(string lpFile, string lpDirectory, StringBuilder lpResult); [DllImport("shell32.dll")] private static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbSizeFileInfo, uint uFlags); [DllImport("user32.dll", EntryPoint = "LoadImage")] private static extern IntPtr LoadImageID(IntPtr hInstance, int uID, uint type, int width, int height, int load); [DllImport("user32.dll", EntryPoint = "LoadImage")] private static extern IntPtr LoadImageName(IntPtr hInstance, string lpszName, uint type, int width, int height, int load); [DllImport("kernel32.dll")] static extern IntPtr LoadLibrary(string Library); [DllImport("gdi32.dll", EntryPoint = "DeleteObject")] public static extern bool DeleteObject(IntPtr hDc); private const uint IMAGE_BITMAP = 0; private const uint IMAGE_ICON = 1; /// /// Get the program to execute or open the file. If it is a exe then it is self /// /// path to the file /// public static string getExecutableType(string path) { StringBuilder objResultBuffer = new StringBuilder(1024); int result = FindExecutable(path, path, objResultBuffer); if (result >= 32) { return objResultBuffer.ToString(); } return null; } /// /// Get the type of a file or folder. On a file it depends on its extension. /// /// /// public static string getFolderType(string path) { SHFILEINFO shinfo = new SHFILEINFO(); if (0 == SHGetFileInfo(path, 0, ref shinfo, (uint)Marshal.SizeOf(shinfo), SHGFI_TYPENAME).ToInt32()) { return null; } return shinfo.szTypeName; } public static IntPtr getIcon(string path, bool getLargeIcon) { SHFILEINFO shinfo = new SHFILEINFO(); if (0 == SHGetFileInfo(path, 0, ref shinfo, (uint)Marshal.SizeOf(shinfo), SHGFI_ICON | (getLargeIcon ? 0 : SHGFI_SMALLICON)).ToInt32()) { return IntPtr.Zero; } return shinfo.hIcon; } public static int[] getIconBits(IntPtr hIcon, int iconSize) { ICONINFO iconInfo; if (GetIconInfo(hIcon, out iconInfo)) { IntPtr hWnd = new IntPtr(0); IntPtr dc = GetDC(hWnd); BITMAPINFO bmi = new BITMAPINFO(); bmi.biSize = 40; bmi.biWidth = iconSize; bmi.biHeight = -iconSize; bmi.biPlanes = 1; bmi.biBitCount = 32; bmi.biCompression = 0; int intArrSize = iconSize * iconSize; int[] iconBits = new int[intArrSize]; GetDIBits(dc, iconInfo.hbmColor, 0, (uint)iconSize, iconBits, ref bmi, 0); bool hasAlpha = false; bool isXP = (Environment.OSVersion.Version.Major >= 6) || (Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor>=1); if (isXP) { for (int i = 0; i < iconBits.Length; i++) { if ((iconBits[i] & 0xFF000000) != 0) { hasAlpha = true; break; } } } if (!hasAlpha) { int[] maskBits = new int[intArrSize]; GetDIBits(dc, iconInfo.hbmMask, 0, (uint)iconSize, maskBits, ref bmi, 0); for (int i = 0; i < iconBits.Length; i++) { if (maskBits[i] == 0) { iconBits[i] = (int)((uint)iconBits[i] | 0xFF000000); } } } DeleteObject(iconInfo.hbmColor); DeleteObject(iconInfo.hbmMask); return iconBits; } return null; } public static int getAttribute(string path) { SHFILEINFO shinfo = new SHFILEINFO(); if (0 == SHGetFileInfo(path, 0, ref shinfo, (uint)Marshal.SizeOf(shinfo), SHGFI_ATTRIBUTES).ToInt32()) { return 0; } return (int)shinfo.dwAttributes; } public static string getLinkLocation(string path) { using (ShellLink link = new ShellLink()) { link.Load(path); return link.GetPath(); } } public static int[] getFileChooserBitmapHandle() { // Code copied from ShellFolder2.cpp Java_sun_awt_shell_Win32ShellFolder2_getFileChooserBitmapBits IntPtr libShell32 = LoadLibrary("shell32.dll"); // Get a handle to an icon. bool isVista = Environment.OSVersion.Version.Major >= 6; IntPtr hBitmap = isVista ? LoadImageName(libShell32, "IDB_TB_SH_DEF_16", IMAGE_BITMAP, 0, 0, 0) : LoadImageID(libShell32, 216, IMAGE_BITMAP, 0, 0, 0); if (hBitmap.ToInt32() == 0) { IntPtr libComCtl32 = LoadLibrary("comctl32.dll"); hBitmap = LoadImageID(libComCtl32, 124, IMAGE_BITMAP, 0, 0, 0); } if (hBitmap.ToInt32() == 0) { return new int[768*16]; } BITMAPINFO bmi = new BITMAPINFO(); GetObject(hBitmap, Marshal.SizeOf(bmi), ref bmi); int width = bmi.biWidth; int height = bmi.biHeight; bmi.biSize = 40; bmi.biHeight = -bmi.biHeight; bmi.biPlanes = 1; bmi.biBitCount = 32; bmi.biCompression = 0; IntPtr hwnd = new IntPtr(0); IntPtr dc = GetDC(hwnd); int[] data = new int[width*height]; GetDIBits(dc, hBitmap, (uint)0, (uint)height, data, ref bmi, 0); DeleteObject(hBitmap); ReleaseDC(hwnd, dc); return data; } public static IntPtr getIconResource(String libName, int iconID, int cxDesired, int cyDesired) { IntPtr hLibName = LoadLibrary(libName); return LoadImageID(hLibName, iconID, IMAGE_ICON, cxDesired, cyDesired, 0); } } class ShellLink : IDisposable { [ComImport] [Guid("0000010B-0000-0000-C000-000000000046")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IPersistFile { [PreserveSig] void GetClassID(out Guid pClassID); [PreserveSig] void IsDirty(); [PreserveSig] void Load([MarshalAs(UnmanagedType.LPWStr)] string pszFileName, uint dwMode); [PreserveSig] void Save([MarshalAs(UnmanagedType.LPWStr)] string pszFileName, [MarshalAs(UnmanagedType.Bool)] bool fRemember); [PreserveSig] void SaveCompleted([MarshalAs(UnmanagedType.LPWStr)] string pszFileName); [PreserveSig] void GetCurFile([MarshalAs(UnmanagedType.LPWStr)] out string ppszFileName); } [ComImport] [Guid("000214F9-0000-0000-C000-000000000046")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] private interface IShellLinkW { void GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, int cchMaxPath, IntPtr pfd, uint fFlags); void GetIDList(out IntPtr ppidl); void SetIDList(IntPtr pidl); void GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, int cchMaxName); void SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName); void GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, int cchMaxPath); void SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir); void GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, int cchMaxPath); void SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs); void GetHotkey(out short pwHotkey); void SetHotkey(short pwHotkey); void GetShowCmd(out uint piShowCmd); void SetShowCmd(uint piShowCmd); void GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, int cchIconPath, out int piIcon); void SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon); void SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, uint dwReserved); void Resolve(IntPtr hWnd, uint fFlags); void SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile); } [Guid("00021401-0000-0000-C000-000000000046")] [ClassInterfaceAttribute(ClassInterfaceType.None)] [ComImport] private class CShellLink { } [Flags] public enum EShowWindowFlags : uint { SW_HIDE = 0, SW_SHOWNORMAL = 1, SW_NORMAL = 1, SW_SHOWMINIMIZED = 2, SW_SHOWMAXIMIZED = 3, SW_MAXIMIZE = 3, SW_SHOWNOACTIVATE = 4, SW_SHOW = 5, SW_MINIMIZE = 6, SW_SHOWMINNOACTIVE = 7, SW_SHOWNA = 8, SW_RESTORE = 9, SW_SHOWDEFAULT = 10, SW_MAX = 10 } private IShellLinkW linkW = (IShellLinkW)new CShellLink(); public void Dispose() { if (linkW != null) { Marshal.ReleaseComObject(linkW); linkW = null; } } public void SetPath(string path) { linkW.SetPath(path); } public void SetDescription(string description) { linkW.SetDescription(description); } public void SetWorkingDirectory(string dir) { linkW.SetWorkingDirectory(dir); } public void SetArguments(string args) { linkW.SetArguments(args); } public void SetShowCmd(EShowWindowFlags cmd) { linkW.SetShowCmd((uint)cmd); } public void Save(string linkFile) { ((IPersistFile)linkW).Save(linkFile, true); } public void Load(string linkFile) { ((IPersistFile)linkW).Load(linkFile, 0); } public string GetArguments() { StringBuilder sb = new StringBuilder(512); linkW.GetArguments(sb, sb.Capacity); return sb.ToString(); } public string GetPath() { StringBuilder sb = new StringBuilder(512); linkW.GetPath(sb, sb.Capacity, IntPtr.Zero, 0); return sb.ToString(); } } } namespace IKVM.NativeCode.sun.java2d { static class DefaultDisposerRecord { public static void invokeNativeDispose(long disposerMethodPointer, long dataPointer) { throw new NotImplementedException(); } } static class Disposer { public static void initIDs() { } } } namespace IKVM.NativeCode.sun.java2d.pipe { static class Region { public static void initIDs(){ } } static class RenderBuffer { public static void copyFromArray(object srcArray, long srcPos, long dstAddr, long length){ throw new NotImplementedException(); } } } namespace IKVM.NativeCode.sun.misc { static class GC { public static long maxObjectInspectionAge() { return 0; } } static class MessageUtils { public static void toStderr(string msg) { Console.Error.Write(msg); } public static void toStdout(string msg) { Console.Out.Write(msg); } } static class MiscHelper { public static object getAssemblyClassLoader(Assembly asm, object extcl) { if (extcl == null || asm.IsDefined(typeof(IKVM.Attributes.CustomAssemblyClassLoaderAttribute), false)) { return AssemblyClassLoader.FromAssembly(asm).GetJavaClassLoader(); } return null; } } static class Signal { public static int findSignal(string sigName) { return 0; } public static long handle0(int sig, long nativeH) { return 0; } public static void raise0(int sig) { throw new NotImplementedException(); } } static class NativeSignalHandler { public static void handle0(int number, long handler) { throw new NotImplementedException(); } } static class Perf { public static object attach(object thisPerf, string user, int lvmid, int mode) { throw new NotImplementedException(); } public static void detach(object thisPerf, object bb) { throw new NotImplementedException(); } public static object createLong(object thisPerf, string name, int variability, int units, long value) { throw new NotImplementedException(); } public static object createByteArray(object thisPerf, string name, int variability, int units, byte[] value, int maxLength) { throw new NotImplementedException(); } public static long highResCounter(object thisPerf) { throw new NotImplementedException(); } public static long highResFrequency(object thisPerf) { throw new NotImplementedException(); } public static void registerNatives() { } } static class Unsafe { public static void throwException(object thisUnsafe, Exception x) { throw x; } public static void ensureClassInitialized(object thisUnsafe, object clazz) { TypeWrapper tw = TypeWrapper.FromClass(clazz); if (!tw.IsArray) { try { tw.Finish(); } catch (RetargetableJavaException x) { throw x.ToJava(); } tw.RunClassInit(); } } public static object allocateInstance(object thisUnsafe, object clazz) { TypeWrapper wrapper = TypeWrapper.FromClass(clazz); try { wrapper.Finish(); } catch (RetargetableJavaException x) { throw x.ToJava(); } return FormatterServices.GetUninitializedObject(wrapper.TypeAsBaseType); } } static class Version { public static string getJvmSpecialVersion() { throw new NotImplementedException(); } public static string getJdkSpecialVersion() { throw new NotImplementedException(); } public static bool getJvmVersionInfo() { throw new NotImplementedException(); } public static void getJdkVersionInfo() { throw new NotImplementedException(); } } static class VM { public static void getThreadStateValues(int[][] vmThreadStateValues, string[][] vmThreadStateNames) { // TODO } public static void initialize() { } } static class VMSupport { public static object initAgentProperties(object props) { return props; } } } namespace IKVM.NativeCode.sun.net.spi { static class DefaultProxySelector { public static bool init() { return true; } public static object getSystemProxy(object thisDefaultProxySelector, string protocol, string host) { // TODO on Whidbey we might be able to use System.Net.Configuration.DefaultProxySection.Proxy return null; } } } namespace IKVM.NativeCode.sun.reflect { #if !FIRST_PASS public interface IReflectionException { jlIllegalArgumentException GetIllegalArgumentException(object obj); jlIllegalArgumentException SetIllegalArgumentException(object obj); } #endif static class Reflection { #if CLASSGC private sealed class State { internal int Value; } private static readonly ConditionalWeakTable isHideFromJavaCache = new ConditionalWeakTable(); internal static bool IsHideFromJava(MethodBase mb) { State state = isHideFromJavaCache.GetOrCreateValue(mb); if (state.Value == 0) { state.Value = IsHideFromJavaImpl(mb); } return state.Value == 1; } private static int IsHideFromJavaImpl(MethodBase mb) { if (mb.Name.StartsWith("__<", StringComparison.Ordinal)) { return 1; } if (mb.IsDefined(typeof(IKVM.Attributes.HideFromJavaAttribute), false) || mb.IsDefined(typeof(IKVM.Attributes.HideFromReflectionAttribute), false)) { return 1; } return 2; } #else private static readonly Dictionary isHideFromJavaCache = new Dictionary(); internal static bool IsHideFromJava(MethodBase mb) { if (mb.Name.StartsWith("__<", StringComparison.Ordinal)) { return true; } RuntimeMethodHandle handle; try { handle = mb.MethodHandle; } catch (InvalidOperationException) { // DynamicMethods don't have a RuntimeMethodHandle and we always want to hide them anyway return true; } catch (NotSupportedException) { // DynamicMethods don't have a RuntimeMethodHandle and we always want to hide them anyway return true; } lock (isHideFromJavaCache) { bool cached; if (isHideFromJavaCache.TryGetValue(handle, out cached)) { return cached; } } bool isHide = mb.IsDefined(typeof(IKVM.Attributes.HideFromJavaAttribute), false) || mb.IsDefined(typeof(IKVM.Attributes.HideFromReflectionAttribute), false); lock (isHideFromJavaCache) { isHideFromJavaCache[handle] = isHide; } return isHide; } #endif // NOTE this method is hooked up explicitly through map.xml to prevent inlining of the native stub // and tail-call optimization in the native stub. public static object getCallerClass(int realFramesToSkip) { #if FIRST_PASS return null; #else int i = 3; if (realFramesToSkip <= 1) { i = 1; realFramesToSkip = Math.Max(realFramesToSkip + 2, 2); } realFramesToSkip--; for (; ; ) { MethodBase method = new StackFrame(i++, false).GetMethod(); if (method == null) { return null; } Type type = method.DeclaringType; // NOTE these checks should be the same as the ones in SecurityManager.getClassContext if (IsHideFromJava(method) || type == null || type.Assembly == typeof(object).Assembly || type.Assembly == typeof(Reflection).Assembly || type.Assembly == java.lang.SecurityManager.jniAssembly || type == typeof(jlrMethod) || type == typeof(jlrConstructor)) { continue; } if (--realFramesToSkip == 0) { return ClassLoaderWrapper.GetWrapperFromType(type).ClassObject; } } #endif } public static int getClassAccessFlags(object clazz) { return (int)TypeWrapper.FromClass(clazz).Modifiers; } public static bool checkInternalAccess(object currentClass, object memberClass) { TypeWrapper current = TypeWrapper.FromClass(currentClass); TypeWrapper member = TypeWrapper.FromClass(memberClass); return member.IsInternal && member.InternalsVisibleTo(current); } } static class ReflectionFactory { #if !FIRST_PASS private static object[] ConvertArgs(TypeWrapper[] argumentTypes, object[] args) { object[] nargs = new object[args == null ? 0 : args.Length]; if (nargs.Length != argumentTypes.Length) { throw new jlIllegalArgumentException("wrong number of arguments"); } for (int i = 0; i < nargs.Length; i++) { if (argumentTypes[i].IsPrimitive) { if (args[i] == null) { throw new jlIllegalArgumentException("primitive wrapper null"); } nargs[i] = JVM.Unbox(args[i]); // NOTE we depend on the fact that the .NET reflection parameter type // widening rules are the same as in Java, but to have this work for byte // we need to convert byte to sbyte. if (nargs[i] is byte && argumentTypes[i] != PrimitiveTypeWrapper.BYTE) { nargs[i] = (sbyte)(byte)nargs[i]; } } else { if (args[i] != null && !argumentTypes[i].IsInstance(args[i])) { throw new jlIllegalArgumentException(); } nargs[i] = args[i]; } } return nargs; } private sealed class MethodAccessorImpl : srMethodAccessor { private readonly MethodWrapper mw; internal MethodAccessorImpl(jlrMethod method) { mw = MethodWrapper.FromMethodOrConstructor(method); } [IKVM.Attributes.HideFromJava] public object invoke(object obj, object[] args, global::ikvm.@internal.CallerID callerID) { if (!mw.IsStatic && !mw.DeclaringType.IsInstance(obj)) { if (obj == null) { throw new jlNullPointerException(); } throw new jlIllegalArgumentException("object is not an instance of declaring class"); } args = ConvertArgs(mw.GetParameters(), args); // if the method is an interface method, we must explicitly run , // because .NET reflection doesn't if (mw.DeclaringType.IsInterface) { mw.DeclaringType.RunClassInit(); } object retval; try { retval = ((ICustomInvoke)mw).Invoke(obj, args, callerID); } catch (MethodAccessException x) { // this can happen if we're calling a non-public method and the call stack doesn't have ReflectionPermission.MemberAccess throw new jlIllegalAccessException().initCause(x); } if (mw.ReturnType.IsPrimitive && mw.ReturnType != PrimitiveTypeWrapper.VOID) { retval = JVM.Box(retval); } return retval; } } internal sealed class FastMethodAccessorImpl : srMethodAccessor { private static readonly MethodInfo valueOfByte; private static readonly MethodInfo valueOfBoolean; private static readonly MethodInfo valueOfChar; private static readonly MethodInfo valueOfShort; private static readonly MethodInfo valueOfInt; private static readonly MethodInfo valueOfFloat; private static readonly MethodInfo valueOfLong; private static readonly MethodInfo valueOfDouble; private static readonly MethodInfo byteValue; private static readonly MethodInfo booleanValue; private static readonly MethodInfo charValue; private static readonly MethodInfo shortValue; private static readonly MethodInfo intValue; private static readonly MethodInfo floatValue; private static readonly MethodInfo longValue; private static readonly MethodInfo doubleValue; internal static readonly ConstructorInfo invocationTargetExceptionCtor; private delegate object Invoker(object obj, object[] args, global::ikvm.@internal.CallerID callerID); private Invoker invoker; static FastMethodAccessorImpl() { valueOfByte = typeof(jlByte).GetMethod("valueOf", new Type[] { typeof(byte) }); valueOfBoolean = typeof(jlBoolean).GetMethod("valueOf", new Type[] { typeof(bool) }); valueOfChar = typeof(jlCharacter).GetMethod("valueOf", new Type[] { typeof(char) }); valueOfShort = typeof(jlShort).GetMethod("valueOf", new Type[] { typeof(short) }); valueOfInt = typeof(jlInteger).GetMethod("valueOf", new Type[] { typeof(int) }); valueOfFloat = typeof(jlFloat).GetMethod("valueOf", new Type[] { typeof(float) }); valueOfLong = typeof(jlLong).GetMethod("valueOf", new Type[] { typeof(long) }); valueOfDouble = typeof(jlDouble).GetMethod("valueOf", new Type[] { typeof(double) }); byteValue = typeof(jlByte).GetMethod("byteValue", Type.EmptyTypes); booleanValue = typeof(jlBoolean).GetMethod("booleanValue", Type.EmptyTypes); charValue = typeof(jlCharacter).GetMethod("charValue", Type.EmptyTypes); shortValue = typeof(jlShort).GetMethod("shortValue", Type.EmptyTypes); intValue = typeof(jlInteger).GetMethod("intValue", Type.EmptyTypes); floatValue = typeof(jlFloat).GetMethod("floatValue", Type.EmptyTypes); longValue = typeof(jlLong).GetMethod("longValue", Type.EmptyTypes); doubleValue = typeof(jlDouble).GetMethod("doubleValue", Type.EmptyTypes); invocationTargetExceptionCtor = typeof(jlrInvocationTargetException).GetConstructor(new Type[] { typeof(Exception) }); } private sealed class RunClassInit { private FastMethodAccessorImpl outer; private TypeWrapper tw; private Invoker invoker; internal RunClassInit(FastMethodAccessorImpl outer, TypeWrapper tw, Invoker invoker) { this.outer = outer; this.tw = tw; this.invoker = invoker; } [IKVM.Attributes.HideFromJava] internal object invoke(object obj, object[] args, global::ikvm.@internal.CallerID callerID) { // FXBUG pre-SP1 a DynamicMethod that calls a static method doesn't trigger the cctor, so we do that explicitly. // even on .NET 2.0 SP2, interface method invocations don't run the interface cctor // NOTE when testing, please test both the x86 and x64 CLR JIT, because they have different bugs (even on .NET 2.0 SP2) tw.RunClassInit(); outer.invoker = invoker; return invoker(obj, args, callerID); } } internal FastMethodAccessorImpl(jlrMethod method, bool nonvirtual) { MethodWrapper mw = MethodWrapper.FromMethodOrConstructor(method); mw.DeclaringType.Finish(); mw.ResolveMethod(); DynamicMethod dm = DynamicMethodUtils.Create("__", mw.DeclaringType.TypeAsBaseType, !mw.IsPublic || !mw.DeclaringType.IsPublic || nonvirtual, typeof(object), new Type[] { typeof(object), typeof(object[]), typeof(global::ikvm.@internal.CallerID) }); CodeEmitter ilgen = CodeEmitter.Create(dm); LocalBuilder ret = ilgen.DeclareLocal(typeof(object)); if (!mw.IsStatic) { // check target for null ilgen.Emit(OpCodes.Ldarg_0); ilgen.EmitNullCheck(); } // check args length CodeEmitterLabel argsLengthOK = ilgen.DefineLabel(); if (mw.GetParameters().Length == 0) { // zero length array may be null ilgen.Emit(OpCodes.Ldarg_1); ilgen.Emit(OpCodes.Brfalse_S, argsLengthOK); } ilgen.Emit(OpCodes.Ldarg_1); ilgen.Emit(OpCodes.Ldlen); ilgen.Emit(OpCodes.Ldc_I4, mw.GetParameters().Length); ilgen.Emit(OpCodes.Beq_S, argsLengthOK); ilgen.EmitThrow("java.lang.IllegalArgumentException"); ilgen.MarkLabel(argsLengthOK); int thisCount = mw.IsStatic ? 0 : 1; LocalBuilder[] args = new LocalBuilder[mw.GetParameters().Length + thisCount]; if (!mw.IsStatic) { args[0] = ilgen.DeclareLocal(mw.DeclaringType.TypeAsSignatureType); } for (int i = thisCount; i < args.Length; i++) { mw.GetParameters()[i - thisCount].Finish(); args[i] = ilgen.DeclareLocal(mw.GetParameters()[i - thisCount].TypeAsSignatureType); } ilgen.BeginExceptionBlock(); if (!mw.IsStatic) { ilgen.Emit(OpCodes.Ldarg_0); mw.DeclaringType.EmitCheckcast(null, ilgen); mw.DeclaringType.EmitConvStackTypeToSignatureType(ilgen, null); ilgen.Emit(OpCodes.Stloc, args[0]); } for (int i = thisCount; i < args.Length; i++) { ilgen.Emit(OpCodes.Ldarg_1); ilgen.Emit(OpCodes.Ldc_I4, i - thisCount); ilgen.Emit(OpCodes.Ldelem_Ref); TypeWrapper tw = mw.GetParameters()[i - thisCount]; EmitUnboxArg(ilgen, tw); tw.EmitConvStackTypeToSignatureType(ilgen, null); ilgen.Emit(OpCodes.Stloc, args[i]); } ilgen.BeginCatchBlock(typeof(InvalidCastException)); ilgen.EmitThrow("java.lang.IllegalArgumentException"); ilgen.BeginCatchBlock(typeof(NullReferenceException)); ilgen.EmitThrow("java.lang.IllegalArgumentException"); ilgen.EndExceptionBlock(); // this is the actual call ilgen.BeginExceptionBlock(); for (int i = 0; i < args.Length; i++) { if (i == 0 && !mw.IsStatic && (mw.DeclaringType.IsNonPrimitiveValueType || mw.DeclaringType.IsGhost)) { ilgen.Emit(OpCodes.Ldloca, args[i]); } else { ilgen.Emit(OpCodes.Ldloc, args[i]); } } if (mw.HasCallerID) { ilgen.Emit(OpCodes.Ldarg_2); } if (mw.IsStatic || nonvirtual) { mw.EmitCall(ilgen); } else { mw.EmitCallvirtReflect(ilgen); } mw.ReturnType.EmitConvSignatureTypeToStackType(ilgen); BoxReturnValue(ilgen, mw.ReturnType); ilgen.Emit(OpCodes.Stloc, ret); ilgen.BeginCatchBlock(typeof(Exception)); ilgen.Emit(OpCodes.Ldc_I4_1); ilgen.Emit(OpCodes.Call, Compiler.mapExceptionFastMethod); ilgen.Emit(OpCodes.Newobj, invocationTargetExceptionCtor); ilgen.Emit(OpCodes.Throw); ilgen.EndExceptionBlock(); ilgen.Emit(OpCodes.Ldloc, ret); ilgen.Emit(OpCodes.Ret); invoker = (Invoker)dm.CreateDelegate(typeof(Invoker)); if ((mw.IsStatic || mw.DeclaringType.IsInterface) && mw.DeclaringType.HasStaticInitializer) { invoker = new Invoker(new RunClassInit(this, mw.DeclaringType, invoker).invoke); } } private static void Expand(CodeEmitter ilgen, TypeWrapper type) { if (type == PrimitiveTypeWrapper.FLOAT) { ilgen.Emit(OpCodes.Conv_R4); } else if (type == PrimitiveTypeWrapper.LONG) { ilgen.Emit(OpCodes.Conv_I8); } else if (type == PrimitiveTypeWrapper.DOUBLE) { ilgen.Emit(OpCodes.Conv_R8); } } internal static void EmitUnboxArg(CodeEmitter ilgen, TypeWrapper type) { if (type == PrimitiveTypeWrapper.BYTE) { ilgen.Emit(OpCodes.Castclass, typeof(jlByte)); ilgen.Emit(OpCodes.Call, byteValue); } else if (type == PrimitiveTypeWrapper.BOOLEAN) { ilgen.Emit(OpCodes.Castclass, typeof(jlBoolean)); ilgen.Emit(OpCodes.Call, booleanValue); } else if (type == PrimitiveTypeWrapper.CHAR) { ilgen.Emit(OpCodes.Castclass, typeof(jlCharacter)); ilgen.Emit(OpCodes.Call, charValue); } else if (type == PrimitiveTypeWrapper.SHORT || type == PrimitiveTypeWrapper.INT || type == PrimitiveTypeWrapper.FLOAT || type == PrimitiveTypeWrapper.LONG || type == PrimitiveTypeWrapper.DOUBLE) { ilgen.Emit(OpCodes.Dup); ilgen.Emit(OpCodes.Isinst, typeof(jlByte)); CodeEmitterLabel next = ilgen.DefineLabel(); ilgen.Emit(OpCodes.Brfalse_S, next); ilgen.Emit(OpCodes.Call, byteValue); ilgen.Emit(OpCodes.Conv_I1); Expand(ilgen, type); CodeEmitterLabel done = ilgen.DefineLabel(); ilgen.Emit(OpCodes.Br_S, done); ilgen.MarkLabel(next); if (type == PrimitiveTypeWrapper.SHORT) { ilgen.Emit(OpCodes.Castclass, typeof(jlShort)); ilgen.Emit(OpCodes.Call, shortValue); } else { ilgen.Emit(OpCodes.Dup); ilgen.Emit(OpCodes.Isinst, typeof(jlShort)); next = ilgen.DefineLabel(); ilgen.Emit(OpCodes.Brfalse_S, next); ilgen.Emit(OpCodes.Call, shortValue); Expand(ilgen, type); ilgen.Emit(OpCodes.Br_S, done); ilgen.MarkLabel(next); ilgen.Emit(OpCodes.Dup); ilgen.Emit(OpCodes.Isinst, typeof(jlCharacter)); next = ilgen.DefineLabel(); ilgen.Emit(OpCodes.Brfalse_S, next); ilgen.Emit(OpCodes.Call, charValue); Expand(ilgen, type); ilgen.Emit(OpCodes.Br_S, done); ilgen.MarkLabel(next); if (type == PrimitiveTypeWrapper.INT) { ilgen.Emit(OpCodes.Castclass, typeof(jlInteger)); ilgen.Emit(OpCodes.Call, intValue); } else { ilgen.Emit(OpCodes.Dup); ilgen.Emit(OpCodes.Isinst, typeof(jlInteger)); next = ilgen.DefineLabel(); ilgen.Emit(OpCodes.Brfalse_S, next); ilgen.Emit(OpCodes.Call, intValue); Expand(ilgen, type); ilgen.Emit(OpCodes.Br_S, done); ilgen.MarkLabel(next); if (type == PrimitiveTypeWrapper.LONG) { ilgen.Emit(OpCodes.Castclass, typeof(jlLong)); ilgen.Emit(OpCodes.Call, longValue); } else { ilgen.Emit(OpCodes.Dup); ilgen.Emit(OpCodes.Isinst, typeof(jlLong)); next = ilgen.DefineLabel(); ilgen.Emit(OpCodes.Brfalse_S, next); ilgen.Emit(OpCodes.Call, longValue); Expand(ilgen, type); ilgen.Emit(OpCodes.Br_S, done); ilgen.MarkLabel(next); if (type == PrimitiveTypeWrapper.FLOAT) { ilgen.Emit(OpCodes.Castclass, typeof(jlFloat)); ilgen.Emit(OpCodes.Call, floatValue); } else if (type == PrimitiveTypeWrapper.DOUBLE) { ilgen.Emit(OpCodes.Dup); ilgen.Emit(OpCodes.Isinst, typeof(jlFloat)); next = ilgen.DefineLabel(); ilgen.Emit(OpCodes.Brfalse_S, next); ilgen.Emit(OpCodes.Call, floatValue); ilgen.Emit(OpCodes.Br_S, done); ilgen.MarkLabel(next); ilgen.Emit(OpCodes.Castclass, typeof(jlDouble)); ilgen.Emit(OpCodes.Call, doubleValue); } else { throw new InvalidOperationException(); } } } } ilgen.MarkLabel(done); } else { type.EmitCheckcast(null, ilgen); } } private static void BoxReturnValue(CodeEmitter ilgen, TypeWrapper type) { if (type == PrimitiveTypeWrapper.VOID) { ilgen.Emit(OpCodes.Ldnull); } else if (type == PrimitiveTypeWrapper.BYTE) { ilgen.Emit(OpCodes.Call, valueOfByte); } else if (type == PrimitiveTypeWrapper.BOOLEAN) { ilgen.Emit(OpCodes.Call, valueOfBoolean); } else if (type == PrimitiveTypeWrapper.CHAR) { ilgen.Emit(OpCodes.Call, valueOfChar); } else if (type == PrimitiveTypeWrapper.SHORT) { ilgen.Emit(OpCodes.Call, valueOfShort); } else if (type == PrimitiveTypeWrapper.INT) { ilgen.Emit(OpCodes.Call, valueOfInt); } else if (type == PrimitiveTypeWrapper.FLOAT) { ilgen.Emit(OpCodes.Call, valueOfFloat); } else if (type == PrimitiveTypeWrapper.LONG) { ilgen.Emit(OpCodes.Call, valueOfLong); } else if (type == PrimitiveTypeWrapper.DOUBLE) { ilgen.Emit(OpCodes.Call, valueOfDouble); } } [IKVM.Attributes.HideFromJava] public object invoke(object obj, object[] args, global::ikvm.@internal.CallerID callerID) { return invoker(obj, args, callerID); } } private sealed class ConstructorAccessorImpl : srConstructorAccessor { private readonly MethodWrapper mw; internal ConstructorAccessorImpl(jlrConstructor constructor) { mw = MethodWrapper.FromMethodOrConstructor(constructor); } [IKVM.Attributes.HideFromJava] public object newInstance(object[] args) { args = ConvertArgs(mw.GetParameters(), args); try { return ((ICustomInvoke)mw).Invoke(null, args, null); } catch (MethodAccessException x) { // this can happen if we're calling a non-public method and the call stack doesn't have ReflectionPermission.MemberAccess throw new jlIllegalAccessException().initCause(x); } } } private sealed class FastConstructorAccessorImpl : srConstructorAccessor { private delegate object Invoker(object[] args); private Invoker invoker; internal FastConstructorAccessorImpl(jlrConstructor constructor) { MethodWrapper mw = MethodWrapper.FromMethodOrConstructor(constructor); mw.DeclaringType.Finish(); mw.ResolveMethod(); DynamicMethod dm = DynamicMethodUtils.Create("__", mw.DeclaringType.TypeAsTBD, !mw.IsPublic || !mw.DeclaringType.IsPublic, typeof(object), new Type[] { typeof(object[]) }); CodeEmitter ilgen = CodeEmitter.Create(dm); LocalBuilder ret = ilgen.DeclareLocal(typeof(object)); // check args length CodeEmitterLabel argsLengthOK = ilgen.DefineLabel(); if (mw.GetParameters().Length == 0) { // zero length array may be null ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Brfalse_S, argsLengthOK); } ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Ldlen); ilgen.Emit(OpCodes.Ldc_I4, mw.GetParameters().Length); ilgen.Emit(OpCodes.Beq_S, argsLengthOK); ilgen.EmitThrow("java.lang.IllegalArgumentException"); ilgen.MarkLabel(argsLengthOK); LocalBuilder[] args = new LocalBuilder[mw.GetParameters().Length]; for (int i = 0; i < args.Length; i++) { mw.GetParameters()[i].Finish(); args[i] = ilgen.DeclareLocal(mw.GetParameters()[i].TypeAsSignatureType); } ilgen.BeginExceptionBlock(); for (int i = 0; i < args.Length; i++) { ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Ldc_I4, i); ilgen.Emit(OpCodes.Ldelem_Ref); TypeWrapper tw = mw.GetParameters()[i]; FastMethodAccessorImpl.EmitUnboxArg(ilgen, tw); tw.EmitConvStackTypeToSignatureType(ilgen, null); ilgen.Emit(OpCodes.Stloc, args[i]); } ilgen.BeginCatchBlock(typeof(InvalidCastException)); ilgen.EmitThrow("java.lang.IllegalArgumentException"); ilgen.BeginCatchBlock(typeof(NullReferenceException)); ilgen.EmitThrow("java.lang.IllegalArgumentException"); ilgen.EndExceptionBlock(); // this is the actual call ilgen.BeginExceptionBlock(); for (int i = 0; i < args.Length; i++) { ilgen.Emit(OpCodes.Ldloc, args[i]); } mw.EmitNewobj(ilgen); ilgen.Emit(OpCodes.Stloc, ret); ilgen.BeginCatchBlock(typeof(Exception)); ilgen.Emit(OpCodes.Ldc_I4_1); ilgen.Emit(OpCodes.Call, Compiler.mapExceptionFastMethod); ilgen.Emit(OpCodes.Newobj, FastMethodAccessorImpl.invocationTargetExceptionCtor); ilgen.Emit(OpCodes.Throw); ilgen.EndExceptionBlock(); ilgen.Emit(OpCodes.Ldloc, ret); ilgen.Emit(OpCodes.Ret); invoker = (Invoker)dm.CreateDelegate(typeof(Invoker)); } [IKVM.Attributes.HideFromJava] public object newInstance(object[] args) { return invoker(args); } } private sealed class FastSerializationConstructorAccessorImpl : srConstructorAccessor { private static readonly MethodInfo GetTypeFromHandleMethod = typeof(Type).GetMethod("GetTypeFromHandle", new Type[] { typeof(RuntimeTypeHandle) }); private static readonly MethodInfo GetUninitializedObjectMethod = typeof(FormatterServices).GetMethod("GetUninitializedObject", new Type[] { typeof(Type) }); private delegate object InvokeCtor(); private InvokeCtor invoker; internal FastSerializationConstructorAccessorImpl(jlrConstructor constructorToCall, jlClass classToInstantiate) { MethodWrapper constructor = MethodWrapper.FromMethodOrConstructor(constructorToCall); if (constructor.GetParameters().Length != 0) { throw new NotImplementedException("Serialization constructor cannot have parameters"); } constructor.Link(); constructor.ResolveMethod(); Type type; try { TypeWrapper wrapper = TypeWrapper.FromClass(classToInstantiate); wrapper.Finish(); type = wrapper.TypeAsBaseType; } catch (RetargetableJavaException x) { throw x.ToJava(); } DynamicMethod dm = DynamicMethodUtils.Create("__", constructor.DeclaringType.TypeAsBaseType, true, typeof(object), null); CodeEmitter ilgen = CodeEmitter.Create(dm); ilgen.Emit(OpCodes.Ldtoken, type); ilgen.Emit(OpCodes.Call, GetTypeFromHandleMethod); ilgen.Emit(OpCodes.Call, GetUninitializedObjectMethod); ilgen.Emit(OpCodes.Dup); constructor.EmitCall(ilgen); ilgen.Emit(OpCodes.Ret); invoker = (InvokeCtor)dm.CreateDelegate(typeof(InvokeCtor)); } [IKVM.Attributes.HideFromJava] public object newInstance(object[] args) { return invoker(); } } sealed class ActivatorConstructorAccessor : srConstructorAccessor { private readonly Type type; internal ActivatorConstructorAccessor(MethodWrapper mw) { this.type = mw.DeclaringType.TypeAsBaseType; } public object newInstance(object[] objarr) { #if FIRST_PASS return null; #else if (objarr != null && objarr.Length != 0) { throw new global::java.lang.IllegalArgumentException(); } try { return Activator.CreateInstance(type); } catch (TargetInvocationException x) { throw new global::java.lang.reflect.InvocationTargetException(global::ikvm.runtime.Util.mapException(x.InnerException)); } #endif } internal static bool IsSuitable(MethodWrapper mw) { MethodBase mb = mw.GetMethod(); return mb != null && mb.IsConstructor && mb.IsPublic && mb.DeclaringType.IsPublic && mb.DeclaringType == mw.DeclaringType.TypeAsBaseType && mb.GetParameters().Length == 0; } } private abstract class FieldAccessorImplBase : srFieldAccessor, IReflectionException { protected static readonly ushort inflationThreshold = 15; protected readonly FieldWrapper fw; protected readonly bool isFinal; protected ushort numInvocations; static FieldAccessorImplBase() { string str = jlSystem.getProperty("ikvm.reflect.field.inflationThreshold"); int value; if (str != null && int.TryParse(str, out value)) { if (value >= ushort.MinValue && value <= ushort.MaxValue) { inflationThreshold = (ushort)value; } } } private FieldAccessorImplBase(jlrField field, bool overrideAccessCheck) { fw = FieldWrapper.FromField(field); isFinal = (!overrideAccessCheck || fw.IsStatic) && fw.IsFinal; } private string GetQualifiedFieldName() { return fw.DeclaringType.Name + "." + fw.Name; } private string GetFieldTypeName() { return ((jlClass)fw.FieldTypeWrapper.ClassObject).getName(); } public jlIllegalArgumentException GetIllegalArgumentException(object obj) { // LAME like JDK 6 we return the wrong exception message (talking about setting the field, instead of getting) return SetIllegalArgumentException(obj); } public jlIllegalArgumentException SetIllegalArgumentException(object obj) { // LAME like JDK 6 we return the wrong exception message (when obj is the object, instead of the value) return SetIllegalArgumentException(obj != null ? irUtil.getClassFromObject(obj).getName() : "", ""); } private jlIllegalArgumentException SetIllegalArgumentException(string attemptedType, string attemptedValue) { return new jlIllegalArgumentException(GetSetMessage(attemptedType, attemptedValue)); } protected jlIllegalAccessException FinalFieldIllegalAccessException(object obj) { return FinalFieldIllegalAccessException(obj != null ? irUtil.getClassFromObject(obj).getName() : "", ""); } private jlIllegalAccessException FinalFieldIllegalAccessException(string attemptedType, string attemptedValue) { return new jlIllegalAccessException(GetSetMessage(attemptedType, attemptedValue)); } private jlIllegalArgumentException GetIllegalArgumentException(string type) { return new jlIllegalArgumentException("Attempt to get " + GetFieldTypeName() + " field \"" + GetQualifiedFieldName() + "\" with illegal data type conversion to " + type); } // this message comes from sun.reflect.UnsafeFieldAccessorImpl private string GetSetMessage(String attemptedType, String attemptedValue) { String err = "Can not set"; if (fw.IsStatic) err += " static"; if (isFinal) err += " final"; err += " " + GetFieldTypeName() + " field " + GetQualifiedFieldName() + " to "; if (attemptedValue.Length > 0) { err += "(" + attemptedType + ")" + attemptedValue; } else { if (attemptedType.Length > 0) err += attemptedType; else err += "null value"; } return err; } public virtual bool getBoolean(object obj) { throw GetIllegalArgumentException("boolean"); } public virtual byte getByte(object obj) { throw GetIllegalArgumentException("byte"); } public virtual char getChar(object obj) { throw GetIllegalArgumentException("char"); } public virtual short getShort(object obj) { throw GetIllegalArgumentException("short"); } public virtual int getInt(object obj) { throw GetIllegalArgumentException("int"); } public virtual long getLong(object obj) { throw GetIllegalArgumentException("long"); } public virtual float getFloat(object obj) { throw GetIllegalArgumentException("float"); } public virtual double getDouble(object obj) { throw GetIllegalArgumentException("double"); } public virtual void setBoolean(object obj, bool z) { throw SetIllegalArgumentException("boolean", jlBoolean.toString(z)); } public virtual void setByte(object obj, byte b) { throw SetIllegalArgumentException("byte", jlByte.toString(b)); } public virtual void setChar(object obj, char c) { throw SetIllegalArgumentException("char", jlCharacter.toString(c)); } public virtual void setShort(object obj, short s) { throw SetIllegalArgumentException("short", jlShort.toString(s)); } public virtual void setInt(object obj, int i) { throw SetIllegalArgumentException("int", jlInteger.toString(i)); } public virtual void setLong(object obj, long l) { throw SetIllegalArgumentException("long", jlLong.toString(l)); } public virtual void setFloat(object obj, float f) { throw SetIllegalArgumentException("float", jlFloat.toString(f)); } public virtual void setDouble(object obj, double d) { throw SetIllegalArgumentException("double", jlDouble.toString(d)); } public abstract object get(object obj); public abstract void set(object obj, object value); private abstract class FieldAccessor : FieldAccessorImplBase { protected delegate void Setter(object obj, T value, FieldAccessor acc); protected delegate T Getter(object obj, FieldAccessor acc); private static readonly Setter initialSetter = lazySet; private static readonly Getter initialGetter = lazyGet; protected Setter setter = initialSetter; protected Getter getter = initialGetter; internal FieldAccessor(jlrField field, bool overrideAccessCheck) : base(field, overrideAccessCheck) { if (!IsSlowPathCompatible(fw)) { // prevent slow path numInvocations = inflationThreshold; } } protected bool IsSpecialType(TypeWrapper tw) { return tw.IsNonPrimitiveValueType || tw.IsGhost || tw.IsFakeNestedType; } protected bool IsSlowPathCompatible(FieldWrapper fw) { if (IsSpecialType(fw.DeclaringType) || IsSpecialType(fw.FieldTypeWrapper)) { return false; } fw.Link(); return fw.GetField() != null; } private static T lazyGet(object obj, FieldAccessor acc) { return acc.lazyGet(obj); } private static void lazySet(object obj, T value, FieldAccessor acc) { acc.lazySet(obj, value); } private T lazyGet(object obj) { if (numInvocations < inflationThreshold) { if (fw.IsStatic) { obj = null; } else if (!fw.DeclaringType.IsInstance(obj)) { throw GetIllegalArgumentException(obj); } if (numInvocations == 0) { fw.DeclaringType.RunClassInit(); fw.DeclaringType.Finish(); fw.ResolveField(); } numInvocations++; return (T)fw.GetField().GetValue(obj); } else { // FXBUG it appears that a ldsfld/stsfld in a DynamicMethod doesn't trigger the class constructor // and if we didn't use the slow path, we haven't yet initialized the class fw.DeclaringType.RunClassInit(); getter = (Getter)GenerateFastGetter(typeof(Getter), typeof(T), fw); return getter(obj, this); } } private void lazySet(object obj, T value) { if (isFinal) { // for some reason Java runs class initialization before checking if the field is final fw.DeclaringType.RunClassInit(); throw FinalFieldIllegalAccessException(JavaBox(value)); } if (numInvocations < inflationThreshold) { if (fw.IsStatic) { obj = null; } else if (!fw.DeclaringType.IsInstance(obj)) { throw SetIllegalArgumentException(obj); } CheckValue(value); if (numInvocations == 0) { fw.DeclaringType.RunClassInit(); fw.DeclaringType.Finish(); fw.ResolveField(); } numInvocations++; fw.GetField().SetValue(obj, value); } else { // FXBUG it appears that a ldsfld/stsfld in a DynamicMethod doesn't trigger the class constructor // and if we didn't use the slow path, we haven't yet initialized the class fw.DeclaringType.RunClassInit(); setter = (Setter)GenerateFastSetter(typeof(Setter), typeof(T), fw); setter(obj, value, this); } } protected virtual void CheckValue(T value) { } protected abstract object JavaBox(T value); } private sealed class ByteField : FieldAccessor { internal ByteField(jlrField field, bool overrideAccessCheck) : base(field, overrideAccessCheck) { } public sealed override short getShort(object obj) { return (sbyte)getByte(obj); } public sealed override int getInt(object obj) { return (sbyte)getByte(obj); } public sealed override long getLong(object obj) { return (sbyte)getByte(obj); } public sealed override float getFloat(object obj) { return (sbyte)getByte(obj); } public sealed override double getDouble(object obj) { return (sbyte)getByte(obj); } public sealed override object get(object obj) { return jlByte.valueOf(getByte(obj)); } public sealed override void set(object obj, object val) { if (!(val is jlByte)) { throw SetIllegalArgumentException(val); } setByte(obj, ((jlByte)val).byteValue()); } public sealed override byte getByte(object obj) { return getter(obj, this); } public sealed override void setByte(object obj, byte value) { setter(obj, value, this); } protected sealed override object JavaBox(byte value) { return jlByte.valueOf(value); } } private sealed class BooleanField : FieldAccessor { internal BooleanField(jlrField field, bool overrideAccessCheck) : base(field, overrideAccessCheck) { } public sealed override object get(object obj) { return jlBoolean.valueOf(getBoolean(obj)); } public sealed override void set(object obj, object val) { if (!(val is jlBoolean)) { throw SetIllegalArgumentException(val); } setBoolean(obj, ((jlBoolean)val).booleanValue()); } public sealed override bool getBoolean(object obj) { return getter(obj, this); } public sealed override void setBoolean(object obj, bool value) { setter(obj, value, this); } protected sealed override object JavaBox(bool value) { return jlBoolean.valueOf(value); } } private sealed class CharField : FieldAccessor { internal CharField(jlrField field, bool overrideAccessCheck) : base(field, overrideAccessCheck) { } public sealed override int getInt(object obj) { return getChar(obj); } public sealed override long getLong(object obj) { return getChar(obj); } public sealed override float getFloat(object obj) { return getChar(obj); } public sealed override double getDouble(object obj) { return getChar(obj); } public sealed override object get(object obj) { return jlCharacter.valueOf(getChar(obj)); } public sealed override void set(object obj, object val) { if (val is jlCharacter) setChar(obj, ((jlCharacter)val).charValue()); else throw SetIllegalArgumentException(val); } public sealed override char getChar(object obj) { return getter(obj, this); } public sealed override void setChar(object obj, char value) { setter(obj, value, this); } protected sealed override object JavaBox(char value) { return jlCharacter.valueOf(value); } } private sealed class ShortField : FieldAccessor { internal ShortField(jlrField field, bool overrideAccessCheck) : base(field, overrideAccessCheck) { } public sealed override int getInt(object obj) { return getShort(obj); } public sealed override long getLong(object obj) { return getShort(obj); } public sealed override float getFloat(object obj) { return getShort(obj); } public sealed override double getDouble(object obj) { return getShort(obj); } public sealed override object get(object obj) { return jlShort.valueOf(getShort(obj)); } public sealed override void set(object obj, object val) { if (val is jlByte || val is jlShort) setShort(obj, ((jlNumber)val).shortValue()); else throw SetIllegalArgumentException(val); } public sealed override void setByte(object obj, byte b) { setShort(obj, (sbyte)b); } public sealed override short getShort(object obj) { return getter(obj, this); } public sealed override void setShort(object obj, short value) { setter(obj, value, this); } protected sealed override object JavaBox(short value) { return jlShort.valueOf(value); } } private sealed class IntField : FieldAccessor { internal IntField(jlrField field, bool overrideAccessCheck) : base(field, overrideAccessCheck) { } public sealed override long getLong(object obj) { return getInt(obj); } public sealed override float getFloat(object obj) { return getInt(obj); } public sealed override double getDouble(object obj) { return getInt(obj); } public sealed override object get(object obj) { return jlInteger.valueOf(getInt(obj)); } public sealed override void set(object obj, object val) { if (val is jlByte || val is jlShort || val is jlInteger) setInt(obj, ((jlNumber)val).intValue()); else if (val is jlCharacter) setInt(obj, ((jlCharacter)val).charValue()); else throw SetIllegalArgumentException(val); } public sealed override void setByte(object obj, byte b) { setInt(obj, (sbyte)b); } public sealed override void setChar(object obj, char c) { setInt(obj, c); } public sealed override void setShort(object obj, short s) { setInt(obj, s); } public sealed override int getInt(object obj) { return getter(obj, this); } public sealed override void setInt(object obj, int value) { setter(obj, value, this); } protected sealed override object JavaBox(int value) { return jlInteger.valueOf(value); } } private sealed class FloatField : FieldAccessor { internal FloatField(jlrField field, bool overrideAccessCheck) : base(field, overrideAccessCheck) { } public sealed override double getDouble(object obj) { return getFloat(obj); } public sealed override object get(object obj) { return jlFloat.valueOf(getFloat(obj)); } public sealed override void set(object obj, object val) { if (val is jlFloat || val is jlByte || val is jlShort || val is jlInteger || val is jlLong) setFloat(obj, ((jlNumber)val).floatValue()); else if (val is jlCharacter) setFloat(obj, ((jlCharacter)val).charValue()); else throw SetIllegalArgumentException(val); } public sealed override void setByte(object obj, byte b) { setFloat(obj, (sbyte)b); } public sealed override void setChar(object obj, char c) { setFloat(obj, c); } public sealed override void setShort(object obj, short s) { setFloat(obj, s); } public sealed override void setInt(object obj, int i) { setFloat(obj, i); } public sealed override void setLong(object obj, long l) { setFloat(obj, l); } public sealed override float getFloat(object obj) { return getter(obj, this); } public sealed override void setFloat(object obj, float value) { setter(obj, value, this); } protected sealed override object JavaBox(float value) { return jlFloat.valueOf(value); } } private sealed class LongField : FieldAccessor { internal LongField(jlrField field, bool overrideAccessCheck) : base(field, overrideAccessCheck) { } public sealed override float getFloat(object obj) { return getLong(obj); } public sealed override double getDouble(object obj) { return getLong(obj); } public sealed override object get(object obj) { return jlLong.valueOf(getLong(obj)); } public sealed override void set(object obj, object val) { if (val is jlLong || val is jlByte || val is jlShort || val is jlInteger) setLong(obj, ((jlNumber)val).longValue()); else if (val is jlCharacter) setLong(obj, ((jlCharacter)val).charValue()); else throw SetIllegalArgumentException(val); } public sealed override void setByte(object obj, byte b) { setLong(obj, (sbyte)b); } public sealed override void setChar(object obj, char c) { setLong(obj, c); } public sealed override void setShort(object obj, short s) { setLong(obj, s); } public sealed override void setInt(object obj, int i) { setLong(obj, i); } public sealed override long getLong(object obj) { return getter(obj, this); } public sealed override void setLong(object obj, long value) { setter(obj, value, this); } protected sealed override object JavaBox(long value) { return jlLong.valueOf(value); } } private sealed class DoubleField : FieldAccessor { internal DoubleField(jlrField field, bool overrideAccessCheck) : base(field, overrideAccessCheck) { } public sealed override object get(object obj) { return jlDouble.valueOf(getDouble(obj)); } public sealed override void set(object obj, object val) { if (val is jlDouble || val is jlFloat || val is jlByte || val is jlShort || val is jlInteger || val is jlLong) setDouble(obj, ((jlNumber)val).doubleValue()); else if (val is jlCharacter) setDouble(obj, ((jlCharacter)val).charValue()); else throw SetIllegalArgumentException(val); } public sealed override void setByte(object obj, byte b) { setDouble(obj, (sbyte)b); } public sealed override void setChar(object obj, char c) { setDouble(obj, c); } public sealed override void setShort(object obj, short s) { setDouble(obj, s); } public sealed override void setInt(object obj, int i) { setDouble(obj, i); } public sealed override void setLong(object obj, long l) { setDouble(obj, l); } public sealed override void setFloat(object obj, float f) { setDouble(obj, f); } public sealed override double getDouble(object obj) { return getter(obj, this); } public sealed override void setDouble(object obj, double value) { setter(obj, value, this); } protected sealed override object JavaBox(double value) { return jlDouble.valueOf(value); } } private sealed class ObjectField : FieldAccessor { internal ObjectField(jlrField field, bool overrideAccessCheck) : base(field, overrideAccessCheck) { } protected sealed override void CheckValue(object value) { if (value != null && !fw.FieldTypeWrapper.IsInstance(value)) { throw SetIllegalArgumentException(value); } } public sealed override object get(object obj) { return getter(obj, this); } public sealed override void set(object obj, object value) { setter(obj, value, this); } protected sealed override object JavaBox(object value) { return value; } } private Delegate GenerateFastGetter(Type delegateType, Type fieldType, FieldWrapper fw) { fw.FieldTypeWrapper.Finish(); fw.DeclaringType.Finish(); fw.ResolveField(); DynamicMethod dm = DynamicMethodUtils.Create("__", fw.DeclaringType.TypeAsBaseType, !fw.IsPublic || !fw.DeclaringType.IsPublic, fieldType, new Type[] { typeof(IReflectionException), typeof(object), typeof(object) }); CodeEmitter ilgen = CodeEmitter.Create(dm); if (fw.IsStatic) { fw.EmitGet(ilgen); fw.FieldTypeWrapper.EmitConvSignatureTypeToStackType(ilgen); } else { ilgen.BeginExceptionBlock(); ilgen.Emit(OpCodes.Ldarg_1); ilgen.Emit(OpCodes.Castclass, fw.DeclaringType.TypeAsBaseType); fw.EmitGet(ilgen); fw.FieldTypeWrapper.EmitConvSignatureTypeToStackType(ilgen); LocalBuilder local = ilgen.DeclareLocal(fieldType); ilgen.Emit(OpCodes.Stloc, local); ilgen.BeginCatchBlock(typeof(InvalidCastException)); ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Ldarg_1); ilgen.Emit(OpCodes.Callvirt, typeof(IReflectionException).GetMethod("GetIllegalArgumentException")); ilgen.Emit(OpCodes.Throw); ilgen.EndExceptionBlock(); ilgen.Emit(OpCodes.Ldloc, local); } ilgen.Emit(OpCodes.Ret); return dm.CreateDelegate(delegateType, this); } private Delegate GenerateFastSetter(Type delegateType, Type fieldType, FieldWrapper fw) { fw.FieldTypeWrapper.Finish(); fw.DeclaringType.Finish(); fw.ResolveField(); DynamicMethod dm = DynamicMethodUtils.Create("__", fw.DeclaringType.TypeAsBaseType, !fw.IsPublic || !fw.DeclaringType.IsPublic, null, new Type[] { typeof(IReflectionException), typeof(object), fieldType, typeof(object) }); CodeEmitter ilgen = CodeEmitter.Create(dm); if (fw.IsStatic) { if (fieldType == typeof(object)) { ilgen.BeginExceptionBlock(); ilgen.Emit(OpCodes.Ldarg_2); fw.FieldTypeWrapper.EmitConvStackTypeToSignatureType(ilgen, null); fw.EmitSet(ilgen); ilgen.BeginCatchBlock(typeof(InvalidCastException)); ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Ldarg_1); ilgen.Emit(OpCodes.Callvirt, typeof(IReflectionException).GetMethod("SetIllegalArgumentException")); ilgen.Emit(OpCodes.Throw); ilgen.EndExceptionBlock(); } else { ilgen.Emit(OpCodes.Ldarg_2); fw.EmitSet(ilgen); } } else { ilgen.BeginExceptionBlock(); ilgen.Emit(OpCodes.Ldarg_1); ilgen.Emit(OpCodes.Castclass, fw.DeclaringType.TypeAsBaseType); ilgen.Emit(OpCodes.Ldarg_2); fw.FieldTypeWrapper.EmitConvStackTypeToSignatureType(ilgen, null); fw.EmitSet(ilgen); ilgen.BeginCatchBlock(typeof(InvalidCastException)); ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Ldarg_1); ilgen.Emit(OpCodes.Callvirt, typeof(IReflectionException).GetMethod("SetIllegalArgumentException")); ilgen.Emit(OpCodes.Throw); ilgen.EndExceptionBlock(); } ilgen.Emit(OpCodes.Ret); return dm.CreateDelegate(delegateType, this); } internal static FieldAccessorImplBase Create(jlrField field, bool overrideAccessCheck) { jlClass type = field.getType(); if (type.isPrimitive()) { if (type == jlByte.TYPE) { return new ByteField(field, overrideAccessCheck); } if (type == jlBoolean.TYPE) { return new BooleanField(field, overrideAccessCheck); } if (type == jlCharacter.TYPE) { return new CharField(field, overrideAccessCheck); } if (type == jlShort.TYPE) { return new ShortField(field, overrideAccessCheck); } if (type == jlInteger.TYPE) { return new IntField(field, overrideAccessCheck); } if (type == jlFloat.TYPE) { return new FloatField(field, overrideAccessCheck); } if (type == jlLong.TYPE) { return new LongField(field, overrideAccessCheck); } if (type == jlDouble.TYPE) { return new DoubleField(field, overrideAccessCheck); } throw new InvalidOperationException("field type: " + type); } else { return new ObjectField(field, overrideAccessCheck); } } } #endif public static object newFieldAccessor(object thisFactory, object field, bool overrideAccessCheck) { #if FIRST_PASS return null; #else return FieldAccessorImplBase.Create((jlrField)field, overrideAccessCheck); #endif } public static object newMethodAccessor(object thisFactory, object method) { #if FIRST_PASS return null; #else jlrMethod m = (jlrMethod)method; MethodWrapper mw = MethodWrapper.FromMethodOrConstructor(method); if (mw is ICustomInvoke) { return new MethodAccessorImpl(m); } else { return new FastMethodAccessorImpl(m, false); } #endif } public static object newConstructorAccessor0(object thisFactory, object constructor) { #if FIRST_PASS return null; #else jlrConstructor cons = (jlrConstructor)constructor; MethodWrapper mw = MethodWrapper.FromMethodOrConstructor(constructor); if (mw is ICustomInvoke) { return new ConstructorAccessorImpl(cons); } else if (ActivatorConstructorAccessor.IsSuitable(mw)) { // we special case public default constructors, because in that case using Activator.CreateInstance() // is almost as fast as FastConstructorAccessorImpl, but it saves us significantly in working set and // startup time (because often during startup a sun.nio.cs.* encoder is instantiated using reflection) return new ActivatorConstructorAccessor(mw); } else { return new FastConstructorAccessorImpl(cons); } #endif } public static object newConstructorAccessorForSerialization(object classToInstantiate, object constructorToCall) { #if FIRST_PASS return null; #else jlrConstructor cons = (jlrConstructor)constructorToCall; return new FastSerializationConstructorAccessorImpl(cons, (jlClass)classToInstantiate); #endif } } static class ConstantPool { public static int getSize0(object thisConstantPool, object constantPoolOop) { throw new NotImplementedException(); } public static object getClassAt0(object thisConstantPool, object constantPoolOop, int index) { throw new NotImplementedException(); } public static object getClassAtIfLoaded0(object thisConstantPool, object constantPoolOop, int index) { throw new NotImplementedException(); } public static object getMethodAt0(object thisConstantPool, object constantPoolOop, int index) { throw new NotImplementedException(); } public static object getMethodAtIfLoaded0(object thisConstantPool, object constantPoolOop, int index) { throw new NotImplementedException(); } public static object getFieldAt0(object thisConstantPool, object constantPoolOop, int index) { throw new NotImplementedException(); } public static object getFieldAtIfLoaded0(object thisConstantPool, object constantPoolOop, int index) { throw new NotImplementedException(); } public static string[] getMemberRefInfoAt0(object thisConstantPool, object constantPoolOop, int index) { throw new NotImplementedException(); } public static int getIntAt0(object thisConstantPool, object constantPoolOop, int index) { throw new NotImplementedException(); } public static long getLongAt0(object thisConstantPool, object constantPoolOop, int index) { throw new NotImplementedException(); } public static float getFloatAt0(object thisConstantPool, object constantPoolOop, int index) { throw new NotImplementedException(); } public static double getDoubleAt0(object thisConstantPool, object constantPoolOop, int index) { throw new NotImplementedException(); } public static string getStringAt0(object thisConstantPool, object constantPoolOop, int index) { throw new NotImplementedException(); } public static string getUTF8At0(object thisConstantPool, object constantPoolOop, int index) { throw new NotImplementedException(); } } } namespace IKVM.NativeCode.sun.rmi.server { static class MarshalInputStream { public static object latestUserDefinedLoader() { return java.io.ObjectInputStream.latestUserDefinedLoader(); } } } namespace IKVM.NativeCode.sun.security.krb5 { static class Credentials { public static object acquireDefaultNativeCreds() { // TODO return null; } } static class Config { public static string getWindowsDirectory() { return Environment.GetEnvironmentVariable("SystemRoot"); } } } namespace IKVM.NativeCode.sun.security.provider { static class NativeSeedGenerator { public static bool nativeGenerateSeed(byte[] result) { try { System.Security.Cryptography.RNGCryptoServiceProvider csp = new System.Security.Cryptography.RNGCryptoServiceProvider(); csp.GetBytes(result); return true; } catch (System.Security.Cryptography.CryptographicException) { return false; } } } } namespace IKVM.NativeCode.com.sun.java.util.jar.pack { static class NativeUnpack { public static void initIDs() { } public static long start(object thisNativeUnpack, object buf, long offset) { throw new NotImplementedException(); } public static bool getNextFile(object thisNativeUnpack, object[] parts) { throw new NotImplementedException(); } public static object getUnusedInput(object thisNativeUnpack) { throw new NotImplementedException(); } public static long finish(object thisNativeUnpack) { throw new NotImplementedException(); } public static bool setOption(object thisNativeUnpack, string opt, string value) { throw new NotImplementedException(); } public static string getOption(object thisNativeUnpack, string opt) { throw new NotImplementedException(); } } } namespace IKVM.NativeCode.com.sun.security.auth.module { static class NTSystem { public static void getCurrent(object thisObj, bool debug) { throw new NotImplementedException(); } } static class SolarisSystem { public static void getSolarisInfo(object thisObj) { throw new NotImplementedException(); } } static class UnixSystem { public static void getUnixInfo(object thisObj) { throw new NotImplementedException(); } } } namespace IKVM.NativeCode.com.sun.media.sound { static class JDK13Services { public static string getDefaultProviderClassName(object deviceClass) { return null; } public static string getDefaultInstanceName(object deviceClass) { return null; } public static object getProviders(object providerClass) { #if FIRST_PASS return null; #else return new global::java.util.ArrayList(); #endif } } } namespace IKVM.NativeCode.java.awt { static class AWTEvent { public static void initIDs() { } public static void nativeSetSource(object thisObj, object peer){ } } static class Button { public static void initIDs() { } } static class Checkbox { public static void initIDs() { } } static class CheckboxMenuItem { public static void initIDs() { } } static class Color { public static void initIDs() { } } static class Component { public static void initIDs() { } } static class Container { public static void initIDs() { } } static class Cursor { public static void initIDs() { } public static void finalizeImpl(Int64 pData){ } } static class Dialog { public static void initIDs() { } } static class Dimension { public static void initIDs() { } } static class Event { public static void initIDs() { } } static class FileDialog { public static void initIDs() { } } static class Frame { public static void initIDs() { } } static class FontMetrics { public static void initIDs() { } } static class Insets { public static void initIDs() { } } static class KeyboardFocusManager { public static void initIDs() { } } static class Label { public static void initIDs() { } } static class Menu { public static void initIDs() { } } static class MenuBar { public static void initIDs() { } } static class MenuComponent { public static void initIDs() { } } static class MenuItem { public static void initIDs() { } } static class Rectangle { public static void initIDs() { } } static class Scrollbar { public static void initIDs() { } } static class ScrollPane { public static void initIDs() { } } static class ScrollPaneAdjustable { public static void initIDs() { } } static class SplashScreen { public static void _update(long splashPtr, int[] data, int x, int y, int width, int height, int scanlineStride){} public static bool _isVisible(long splashPtr){return false;} public static object _getBounds(long splashPtr){return null;} public static long _getInstance(){return 0;} public static void _close(long splashPtr){} public static String _getImageFileName(long splashPtr){return null;} public static String _getImageJarName(long splashPtr){return null;} public static bool _setImageData(long splashPtr, byte[] data){return false;} } static class TextArea { public static void initIDs() { } } static class TextField { public static void initIDs() { } } static class Toolkit { public static void initIDs() { } } static class TrayIcon { public static void initIDs() { } } static class Window { public static void initIDs() { } } } namespace IKVM.NativeCode.java.awt.@event { static class InputEvent { public static void initIDs() { } } static class MouseEvent { public static void initIDs() { } } static class KeyEvent { public static void initIDs() { } } } namespace IKVM.NativeCode.java.awt.image { static class ColorModel { public static void initIDs() { } } static class ComponentSampleModel { public static void initIDs() { } } static class Kernel { public static void initIDs() { } } static class Raster { public static void initIDs() { } } static class SinglePixelPackedSampleModel { public static void initIDs() { } } static class SampleModel { public static void initIDs() { } } }