📄 objectstreamclassimpl.c
字号:
/* * Java core library component. * * Copyright (c) 1997, 1998, 1999 * Transvirtual Technologies, Inc. All rights reserved. * * See the file "license.terms" for information on usage and redistribution * of this file. */#include "config.h"#include "config-std.h"#include "config-mem.h"#include "config-net.h"#include "../../../kaffe/kaffevm/classMethod.h"#include "../../../kaffe/kaffevm/itypes.h"#include "../../../kaffe/kaffevm/lookup.h"#include "../../../kaffe/kaffevm/access.h"#include "../../../kaffe/kaffevm/stringSupport.h"#include "../../../kaffe/kaffevm/support.h"#include "../../../kaffe/kaffevm/exception.h"#include "../../../kaffe/kaffevm/baseClasses.h"#include "../../../kaffe/kaffevm/sha-1.h"#include <native.h>#include "java_io_ObjectInputStream.h"#include "java_io_ObjectOutputStream.h"#include "kaffe_io_ObjectStreamClassImpl.h"#include <jni.h>static Hjava_lang_Object* newSerialObject(Hjava_lang_Class*,Hjava_lang_Object*);static HArrayOfObject* getFields(struct Hkaffe_io_ObjectStreamClassImpl*);static char* getClassName(Hjava_lang_Class* cls);/* NB: these guys are all write once and then immutable */static Utf8Const* serialVersionUIDName;static Utf8Const* writeObjectName;static Utf8Const* readObjectName;static Utf8Const* ObjectOutputStreamSig;static Utf8Const* ObjectInputStreamSig;static Hjava_lang_Class* ptrType;/* * Used to hold a descriptor item while calculating the serialUID. */typedef struct { const char* name; const char* desc; int modifier;} uidItem;voidkaffe_io_ObjectStreamClassImpl_init(void){ errorInfo einfo; serialVersionUIDName = checkPtr(utf8ConstNew("serialVersionUID" , -1)); writeObjectName = utf8ConstNew("writeObject", -1); if (!writeObjectName) { postOutOfMemory(&einfo); goto svun; } readObjectName = utf8ConstNew("readObject", -1); if (!readObjectName) { postOutOfMemory(&einfo); goto won; } ObjectOutputStreamSig = utf8ConstNew("(Ljava/io/ObjectOutputStream;)V", -1); if (!ObjectOutputStreamSig) { postOutOfMemory(&einfo); goto ron; } ObjectInputStreamSig = utf8ConstNew("(Ljava/io/ObjectInputStream;)V", -1); if (!ObjectInputStreamSig) { postOutOfMemory(&einfo); goto oos; } ptrType = lookupClass("kaffe/util/Ptr", NULL, &einfo); if (ptrType == 0) { utf8ConstRelease(ObjectInputStreamSig);oos: utf8ConstRelease(ObjectOutputStreamSig);ron: utf8ConstRelease(readObjectName);won: utf8ConstRelease(writeObjectName);svun: utf8ConstRelease(serialVersionUIDName); throwError(&einfo); }}struct Hjava_lang_Object*kaffe_io_ObjectStreamClassImpl_allocateNewObject(struct Hkaffe_io_ObjectStreamClassImpl* cls){ Hjava_lang_Object* obj; Hjava_lang_Class* clazz; Method* meth; /* Get the class and create an empty object of that type */ clazz = unhand(cls)->clazz; obj = newObject(clazz); /* Work our way down the superstreams until we get to the point where * we no longer are serializing. We get the superclass at that point * and invoke the <init>() constructor. */ do { clazz = clazz->superclass; cls = unhand(cls)->superstream; } while (cls != 0); meth = findMethodLocal(clazz, constructor_name, void_signature); if (meth == 0) { SignalErrorf("java.io.InvalidClassException", "%s; Missing no-arg constructor for class", CLASS_CNAME(clazz)); return (0); } else if ((meth->accflags & (ACC_CONSTRUCTOR|ACC_PRIVATE)) != ACC_CONSTRUCTOR) { SignalErrorf("java.io.InvalidClassException", "%s; IllegalAccessException", CLASS_CNAME(clazz)); return (0); } else { do_execute_java_method(obj, 0, 0, meth, 0); return (obj); }}struct Hjava_lang_Object*kaffe_io_ObjectStreamClassImpl_allocateNewArray(struct Hkaffe_io_ObjectStreamClassImpl* cls, jint sz){ return (newArray(CLASS_ELEMENT_TYPE(unhand(cls)->clazz), sz));}voidkaffe_io_ObjectStreamClassImpl_inputClassFields(struct Hkaffe_io_ObjectStreamClassImpl* cls, struct Hjava_lang_Object* obj, struct Hjava_io_ObjectInputStream* in){ int i; int len; Field** fld; if (unhand(cls)->fields == 0) { unhand(cls)->fields = getFields(cls); } fld = (Field**)unhand_array(unhand(cls)->fields)->body; len = obj_length(unhand(cls)->fields); if (unhand(cls)->iclazz != unhand(cls)->clazz) { obj = newSerialObject(unhand(cls)->iclazz, obj); }#define READ(FUNC,SIG,TYPE) \ ((jvalue*)(((uint8*)obj) + FIELD_BOFFSET(*fld)))->TYPE = \ do_execute_java_method(in, #FUNC, #SIG, 0, 0).TYPE for (i = 0; i < len; i++, fld++) { if (FIELD_ISREF(*fld)) { READ(readObject, ()Ljava/lang/Object;, l); } else switch (CLASS_PRIM_SIG(FIELD_TYPE(*fld))) { case 'B': READ(readByte, ()B, b); break; case 'C': READ(readChar, ()C, c); break; case 'D': READ(readDouble, ()D, d); break; case 'F': READ(readFloat, ()F, f); break; case 'J': READ(readLong, ()J, j); break; case 'S': READ(readShort, ()S, s); break; case 'Z': READ(readBoolean, ()Z, z); break; case 'I': READ(readInt, ()I, i); break; default: SignalError("java.io.InvalidClassException", "Unknown data type"); } } if (unhand(cls)->clazz != unhand(cls)->iclazz) { /* Transfer the inner class data to the outer class */ do_execute_java_method(obj, "readDefaultObject", "()V", 0, 0); }}voidkaffe_io_ObjectStreamClassImpl_outputClassFields(struct Hkaffe_io_ObjectStreamClassImpl* cls, struct Hjava_lang_Object* obj, struct Hjava_io_ObjectOutputStream* out){ int i; int len; Field** fld; if (unhand(cls)->fields == 0) { unhand(cls)->fields = getFields(cls); } fld = (Field**)unhand_array(unhand(cls)->fields)->body; len = obj_length(unhand(cls)->fields); if (unhand(cls)->iclazz != unhand(cls)->clazz) { /* Transfer the outer class data to the inner class */ obj = newSerialObject(unhand(cls)->iclazz, obj); do_execute_java_method(obj, "writeDefaultObject", "()V", 0, 0); }#define WRITE(FUNC,SIG,TYPE) \ do_execute_java_method(out, #FUNC, #SIG, 0, 0, \ ((jvalue*)(((uint8*)obj) + FIELD_BOFFSET(*fld)))->TYPE) for (i = 0; i < len; i++, fld++) { if (FIELD_ISREF(*fld)) { WRITE(writeObject, (Ljava/lang/Object;)V, l); } else switch (CLASS_PRIM_SIG(FIELD_TYPE(*fld))) { case 'B': WRITE(writeByte, (I)V, b); break; case 'C': WRITE(writeChar, (I)V, c); break; case 'D': WRITE(writeDouble, (D)V, d); break; case 'F': WRITE(writeFloat, (F)V, f); break; case 'J': WRITE(writeLong, (J)V, j); break; case 'S': WRITE(writeShort, (I)V, s); break; case 'Z': WRITE(writeBoolean, (Z)V, z); break; case 'I': WRITE(writeInt, (I)V, i); break; default: SignalError("java.io.InvalidClassException", "Unknown data type"); } }}voidkaffe_io_ObjectStreamClassImpl_outputClassFieldInfo(struct Hkaffe_io_ObjectStreamClassImpl* cls, struct Hjava_io_ObjectOutputStream* out){ Hjava_lang_Class* type; int i; int len; Field** fld; char* tname; char buf[128]; /* If we have no fields, we must build an array of field pointers * and sort them. */ if (unhand(cls)->fields == 0) { unhand(cls)->fields = getFields(cls); } fld = (Field**)unhand_array(unhand(cls)->fields)->body; len = obj_length(unhand(cls)->fields); do_execute_java_method(out, "writeShort", "(I)V", 0, 0, len); for (i = 0; i < len; i++, fld++) { type = FIELD_TYPE(*fld); if (CLASS_IS_PRIMITIVE(type)) { do_execute_java_method(out, "writeByte", "(I)V", 0, 0, CLASS_PRIM_SIG(type)); do_execute_java_method(out, "writeUTF", "(Ljava/lang/String;)V", 0, 0, checkPtr(utf8Const2Java((*fld)->name)));/* We dont output the modifiers do_execute_java_method(out, "writeShort", "(I)V", 0, 0, (*fld)->accflags);*/ } else { if (!FIELD_RESOLVED(*fld)) { tname = (char*)((Utf8Const*)type)->data; } else { tname = (char*)type->name->data; } if (tname[0] == '[') { strcpy(buf, tname); } else { strcpy(buf, "L"); strcat(buf, tname); strcat(buf, ";"); } do_execute_java_method(out, "writeByte", "(I)V", 0, 0, buf[0]); do_execute_java_method(out, "writeUTF", "(Ljava/lang/String;)V", 0, 0, checkPtr(utf8Const2Java((*fld)->name)));/* We dont output the modifiers do_execute_java_method(out, "writeShort", "(I)V", 0, 0, (*fld)->accflags);*/ do_execute_java_method(out, "writeObject", "(Ljava/lang/Object;)V", 0, 0, checkPtr(stringC2Java(buf))); } }}jbooleankaffe_io_ObjectStreamClassImpl_invokeObjectReader0(struct Hkaffe_io_ObjectStreamClassImpl* cls, struct Hjava_lang_Object* obj, struct Hjava_io_ObjectInputStream* in){ Method* meth; Hjava_lang_Object* oldObj; struct Hjava_io_ObjectStreamClass* oldCls; oldObj = unhand(in)->currentObject; oldCls = unhand(in)->currentStreamClass; unhand(in)->currentObject = obj; unhand(in)->currentStreamClass = (struct Hjava_io_ObjectStreamClass*)cls; meth = findMethodLocal(unhand(cls)->clazz, readObjectName, ObjectInputStreamSig); if (meth == 0) { errorInfo info; postExceptionMessage(&info, JAVA_LANG(NoSuchMethodError), readObjectName->data); throwError(&info); } do_execute_java_method(obj, 0, 0, meth, 0, in); unhand(in)->currentObject = oldObj; unhand(in)->currentStreamClass = oldCls; return (true);}jbooleankaffe_io_ObjectStreamClassImpl_invokeObjectWriter0(struct Hkaffe_io_ObjectStreamClassImpl* cls, struct Hjava_lang_Object* obj, struct Hjava_io_ObjectOutputStream* out){ Method* meth; Hjava_lang_Object* oldObj; struct Hjava_io_ObjectStreamClass* oldCls; oldObj = unhand(out)->currentObject; oldCls = unhand(out)->currentStreamClass; unhand(out)->currentObject = obj; unhand(out)->currentStreamClass = (struct Hjava_io_ObjectStreamClass*)cls; meth = findMethodLocal(unhand(cls)->clazz, writeObjectName, ObjectOutputStreamSig); do_execute_java_method(obj, 0, 0, meth, 0, out); unhand(out)->currentObject = oldObj; unhand(out)->currentStreamClass = oldCls; return (true);}staticintcompareUidItem(const void* one, const void* two){ int r; uidItem* o = (uidItem*)one; uidItem* t = (uidItem*)two; /* push null entries to the right end of the array */ if (o->name == 0) { return (1); } if (t->name == 0) { return (-1); } r = strcmp(o->name, t->name); if (r == 0) { r = strcmp(o->desc, t->desc); } return (r);}staticvoidaddToSHA(SHA1_CTX* c, uidItem* base, int len){ int i; int mod; jshort tmp; /* Sort the items into the required order */ if (len > 1) { qsort(base, len, sizeof(uidItem), compareUidItem); } /* Now enter the data into the SHA */ for (i = 0; i < len; i++) { if (base[i].name != 0) { tmp = htons(strlen(base[i].name)); SHA1Update(c, (char*)&tmp, sizeof(tmp)); SHA1Update(c, base[i].name, strlen(base[i].name)); if (base[i].modifier != -1) { /* Java is in 'network' order - bad but handy */ mod = htonl(base[i].modifier & ACC_MASK); SHA1Update(c, (char*)&mod, sizeof(mod)); tmp = htons(strlen(base[i].desc)); SHA1Update(c, (char*)&tmp, sizeof(tmp)); SHA1Update(c, base[i].desc, strlen(base[i].desc)); } } }}/* * Take a class name in slashed form pkg/subpkg/name, returns * a newly allocated one in dot form pkg.subpkg.name. * Caller must free using KFREE. */char*pathname2ClassnameCopy(const char *orig){ char* str; str = KMALLOC(strlen(orig) + 1); if (str != 0) { pathname2classname(orig, str); } return (str);}/* Return field description in slashed form, like Ljava/lang/String; * or like [I or like C or like [[Ljava/lang/String; * Caller frees with KFREE. */staticconst char*getFieldDesc(Field* fld){ char* str;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -