/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * * See the License for the specific language governing permissions and * limitations under the License. */ /** * @author Khen G. Kim, Aleksey V. Yantsen */ /** * Created on 10.01.2004 */ package org.apache.harmony.jpda.tests.framework.jdwp; import java.io.UnsupportedEncodingException; import org.apache.harmony.jpda.tests.framework.TestErrorException; import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants; import org.apache.harmony.jpda.tests.framework.jdwp.TypesLengths; /** * This base class represents JDWP packet. */ public class Packet { public static final int REPLY_PACKET_FLAG = 0x80; public static final int FLAGS_INDEX = 8; public static final int HEADER_SIZE = 11; /** * The size in bytes of the BYTE type value. */ protected static final int BYTE_SIZE = 1; /** * The size in bytes of the SHORT type value. */ protected static final int SHORT_SIZE = 2; /** * The size in bytes of the INT type value. */ protected static final int INT_SIZE = 4; /** * The size in bytes of the LONG type value. */ protected static final int LONG_SIZE = 8; private static final int LENGTH_INDEX = 0; private static final int ID_INDEX = 4; private int id; private byte flags; private int length; private byte data[]; private int reading_data_index; /** * A constructor that creates an empty CommandPacket with empty header * fields and no data. */ public Packet() { reading_data_index = 0; data = new byte[0]; } /** * A constructor that creates Packet from array of bytes including header * and data sections. * * @param p array of bytes for new packet. */ public Packet(byte p[]) { length = (int) readFromByteArray(p, LENGTH_INDEX, INT_SIZE); if (length < HEADER_SIZE) { throw new TestErrorException( "Packet creation error: size of packet = " + length + "is less than header size = " + HEADER_SIZE); } id = (int) readFromByteArray(p, ID_INDEX, INT_SIZE); flags = p[FLAGS_INDEX]; data = new byte[p.length - HEADER_SIZE]; System.arraycopy(p, HEADER_SIZE, data, 0, p.length - HEADER_SIZE); reading_data_index = 0; } /** * Gets the length value of the header of the Packet. * * @return the length value of the header of the Packet. */ public int getLength() { return length; } /** * Sets the id value of the header of the Packet. * * @param i * the id value of the header of the Packet. */ public void setId(int i) { id = i; } /** * Gets the id value of the header of the Packet. * * @return the id value of the header of the Packet. */ public int getId() { return id; } /** * Sets the flags value of the header of the Packet. * * @param f * the flags value of the header of the Packet. */ public void setFlags(byte f) { flags = f; } /** * Gets the flags value of the header of the Packet. * * @return the flags value of the header of the Packet. */ public byte getFlags() { return flags; } /** * Gets the flags value from the header of the Packet. * * @param tag * Type tag (see JDWP.tag) * @return the flags value of the header of the Packet. */ public boolean isValuePrimitiveType(byte tag) { switch (tag) { case JDWPConstants.Tag.ARRAY_TAG: { return false; } case JDWPConstants.Tag.BYTE_TAG: { return true; } case JDWPConstants.Tag.CHAR_TAG: { return true; } case JDWPConstants.Tag.OBJECT_TAG: { return false; } case JDWPConstants.Tag.FLOAT_TAG: { return true; } case JDWPConstants.Tag.DOUBLE_TAG: { return true; } case JDWPConstants.Tag.INT_TAG: { return true; } case JDWPConstants.Tag.LONG_TAG: { return true; } case JDWPConstants.Tag.SHORT_TAG: { return true; } case JDWPConstants.Tag.VOID_TAG: { return true; } case JDWPConstants.Tag.BOOLEAN_TAG: { return true; } case JDWPConstants.Tag.STRING_TAG: { return false; } case JDWPConstants.Tag.THREAD_TAG: { return false; } case JDWPConstants.Tag.THREAD_GROUP_TAG: { return false; } case JDWPConstants.Tag.CLASS_LOADER_TAG: { return false; } case JDWPConstants.Tag.CLASS_OBJECT_TAG: { return false; } case JDWPConstants.Tag.NO_TAG: { return true; } default: { throw new TestErrorException("Improper JDWP.tag value = " + tag); } } } /** * Sets the next value of the data of the Packet as byte. * * @param val * the byte value. */ public void setNextValueAsByte(byte val) { int new_data_size = data.length + BYTE_SIZE; byte data_temp[] = data; data = new byte[new_data_size]; System.arraycopy(data_temp, 0, data, 0, new_data_size - BYTE_SIZE); data[new_data_size - BYTE_SIZE] = val; } /** * Gets the next value of the data of the Packet as byte. * * @return the next value of the data of the Packet as byte. */ public byte getNextValueAsByte() { reading_data_index = reading_data_index + BYTE_SIZE; return data[reading_data_index - BYTE_SIZE]; } /** * Sets the next value of the data of the Packet as boolean. * * @param val * the boolean value. */ public void setNextValueAsBoolean(boolean val) { int old_data_size = data.length; int new_data_size = old_data_size + TypesLengths.getTypeLength(TypesLengths.BOOLEAN_ID); byte data_temp[] = data; data = new byte[new_data_size]; System.arraycopy(data_temp, 0, data, 0, old_data_size); if (val) { data[old_data_size] = 1; } else { data[old_data_size] = 0; } } /** * Gets the next value of the data of the Packet as boolean. * * @return the next value of the data of the Packet as boolean. */ public boolean getNextValueAsBoolean() { int res = (int) data[reading_data_index] & 0xFF; reading_data_index = reading_data_index + TypesLengths.getTypeLength(TypesLengths.BOOLEAN_ID); return (res != 0); } /** * Sets the next value of the data of the Packet as short. * * @param val * the short value. */ public void setNextValueAsShort(short val) { int new_data_size = data.length + TypesLengths.getTypeLength(TypesLengths.SHORT_ID); byte data_temp[] = data; data = new byte[new_data_size]; System.arraycopy(data_temp, 0, data, 0, new_data_size - TypesLengths.getTypeLength(TypesLengths.SHORT_ID)); this.writeAtByteArray((long) val, data, new_data_size - TypesLengths.getTypeLength(TypesLengths.SHORT_ID), TypesLengths.getTypeLength(TypesLengths.SHORT_ID)); } /** * Gets the next value of the data of the Packet as short. * * @return the next value of the data of the Packet as short. */ public short getNextValueAsShort() { reading_data_index = reading_data_index + TypesLengths.getTypeLength(TypesLengths.SHORT_ID); return (short) readFromByteArray(data, reading_data_index - TypesLengths.getTypeLength(TypesLengths.SHORT_ID), TypesLengths.getTypeLength(TypesLengths.SHORT_ID)); } /** * Sets the next value of the data of the Packet as int. * * @param val * the int value. */ public void setNextValueAsInt(int val) { int new_data_size = data.length + TypesLengths.getTypeLength(TypesLengths.INT_ID); byte data_temp[] = data; data = new byte[new_data_size]; System.arraycopy(data_temp, 0, data, 0, new_data_size - TypesLengths.getTypeLength(TypesLengths.INT_ID)); this.writeAtByteArray((long) val, data, new_data_size - TypesLengths.getTypeLength(TypesLengths.INT_ID), TypesLengths .getTypeLength(TypesLengths.INT_ID)); } /** * Gets the next value of the data of the Packet as int. * * @return the next value of the data of the Packet as int. */ public int getNextValueAsInt() { reading_data_index = reading_data_index + TypesLengths.getTypeLength(TypesLengths.INT_ID); return (int) readFromByteArray(data, reading_data_index - TypesLengths.getTypeLength(TypesLengths.INT_ID), TypesLengths .getTypeLength(TypesLengths.INT_ID)); } /** * Sets the next value of the data of the Packet as double. * * @param dval * the double value. */ public void setNextValueAsDouble(double dval) { int new_data_size = data.length + TypesLengths.getTypeLength(TypesLengths.DOUBLE_ID); byte data_temp[] = data; long val = Double.doubleToLongBits(dval); data = new byte[new_data_size]; System.arraycopy(data_temp, 0, data, 0, new_data_size - TypesLengths.getTypeLength(TypesLengths.DOUBLE_ID)); this.writeAtByteArray((long) val, data, new_data_size - TypesLengths.getTypeLength(TypesLengths.DOUBLE_ID), TypesLengths.getTypeLength(TypesLengths.DOUBLE_ID)); } /** * Gets the next value of the data of the Packet as double. * * @return the next value of the data of the Packet as double. */ public double getNextValueAsDouble() { reading_data_index = reading_data_index + TypesLengths.getTypeLength(TypesLengths.DOUBLE_ID); long res = readFromByteArray(data, reading_data_index - TypesLengths.getTypeLength(TypesLengths.DOUBLE_ID), TypesLengths.getTypeLength(TypesLengths.DOUBLE_ID)); return Double.longBitsToDouble(res); } /** * Sets the next value of the data of the Packet as float. * * @param fval * the float value. */ public void setNextValueAsFloat(float fval) { int new_data_size = data.length + TypesLengths.getTypeLength(TypesLengths.FLOAT_ID); byte data_temp[] = data; long val = Float.floatToIntBits(fval); data = new byte[new_data_size]; System.arraycopy(data_temp, 0, data, 0, new_data_size - TypesLengths.getTypeLength(TypesLengths.FLOAT_ID)); this.writeAtByteArray((long) val, data, new_data_size - TypesLengths.getTypeLength(TypesLengths.FLOAT_ID), TypesLengths.getTypeLength(TypesLengths.FLOAT_ID)); } /** * Gets the next value of the data of the Packet as float. * * @return the next value of the data of the Packet as float. */ public float getNextValueAsFloat() { reading_data_index = reading_data_index + TypesLengths.getTypeLength(TypesLengths.FLOAT_ID); long res = readFromByteArray(data, reading_data_index - TypesLengths.getTypeLength(TypesLengths.FLOAT_ID), TypesLengths.getTypeLength(TypesLengths.FLOAT_ID)); return Float.intBitsToFloat((int) res); } /** * Sets the next value of the data of the Packet as char. * * @param val * the char value. */ public void setNextValueAsChar(char val) { int new_data_size = data.length + TypesLengths.getTypeLength(TypesLengths.CHAR_ID); byte data_temp[] = data; data = new byte[new_data_size]; System.arraycopy(data_temp, 0, data, 0, new_data_size - TypesLengths.getTypeLength(TypesLengths.CHAR_ID)); this.writeAtByteArray((long) val, data, new_data_size - TypesLengths.getTypeLength(TypesLengths.CHAR_ID), TypesLengths.getTypeLength(TypesLengths.CHAR_ID)); } /** * Gets the next value of the data of the Packet as char. * * @return the next value of the data of the Packet as char. */ public char getNextValueAsChar() { reading_data_index = reading_data_index + TypesLengths.getTypeLength(TypesLengths.CHAR_ID); return (char) readFromByteArray(data, reading_data_index - TypesLengths.getTypeLength(TypesLengths.CHAR_ID), TypesLengths.getTypeLength(TypesLengths.CHAR_ID)); } /** * Sets the next value of the data of the Packet as long. * * @param val * the long value. */ public void setNextValueAsLong(long val) { int new_data_size = data.length + TypesLengths.getTypeLength(TypesLengths.LONG_ID); byte data_temp[] = data; data = new byte[new_data_size]; System.arraycopy(data_temp, 0, data, 0, new_data_size - TypesLengths.getTypeLength(TypesLengths.LONG_ID)); this.writeAtByteArray(val, data, new_data_size - TypesLengths.getTypeLength(TypesLengths.LONG_ID), TypesLengths.getTypeLength(TypesLengths.LONG_ID)); } /** * Gets the next value of the data of the Packet as long. * * @return the next value of the data of the Packet as long. */ public long getNextValueAsLong() { reading_data_index = reading_data_index + TypesLengths.getTypeLength(TypesLengths.LONG_ID); return readFromByteArray(data, reading_data_index - TypesLengths.getTypeLength(TypesLengths.LONG_ID), TypesLengths.getTypeLength(TypesLengths.LONG_ID)); } /** * Sets the next value of the data of the Packet as String in the "UTF-8" * Charset. * * @param val * the String in the "UTF-8" Charset. */ public void setNextValueAsString(String val) { byte data_temp[] = data; byte val_as_bytes[]; try { val_as_bytes = val.getBytes("UTF-8"); } catch (UnsupportedEncodingException e) { throw new TestErrorException(e); } int new_data_size = data.length + val_as_bytes.length + TypesLengths.getTypeLength(TypesLengths.INT_ID); data = new byte[new_data_size]; System.arraycopy(data_temp, 0, data, 0, new_data_size - val_as_bytes.length - TypesLengths.getTypeLength(TypesLengths.INT_ID)); this.writeAtByteArray((long) val_as_bytes.length, data, new_data_size - val_as_bytes.length - TypesLengths.getTypeLength(TypesLengths.INT_ID), TypesLengths .getTypeLength(TypesLengths.INT_ID)); System.arraycopy(val_as_bytes, 0, data, new_data_size - val_as_bytes.length, val_as_bytes.length); } /** * Gets the next value of the data of the Packet as String in the "UTF-8" * Charset. * * @return the next value of the data of the Packet as String in the "UTF-8" * Charset. */ public String getNextValueAsString() { int string_length = this.getNextValueAsInt(); String res = null; try { res = new String(data, reading_data_index, string_length, "UTF-8"); } catch (UnsupportedEncodingException e) { throw new TestErrorException(e); } reading_data_index = reading_data_index + string_length; return res; } /** * Sets the next value of the data of the Packet as objectID VM-sensitive * value. If length is less than 8 bytes, the appropriate high bits in the * val value will be ignored. * * @param val * the ObjectID value. */ public void setNextValueAsObjectID(long val) { if (TypesLengths.getTypeLength(TypesLengths.OBJECT_ID) < 0 || TypesLengths.getTypeLength(TypesLengths.OBJECT_ID) > 8) { throw new TestErrorException("Improper ObjectID value length = " + TypesLengths.getTypeLength(TypesLengths.OBJECT_ID)); } int new_data_size = data.length + TypesLengths.getTypeLength(TypesLengths.OBJECT_ID); byte data_temp[] = data; data = new byte[new_data_size]; System.arraycopy(data_temp, 0, data, 0, new_data_size - TypesLengths.getTypeLength(TypesLengths.OBJECT_ID)); this.writeAtByteArray(val, data, new_data_size - TypesLengths.getTypeLength(TypesLengths.OBJECT_ID), TypesLengths.getTypeLength(TypesLengths.OBJECT_ID)); } /** * Gets the next value of the data of the Packet as objectID VM-sensitive * value. If length is less than 8 bytes, the appropriate high bits in the * returned value can be ignored. * * @return the next value of the data of the Packet as VM-sensitive value. */ public long getNextValueAsObjectID() { if (TypesLengths.getTypeLength(TypesLengths.OBJECT_ID) < 0 || TypesLengths.getTypeLength(TypesLengths.OBJECT_ID) > 8) { throw new TestErrorException("Improper ObjectID value length = " + TypesLengths.getTypeLength(TypesLengths.OBJECT_ID) + "!"); } reading_data_index = reading_data_index + TypesLengths.getTypeLength(TypesLengths.OBJECT_ID); return (int) readFromByteArray(data, reading_data_index - TypesLengths.getTypeLength(TypesLengths.OBJECT_ID), TypesLengths.getTypeLength(TypesLengths.OBJECT_ID)); } /** * Sets the next value of the data of the Packet as ThreadID VM-sensitive * value. If length is less than 8 bytes, the appropriate high bits in the * val value will be ignored. * * @param val * the ThreadID value. */ public void setNextValueAsThreadID(long val) { this.setNextValueAsObjectID(val); } /** * Gets the next value of the data of the Packet as ThreadID VM-sensitive * value. If length is less than 8 bytes, the appropriate high bits in the * returned value can be ignored. * * @return the next value of the data of the Packet as VM-sensitive value. */ public long getNextValueAsThreadID() { return this.getNextValueAsObjectID(); } /** * Sets the next value of the data of the Packet as ThreadGroupID * VM-sensitive value. If length is less than 8 bytes, the appropriate high * bits in the val value will be ignored. * * @param val * the ThreadGroupID value. */ public void setNextValueAsThreadGroupID(long val) { this.setNextValueAsObjectID(val); } /** * Gets the next value of the data of the Packet as ThreadGroupID * VM-sensitive value. If length is less than 8 bytes, the appropriate high * bits in the returned value can be ignored. * * @return the next value of the data of the Packet as VM-sensitive value. */ public long getNextValueAsThreadGroupID() { return this.getNextValueAsObjectID(); } /** * Sets the next value of the data of the Packet as StringID VM-sensitive * value. If length is less than 8 bytes, the appropriate high bits in the * val value will be ignored. * * @param val * the StringID value. */ public void setNextValueAsStringID(long val) { this.setNextValueAsObjectID(val); } /** * Gets the next value of the data of the Packet as StringID VM-sensitive * value. If length is less than 8 bytes, the appropriate high bits in the * returned value can be ignored. * * @return the next value of the data of the Packet as VM-sensitive value. */ public long getNextValueAsStringID() { return this.getNextValueAsObjectID(); } /** * Sets the next value of the data of the Packet as ClassLoaderID * VM-sensitive value. If length is less than 8 bytes, the appropriate high * bits in the val value will be ignored. * * @param val * the ClassLoaderID value. */ public void setNextValueAsClassLoaderID(long val) { this.setNextValueAsObjectID(val); } /** * Gets the next value of the data of the Packet as ClassLoaderID * VM-sensitive value. If length is less than 8 bytes, the appropriate high * bits in the returned value can be ignored. * * @return the next value of the data of the Packet as VM-sensitive value. */ public long getNextValueAsClassLoaderID() { return this.getNextValueAsObjectID(); } /** * Sets the next value of the data of the Packet as ClassObjectID * VM-sensitive value. If length is less than 8 bytes, the appropriate high * bits in the val value will be ignored. * * @param val * the ClassObjectID value. */ public void setNextValueAsClassObjectID(long val) { this.setNextValueAsObjectID(val); } /** * Gets the next value of the data of the Packet as ClassObjectID * VM-sensitive value. If length is less than 8 bytes, the appropriate high * bits in the returned value can be ignored. * * @return the next value of the data of the Packet as VM-sensitive value. */ public long getNextValueAsClassObjectID() { return this.getNextValueAsObjectID(); } /** * Sets the next value of the data of the Packet as ArrayID VM-sensitive * value. If length is less than 8 bytes, the appropriate high bits in the * val value will be ignored. * * @param val * the ArrayID value. */ public void setNextValueAsArrayID(long val) { this.setNextValueAsObjectID(val); } /** * Gets the next value of the data of the Packet as ArrayID VM-sensitive * value. If length is less than 8 bytes, the appropriate high bits in the * returned value can be ignored. * * @return the next value of the data of the Packet as VM-sensitive value. */ public long getNextValueAsClassArrayID() { return this.getNextValueAsObjectID(); } /** * Sets the next value of the data of the Packet as ReferenceTypeID * VM-sensitive value. If length is less than 8 bytes, the appropriate high * bits in the val value will be ignored. * * @param val * the ReferenceTypeID value. */ public void setNextValueAsReferenceTypeID(long val) { this.setNextValueAsObjectID(val); } /** * Gets the next value of the data of the Packet as ReferenceTypeID * VM-sensitive value. If length is less than 8 bytes, the appropriate high * bits in the returned value can be ignored. * * @return the next value of the data of the Packet as VM-sensitive value. */ public long getNextValueAsReferenceTypeID() { return this.getNextValueAsObjectID(); } /** * Sets the next value of the data of the Packet as ClassID VM-sensitive * value. If length is less than 8 bytes, the appropriate high bits in the * val value will be ignored. * * @param val * the ClassID value. */ public void setNextValueAsClassID(long val) { this.setNextValueAsObjectID(val); } /** * Gets the next value of the data of the Packet as ClassID VM-sensitive * value. If length is less than 8 bytes, the appropriate high bits in the * returned value can be ignored. * * @return the next value of the data of the Packet as VM-sensitive value. */ public long getNextValueAsClassID() { return this.getNextValueAsObjectID(); } /** * Sets the next value of the data of the Packet as InterfaceID VM-sensitive * value. If length is less than 8 bytes, the appropriate high bits in the * val value will be ignored. * * @param val * the InterfaceID value. */ public void setNextValueAsInterfaceID(long val) { this.setNextValueAsObjectID(val); } /** * Gets the next value of the data of the Packet as InterfaceID VM-sensitive * value. If length is less than 8 bytes, the appropriate high bits in the * returned value can be ignored. * * @return the next value of the data of the Packet as VM-sensitive value. */ public long getNextValueAsInterfaceID() { return this.getNextValueAsObjectID(); } /** * Sets the next value of the data of the Packet as ArrayTypeID VM-sensitive * value. If length is less than 8 bytes, the appropriate high bits in the * val value will be ignored. * * @param val * the ArrayTypeID value. */ public void setNextValueAsArrayTypeID(long val) { this.setNextValueAsObjectID(val); } /** * Gets the next value of the data of the Packet as ArrayTypeID VM-sensitive * value. If length is less than 8 bytes, the appropriate high bits in the * returned value can be ignored. * * @return the next value of the data of the Packet as VM-sensitive value. */ public long getNextValueAsArrayTypeID() { return this.getNextValueAsObjectID(); } /** * Sets the next value of the data of the Packet as tagged-objectID * VM-sensitive value. If length is less than 8 bytes, the appropriate high * bits in the val value will be ignored. * * @param taggedObject * TaggedObject value. */ public void setNextValueAsTaggedObject(TaggedObject taggedObject) { this.setNextValueAsByte(taggedObject.tag); this.setNextValueAsObjectID(taggedObject.objectID); } /** * Gets the next value of the data of the Packet as tagged-objectID * VM-sensitive value. If length is less than 8 bytes, the appropriate high * bits in the returned value can be ignored. * * @return the next value of the data of the Packet as VM-sensitive value. */ public TaggedObject getNextValueAsTaggedObject() { if (TypesLengths.getTypeLength(TypesLengths.OBJECT_ID) < 0 || TypesLengths.getTypeLength(TypesLengths.OBJECT_ID) > 8) { throw new TestErrorException("Improper ObjectID value length = " + TypesLengths.getTypeLength(TypesLengths.OBJECT_ID)); } TaggedObject taggedObject = new TaggedObject(); taggedObject.tag = this.getNextValueAsByte(); taggedObject.objectID = this.getNextValueAsObjectID(); return taggedObject; } /** * Sets the next value of the data of the Packet as MethodID VM-sensitive * value. If length is less than 8 bytes, the appropriate high bits in the * val value will be ignored. * * @param methodID * MethodID value. */ public void setNextValueAsMethodID(long methodID) { if (TypesLengths.getTypeLength(TypesLengths.METHOD_ID) < 0 || TypesLengths.getTypeLength(TypesLengths.METHOD_ID) > 8) { throw new TestErrorException("Improper MethodID value length = " + TypesLengths.getTypeLength(TypesLengths.METHOD_ID)); } int new_data_size = data.length + TypesLengths.getTypeLength(TypesLengths.METHOD_ID); byte data_temp[] = data; data = new byte[new_data_size]; System.arraycopy(data_temp, 0, data, 0, new_data_size - TypesLengths.getTypeLength(TypesLengths.METHOD_ID)); this.writeAtByteArray(methodID, data, new_data_size - TypesLengths.getTypeLength(TypesLengths.METHOD_ID), TypesLengths.getTypeLength(TypesLengths.METHOD_ID)); } /** * Gets the next value of the data of the Packet as MethodID VM-sensitive * value. If length is less than 8 bytes, the appropriate high bits in the * returned value can be ignored. * * @return the next value of the data of the Packet as VM-sensitive value. */ public long getNextValueAsMethodID() { if (TypesLengths.getTypeLength(TypesLengths.METHOD_ID) < 0 || TypesLengths.getTypeLength(TypesLengths.METHOD_ID) > 8) { throw new TestErrorException("Improper MethodID value length = " + TypesLengths.getTypeLength(TypesLengths.METHOD_ID)); } reading_data_index = reading_data_index + TypesLengths.getTypeLength(TypesLengths.METHOD_ID); long result = readFromByteArray(data, reading_data_index - TypesLengths.getTypeLength(TypesLengths.METHOD_ID), TypesLengths.getTypeLength(TypesLengths.METHOD_ID)); return result; } /** * Sets the next value of the data of the Packet as FieldID VM-sensitive * value. If length is less than 8 bytes, the appropriate high bits in the * val value will be ignored. * * @param fieldID * FieldID value. */ public void setNextValueAsFieldID(long fieldID) { if (TypesLengths.getTypeLength(TypesLengths.FIELD_ID) < 0 || TypesLengths.getTypeLength(TypesLengths.FIELD_ID) > 8) { throw new TestErrorException("Improper FieldID value length = " + TypesLengths.getTypeLength(TypesLengths.FIELD_ID)); } int new_data_size = data.length + TypesLengths.getTypeLength(TypesLengths.FIELD_ID); byte data_temp[] = data; data = new byte[new_data_size]; System.arraycopy(data_temp, 0, data, 0, new_data_size - TypesLengths.getTypeLength(TypesLengths.FIELD_ID)); this.writeAtByteArray(fieldID, data, new_data_size - TypesLengths.getTypeLength(TypesLengths.FIELD_ID), TypesLengths.getTypeLength(TypesLengths.FIELD_ID)); } /** * Gets the next value of the data of the Packet as FieldID VM-sensitive * value. If length is less than 8 bytes, the appropriate high bits in the * returned value can be ignored. * * @return the next value of the data of the Packet as VM-sensitive value. */ public long getNextValueAsFieldID() { if (TypesLengths.getTypeLength(TypesLengths.FIELD_ID) < 0 || TypesLengths.getTypeLength(TypesLengths.FIELD_ID) > 8) { throw new TestErrorException("Improper FieldID value length = " + TypesLengths.getTypeLength(TypesLengths.FIELD_ID)); } reading_data_index = reading_data_index + TypesLengths.getTypeLength(TypesLengths.FIELD_ID); long result = readFromByteArray(data, reading_data_index - TypesLengths.getTypeLength(TypesLengths.FIELD_ID), TypesLengths.getTypeLength(TypesLengths.FIELD_ID)); return result; } /** * Sets the next value of the data of the Packet as FrameID VM-sensitive * value. If length is less than 8 bytes, the appropriate high bits in the * val value will be ignored. * * @param frameID * FrameID value. */ public void setNextValueAsFrameID(long frameID) { if (TypesLengths.getTypeLength(TypesLengths.FRAME_ID) < 0 || TypesLengths.getTypeLength(TypesLengths.FRAME_ID) > 8) { throw new TestErrorException("Improper FrameID value length = " + TypesLengths.getTypeLength(TypesLengths.FRAME_ID)); } int new_data_size = data.length + TypesLengths.getTypeLength(TypesLengths.FRAME_ID); byte data_temp[] = data; data = new byte[new_data_size]; System.arraycopy(data_temp, 0, data, 0, new_data_size - TypesLengths.getTypeLength(TypesLengths.FRAME_ID)); this.writeAtByteArray(frameID, data, new_data_size - TypesLengths.getTypeLength(TypesLengths.FRAME_ID), TypesLengths.getTypeLength(TypesLengths.FRAME_ID)); } /** * Gets the next value of the data of the Packet as FrameID VM-sensitive * value. If length is less than 8 bytes, the appropriate high bits in the * returned value can be ignored. * * @return the next value of the data of the Packet as VM-sensitive value. */ public long getNextValueAsFrameID() { if (TypesLengths.getTypeLength(TypesLengths.FRAME_ID) < 0 || TypesLengths.getTypeLength(TypesLengths.FRAME_ID) > 8) { throw new TestErrorException("Improper FrameID value length = " + TypesLengths.getTypeLength(TypesLengths.FRAME_ID)); } reading_data_index = reading_data_index + TypesLengths.getTypeLength(TypesLengths.FRAME_ID); long result = readFromByteArray(data, reading_data_index - TypesLengths.getTypeLength(TypesLengths.FRAME_ID), TypesLengths.getTypeLength(TypesLengths.FRAME_ID)); return result; } /** * Sets the next value of the data of the Packet as Location VM-sensitive * value. If length is less than 8 bytes, the appropriate high bits in the * val value will be ignored. * * @param location * Location value. */ public void setNextValueAsLocation(Location location) { this.setNextValueAsByte(location.tag); this.setNextValueAsClassID(location.classID); this.setNextValueAsMethodID(location.methodID); this.setNextValueAsLong(location.index); } /** * Gets the next value of the data of the Packet as Location VM-sensitive * value. If length is less than 8 bytes, the appropriate high bits in the * returned value can be ignored. * * @return the next value of the data of the Packet as VM-sensitive value. */ public Location getNextValueAsLocation() { Location location = new Location(); location.tag = this.getNextValueAsByte(); location.classID = this.getNextValueAsClassID(); location.methodID = this.getNextValueAsMethodID(); location.index = this.getNextValueAsLong(); return location; } /** * Sets the next value of the data of the Packet as Value VM-sensitive * value. If length is less than 8 bytes, the appropriate high bits in the * val value will be ignored. * * @param value * Value value. * @throws UnsupportedEncodingException */ public void setNextValueAsValue(Value value) { this.setNextValueAsByte(value.getTag()); setNextValueAsUntaggedValue(value); } /** * Gets the next value of the data of the Packet as Value VM-sensitive * value. If length is less than 8 bytes, the appropriate high bits in the * returned value can be ignored. * * @return the next value of the data of the Packet as VM-sensitive value. */ public Value getNextValueAsValue() { byte tag = this.getNextValueAsByte(); return getNextValueAsUntaggedValue(tag); } /** * Sets the next value of the data of the Packet as UntaggedValue * VM-sensitive value. If length is less than 8 bytes, the appropriate high * bits in the val value will be ignored. * * @param value * UntaggedValue value. * @throws UnsupportedEncodingException */ public void setNextValueAsUntaggedValue(Value value) { switch (value.getTag()) { case JDWPConstants.Tag.BOOLEAN_TAG: this.setNextValueAsBoolean(value.getBooleanValue()); break; case JDWPConstants.Tag.BYTE_TAG: this.setNextValueAsByte(value.getByteValue()); break; case JDWPConstants.Tag.CHAR_TAG: this.setNextValueAsChar(value.getCharValue()); break; case JDWPConstants.Tag.DOUBLE_TAG: this.setNextValueAsDouble(value.getDoubleValue()); break; case JDWPConstants.Tag.FLOAT_TAG: this.setNextValueAsFloat(value.getFloatValue()); break; case JDWPConstants.Tag.INT_TAG: this.setNextValueAsInt(value.getIntValue()); break; case JDWPConstants.Tag.LONG_TAG: this.setNextValueAsLong(value.getLongValue()); break; case JDWPConstants.Tag.SHORT_TAG: this.setNextValueAsShort(value.getShortValue()); break; case JDWPConstants.Tag.VOID_TAG: break; case JDWPConstants.Tag.STRING_TAG: case JDWPConstants.Tag.ARRAY_TAG: case JDWPConstants.Tag.CLASS_LOADER_TAG: case JDWPConstants.Tag.CLASS_OBJECT_TAG: case JDWPConstants.Tag.OBJECT_TAG: case JDWPConstants.Tag.THREAD_GROUP_TAG: case JDWPConstants.Tag.THREAD_TAG: this.setNextValueAsObjectID(value.getLongValue()); break; default: throw new TestErrorException("Illegal tag value = " + value.getTag()); } } /** * Gets the next value of the data of the Packet as UntaggedValue * VM-sensitive value. If length is less than 8 bytes, the appropriate high * bits in the returned value can be ignored. * * @return the next value of the data of the Packet as VM-sensitive value. */ public Value getNextValueAsUntaggedValue(byte tag) { Value value = null; switch (tag) { case JDWPConstants.Tag.BOOLEAN_TAG: value = new Value(this.getNextValueAsBoolean()); break; case JDWPConstants.Tag.BYTE_TAG: value = new Value(this.getNextValueAsByte()); break; case JDWPConstants.Tag.CHAR_TAG: value = new Value(this.getNextValueAsChar()); break; case JDWPConstants.Tag.DOUBLE_TAG: value = new Value(this.getNextValueAsDouble()); break; case JDWPConstants.Tag.FLOAT_TAG: value = new Value(this.getNextValueAsFloat()); break; case JDWPConstants.Tag.INT_TAG: value = new Value(this.getNextValueAsInt()); break; case JDWPConstants.Tag.LONG_TAG: value = new Value(this.getNextValueAsLong()); break; case JDWPConstants.Tag.SHORT_TAG: value = new Value(this.getNextValueAsShort()); break; case JDWPConstants.Tag.STRING_TAG: case JDWPConstants.Tag.ARRAY_TAG: case JDWPConstants.Tag.CLASS_LOADER_TAG: case JDWPConstants.Tag.CLASS_OBJECT_TAG: case JDWPConstants.Tag.OBJECT_TAG: case JDWPConstants.Tag.THREAD_GROUP_TAG: case JDWPConstants.Tag.THREAD_TAG: value = new Value(tag, this.getNextValueAsObjectID()); break; case JDWPConstants.Tag.VOID_TAG: // no bytes to read. break; default: throw new TestErrorException("Illegal tag value = " + tag); } return value; } /** * Sets the next value of the data of the Packet as ArrayRegion VM-sensitive * value. If length is less than 8 bytes, the appropriate high bits in the * val value will be ignored. * * @param array * ArrayRegion value. * @throws UnsupportedEncodingException */ // public void setNextValueAsArrayRegion(ArrayRegion array) throws // UnsupportedEncodingException { public void setNextValueAsArrayRegion(ArrayRegion array) { this.setNextValueAsByte(array.getTag()); this.setNextValueAsInt(array.getLength()); for (int i = 0; i < array.getLength(); i++) { if (isValuePrimitiveType(array.getTag())) { switch (array.getTag()) { case JDWPConstants.Tag.BOOLEAN_TAG: this.setNextValueAsBoolean(array.getValue(i) .getBooleanValue()); break; case JDWPConstants.Tag.BYTE_TAG: this.setNextValueAsByte(array.getValue(i).getByteValue()); break; case JDWPConstants.Tag.DOUBLE_TAG: this.setNextValueAsDouble(array.getValue(i) .getDoubleValue()); break; case JDWPConstants.Tag.FLOAT_TAG: this.setNextValueAsFloat(array.getValue(i).getFloatValue()); break; case JDWPConstants.Tag.INT_TAG: this.setNextValueAsInt(array.getValue(i).getIntValue()); break; case JDWPConstants.Tag.LONG_TAG: this.setNextValueAsLong(array.getValue(i).getLongValue()); break; case JDWPConstants.Tag.SHORT_TAG: this.setNextValueAsShort(array.getValue(i).getShortValue()); break; default: throw new TestErrorException("Illegal tag value = " + array.getTag()); } } else { this.setNextValueAsValue(array.getValue(i)); } } } /** * Gets the next value of the data of the Packet as ArrayRegion VM-sensitive * value. If length is less than 8 bytes, the appropriate high bits in the * returned value can be ignored. * * @return the next value of the data of the Packet as VM-sensitive value. */ public ArrayRegion getNextValueAsArrayRegion() { byte array_tag = this.getNextValueAsByte(); int array_length = this.getNextValueAsInt(); ArrayRegion array = new ArrayRegion(array_tag, array_length); for (int i = 0; i < array_length; i++) { if (isValuePrimitiveType(array_tag)) array.setValue(i, this.getNextValueAsUntaggedValue(array_tag)); else array.setValue(i, this.getNextValueAsValue()); } return array; } /** * Gets the representation of the Packet as array of bytes in the JDWP * format including header and data sections. * * @return bytes representation of this packet */ public byte[] toBytesArray() { byte res[] = new byte[data.length + HEADER_SIZE]; writeAtByteArray(data.length + HEADER_SIZE, res, LENGTH_INDEX, INT_SIZE); writeAtByteArray(id, res, ID_INDEX, INT_SIZE); res[FLAGS_INDEX] = flags; System.arraycopy(data, 0, res, HEADER_SIZE, data.length); return res; } /** * Reads value from array of bytes ar[] starting form index and reading size * bytes. If size is less than 8, the appropriate high bits in the resulting * long value will be zero. * * @param ar * the array of bytes where the value is read from. * @param from * index to start reading bytes. * @param size * number of bytes to read */ protected static long readFromByteArray(byte ar[], int from, int size) { long res = 0; byte temp; for (int i = 0; i < size; i++) { temp = ar[from + i]; res = (res << 8) | (((long) temp) & 0xFF); } return res; } /** * Tells whether the packet is reply. * * @return true if this packet is reply, false if it is command */ public boolean isReply() { return (flags & REPLY_PACKET_FLAG) != 0; } /** * Checks whether all data has been read from the packet. * * @return boolean */ public boolean isAllDataRead() { return reading_data_index == data.length; } /** * Writes value - val to the array of bytes ar[], beginning from index - to, * size of value is - size bytes. If size is less than 8, the appropriate * high bits in the val value will be ignored. * * @param val * the value, which will be written in the array. * @param ar * the array of bytes where the value is read from. * @param to * the beginning index in the array of bytes. * @param size * size of value in bytes. */ protected void writeAtByteArray(long val, byte ar[], int to, int size) { for (int i = 0; i < size; i++) { ar[to + i] = (byte) (val >> 8 * (size - 1 - i)); } } /** * Returns true if this bytes array can be interpreted as reply packet. * * @param p * bytes representation of packet * @return true or false */ public static boolean isReply(byte[] p) { if (p.length < FLAGS_INDEX) return false; return (p[FLAGS_INDEX] & REPLY_PACKET_FLAG) != 0; } /** * Returns packet length from header of given packet bytes. * * @param p * bytes representation of packet * @return true or false */ public static int getPacketLength(byte[] p) { return (int) readFromByteArray(p, LENGTH_INDEX, INT_SIZE); } /** * Enwraps this bytes array either to ReplyPacket or EventPacket instance, * according to result of isReply(). * * @param p * bytes array to enwrap into packet * @return new created ReplyPacket or CommandPacket */ public static Packet interpretPacket(byte[] p) { if (p.length < HEADER_SIZE) throw new TestErrorException("Wrong packet"); if (Packet.isReply(p)) return new ReplyPacket(p); return new EventPacket(p); } }