--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/back/inStream.c Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,490 @@
+/*
+ * Copyright 1998-2006 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+#include "util.h"
+#include "stream.h"
+#include "inStream.h"
+#include "transport.h"
+#include "bag.h"
+#include "commonRef.h"
+#include "FrameID.h"
+#include "typedefs.h"
+
+#define INITIAL_REF_ALLOC 50
+#define SMALLEST(a, b) ((a) < (b)) ? (a) : (b)
+
+/*
+ * TO DO: Support processing of replies through command input streams.
+ */
+void
+inStream_init(PacketInputStream *stream, jdwpPacket packet)
+{
+ stream->packet = packet;
+ stream->error = JDWP_ERROR(NONE);
+ stream->left = packet.type.cmd.len;
+ stream->current = packet.type.cmd.data;
+ stream->refs = bagCreateBag(sizeof(jobject), INITIAL_REF_ALLOC);
+ if (stream->refs == NULL) {
+ stream->error = JDWP_ERROR(OUT_OF_MEMORY);
+ }
+}
+
+jint
+inStream_id(PacketInputStream *stream)
+{
+ return stream->packet.type.cmd.id;
+}
+
+jbyte
+inStream_command(PacketInputStream *stream)
+{
+ return stream->packet.type.cmd.cmd;
+}
+
+static jdwpError
+readBytes(PacketInputStream *stream, void *dest, int size)
+{
+ if (stream->error) {
+ return stream->error;
+ }
+
+ if (size > stream->left) {
+ stream->error = JDWP_ERROR(INTERNAL);
+ return stream->error;
+ }
+
+ if (dest) {
+ (void)memcpy(dest, stream->current, size);
+ }
+ stream->current += size;
+ stream->left -= size;
+
+ return stream->error;
+}
+
+jdwpError
+inStream_skipBytes(PacketInputStream *stream, jint size) {
+ return readBytes(stream, NULL, size);
+}
+
+jboolean
+inStream_readBoolean(PacketInputStream *stream)
+{
+ jbyte flag = 0;
+ (void)readBytes(stream, &flag, sizeof(flag));
+ if (stream->error) {
+ return 0;
+ } else {
+ return flag ? JNI_TRUE : JNI_FALSE;
+ }
+}
+
+jbyte
+inStream_readByte(PacketInputStream *stream)
+{
+ jbyte val = 0;
+ (void)readBytes(stream, &val, sizeof(val));
+ return val;
+}
+
+jbyte *
+inStream_readBytes(PacketInputStream *stream, int length, jbyte *buf)
+{
+ (void)readBytes(stream, buf, length);
+ return buf;
+}
+
+jchar
+inStream_readChar(PacketInputStream *stream)
+{
+ jchar val = 0;
+ (void)readBytes(stream, &val, sizeof(val));
+ return JAVA_TO_HOST_CHAR(val);
+}
+
+jshort
+inStream_readShort(PacketInputStream *stream)
+{
+ jshort val = 0;
+ (void)readBytes(stream, &val, sizeof(val));
+ return JAVA_TO_HOST_SHORT(val);
+}
+
+jint
+inStream_readInt(PacketInputStream *stream)
+{
+ jint val = 0;
+ (void)readBytes(stream, &val, sizeof(val));
+ return JAVA_TO_HOST_INT(val);
+}
+
+jlong
+inStream_readLong(PacketInputStream *stream)
+{
+ jlong val = 0;
+ (void)readBytes(stream, &val, sizeof(val));
+ return JAVA_TO_HOST_LONG(val);
+}
+
+jfloat
+inStream_readFloat(PacketInputStream *stream)
+{
+ jfloat val = 0;
+ (void)readBytes(stream, &val, sizeof(val));
+ return JAVA_TO_HOST_FLOAT(val);
+}
+
+jdouble
+inStream_readDouble(PacketInputStream *stream)
+{
+ jdouble val = 0;
+ (void)readBytes(stream, &val, sizeof(val));
+ return JAVA_TO_HOST_DOUBLE(val);
+}
+
+/*
+ * Read an object from the stream. The ID used in the wire protocol
+ * is converted to a reference which is returned. The reference is
+ * global and strong, but it should *not* be deleted by the caller
+ * since it is freed when this stream is destroyed.
+ */
+jobject
+inStream_readObjectRef(JNIEnv *env, PacketInputStream *stream)
+{
+ jobject ref;
+ jobject *refPtr;
+ jlong id = inStream_readLong(stream);
+ if (stream->error) {
+ return NULL;
+ }
+ if (id == NULL_OBJECT_ID) {
+ return NULL;
+ }
+
+ ref = commonRef_idToRef(env, id);
+ if (ref == NULL) {
+ stream->error = JDWP_ERROR(INVALID_OBJECT);
+ return NULL;
+ }
+
+ refPtr = bagAdd(stream->refs);
+ if (refPtr == NULL) {
+ commonRef_idToRef_delete(env, ref);
+ return NULL;
+ }
+
+ *refPtr = ref;
+ return ref;
+}
+
+/*
+ * Read a raw object id from the stream. This should be used rarely.
+ * Normally, inStream_readObjectRef is preferred since it takes care
+ * of reference conversion and tracking. Only code that needs to
+ * perform maintence of the commonRef hash table uses this function.
+ */
+jlong
+inStream_readObjectID(PacketInputStream *stream)
+{
+ return inStream_readLong(stream);
+}
+
+jclass
+inStream_readClassRef(JNIEnv *env, PacketInputStream *stream)
+{
+ jobject object = inStream_readObjectRef(env, stream);
+ if (object == NULL) {
+ /*
+ * Could be error or just the null reference. In either case,
+ * stop now.
+ */
+ return NULL;
+ }
+ if (!isClass(object)) {
+ stream->error = JDWP_ERROR(INVALID_CLASS);
+ return NULL;
+ }
+ return object;
+}
+
+jthread
+inStream_readThreadRef(JNIEnv *env, PacketInputStream *stream)
+{
+ jobject object = inStream_readObjectRef(env, stream);
+ if (object == NULL) {
+ /*
+ * Could be error or just the null reference. In either case,
+ * stop now.
+ */
+ return NULL;
+ }
+ if (!isThread(object)) {
+ stream->error = JDWP_ERROR(INVALID_THREAD);
+ return NULL;
+ }
+ return object;
+}
+
+jthreadGroup
+inStream_readThreadGroupRef(JNIEnv *env, PacketInputStream *stream)
+{
+ jobject object = inStream_readObjectRef(env, stream);
+ if (object == NULL) {
+ /*
+ * Could be error or just the null reference. In either case,
+ * stop now.
+ */
+ return NULL;
+ }
+ if (!isThreadGroup(object)) {
+ stream->error = JDWP_ERROR(INVALID_THREAD_GROUP);
+ return NULL;
+ }
+ return object;
+}
+
+jstring
+inStream_readStringRef(JNIEnv *env, PacketInputStream *stream)
+{
+ jobject object = inStream_readObjectRef(env, stream);
+ if (object == NULL) {
+ /*
+ * Could be error or just the null reference. In either case,
+ * stop now.
+ */
+ return NULL;
+ }
+ if (!isString(object)) {
+ stream->error = JDWP_ERROR(INVALID_STRING);
+ return NULL;
+ }
+ return object;
+}
+
+jclass
+inStream_readClassLoaderRef(JNIEnv *env, PacketInputStream *stream)
+{
+ jobject object = inStream_readObjectRef(env, stream);
+ if (object == NULL) {
+ /*
+ * Could be error or just the null reference. In either case,
+ * stop now.
+ */
+ return NULL;
+ }
+ if (!isClassLoader(object)) {
+ stream->error = JDWP_ERROR(INVALID_CLASS_LOADER);
+ return NULL;
+ }
+ return object;
+}
+
+jarray
+inStream_readArrayRef(JNIEnv *env, PacketInputStream *stream)
+{
+ jobject object = inStream_readObjectRef(env, stream);
+ if (object == NULL) {
+ /*
+ * Could be error or just the null reference. In either case,
+ * stop now.
+ */
+ return NULL;
+ }
+ if (!isArray(object)) {
+ stream->error = JDWP_ERROR(INVALID_ARRAY);
+ return NULL;
+ }
+ return object;
+}
+
+/*
+ * Next 3 functions read an Int and convert to a Pointer!?
+ * If sizeof(jxxxID) == 8 we must read these values as Longs.
+ */
+FrameID
+inStream_readFrameID(PacketInputStream *stream)
+{
+ if (sizeof(FrameID) == 8) {
+ /*LINTED*/
+ return (FrameID)inStream_readLong(stream);
+ } else {
+ /*LINTED*/
+ return (FrameID)inStream_readInt(stream);
+ }
+}
+
+jmethodID
+inStream_readMethodID(PacketInputStream *stream)
+{
+ if (sizeof(jmethodID) == 8) {
+ /*LINTED*/
+ return (jmethodID)(intptr_t)inStream_readLong(stream);
+ } else {
+ /*LINTED*/
+ return (jmethodID)(intptr_t)inStream_readInt(stream);
+ }
+}
+
+jfieldID
+inStream_readFieldID(PacketInputStream *stream)
+{
+ if (sizeof(jfieldID) == 8) {
+ /*LINTED*/
+ return (jfieldID)(intptr_t)inStream_readLong(stream);
+ } else {
+ /*LINTED*/
+ return (jfieldID)(intptr_t)inStream_readInt(stream);
+ }
+}
+
+jlocation
+inStream_readLocation(PacketInputStream *stream)
+{
+ return (jlocation)inStream_readLong(stream);
+}
+
+char *
+inStream_readString(PacketInputStream *stream)
+{
+ int length;
+ char *string;
+
+ length = inStream_readInt(stream);
+ string = jvmtiAllocate(length + 1);
+ if (string != NULL) {
+ int new_length;
+
+ (void)readBytes(stream, string, length);
+ string[length] = '\0';
+
+ /* This is Standard UTF-8, convert to Modified UTF-8 if necessary */
+ new_length = (gdata->npt->utf8sToUtf8mLength)
+ (gdata->npt->utf, (jbyte*)string, length);
+ if ( new_length != length ) {
+ char *new_string;
+
+ new_string = jvmtiAllocate(new_length+1);
+ (gdata->npt->utf8sToUtf8m)
+ (gdata->npt->utf, (jbyte*)string, length,
+ (jbyte*)new_string, new_length);
+ jvmtiDeallocate(string);
+ return new_string;
+ }
+ }
+ return string;
+}
+
+jboolean
+inStream_endOfInput(PacketInputStream *stream)
+{
+ return (stream->left > 0);
+}
+
+jdwpError
+inStream_error(PacketInputStream *stream)
+{
+ return stream->error;
+}
+
+void
+inStream_clearError(PacketInputStream *stream) {
+ stream->error = JDWP_ERROR(NONE);
+}
+
+jvalue
+inStream_readValue(PacketInputStream *stream, jbyte *typeKeyPtr)
+{
+ jvalue value;
+ jbyte typeKey = inStream_readByte(stream);
+ if (stream->error) {
+ value.j = 0L;
+ return value;
+ }
+
+ if (isObjectTag(typeKey)) {
+ value.l = inStream_readObjectRef(getEnv(), stream);
+ } else {
+ switch (typeKey) {
+ case JDWP_TAG(BYTE):
+ value.b = inStream_readByte(stream);
+ break;
+
+ case JDWP_TAG(CHAR):
+ value.c = inStream_readChar(stream);
+ break;
+
+ case JDWP_TAG(FLOAT):
+ value.f = inStream_readFloat(stream);
+ break;
+
+ case JDWP_TAG(DOUBLE):
+ value.d = inStream_readDouble(stream);
+ break;
+
+ case JDWP_TAG(INT):
+ value.i = inStream_readInt(stream);
+ break;
+
+ case JDWP_TAG(LONG):
+ value.j = inStream_readLong(stream);
+ break;
+
+ case JDWP_TAG(SHORT):
+ value.s = inStream_readShort(stream);
+ break;
+
+ case JDWP_TAG(BOOLEAN):
+ value.z = inStream_readBoolean(stream);
+ break;
+ default:
+ stream->error = JDWP_ERROR(INVALID_TAG);
+ break;
+ }
+ }
+ if (typeKeyPtr) {
+ *typeKeyPtr = typeKey;
+ }
+ return value;
+}
+
+static jboolean
+deleteRef(void *elementPtr, void *arg)
+{
+ JNIEnv *env = arg;
+ jobject *refPtr = elementPtr;
+ commonRef_idToRef_delete(env, *refPtr);
+ return JNI_TRUE;
+}
+
+void
+inStream_destroy(PacketInputStream *stream)
+{
+ if (stream->packet.type.cmd.data != NULL) {
+ jvmtiDeallocate(stream->packet.type.cmd.data);
+ }
+
+ (void)bagEnumerateOver(stream->refs, deleteRef, (void *)getEnv());
+ bagDestroyBag(stream->refs);
+}