alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (outStream.c)

This example Java source code file (outStream.c) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

exit_error, host_to_java_long, host_to_java_short, initial_id_alloc, invalid, jdwp_error, jdwp_tag, jni_false, jni_true, null, null_object_id, packetdata, packetoutputstream, smallest

The outStream.c Java example source code

/*
 * Copyright (c) 1998, 2013, Oracle and/or its affiliates. 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.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

#include "util.h"
#include "stream.h"
#include "outStream.h"
#include "inStream.h"
#include "transport.h"
#include "commonRef.h"
#include "bag.h"
#include "FrameID.h"

#define INITIAL_ID_ALLOC  50
#define SMALLEST(a, b) ((a) < (b)) ? (a) : (b)

static void
commonInit(PacketOutputStream *stream)
{
    stream->current = &stream->initialSegment[0];
    stream->left = sizeof(stream->initialSegment);
    stream->segment = &stream->firstSegment;
    stream->segment->length = 0;
    stream->segment->data = &stream->initialSegment[0];
    stream->segment->next = NULL;
    stream->error = JDWP_ERROR(NONE);
    stream->sent = JNI_FALSE;
    stream->ids = bagCreateBag(sizeof(jlong), INITIAL_ID_ALLOC);
    if (stream->ids == NULL) {
        stream->error = JDWP_ERROR(OUT_OF_MEMORY);
    }
}

void
outStream_initCommand(PacketOutputStream *stream, jint id,
                      jbyte flags, jbyte commandSet, jbyte command)
{
    commonInit(stream);

    /*
     * Command-specific initialization
     */
    stream->packet.type.cmd.id = id;
    stream->packet.type.cmd.cmdSet = commandSet;
    stream->packet.type.cmd.cmd = command;

    stream->packet.type.cmd.flags = flags;
}

void
outStream_initReply(PacketOutputStream *stream, jint id)
{
    commonInit(stream);

    /*
     * Reply-specific initialization
     */
    stream->packet.type.reply.id = id;
    stream->packet.type.reply.errorCode = 0x0;
    stream->packet.type.cmd.flags = (jbyte)JDWPTRANSPORT_FLAGS_REPLY;
}

jint
outStream_id(PacketOutputStream *stream)
{
    return stream->packet.type.cmd.id;
}

jbyte
outStream_command(PacketOutputStream *stream)
{
    /* Only makes sense for commands */
    JDI_ASSERT(!(stream->packet.type.cmd.flags & JDWPTRANSPORT_FLAGS_REPLY));
    return stream->packet.type.cmd.cmd;
}

static jdwpError
writeBytes(PacketOutputStream *stream, void *source, int size)
{
    jbyte *bytes = (jbyte *)source;

    if (stream->error) {
        return stream->error;
    }
    while (size > 0) {
        jint count;
        if (stream->left == 0) {
            jint segSize = SMALLEST(2 * stream->segment->length, MAX_SEGMENT_SIZE);
            jbyte *newSeg = jvmtiAllocate(segSize);
            struct PacketData *newHeader = jvmtiAllocate(sizeof(*newHeader));
            if ((newSeg == NULL) || (newHeader == NULL)) {
                jvmtiDeallocate(newSeg);
                jvmtiDeallocate(newHeader);
                stream->error = JDWP_ERROR(OUT_OF_MEMORY);
                return stream->error;
            }
            newHeader->length = 0;
            newHeader->data = newSeg;
            newHeader->next = NULL;
            stream->segment->next = newHeader;
            stream->segment = newHeader;
            stream->current = newHeader->data;
            stream->left = segSize;
        }
        count = SMALLEST(size, stream->left);
        (void)memcpy(stream->current, bytes, count);
        stream->current += count;
        stream->left -= count;
        stream->segment->length += count;
        size -= count;
        bytes += count;
    }
    return JDWP_ERROR(NONE);
}

jdwpError
outStream_writeBoolean(PacketOutputStream *stream, jboolean val)
{
    jbyte byte = (val != 0) ? 1 : 0;
    return writeBytes(stream, &byte, sizeof(byte));
}

jdwpError
outStream_writeByte(PacketOutputStream *stream, jbyte val)
{
    return writeBytes(stream, &val, sizeof(val));
}

jdwpError
outStream_writeChar(PacketOutputStream *stream, jchar val)
{
    val = HOST_TO_JAVA_CHAR(val);
    return writeBytes(stream, &val, sizeof(val));
}

jdwpError
outStream_writeShort(PacketOutputStream *stream, jshort val)
{
    val = HOST_TO_JAVA_SHORT(val);
    return writeBytes(stream, &val, sizeof(val));
}

jdwpError
outStream_writeInt(PacketOutputStream *stream, jint val)
{
    val = HOST_TO_JAVA_INT(val);
    return writeBytes(stream, &val, sizeof(val));
}

