source: trunk/openjdk/jdk/src/share/back/inStream.c

Last change on this file was 278, checked in by dmik, 14 years ago

trunk: Merged in openjdk6 b22 from branches/vendor/oracle.

File size: 11.7 KB
Line 
1/*
2 * Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26#include "util.h"
27#include "stream.h"
28#include "inStream.h"
29#include "transport.h"
30#include "bag.h"
31#include "commonRef.h"
32#include "FrameID.h"
33
34#define INITIAL_REF_ALLOC 50
35#define SMALLEST(a, b) ((a) < (b)) ? (a) : (b)
36
37/*
38 * TO DO: Support processing of replies through command input streams.
39 */
40void
41inStream_init(PacketInputStream *stream, jdwpPacket packet)
42{
43 stream->packet = packet;
44 stream->error = JDWP_ERROR(NONE);
45 stream->left = packet.type.cmd.len;
46 stream->current = packet.type.cmd.data;
47 stream->refs = bagCreateBag(sizeof(jobject), INITIAL_REF_ALLOC);
48 if (stream->refs == NULL) {
49 stream->error = JDWP_ERROR(OUT_OF_MEMORY);
50 }
51}
52
53jint
54inStream_id(PacketInputStream *stream)
55{
56 return stream->packet.type.cmd.id;
57}
58
59jbyte
60inStream_command(PacketInputStream *stream)
61{
62 return stream->packet.type.cmd.cmd;
63}
64
65static jdwpError
66readBytes(PacketInputStream *stream, void *dest, int size)
67{
68 if (stream->error) {
69 return stream->error;
70 }
71
72 if (size > stream->left) {
73 stream->error = JDWP_ERROR(INTERNAL);
74 return stream->error;
75 }
76
77 if (dest) {
78 (void)memcpy(dest, stream->current, size);
79 }
80 stream->current += size;
81 stream->left -= size;
82
83 return stream->error;
84}
85
86jdwpError
87inStream_skipBytes(PacketInputStream *stream, jint size) {
88 return readBytes(stream, NULL, size);
89}
90
91jboolean
92inStream_readBoolean(PacketInputStream *stream)
93{
94 jbyte flag = 0;
95 (void)readBytes(stream, &flag, sizeof(flag));
96 if (stream->error) {
97 return 0;
98 } else {
99 return flag ? JNI_TRUE : JNI_FALSE;
100 }
101}
102
103jbyte
104inStream_readByte(PacketInputStream *stream)
105{
106 jbyte val = 0;
107 (void)readBytes(stream, &val, sizeof(val));
108 return val;
109}
110
111jbyte *
112inStream_readBytes(PacketInputStream *stream, int length, jbyte *buf)
113{
114 (void)readBytes(stream, buf, length);
115 return buf;
116}
117
118jchar
119inStream_readChar(PacketInputStream *stream)
120{
121 jchar val = 0;
122 (void)readBytes(stream, &val, sizeof(val));
123 return JAVA_TO_HOST_CHAR(val);
124}
125
126jshort
127inStream_readShort(PacketInputStream *stream)
128{
129 jshort val = 0;
130 (void)readBytes(stream, &val, sizeof(val));
131 return JAVA_TO_HOST_SHORT(val);
132}
133
134jint
135inStream_readInt(PacketInputStream *stream)
136{
137 jint val = 0;
138 (void)readBytes(stream, &val, sizeof(val));
139 return JAVA_TO_HOST_INT(val);
140}
141
142jlong
143inStream_readLong(PacketInputStream *stream)
144{
145 jlong val = 0;
146 (void)readBytes(stream, &val, sizeof(val));
147 return JAVA_TO_HOST_LONG(val);
148}
149
150jfloat
151inStream_readFloat(PacketInputStream *stream)
152{
153 jfloat val = 0;
154 (void)readBytes(stream, &val, sizeof(val));
155 return JAVA_TO_HOST_FLOAT(val);
156}
157
158jdouble
159inStream_readDouble(PacketInputStream *stream)
160{
161 jdouble val = 0;
162 (void)readBytes(stream, &val, sizeof(val));
163 return JAVA_TO_HOST_DOUBLE(val);
164}
165
166/*
167 * Read an object from the stream. The ID used in the wire protocol
168 * is converted to a reference which is returned. The reference is
169 * global and strong, but it should *not* be deleted by the caller
170 * since it is freed when this stream is destroyed.
171 */
172jobject
173inStream_readObjectRef(JNIEnv *env, PacketInputStream *stream)
174{
175 jobject ref;
176 jobject *refPtr;
177 jlong id = inStream_readLong(stream);
178 if (stream->error) {
179 return NULL;
180 }
181 if (id == NULL_OBJECT_ID) {
182 return NULL;
183 }
184
185 ref = commonRef_idToRef(env, id);
186 if (ref == NULL) {
187 stream->error = JDWP_ERROR(INVALID_OBJECT);
188 return NULL;
189 }
190
191 refPtr = bagAdd(stream->refs);
192 if (refPtr == NULL) {
193 commonRef_idToRef_delete(env, ref);
194 return NULL;
195 }
196
197 *refPtr = ref;
198 return ref;
199}
200
201/*
202 * Read a raw object id from the stream. This should be used rarely.
203 * Normally, inStream_readObjectRef is preferred since it takes care
204 * of reference conversion and tracking. Only code that needs to
205 * perform maintence of the commonRef hash table uses this function.
206 */
207jlong
208inStream_readObjectID(PacketInputStream *stream)
209{
210 return inStream_readLong(stream);
211}
212
213jclass
214inStream_readClassRef(JNIEnv *env, PacketInputStream *stream)
215{
216 jobject object = inStream_readObjectRef(env, stream);
217 if (object == NULL) {
218 /*
219 * Could be error or just the null reference. In either case,
220 * stop now.
221 */
222 return NULL;
223 }
224 if (!isClass(object)) {
225 stream->error = JDWP_ERROR(INVALID_CLASS);
226 return NULL;
227 }
228 return object;
229}
230
231jthread
232inStream_readThreadRef(JNIEnv *env, PacketInputStream *stream)
233{
234 jobject object = inStream_readObjectRef(env, stream);
235 if (object == NULL) {
236 /*
237 * Could be error or just the null reference. In either case,
238 * stop now.
239 */
240 return NULL;
241 }
242 if (!isThread(object)) {
243 stream->error = JDWP_ERROR(INVALID_THREAD);
244 return NULL;
245 }
246 return object;
247}
248
249jthreadGroup
250inStream_readThreadGroupRef(JNIEnv *env, PacketInputStream *stream)
251{
252 jobject object = inStream_readObjectRef(env, stream);
253 if (object == NULL) {
254 /*
255 * Could be error or just the null reference. In either case,
256 * stop now.
257 */
258 return NULL;
259 }
260 if (!isThreadGroup(object)) {
261 stream->error = JDWP_ERROR(INVALID_THREAD_GROUP);
262 return NULL;
263 }
264 return object;
265}
266
267jstring
268inStream_readStringRef(JNIEnv *env, PacketInputStream *stream)
269{
270 jobject object = inStream_readObjectRef(env, stream);
271 if (object == NULL) {
272 /*
273 * Could be error or just the null reference. In either case,
274 * stop now.
275 */
276 return NULL;
277 }
278 if (!isString(object)) {
279 stream->error = JDWP_ERROR(INVALID_STRING);
280 return NULL;
281 }
282 return object;
283}
284
285jclass
286inStream_readClassLoaderRef(JNIEnv *env, PacketInputStream *stream)
287{
288 jobject object = inStream_readObjectRef(env, stream);
289 if (object == NULL) {
290 /*
291 * Could be error or just the null reference. In either case,
292 * stop now.
293 */
294 return NULL;
295 }
296 if (!isClassLoader(object)) {
297 stream->error = JDWP_ERROR(INVALID_CLASS_LOADER);
298 return NULL;
299 }
300 return object;
301}
302
303jarray
304inStream_readArrayRef(JNIEnv *env, PacketInputStream *stream)
305{
306 jobject object = inStream_readObjectRef(env, stream);
307 if (object == NULL) {
308 /*
309 * Could be error or just the null reference. In either case,
310 * stop now.
311 */
312 return NULL;
313 }
314 if (!isArray(object)) {
315 stream->error = JDWP_ERROR(INVALID_ARRAY);
316 return NULL;
317 }
318 return object;
319}
320
321/*
322 * Next 3 functions read an Int and convert to a Pointer!?
323 * If sizeof(jxxxID) == 8 we must read these values as Longs.
324 */
325FrameID
326inStream_readFrameID(PacketInputStream *stream)
327{
328 if (sizeof(FrameID) == 8) {
329 /*LINTED*/
330 return (FrameID)inStream_readLong(stream);
331 } else {
332 /*LINTED*/
333 return (FrameID)inStream_readInt(stream);
334 }
335}
336
337jmethodID
338inStream_readMethodID(PacketInputStream *stream)
339{
340 if (sizeof(jmethodID) == 8) {
341 /*LINTED*/
342 return (jmethodID)(intptr_t)inStream_readLong(stream);
343 } else {
344 /*LINTED*/
345 return (jmethodID)(intptr_t)inStream_readInt(stream);
346 }
347}
348
349jfieldID
350inStream_readFieldID(PacketInputStream *stream)
351{
352 if (sizeof(jfieldID) == 8) {
353 /*LINTED*/
354 return (jfieldID)(intptr_t)inStream_readLong(stream);
355 } else {
356 /*LINTED*/
357 return (jfieldID)(intptr_t)inStream_readInt(stream);
358 }
359}
360
361jlocation
362inStream_readLocation(PacketInputStream *stream)
363{
364 return (jlocation)inStream_readLong(stream);
365}
366
367char *
368inStream_readString(PacketInputStream *stream)
369{
370 int length;
371 char *string;
372
373 length = inStream_readInt(stream);
374 string = jvmtiAllocate(length + 1);
375 if (string != NULL) {
376 int new_length;
377
378 (void)readBytes(stream, string, length);
379 string[length] = '\0';
380
381 /* This is Standard UTF-8, convert to Modified UTF-8 if necessary */
382 new_length = (gdata->npt->utf8sToUtf8mLength)
383 (gdata->npt->utf, (jbyte*)string, length);
384 if ( new_length != length ) {
385 char *new_string;
386
387 new_string = jvmtiAllocate(new_length+1);
388 (gdata->npt->utf8sToUtf8m)
389 (gdata->npt->utf, (jbyte*)string, length,
390 (jbyte*)new_string, new_length);
391 jvmtiDeallocate(string);
392 return new_string;
393 }
394 }
395 return string;
396}
397
398jboolean
399inStream_endOfInput(PacketInputStream *stream)
400{
401 return (stream->left > 0);
402}
403
404jdwpError
405inStream_error(PacketInputStream *stream)
406{
407 return stream->error;
408}
409
410void
411inStream_clearError(PacketInputStream *stream) {
412 stream->error = JDWP_ERROR(NONE);
413}
414
415jvalue
416inStream_readValue(PacketInputStream *stream, jbyte *typeKeyPtr)
417{
418 jvalue value;
419 jbyte typeKey = inStream_readByte(stream);
420 if (stream->error) {
421 value.j = 0L;
422 return value;
423 }
424
425 if (isObjectTag(typeKey)) {
426 value.l = inStream_readObjectRef(getEnv(), stream);
427 } else {
428 switch (typeKey) {
429 case JDWP_TAG(BYTE):
430 value.b = inStream_readByte(stream);
431 break;
432
433 case JDWP_TAG(CHAR):
434 value.c = inStream_readChar(stream);
435 break;
436
437 case JDWP_TAG(FLOAT):
438 value.f = inStream_readFloat(stream);
439 break;
440
441 case JDWP_TAG(DOUBLE):
442 value.d = inStream_readDouble(stream);
443 break;
444
445 case JDWP_TAG(INT):
446 value.i = inStream_readInt(stream);
447 break;
448
449 case JDWP_TAG(LONG):
450 value.j = inStream_readLong(stream);
451 break;
452
453 case JDWP_TAG(SHORT):
454 value.s = inStream_readShort(stream);
455 break;
456
457 case JDWP_TAG(BOOLEAN):
458 value.z = inStream_readBoolean(stream);
459 break;
460 default:
461 stream->error = JDWP_ERROR(INVALID_TAG);
462 break;
463 }
464 }
465 if (typeKeyPtr) {
466 *typeKeyPtr = typeKey;
467 }
468 return value;
469}
470
471static jboolean
472deleteRef(void *elementPtr, void *arg)
473{
474 JNIEnv *env = arg;
475 jobject *refPtr = elementPtr;
476 commonRef_idToRef_delete(env, *refPtr);
477 return JNI_TRUE;
478}
479
480void
481inStream_destroy(PacketInputStream *stream)
482{
483 if (stream->packet.type.cmd.data != NULL) {
484 jvmtiDeallocate(stream->packet.type.cmd.data);
485 }
486
487 (void)bagEnumerateOver(stream->refs, deleteRef, (void *)getEnv());
488 bagDestroyBag(stream->refs);
489}
Note: See TracBrowser for help on using the repository browser.