1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements.  See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *
15 *  See the License for the specific language governing permissions and
16 *  limitations under the License.
17 */
18
19/**
20 * @author Khen G. Kim, Aleksey V. Yantsen
21 */
22
23/**
24 * Created on 10.01.2004
25 */
26package org.apache.harmony.jpda.tests.framework.jdwp;
27
28import java.io.UnsupportedEncodingException;
29
30import org.apache.harmony.jpda.tests.framework.TestErrorException;
31import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants;
32import org.apache.harmony.jpda.tests.framework.jdwp.TypesLengths;
33
34/**
35 * This base class represents JDWP packet.
36 */
37public class Packet {
38
39    public static final int REPLY_PACKET_FLAG = 0x80;
40
41    public static final int FLAGS_INDEX = 8;
42
43    public static final int HEADER_SIZE = 11;
44
45    /**
46     * The size in bytes of the BYTE type value.
47     */
48    protected static final int BYTE_SIZE = 1;
49
50    /**
51     * The size in bytes of the SHORT type value.
52     */
53    protected static final int SHORT_SIZE = 2;
54
55    /**
56     * The size in bytes of the INT type value.
57     */
58    protected static final int INT_SIZE = 4;
59
60    /**
61     * The size in bytes of the LONG type value.
62     */
63    protected static final int LONG_SIZE = 8;
64
65    private static final int LENGTH_INDEX = 0;
66
67    private static final int ID_INDEX = 4;
68
69    private int id;
70
71    private byte flags;
72
73    private int length;
74
75    private byte data[];
76
77    private int reading_data_index;
78
79    /**
80     * A constructor that creates an empty CommandPacket with empty header
81     * fields and no data.
82     */
83    public Packet() {
84        reading_data_index = 0;
85        data = new byte[0];
86    }
87
88    /**
89     * A constructor that creates Packet from array of bytes including header
90     * and data sections.
91     *
92     * @param p array of bytes for new packet.
93     */
94    public Packet(byte p[]) {
95        length = (int) readFromByteArray(p, LENGTH_INDEX, INT_SIZE);
96        if (length < HEADER_SIZE) {
97            throw new TestErrorException(
98                    "Packet creation error: size of packet = " + length
99                            + "is less than header size = " + HEADER_SIZE);
100        }
101        id = (int) readFromByteArray(p, ID_INDEX, INT_SIZE);
102        flags = p[FLAGS_INDEX];
103        data = new byte[p.length - HEADER_SIZE];
104        System.arraycopy(p, HEADER_SIZE, data, 0, p.length - HEADER_SIZE);
105        reading_data_index = 0;
106    }
107
108    /**
109     * Gets the length value of the header of the Packet.
110     *
111     * @return the length value of the header of the Packet.
112     */
113    public int getLength() {
114        return length;
115    }
116
117    /**
118     * Sets the id value of the header of the Packet.
119     *
120     * @param i
121     *            the id value of the header of the Packet.
122     */
123    public void setId(int i) {
124        id = i;
125    }
126
127    /**
128     * Gets the id value of the header of the Packet.
129     *
130     * @return the id value of the header of the Packet.
131     */
132    public int getId() {
133        return id;
134    }
135
136    /**
137     * Sets the flags value of the header of the Packet.
138     *
139     * @param f
140     *            the flags value of the header of the Packet.
141     */
142    public void setFlags(byte f) {
143        flags = f;
144    }
145
146    /**
147     * Gets the flags value of the header of the Packet.
148     *
149     * @return the flags value of the header of the Packet.
150     */
151    public byte getFlags() {
152        return flags;
153    }
154
155    /**
156     * Gets the flags value from the header of the Packet.
157     *
158     * @param tag
159     *            Type tag (see JDWP.tag)
160     * @return the flags value of the header of the Packet.
161     */
162    public boolean isValuePrimitiveType(byte tag) {
163        switch (tag) {
164        case JDWPConstants.Tag.ARRAY_TAG: {
165            return false;
166        }
167        case JDWPConstants.Tag.BYTE_TAG: {
168            return true;
169        }
170        case JDWPConstants.Tag.CHAR_TAG: {
171            return true;
172        }
173        case JDWPConstants.Tag.OBJECT_TAG: {
174            return false;
175        }
176        case JDWPConstants.Tag.FLOAT_TAG: {
177            return true;
178        }
179        case JDWPConstants.Tag.DOUBLE_TAG: {
180            return true;
181        }
182        case JDWPConstants.Tag.INT_TAG: {
183            return true;
184        }
185        case JDWPConstants.Tag.LONG_TAG: {
186            return true;
187        }
188        case JDWPConstants.Tag.SHORT_TAG: {
189            return true;
190        }
191        case JDWPConstants.Tag.VOID_TAG: {
192            return true;
193        }
194        case JDWPConstants.Tag.BOOLEAN_TAG: {
195            return true;
196        }
197        case JDWPConstants.Tag.STRING_TAG: {
198            return false;
199        }
200        case JDWPConstants.Tag.THREAD_TAG: {
201            return false;
202        }
203        case JDWPConstants.Tag.THREAD_GROUP_TAG: {
204            return false;
205        }
206        case JDWPConstants.Tag.CLASS_LOADER_TAG: {
207            return false;
208        }
209        case JDWPConstants.Tag.CLASS_OBJECT_TAG: {
210            return false;
211        }
212        case JDWPConstants.Tag.NO_TAG: {
213            return true;
214        }
215        default: {
216            throw new TestErrorException("Improper JDWP.tag value = " + tag);
217        }
218        }
219    }
220
221    /**
222     * Sets the next value of the data of the Packet as byte.
223     *
224     * @param val
225     *            the byte value.
226     */
227    public void setNextValueAsByte(byte val) {
228        int new_data_size = data.length + BYTE_SIZE;
229        byte data_temp[] = data;
230        data = new byte[new_data_size];
231        System.arraycopy(data_temp, 0, data, 0, new_data_size - BYTE_SIZE);
232        data[new_data_size - BYTE_SIZE] = val;
233    }
234
235    /**
236     * Gets the next value of the data of the Packet as byte.
237     *
238     * @return the next value of the data of the Packet as byte.
239     */
240    public byte getNextValueAsByte() {
241        reading_data_index = reading_data_index + BYTE_SIZE;
242        return data[reading_data_index - BYTE_SIZE];
243    }
244
245    /**
246     * Sets the next value of the data of the Packet as boolean.
247     *
248     * @param val
249     *            the boolean value.
250     */
251    public void setNextValueAsBoolean(boolean val) {
252        int old_data_size = data.length;
253        int new_data_size = old_data_size
254                + TypesLengths.getTypeLength(TypesLengths.BOOLEAN_ID);
255        byte data_temp[] = data;
256        data = new byte[new_data_size];
257        System.arraycopy(data_temp, 0, data, 0, old_data_size);
258        if (val) {
259            data[old_data_size] = 1;
260        } else {
261            data[old_data_size] = 0;
262        }
263    }
264
265    /**
266     * Gets the next value of the data of the Packet as boolean.
267     *
268     * @return the next value of the data of the Packet as boolean.
269     */
270    public boolean getNextValueAsBoolean() {
271        int res = (int) data[reading_data_index] & 0xFF;
272        reading_data_index = reading_data_index
273                + TypesLengths.getTypeLength(TypesLengths.BOOLEAN_ID);
274        return (res != 0);
275    }
276
277    /**
278     * Sets the next value of the data of the Packet as short.
279     *
280     * @param val
281     *            the short value.
282     */
283    public void setNextValueAsShort(short val) {
284        int new_data_size = data.length
285                + TypesLengths.getTypeLength(TypesLengths.SHORT_ID);
286        byte data_temp[] = data;
287        data = new byte[new_data_size];
288        System.arraycopy(data_temp, 0, data, 0, new_data_size
289                - TypesLengths.getTypeLength(TypesLengths.SHORT_ID));
290        this.writeAtByteArray((long) val, data, new_data_size
291                - TypesLengths.getTypeLength(TypesLengths.SHORT_ID),
292                TypesLengths.getTypeLength(TypesLengths.SHORT_ID));
293    }
294
295    /**
296     * Gets the next value of the data of the Packet as short.
297     *
298     * @return the next value of the data of the Packet as short.
299     */
300    public short getNextValueAsShort() {
301        reading_data_index = reading_data_index
302                + TypesLengths.getTypeLength(TypesLengths.SHORT_ID);
303        return (short) readFromByteArray(data, reading_data_index
304                - TypesLengths.getTypeLength(TypesLengths.SHORT_ID),
305                TypesLengths.getTypeLength(TypesLengths.SHORT_ID));
306    }
307
308    /**
309     * Sets the next value of the data of the Packet as int.
310     *
311     * @param val
312     *            the int value.
313     */
314    public void setNextValueAsInt(int val) {
315        int new_data_size = data.length
316                + TypesLengths.getTypeLength(TypesLengths.INT_ID);
317        byte data_temp[] = data;
318        data = new byte[new_data_size];
319        System.arraycopy(data_temp, 0, data, 0, new_data_size
320                - TypesLengths.getTypeLength(TypesLengths.INT_ID));
321        this.writeAtByteArray((long) val, data, new_data_size
322                - TypesLengths.getTypeLength(TypesLengths.INT_ID), TypesLengths
323                .getTypeLength(TypesLengths.INT_ID));
324    }
325
326    /**
327     * Gets the next value of the data of the Packet as int.
328     *
329     * @return the next value of the data of the Packet as int.
330     */
331    public int getNextValueAsInt() {
332        reading_data_index = reading_data_index
333                + TypesLengths.getTypeLength(TypesLengths.INT_ID);
334        return (int) readFromByteArray(data, reading_data_index
335                - TypesLengths.getTypeLength(TypesLengths.INT_ID), TypesLengths
336                .getTypeLength(TypesLengths.INT_ID));
337    }
338
339    /**
340     * Sets the next value of the data of the Packet as double.
341     *
342     * @param dval
343     *            the double value.
344     */
345    public void setNextValueAsDouble(double dval) {
346        int new_data_size = data.length
347                + TypesLengths.getTypeLength(TypesLengths.DOUBLE_ID);
348        byte data_temp[] = data;
349        long val = Double.doubleToLongBits(dval);
350        data = new byte[new_data_size];
351        System.arraycopy(data_temp, 0, data, 0, new_data_size
352                - TypesLengths.getTypeLength(TypesLengths.DOUBLE_ID));
353        this.writeAtByteArray((long) val, data, new_data_size
354                - TypesLengths.getTypeLength(TypesLengths.DOUBLE_ID),
355                TypesLengths.getTypeLength(TypesLengths.DOUBLE_ID));
356    }
357
358    /**
359     * Gets the next value of the data of the Packet as double.
360     *
361     * @return the next value of the data of the Packet as double.
362     */
363    public double getNextValueAsDouble() {
364        reading_data_index = reading_data_index
365                + TypesLengths.getTypeLength(TypesLengths.DOUBLE_ID);
366        long res = readFromByteArray(data, reading_data_index
367                - TypesLengths.getTypeLength(TypesLengths.DOUBLE_ID),
368                TypesLengths.getTypeLength(TypesLengths.DOUBLE_ID));
369
370        return Double.longBitsToDouble(res);
371    }
372
373    /**
374     * Sets the next value of the data of the Packet as float.
375     *
376     * @param fval
377     *            the float value.
378     */
379    public void setNextValueAsFloat(float fval) {
380        int new_data_size = data.length
381                + TypesLengths.getTypeLength(TypesLengths.FLOAT_ID);
382        byte data_temp[] = data;
383        long val = Float.floatToIntBits(fval);
384        data = new byte[new_data_size];
385        System.arraycopy(data_temp, 0, data, 0, new_data_size
386                - TypesLengths.getTypeLength(TypesLengths.FLOAT_ID));
387        this.writeAtByteArray((long) val, data, new_data_size
388                - TypesLengths.getTypeLength(TypesLengths.FLOAT_ID),
389                TypesLengths.getTypeLength(TypesLengths.FLOAT_ID));
390    }
391
392    /**
393     * Gets the next value of the data of the Packet as float.
394     *
395     * @return the next value of the data of the Packet as float.
396     */
397    public float getNextValueAsFloat() {
398        reading_data_index = reading_data_index
399                + TypesLengths.getTypeLength(TypesLengths.FLOAT_ID);
400        long res = readFromByteArray(data, reading_data_index
401                - TypesLengths.getTypeLength(TypesLengths.FLOAT_ID),
402                TypesLengths.getTypeLength(TypesLengths.FLOAT_ID));
403
404        return Float.intBitsToFloat((int) res);
405    }
406
407    /**
408     * Sets the next value of the data of the Packet as char.
409     *
410     * @param val
411     *            the char value.
412     */
413    public void setNextValueAsChar(char val) {
414        int new_data_size = data.length
415                + TypesLengths.getTypeLength(TypesLengths.CHAR_ID);
416        byte data_temp[] = data;
417        data = new byte[new_data_size];
418        System.arraycopy(data_temp, 0, data, 0, new_data_size
419                - TypesLengths.getTypeLength(TypesLengths.CHAR_ID));
420        this.writeAtByteArray((long) val, data, new_data_size
421                - TypesLengths.getTypeLength(TypesLengths.CHAR_ID),
422                TypesLengths.getTypeLength(TypesLengths.CHAR_ID));
423    }
424
425    /**
426     * Gets the next value of the data of the Packet as char.
427     *
428     * @return the next value of the data of the Packet as char.
429     */
430    public char getNextValueAsChar() {
431        reading_data_index = reading_data_index
432                + TypesLengths.getTypeLength(TypesLengths.CHAR_ID);
433        return (char) readFromByteArray(data, reading_data_index
434                - TypesLengths.getTypeLength(TypesLengths.CHAR_ID),
435                TypesLengths.getTypeLength(TypesLengths.CHAR_ID));
436    }
437
438    /**
439     * Sets the next value of the data of the Packet as long.
440     *
441     * @param val
442     *            the long value.
443     */
444    public void setNextValueAsLong(long val) {
445        int new_data_size = data.length
446                + TypesLengths.getTypeLength(TypesLengths.LONG_ID);
447        byte data_temp[] = data;
448        data = new byte[new_data_size];
449        System.arraycopy(data_temp, 0, data, 0, new_data_size
450                - TypesLengths.getTypeLength(TypesLengths.LONG_ID));
451        this.writeAtByteArray(val, data, new_data_size
452                - TypesLengths.getTypeLength(TypesLengths.LONG_ID),
453                TypesLengths.getTypeLength(TypesLengths.LONG_ID));
454    }
455
456    /**
457     * Gets the next value of the data of the Packet as long.
458     *
459     * @return the next value of the data of the Packet as long.
460     */
461    public long getNextValueAsLong() {
462        reading_data_index = reading_data_index
463                + TypesLengths.getTypeLength(TypesLengths.LONG_ID);
464        return readFromByteArray(data, reading_data_index
465                - TypesLengths.getTypeLength(TypesLengths.LONG_ID),
466                TypesLengths.getTypeLength(TypesLengths.LONG_ID));
467    }
468
469    /**
470     * Sets the next value of the data of the Packet as String in the "UTF-8"
471     * Charset.
472     *
473     * @param val
474     *            the String in the "UTF-8" Charset.
475     */
476    public void setNextValueAsString(String val) {
477        byte data_temp[] = data;
478        byte val_as_bytes[];
479        try {
480            val_as_bytes = val.getBytes("UTF-8");
481        } catch (UnsupportedEncodingException e) {
482            throw new TestErrorException(e);
483        }
484        int new_data_size = data.length + val_as_bytes.length
485                + TypesLengths.getTypeLength(TypesLengths.INT_ID);
486        data = new byte[new_data_size];
487        System.arraycopy(data_temp, 0, data, 0, new_data_size
488                - val_as_bytes.length
489                - TypesLengths.getTypeLength(TypesLengths.INT_ID));
490        this.writeAtByteArray((long) val_as_bytes.length, data, new_data_size
491                - val_as_bytes.length
492                - TypesLengths.getTypeLength(TypesLengths.INT_ID), TypesLengths
493                .getTypeLength(TypesLengths.INT_ID));
494        System.arraycopy(val_as_bytes, 0, data, new_data_size
495                - val_as_bytes.length, val_as_bytes.length);
496    }
497
498    /**
499     * Gets the next value of the data of the Packet as String in the "UTF-8"
500     * Charset.
501     *
502     * @return the next value of the data of the Packet as String in the "UTF-8"
503     *         Charset.
504     */
505    public String getNextValueAsString() {
506        int string_length = this.getNextValueAsInt();
507        String res = null;
508        try {
509            res = new String(data, reading_data_index, string_length, "UTF-8");
510        } catch (UnsupportedEncodingException e) {
511            throw new TestErrorException(e);
512        }
513        reading_data_index = reading_data_index + string_length;
514        return res;
515    }
516
517    /**
518     * Sets the next value of the data of the Packet as objectID VM-sensitive
519     * value. If length is less than 8 bytes, the appropriate high bits in the
520     * val value will be ignored.
521     *
522     * @param val
523     *            the ObjectID value.
524     */
525    public void setNextValueAsObjectID(long val) {
526        if (TypesLengths.getTypeLength(TypesLengths.OBJECT_ID) < 0
527                || TypesLengths.getTypeLength(TypesLengths.OBJECT_ID) > 8) {
528            throw new TestErrorException("Improper ObjectID value length = "
529                    + TypesLengths.getTypeLength(TypesLengths.OBJECT_ID));
530        }
531        int new_data_size = data.length
532                + TypesLengths.getTypeLength(TypesLengths.OBJECT_ID);
533        byte data_temp[] = data;
534        data = new byte[new_data_size];
535        System.arraycopy(data_temp, 0, data, 0, new_data_size
536                - TypesLengths.getTypeLength(TypesLengths.OBJECT_ID));
537        this.writeAtByteArray(val, data, new_data_size
538                - TypesLengths.getTypeLength(TypesLengths.OBJECT_ID),
539                TypesLengths.getTypeLength(TypesLengths.OBJECT_ID));
540    }
541
542    /**
543     * Gets the next value of the data of the Packet as objectID VM-sensitive
544     * value. If length is less than 8 bytes, the appropriate high bits in the
545     * returned value can be ignored.
546     *
547     * @return the next value of the data of the Packet as VM-sensitive value.
548     */
549    public long getNextValueAsObjectID() {
550        if (TypesLengths.getTypeLength(TypesLengths.OBJECT_ID) < 0
551                || TypesLengths.getTypeLength(TypesLengths.OBJECT_ID) > 8) {
552            throw new TestErrorException("Improper ObjectID value length = "
553                    + TypesLengths.getTypeLength(TypesLengths.OBJECT_ID) + "!");
554        }
555        reading_data_index = reading_data_index
556                + TypesLengths.getTypeLength(TypesLengths.OBJECT_ID);
557        return (int) readFromByteArray(data, reading_data_index
558                - TypesLengths.getTypeLength(TypesLengths.OBJECT_ID),
559                TypesLengths.getTypeLength(TypesLengths.OBJECT_ID));
560    }
561
562    /**
563     * Sets the next value of the data of the Packet as ThreadID VM-sensitive
564     * value. If length is less than 8 bytes, the appropriate high bits in the
565     * val value will be ignored.
566     *
567     * @param val
568     *            the ThreadID value.
569     */
570    public void setNextValueAsThreadID(long val) {
571        this.setNextValueAsObjectID(val);
572    }
573
574    /**
575     * Gets the next value of the data of the Packet as ThreadID VM-sensitive
576     * value. If length is less than 8 bytes, the appropriate high bits in the
577     * returned value can be ignored.
578     *
579     * @return the next value of the data of the Packet as VM-sensitive value.
580     */
581    public long getNextValueAsThreadID() {
582        return this.getNextValueAsObjectID();
583    }
584
585    /**
586     * Sets the next value of the data of the Packet as ThreadGroupID
587     * VM-sensitive value. If length is less than 8 bytes, the appropriate high
588     * bits in the val value will be ignored.
589     *
590     * @param val
591     *            the ThreadGroupID value.
592     */
593    public void setNextValueAsThreadGroupID(long val) {
594        this.setNextValueAsObjectID(val);
595    }
596
597    /**
598     * Gets the next value of the data of the Packet as ThreadGroupID
599     * VM-sensitive value. If length is less than 8 bytes, the appropriate high
600     * bits in the returned value can be ignored.
601     *
602     * @return the next value of the data of the Packet as VM-sensitive value.
603     */
604    public long getNextValueAsThreadGroupID() {
605        return this.getNextValueAsObjectID();
606    }
607
608    /**
609     * Sets the next value of the data of the Packet as StringID VM-sensitive
610     * value. If length is less than 8 bytes, the appropriate high bits in the
611     * val value will be ignored.
612     *
613     * @param val
614     *            the StringID value.
615     */
616    public void setNextValueAsStringID(long val) {
617        this.setNextValueAsObjectID(val);
618    }
619
620    /**
621     * Gets the next value of the data of the Packet as StringID VM-sensitive
622     * value. If length is less than 8 bytes, the appropriate high bits in the
623     * returned value can be ignored.
624     *
625     * @return the next value of the data of the Packet as VM-sensitive value.
626     */
627    public long getNextValueAsStringID() {
628        return this.getNextValueAsObjectID();
629    }
630
631    /**
632     * Sets the next value of the data of the Packet as ClassLoaderID
633     * VM-sensitive value. If length is less than 8 bytes, the appropriate high
634     * bits in the val value will be ignored.
635     *
636     * @param val
637     *            the ClassLoaderID value.
638     */
639    public void setNextValueAsClassLoaderID(long val) {
640        this.setNextValueAsObjectID(val);
641    }
642
643    /**
644     * Gets the next value of the data of the Packet as ClassLoaderID
645     * VM-sensitive value. If length is less than 8 bytes, the appropriate high
646     * bits in the returned value can be ignored.
647     *
648     * @return the next value of the data of the Packet as VM-sensitive value.
649     */
650    public long getNextValueAsClassLoaderID() {
651        return this.getNextValueAsObjectID();
652    }
653
654    /**
655     * Sets the next value of the data of the Packet as ClassObjectID
656     * VM-sensitive value. If length is less than 8 bytes, the appropriate high
657     * bits in the val value will be ignored.
658     *
659     * @param val
660     *            the ClassObjectID value.
661     */
662    public void setNextValueAsClassObjectID(long val) {
663        this.setNextValueAsObjectID(val);
664    }
665
666    /**
667     * Gets the next value of the data of the Packet as ClassObjectID
668     * VM-sensitive value. If length is less than 8 bytes, the appropriate high
669     * bits in the returned value can be ignored.
670     *
671     * @return the next value of the data of the Packet as VM-sensitive value.
672     */
673    public long getNextValueAsClassObjectID() {
674        return this.getNextValueAsObjectID();
675    }
676
677    /**
678     * Sets the next value of the data of the Packet as ArrayID VM-sensitive
679     * value. If length is less than 8 bytes, the appropriate high bits in the
680     * val value will be ignored.
681     *
682     * @param val
683     *            the ArrayID value.
684     */
685    public void setNextValueAsArrayID(long val) {
686        this.setNextValueAsObjectID(val);
687    }
688
689    /**
690     * Gets the next value of the data of the Packet as ArrayID VM-sensitive
691     * value. If length is less than 8 bytes, the appropriate high bits in the
692     * returned value can be ignored.
693     *
694     * @return the next value of the data of the Packet as VM-sensitive value.
695     */
696    public long getNextValueAsClassArrayID() {
697        return this.getNextValueAsObjectID();
698    }
699
700    /**
701     * Sets the next value of the data of the Packet as ReferenceTypeID
702     * VM-sensitive value. If length is less than 8 bytes, the appropriate high
703     * bits in the val value will be ignored.
704     *
705     * @param val
706     *            the ReferenceTypeID value.
707     */
708    public void setNextValueAsReferenceTypeID(long val) {
709        this.setNextValueAsObjectID(val);
710    }
711
712    /**
713     * Gets the next value of the data of the Packet as ReferenceTypeID
714     * VM-sensitive value. If length is less than 8 bytes, the appropriate high
715     * bits in the returned value can be ignored.
716     *
717     * @return the next value of the data of the Packet as VM-sensitive value.
718     */
719    public long getNextValueAsReferenceTypeID() {
720        return this.getNextValueAsObjectID();
721    }
722
723    /**
724     * Sets the next value of the data of the Packet as ClassID VM-sensitive
725     * value. If length is less than 8 bytes, the appropriate high bits in the
726     * val value will be ignored.
727     *
728     * @param val
729     *            the ClassID value.
730     */
731    public void setNextValueAsClassID(long val) {
732        this.setNextValueAsObjectID(val);
733    }
734
735    /**
736     * Gets the next value of the data of the Packet as ClassID VM-sensitive
737     * value. If length is less than 8 bytes, the appropriate high bits in the
738     * returned value can be ignored.
739     *
740     * @return the next value of the data of the Packet as VM-sensitive value.
741     */
742    public long getNextValueAsClassID() {
743        return this.getNextValueAsObjectID();
744    }
745
746    /**
747     * Sets the next value of the data of the Packet as InterfaceID VM-sensitive
748     * value. If length is less than 8 bytes, the appropriate high bits in the
749     * val value will be ignored.
750     *
751     * @param val
752     *            the InterfaceID value.
753     */
754    public void setNextValueAsInterfaceID(long val) {
755        this.setNextValueAsObjectID(val);
756    }
757
758    /**
759     * Gets the next value of the data of the Packet as InterfaceID VM-sensitive
760     * value. If length is less than 8 bytes, the appropriate high bits in the
761     * returned value can be ignored.
762     *
763     * @return the next value of the data of the Packet as VM-sensitive value.
764     */
765    public long getNextValueAsInterfaceID() {
766        return this.getNextValueAsObjectID();
767    }
768
769    /**
770     * Sets the next value of the data of the Packet as ArrayTypeID VM-sensitive
771     * value. If length is less than 8 bytes, the appropriate high bits in the
772     * val value will be ignored.
773     *
774     * @param val
775     *            the ArrayTypeID value.
776     */
777    public void setNextValueAsArrayTypeID(long val) {
778        this.setNextValueAsObjectID(val);
779    }
780
781    /**
782     * Gets the next value of the data of the Packet as ArrayTypeID VM-sensitive
783     * value. If length is less than 8 bytes, the appropriate high bits in the
784     * returned value can be ignored.
785     *
786     * @return the next value of the data of the Packet as VM-sensitive value.
787     */
788    public long getNextValueAsArrayTypeID() {
789        return this.getNextValueAsObjectID();
790    }
791
792    /**
793     * Sets the next value of the data of the Packet as tagged-objectID
794     * VM-sensitive value. If length is less than 8 bytes, the appropriate high
795     * bits in the val value will be ignored.
796     *
797     * @param taggedObject
798     *            TaggedObject value.
799     */
800    public void setNextValueAsTaggedObject(TaggedObject taggedObject) {
801        this.setNextValueAsByte(taggedObject.tag);
802        this.setNextValueAsObjectID(taggedObject.objectID);
803    }
804
805    /**
806     * Gets the next value of the data of the Packet as tagged-objectID
807     * VM-sensitive value. If length is less than 8 bytes, the appropriate high
808     * bits in the returned value can be ignored.
809     *
810     * @return the next value of the data of the Packet as VM-sensitive value.
811     */
812    public TaggedObject getNextValueAsTaggedObject() {
813        if (TypesLengths.getTypeLength(TypesLengths.OBJECT_ID) < 0
814                || TypesLengths.getTypeLength(TypesLengths.OBJECT_ID) > 8) {
815            throw new TestErrorException("Improper ObjectID value length = "
816                    + TypesLengths.getTypeLength(TypesLengths.OBJECT_ID));
817        }
818        TaggedObject taggedObject = new TaggedObject();
819        taggedObject.tag = this.getNextValueAsByte();
820        taggedObject.objectID = this.getNextValueAsObjectID();
821        return taggedObject;
822    }
823
824    /**
825     * Sets the next value of the data of the Packet as MethodID VM-sensitive
826     * value. If length is less than 8 bytes, the appropriate high bits in the
827     * val value will be ignored.
828     *
829     * @param methodID
830     *            MethodID value.
831     */
832    public void setNextValueAsMethodID(long methodID) {
833        if (TypesLengths.getTypeLength(TypesLengths.METHOD_ID) < 0
834                || TypesLengths.getTypeLength(TypesLengths.METHOD_ID) > 8) {
835            throw new TestErrorException("Improper MethodID value length = "
836                    + TypesLengths.getTypeLength(TypesLengths.METHOD_ID));
837        }
838        int new_data_size = data.length
839                + TypesLengths.getTypeLength(TypesLengths.METHOD_ID);
840        byte data_temp[] = data;
841        data = new byte[new_data_size];
842        System.arraycopy(data_temp, 0, data, 0, new_data_size
843                - TypesLengths.getTypeLength(TypesLengths.METHOD_ID));
844        this.writeAtByteArray(methodID, data, new_data_size
845                - TypesLengths.getTypeLength(TypesLengths.METHOD_ID),
846                TypesLengths.getTypeLength(TypesLengths.METHOD_ID));
847    }
848
849    /**
850     * Gets the next value of the data of the Packet as MethodID VM-sensitive
851     * value. If length is less than 8 bytes, the appropriate high bits in the
852     * returned value can be ignored.
853     *
854     * @return the next value of the data of the Packet as VM-sensitive value.
855     */
856    public long getNextValueAsMethodID() {
857        if (TypesLengths.getTypeLength(TypesLengths.METHOD_ID) < 0
858                || TypesLengths.getTypeLength(TypesLengths.METHOD_ID) > 8) {
859            throw new TestErrorException("Improper MethodID value length = "
860                    + TypesLengths.getTypeLength(TypesLengths.METHOD_ID));
861        }
862        reading_data_index = reading_data_index
863                + TypesLengths.getTypeLength(TypesLengths.METHOD_ID);
864        long result = readFromByteArray(data, reading_data_index
865                - TypesLengths.getTypeLength(TypesLengths.METHOD_ID),
866                TypesLengths.getTypeLength(TypesLengths.METHOD_ID));
867        return result;
868    }
869
870    /**
871     * Sets the next value of the data of the Packet as FieldID VM-sensitive
872     * value. If length is less than 8 bytes, the appropriate high bits in the
873     * val value will be ignored.
874     *
875     * @param fieldID
876     *            FieldID value.
877     */
878    public void setNextValueAsFieldID(long fieldID) {
879        if (TypesLengths.getTypeLength(TypesLengths.FIELD_ID) < 0
880                || TypesLengths.getTypeLength(TypesLengths.FIELD_ID) > 8) {
881            throw new TestErrorException("Improper FieldID value length = "
882                    + TypesLengths.getTypeLength(TypesLengths.FIELD_ID));
883        }
884        int new_data_size = data.length
885                + TypesLengths.getTypeLength(TypesLengths.FIELD_ID);
886        byte data_temp[] = data;
887        data = new byte[new_data_size];
888        System.arraycopy(data_temp, 0, data, 0, new_data_size
889                - TypesLengths.getTypeLength(TypesLengths.FIELD_ID));
890        this.writeAtByteArray(fieldID, data, new_data_size
891                - TypesLengths.getTypeLength(TypesLengths.FIELD_ID),
892                TypesLengths.getTypeLength(TypesLengths.FIELD_ID));
893    }
894
895    /**
896     * Gets the next value of the data of the Packet as FieldID VM-sensitive
897     * value. If length is less than 8 bytes, the appropriate high bits in the
898     * returned value can be ignored.
899     *
900     * @return the next value of the data of the Packet as VM-sensitive value.
901     */
902    public long getNextValueAsFieldID() {
903        if (TypesLengths.getTypeLength(TypesLengths.FIELD_ID) < 0
904                || TypesLengths.getTypeLength(TypesLengths.FIELD_ID) > 8) {
905            throw new TestErrorException("Improper FieldID value length = "
906                    + TypesLengths.getTypeLength(TypesLengths.FIELD_ID));
907        }
908        reading_data_index = reading_data_index
909                + TypesLengths.getTypeLength(TypesLengths.FIELD_ID);
910        long result = readFromByteArray(data, reading_data_index
911                - TypesLengths.getTypeLength(TypesLengths.FIELD_ID),
912                TypesLengths.getTypeLength(TypesLengths.FIELD_ID));
913        return result;
914    }
915
916    /**
917     * Sets the next value of the data of the Packet as FrameID VM-sensitive
918     * value. If length is less than 8 bytes, the appropriate high bits in the
919     * val value will be ignored.
920     *
921     * @param frameID
922     *            FrameID value.
923     */
924    public void setNextValueAsFrameID(long frameID) {
925        if (TypesLengths.getTypeLength(TypesLengths.FRAME_ID) < 0
926                || TypesLengths.getTypeLength(TypesLengths.FRAME_ID) > 8) {
927            throw new TestErrorException("Improper FrameID value length = "
928                    + TypesLengths.getTypeLength(TypesLengths.FRAME_ID));
929        }
930        int new_data_size = data.length
931                + TypesLengths.getTypeLength(TypesLengths.FRAME_ID);
932        byte data_temp[] = data;
933        data = new byte[new_data_size];
934        System.arraycopy(data_temp, 0, data, 0, new_data_size
935                - TypesLengths.getTypeLength(TypesLengths.FRAME_ID));
936        this.writeAtByteArray(frameID, data, new_data_size
937                - TypesLengths.getTypeLength(TypesLengths.FRAME_ID),
938                TypesLengths.getTypeLength(TypesLengths.FRAME_ID));
939    }
940
941    /**
942     * Gets the next value of the data of the Packet as FrameID VM-sensitive
943     * value. If length is less than 8 bytes, the appropriate high bits in the
944     * returned value can be ignored.
945     *
946     * @return the next value of the data of the Packet as VM-sensitive value.
947     */
948    public long getNextValueAsFrameID() {
949        if (TypesLengths.getTypeLength(TypesLengths.FRAME_ID) < 0
950                || TypesLengths.getTypeLength(TypesLengths.FRAME_ID) > 8) {
951            throw new TestErrorException("Improper FrameID value length = "
952                    + TypesLengths.getTypeLength(TypesLengths.FRAME_ID));
953        }
954        reading_data_index = reading_data_index
955                + TypesLengths.getTypeLength(TypesLengths.FRAME_ID);
956        long result = readFromByteArray(data, reading_data_index
957                - TypesLengths.getTypeLength(TypesLengths.FRAME_ID),
958                TypesLengths.getTypeLength(TypesLengths.FRAME_ID));
959        return result;
960    }
961
962    /**
963     * Sets the next value of the data of the Packet as Location VM-sensitive
964     * value. If length is less than 8 bytes, the appropriate high bits in the
965     * val value will be ignored.
966     *
967     * @param location
968     *            Location value.
969     */
970    public void setNextValueAsLocation(Location location) {
971        this.setNextValueAsByte(location.tag);
972        this.setNextValueAsClassID(location.classID);
973        this.setNextValueAsMethodID(location.methodID);
974        this.setNextValueAsLong(location.index);
975    }
976
977    /**
978     * Gets the next value of the data of the Packet as Location VM-sensitive
979     * value. If length is less than 8 bytes, the appropriate high bits in the
980     * returned value can be ignored.
981     *
982     * @return the next value of the data of the Packet as VM-sensitive value.
983     */
984    public Location getNextValueAsLocation() {
985        Location location = new Location();
986        location.tag = this.getNextValueAsByte();
987        location.classID = this.getNextValueAsClassID();
988        location.methodID = this.getNextValueAsMethodID();
989        location.index = this.getNextValueAsLong();
990        return location;
991    }
992
993    /**
994     * Sets the next value of the data of the Packet as Value VM-sensitive
995     * value. If length is less than 8 bytes, the appropriate high bits in the
996     * val value will be ignored.
997     *
998     * @param value
999     *            Value value.
1000     * @throws UnsupportedEncodingException
1001     */
1002    public void setNextValueAsValue(Value value) {
1003        this.setNextValueAsByte(value.getTag());
1004        setNextValueAsUntaggedValue(value);
1005    }
1006
1007    /**
1008     * Gets the next value of the data of the Packet as Value VM-sensitive
1009     * value. If length is less than 8 bytes, the appropriate high bits in the
1010     * returned value can be ignored.
1011     *
1012     * @return the next value of the data of the Packet as VM-sensitive value.
1013     */
1014    public Value getNextValueAsValue() {
1015        byte tag = this.getNextValueAsByte();
1016        return getNextValueAsUntaggedValue(tag);
1017    }
1018
1019    /**
1020     * Sets the next value of the data of the Packet as UntaggedValue
1021     * VM-sensitive value. If length is less than 8 bytes, the appropriate high
1022     * bits in the val value will be ignored.
1023     *
1024     * @param value
1025     *            UntaggedValue value.
1026     * @throws UnsupportedEncodingException
1027     */
1028    public void setNextValueAsUntaggedValue(Value value) {
1029        switch (value.getTag()) {
1030        case JDWPConstants.Tag.BOOLEAN_TAG:
1031            this.setNextValueAsBoolean(value.getBooleanValue());
1032            break;
1033        case JDWPConstants.Tag.BYTE_TAG:
1034            this.setNextValueAsByte(value.getByteValue());
1035            break;
1036        case JDWPConstants.Tag.CHAR_TAG:
1037            this.setNextValueAsChar(value.getCharValue());
1038            break;
1039        case JDWPConstants.Tag.DOUBLE_TAG:
1040            this.setNextValueAsDouble(value.getDoubleValue());
1041            break;
1042        case JDWPConstants.Tag.FLOAT_TAG:
1043            this.setNextValueAsFloat(value.getFloatValue());
1044            break;
1045        case JDWPConstants.Tag.INT_TAG:
1046            this.setNextValueAsInt(value.getIntValue());
1047            break;
1048        case JDWPConstants.Tag.LONG_TAG:
1049            this.setNextValueAsLong(value.getLongValue());
1050            break;
1051        case JDWPConstants.Tag.SHORT_TAG:
1052            this.setNextValueAsShort(value.getShortValue());
1053            break;
1054        case JDWPConstants.Tag.VOID_TAG:
1055            break;
1056        case JDWPConstants.Tag.STRING_TAG:
1057        case JDWPConstants.Tag.ARRAY_TAG:
1058        case JDWPConstants.Tag.CLASS_LOADER_TAG:
1059        case JDWPConstants.Tag.CLASS_OBJECT_TAG:
1060        case JDWPConstants.Tag.OBJECT_TAG:
1061        case JDWPConstants.Tag.THREAD_GROUP_TAG:
1062        case JDWPConstants.Tag.THREAD_TAG:
1063            this.setNextValueAsObjectID(value.getLongValue());
1064            break;
1065        default:
1066            throw new TestErrorException("Illegal tag value = "
1067                    + value.getTag());
1068        }
1069    }
1070
1071    /**
1072     * Gets the next value of the data of the Packet as UntaggedValue
1073     * VM-sensitive value. If length is less than 8 bytes, the appropriate high
1074     * bits in the returned value can be ignored.
1075     *
1076     * @return the next value of the data of the Packet as VM-sensitive value.
1077     */
1078    public Value getNextValueAsUntaggedValue(byte tag) {
1079        Value value = null;
1080        switch (tag) {
1081        case JDWPConstants.Tag.BOOLEAN_TAG:
1082            value = new Value(this.getNextValueAsBoolean());
1083            break;
1084        case JDWPConstants.Tag.BYTE_TAG:
1085            value = new Value(this.getNextValueAsByte());
1086            break;
1087        case JDWPConstants.Tag.CHAR_TAG:
1088            value = new Value(this.getNextValueAsChar());
1089            break;
1090        case JDWPConstants.Tag.DOUBLE_TAG:
1091            value = new Value(this.getNextValueAsDouble());
1092            break;
1093        case JDWPConstants.Tag.FLOAT_TAG:
1094            value = new Value(this.getNextValueAsFloat());
1095            break;
1096        case JDWPConstants.Tag.INT_TAG:
1097            value = new Value(this.getNextValueAsInt());
1098            break;
1099        case JDWPConstants.Tag.LONG_TAG:
1100            value = new Value(this.getNextValueAsLong());
1101            break;
1102        case JDWPConstants.Tag.SHORT_TAG:
1103            value = new Value(this.getNextValueAsShort());
1104            break;
1105        case JDWPConstants.Tag.STRING_TAG:
1106        case JDWPConstants.Tag.ARRAY_TAG:
1107        case JDWPConstants.Tag.CLASS_LOADER_TAG:
1108        case JDWPConstants.Tag.CLASS_OBJECT_TAG:
1109        case JDWPConstants.Tag.OBJECT_TAG:
1110        case JDWPConstants.Tag.THREAD_GROUP_TAG:
1111        case JDWPConstants.Tag.THREAD_TAG:
1112            value = new Value(tag, this.getNextValueAsObjectID());
1113            break;
1114        case JDWPConstants.Tag.VOID_TAG:
1115            // no bytes to read.
1116            break;
1117        default:
1118            throw new TestErrorException("Illegal tag value = " + tag);
1119        }
1120        return value;
1121    }
1122
1123    /**
1124     * Sets the next value of the data of the Packet as ArrayRegion VM-sensitive
1125     * value. If length is less than 8 bytes, the appropriate high bits in the
1126     * val value will be ignored.
1127     *
1128     * @param array
1129     *            ArrayRegion value.
1130     * @throws UnsupportedEncodingException
1131     */
1132    // public void setNextValueAsArrayRegion(ArrayRegion array) throws
1133    // UnsupportedEncodingException {
1134    public void setNextValueAsArrayRegion(ArrayRegion array) {
1135        this.setNextValueAsByte(array.getTag());
1136        this.setNextValueAsInt(array.getLength());
1137        for (int i = 0; i < array.getLength(); i++) {
1138            if (isValuePrimitiveType(array.getTag())) {
1139                switch (array.getTag()) {
1140                case JDWPConstants.Tag.BOOLEAN_TAG:
1141                    this.setNextValueAsBoolean(array.getValue(i)
1142                            .getBooleanValue());
1143                    break;
1144                case JDWPConstants.Tag.BYTE_TAG:
1145                    this.setNextValueAsByte(array.getValue(i).getByteValue());
1146                    break;
1147                case JDWPConstants.Tag.DOUBLE_TAG:
1148                    this.setNextValueAsDouble(array.getValue(i)
1149                            .getDoubleValue());
1150                    break;
1151                case JDWPConstants.Tag.FLOAT_TAG:
1152                    this.setNextValueAsFloat(array.getValue(i).getFloatValue());
1153                    break;
1154                case JDWPConstants.Tag.INT_TAG:
1155                    this.setNextValueAsInt(array.getValue(i).getIntValue());
1156                    break;
1157                case JDWPConstants.Tag.LONG_TAG:
1158                    this.setNextValueAsLong(array.getValue(i).getLongValue());
1159                    break;
1160                case JDWPConstants.Tag.SHORT_TAG:
1161                    this.setNextValueAsShort(array.getValue(i).getShortValue());
1162                    break;
1163                default:
1164                    throw new TestErrorException("Illegal tag value = "
1165                            + array.getTag());
1166                }
1167            } else {
1168                this.setNextValueAsValue(array.getValue(i));
1169            }
1170        }
1171    }
1172
1173    /**
1174     * Gets the next value of the data of the Packet as ArrayRegion VM-sensitive
1175     * value. If length is less than 8 bytes, the appropriate high bits in the
1176     * returned value can be ignored.
1177     *
1178     * @return the next value of the data of the Packet as VM-sensitive value.
1179     */
1180    public ArrayRegion getNextValueAsArrayRegion() {
1181        byte array_tag = this.getNextValueAsByte();
1182        int array_length = this.getNextValueAsInt();
1183
1184        ArrayRegion array = new ArrayRegion(array_tag, array_length);
1185
1186        for (int i = 0; i < array_length; i++) {
1187            if (isValuePrimitiveType(array_tag))
1188                array.setValue(i, this.getNextValueAsUntaggedValue(array_tag));
1189            else
1190                array.setValue(i, this.getNextValueAsValue());
1191        }
1192        return array;
1193    }
1194
1195    /**
1196     * Gets the representation of the Packet as array of bytes in the JDWP
1197     * format including header and data sections.
1198     *
1199     * @return bytes representation of this packet
1200     */
1201    public byte[] toBytesArray() {
1202        byte res[] = new byte[data.length + HEADER_SIZE];
1203        writeAtByteArray(data.length + HEADER_SIZE, res, LENGTH_INDEX, INT_SIZE);
1204        writeAtByteArray(id, res, ID_INDEX, INT_SIZE);
1205        res[FLAGS_INDEX] = flags;
1206        System.arraycopy(data, 0, res, HEADER_SIZE, data.length);
1207        return res;
1208    }
1209
1210    /**
1211     * Reads value from array of bytes ar[] starting form index and reading size
1212     * bytes. If size is less than 8, the appropriate high bits in the resulting
1213     * long value will be zero.
1214     *
1215     * @param ar
1216     *            the array of bytes where the value is read from.
1217     * @param from
1218     *            index to start reading bytes.
1219     * @param size
1220     *            number of bytes to read
1221     */
1222    protected static long readFromByteArray(byte ar[], int from, int size) {
1223        long res = 0;
1224        byte temp;
1225        for (int i = 0; i < size; i++) {
1226            temp = ar[from + i];
1227            res = (res << 8) | (((long) temp) & 0xFF);
1228        }
1229        return res;
1230    }
1231
1232    /**
1233     * Tells whether the packet is reply.
1234     *
1235     * @return true if this packet is reply, false if it is command
1236     */
1237    public boolean isReply() {
1238        return (flags & REPLY_PACKET_FLAG) != 0;
1239    }
1240
1241    /**
1242     * Checks whether all data has been read from the packet.
1243     *
1244     * @return boolean
1245     */
1246    public boolean isAllDataRead() {
1247        return reading_data_index == data.length;
1248    }
1249
1250    /**
1251     * Writes value - val to the array of bytes ar[], beginning from index - to,
1252     * size of value is - size bytes. If size is less than 8, the appropriate
1253     * high bits in the val value will be ignored.
1254     *
1255     * @param val
1256     *            the value, which will be written in the array.
1257     * @param ar
1258     *            the array of bytes where the value is read from.
1259     * @param to
1260     *            the beginning index in the array of bytes.
1261     * @param size
1262     *            size of value in bytes.
1263     */
1264    protected void writeAtByteArray(long val, byte ar[], int to, int size) {
1265        for (int i = 0; i < size; i++) {
1266            ar[to + i] = (byte) (val >> 8 * (size - 1 - i));
1267        }
1268    }
1269
1270    /**
1271     * Returns true if this bytes array can be interpreted as reply packet.
1272     *
1273     * @param p
1274     *            bytes representation of packet
1275     * @return true or false
1276     */
1277    public static boolean isReply(byte[] p) {
1278        if (p.length < FLAGS_INDEX)
1279            return false;
1280        return (p[FLAGS_INDEX] & REPLY_PACKET_FLAG) != 0;
1281    }
1282
1283    /**
1284     * Returns packet length from header of given packet bytes.
1285     *
1286     * @param p
1287     *            bytes representation of packet
1288     * @return true or false
1289     */
1290    public static int getPacketLength(byte[] p) {
1291        return (int) readFromByteArray(p, LENGTH_INDEX, INT_SIZE);
1292    }
1293
1294    /**
1295     * Enwraps this bytes array either to ReplyPacket or EventPacket instance,
1296     * according to result of isReply().
1297     *
1298     * @param p
1299     *            bytes array to enwrap into packet
1300     * @return new created ReplyPacket or CommandPacket
1301     */
1302    public static Packet interpretPacket(byte[] p) {
1303        if (p.length < HEADER_SIZE)
1304            throw new TestErrorException("Wrong packet");
1305        if (Packet.isReply(p))
1306            return new ReplyPacket(p);
1307        return new EventPacket(p);
1308    }
1309}
1310