jdwpError
outStream_writeLong(PacketOutputStream *stream, jlong val)
{
    val = HOST_TO_JAVA_LONG(val);
    return writeBytes(stream, &val, sizeof(val));
}

jdwpError
outStream_writeFloat(PacketOutputStream *stream, jfloat val)
{
    val = HOST_TO_JAVA_FLOAT(val);
    return writeBytes(stream, &val, sizeof(val));
}

jdwpError
outStream_writeDouble(PacketOutputStream *stream, jdouble val)
{
    val = HOST_TO_JAVA_DOUBLE(val);
    return writeBytes(stream, &val, sizeof(val));
}

jdwpError
outStream_writeObjectTag(JNIEnv *env, PacketOutputStream *stream, jobject val)
{
    return outStream_writeByte(stream, specificTypeKey(env, val));
}

jdwpError
outStream_writeObjectRef(JNIEnv *env, PacketOutputStream *stream, jobject val)
{
    jlong id;
    jlong *idPtr;

    if (stream->error) {
        return stream->error;
    }

    if (val == NULL) {
        id = NULL_OBJECT_ID;
    } else {
        /* Convert the object to an object id */
        id = commonRef_refToID(env, val);
        if (id == NULL_OBJECT_ID) {
            stream->error = JDWP_ERROR(OUT_OF_MEMORY);
            return stream->error;
        }

        /* Track the common ref in case we need to release it on a future error */
        idPtr = bagAdd(stream->ids);
        if (idPtr == NULL) {
            commonRef_release(env, id);
            stream->error = JDWP_ERROR(OUT_OF_MEMORY);
            return stream->error;
        } else {
            *idPtr = id;
        }

        /* Add the encoded object id to the stream */
        id = HOST_TO_JAVA_LONG(id);
    }

    return writeBytes(stream, &id, sizeof(id));
}

jdwpError
outStream_writeFrameID(PacketOutputStream *stream, FrameID val)
{
    /*
     * Not good - we're writing a pointer as a jint.  Need
     * to write as a jlong if sizeof(FrameID) == 8.
     */
    if (sizeof(FrameID) == 8) {
        /*LINTED*/
        return outStream_writeLong(stream, (jlong)val);
    } else {
        /*LINTED*/
        return outStream_writeInt(stream, (jint)val);
    }
}

jdwpError
outStream_writeMethodID(PacketOutputStream *stream, jmethodID val)
{
    /*
     * Not good - we're writing a pointer as a jint.  Need
     * to write as a jlong if sizeof(jmethodID) == 8.
     */
    if (sizeof(jmethodID) == 8) {
        /*LINTED*/
        return outStream_writeLong(stream, (jlong)(intptr_t)val);
    } else {
        /*LINTED*/
        return outStream_writeInt(stream, (jint)(intptr_t)val);
    }
}

jdwpError
outStream_writeFieldID(PacketOutputStream *stream, jfieldID val)
{
    /*
     * Not good - we're writing a pointer as a jint.  Need
     * to write as a jlong if sizeof(jfieldID) == 8.
     */
    if (sizeof(jfieldID) == 8) {
        /*LINTED*/
        return outStream_writeLong(stream, (jlong)(intptr_t)val);
    } else {
        /*LINTED*/
        return outStream_writeInt(stream, (jint)(intptr_t)val);
    }
}

jdwpError
outStream_writeLocation(PacketOutputStream *stream, jlocation val)
{
    return outStream_writeLong(stream, (jlong)val);
}

jdwpError
outStream_writeByteArray(PacketOutputStream*stream, jint length,
                         jbyte *bytes)
{
    (void)outStream_writeInt(stream, length);
    return writeBytes(stream, bytes, length);
}

jdwpError
outStream_writeString(PacketOutputStream *stream, char *string)
{
    jdwpError error;
    jint      length = string != NULL ? (int)strlen(string) : 0;

    /* Options utf8=y/n controls if we want Standard UTF-8 or Modified */
    if ( gdata->modifiedUtf8 ) {
        (void)outStream_writeInt(stream, length);
        error = writeBytes(stream, (jbyte *)string, length);
    } else {
        jint      new_length;

        new_length = (gdata->npt->utf8mToUtf8sLength)
                            (gdata->npt->utf, (jbyte*)string, length);
        if ( new_length == length ) {
            (void)outStream_writeInt(stream, length);
            error = writeBytes(stream, (jbyte *)string, length);
        } else {
            char *new_string;

            new_string = jvmtiAllocate(new_length+1);
            (gdata->npt->utf8mToUtf8s)
                            (gdata->npt->utf, (jbyte*)string, length,
                             (jbyte*)new_string, new_length);
            (void)outStream_writeInt(stream, new_length);
            error = writeBytes(stream, (jbyte *)new_string, new_length);
            jvmtiDeallocate(new_string);
        }
    }
    return error;
}

jdwpError
outStream_writeValue(JNIEnv *env, PacketOutputStream *out,
                     jbyte typeKey, jvalue value)
{
    if (typeKey == JDWP_TAG(OBJECT)) {
        (void)outStream_writeByte(out, specificTypeKey(env, value.l));
    } else {
        (void)outStream_writeByte(out, typeKey);
    }
    if (isObjectTag(typeKey)) {
        (void)outStream_writeObjectRef(env, out, value.l);
    } else {
        switch (typeKey) {
            case JDWP_TAG(BYTE):
                return outStream_writeByte(out, value.b);

            case JDWP_TAG(CHAR):
                return outStream_writeChar(out, value.c);

            case JDWP_TAG(FLOAT):
                return outStream_writeFloat(out, value.f);

            case JDWP_TAG(DOUBLE):
                return outStream_writeDouble(out, value.d);

            case JDWP_TAG(INT):
                return outStream_writeInt(out, value.i);

            case JDWP_TAG(LONG):
                return outStream_writeLong(out, value.j);

            case JDWP_TAG(SHORT):
                return outStream_writeShort(out, value.s);

            case JDWP_TAG(BOOLEAN):
                return outStream_writeBoolean(out, value.z);

            case JDWP_TAG(VOID):  /* happens with function return values */
                /* write nothing */
                return JDWP_ERROR(NONE);

            default:
                EXIT_ERROR(AGENT_ERROR_INVALID_OBJECT,"Invalid type key");
                break;
        }
    }
    return JDWP_ERROR(NONE);
}

jdwpError
outStream_skipBytes(PacketOutputStream *stream, jint count)
{
    int i;
    for (i = 0; i < count; i++) {
        (void)outStream_writeByte(stream, 0);
    }
    return stream->error;
}

jdwpError
outStream_error(PacketOutputStream *stream)
{
    return stream->error;
}

void
outStream_setError(PacketOutputStream *stream, jdwpError error)
{
    if (stream->error == JDWP_ERROR(NONE)) {
        stream->error = error;
        LOG_MISC(("outStream_setError error=%s(%d)", jdwpErrorText(error), error));
    }
}

static jint
outStream_send(PacketOutputStream *stream) {

    jint rc;
    jint len = 0;
    PacketData *segment;
    jbyte *data, *posP;

    /*
     * If there's only 1 segment then we just send the
     * packet.
     */
    if (stream->firstSegment.next == NULL) {
        stream->packet.type.cmd.len = 11 + stream->firstSegment.length;
        stream->packet.type.cmd.data = stream->firstSegment.data;
        rc = transport_sendPacket(&stream->packet);
        return rc;
    }

    /*
     * Multiple segments
     */
    len = 0;
    segment = (PacketData *)&(stream->firstSegment);
    do {
        len += segment->length;
        segment = segment->next;
    } while (segment != NULL);

    data = jvmtiAllocate(len);
    if (data == NULL) {
        return JDWP_ERROR(OUT_OF_MEMORY);
    }

    posP = data;
    segment = (PacketData *)&(stream->firstSegment);
    while (segment != NULL) {
        (void)memcpy(posP, segment->data, segment->length);
        posP += segment->length;
        segment = segment->next;
    }

    stream->packet.type.cmd.len = 11 + len;
    stream->packet.type.cmd.data = data;
    rc = transport_sendPacket(&stream->packet);
    stream->packet.type.cmd.data = NULL;
    jvmtiDeallocate(data);

    return rc;
}

void
outStream_sendReply(PacketOutputStream *stream)
{
    jint rc;
    if (stream->error) {
        /*
         * Don't send any collected stream data on an error reply
         */
        stream->packet.type.reply.len = 0;
        stream->packet.type.reply.errorCode = (jshort)stream->error;
    }
    rc = outStream_send(stream);
    if (rc == 0) {
        stream->sent = JNI_TRUE;
    }
}

void
outStream_sendCommand(PacketOutputStream *stream)
{
    jint rc;
    if (!stream->error) {
        rc = outStream_send(stream);
        if (rc == 0) {
            stream->sent = JNI_TRUE;
        }
    }
}


static jboolean
releaseID(void *elementPtr, void *arg)
{
    jlong *idPtr = elementPtr;
    commonRef_release(getEnv(), *idPtr);
    return JNI_TRUE;
}

void
outStream_destroy(PacketOutputStream *stream)
{
    struct PacketData *next;

    if (stream->error || !stream->sent) {
        (void)bagEnumerateOver(stream->ids, releaseID, NULL);
    }

    next = stream->firstSegment.next;
    while (next != NULL) {
        struct PacketData *p = next;
        next = p->next;
        jvmtiDeallocate(p->data);
        jvmtiDeallocate(p);
    }
    bagDestroyBag(stream->ids);
}

Other Java examples (source code examples)

Here is a short list of links related to this Java outStream.c source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.