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 Anton V. Karnachuk
21 */
22
23/**
24 * Created on 17.03.2005
25 */
26package org.apache.harmony.jpda.tests.framework.jdwp;
27
28import org.apache.harmony.jpda.tests.framework.TestErrorException;
29
30/**
31 * This class represent parsed EventPacket with received event set data.
32 */
33public class ParsedEvent {
34
35    private byte suspendPolicy;
36
37    private int requestID;
38
39    private byte eventKind;
40
41    /**
42     * Create new instance with specified data.
43     */
44    protected ParsedEvent(byte suspendPolicy, Packet packet, byte eventKind) {
45        this.suspendPolicy = suspendPolicy;
46        this.requestID = packet.getNextValueAsInt();
47        this.eventKind = eventKind;
48    }
49
50    /**
51     * Returns RequestID of this event set.
52     *
53     * @return RequestID of this event set
54     */
55    public int getRequestID() {
56        return requestID;
57    }
58
59    /**
60     * Returns suspend policy of this event set.
61     *
62     * @return suspend policy of this event set
63     */
64    public byte getSuspendPolicy() {
65        return suspendPolicy;
66    }
67
68    /**
69     * @return Returns the eventKind.
70     */
71    public byte getEventKind() {
72        return eventKind;
73    }
74
75    /**
76     * The class extends ParsedEvent by associating it with a thread.
77     */
78    public static class EventThread extends ParsedEvent {
79
80        private long threadID;
81
82        /**
83         * A constructor.
84         *
85         * @param suspendPolicy
86         * @param packet
87         */
88        protected EventThread(byte suspendPolicy, Packet packet, byte eventKind) {
89            super(suspendPolicy, packet, eventKind);
90            this.threadID = packet.getNextValueAsThreadID();
91        }
92
93        /**
94         * @return Returns the thread id.
95         */
96        public long getThreadID() {
97            return threadID;
98        }
99    }
100
101    /**
102     * The class extends EventThread by associating it with a location.
103     */
104    public static class EventThreadLocation extends EventThread {
105
106        private Location location;
107
108        /**
109         * A constructor.
110         *
111         * @param suspendPolicy
112         * @param packet
113         */
114        protected EventThreadLocation(byte suspendPolicy, Packet packet,
115                byte eventKind) {
116            super(suspendPolicy, packet, eventKind);
117            this.location = packet.getNextValueAsLocation();
118        }
119
120        /**
121         * @return Returns the location.
122         */
123        public Location getLocation() {
124            return location;
125        }
126    }
127
128    /**
129     * The class extends EventThread by associating it with monitor object and location.
130     */
131    private static class EventThreadMonitor extends EventThread {
132
133        private TaggedObject taggedObject;
134        private Location location;
135
136        /**
137         * A constructor.
138         *
139         * @param suspendPolicy
140         * @param packet
141         */
142        protected EventThreadMonitor(byte suspendPolicy, Packet packet,
143                byte eventKind) {
144            super(suspendPolicy, packet, eventKind);
145            this.taggedObject = packet.getNextValueAsTaggedObject();
146            this.location = packet.getNextValueAsLocation();
147        }
148
149        /**
150         * @return Returns the location.
151         */
152        public Location getLocation() {
153            return location;
154        }
155
156        /**
157         * @return Returns the taggedObject.
158         */
159        public TaggedObject getTaggedObject() {
160            return taggedObject;
161        }
162    }
163
164    /**
165     * The class implements JDWP VM_START event.
166     */
167    public static final class Event_VM_START extends EventThread {
168
169        /**
170         * A constructor.
171         *
172         * @param suspendPolicy
173         * @param packet
174         */
175        private Event_VM_START(byte suspendPolicy, Packet packet) {
176            super(suspendPolicy, packet, JDWPConstants.EventKind.VM_START);
177        }
178    }
179
180    /**
181     * The class implements JDWP SINGLE_STEP event.
182     */
183    public static final class Event_SINGLE_STEP extends EventThreadLocation {
184
185        /**
186         * A constructor.
187         *
188         * @param suspendPolicy
189         * @param packet
190         */
191        private Event_SINGLE_STEP(byte suspendPolicy, Packet packet) {
192            super(suspendPolicy, packet, JDWPConstants.EventKind.SINGLE_STEP);
193        }
194    }
195
196    /**
197     * The class implements JDWP BREAKPOINT event.
198     */
199    public static final class Event_BREAKPOINT extends EventThreadLocation {
200
201        /**
202         * A constructor.
203         *
204         * @param suspendPolicy
205         * @param packet
206         */
207        private Event_BREAKPOINT(byte suspendPolicy, Packet packet) {
208            super(suspendPolicy, packet, JDWPConstants.EventKind.BREAKPOINT);
209        }
210    }
211
212    /**
213     * The class implements JDWP METHOD_ENTRY event.
214     */
215    public static final class Event_METHOD_ENTRY extends EventThreadLocation {
216
217        /**
218         * A constructor.
219         *
220         * @param suspendPolicy
221         * @param packet
222         */
223        private Event_METHOD_ENTRY(byte suspendPolicy, Packet packet) {
224            super(suspendPolicy, packet, JDWPConstants.EventKind.METHOD_ENTRY);
225        }
226    }
227
228    /**
229     * The class implements JDWP METHOD_EXIT event.
230     */
231    public static final class Event_METHOD_EXIT extends EventThreadLocation {
232
233        /**
234         * A constructor.
235         *
236         * @param suspendPolicy
237         * @param packet
238         */
239        private Event_METHOD_EXIT(byte suspendPolicy, Packet packet) {
240            super(suspendPolicy, packet, JDWPConstants.EventKind.METHOD_EXIT);
241        }
242    }
243
244    /**
245     * The class implements JDWP METHOD_EXIT_WITH_RETURN_VALUE event.
246     */
247    public static final class Event_METHOD_EXIT_WITH_RETURN_VALUE extends EventThreadLocation {
248
249        private Value returnValue;
250
251        /**
252         * A constructor.
253         *
254         * @param suspendPolicy
255         * @param packet
256         */
257        private Event_METHOD_EXIT_WITH_RETURN_VALUE(byte suspendPolicy, Packet packet) {
258            super(suspendPolicy, packet, JDWPConstants.EventKind.METHOD_EXIT_WITH_RETURN_VALUE);
259            returnValue = packet.getNextValueAsValue();
260        }
261
262        public Value getReturnValue(){
263			return returnValue;
264        }
265    }
266
267    /**
268     * The class implements JDWP MONITOR_CONTENDED_ENTER event.
269     */
270    public static final class Event_MONITOR_CONTENDED_ENTER extends EventThreadMonitor {
271
272        /**
273         * A constructor.
274         *
275         * @param suspendPolicy
276         * @param packet
277         */
278        private Event_MONITOR_CONTENDED_ENTER(byte suspendPolicy, Packet packet) {
279            super(suspendPolicy, packet, JDWPConstants.EventKind.MONITOR_CONTENDED_ENTER);
280        }
281
282    }
283
284    /**
285     * The class implements JDWP MONITOR_CONTENDED_ENTERED event.
286     */
287    public static final class Event_MONITOR_CONTENDED_ENTERED extends EventThreadMonitor {
288
289        /**
290         * A constructor.
291         *
292         * @param suspendPolicy
293         * @param packet
294         */
295        private Event_MONITOR_CONTENDED_ENTERED(byte suspendPolicy, Packet packet) {
296            super(suspendPolicy, packet, JDWPConstants.EventKind.MONITOR_CONTENDED_ENTERED);
297        }
298
299    }
300
301    /**
302     * The class implements JDWP METHOD_EXIT_WITH_RETURN_VALUE event.
303     */
304    public static final class Event_MONITOR_WAIT extends EventThreadMonitor {
305
306        private long timeout;
307
308        /**
309         * A constructor.
310         *
311         * @param suspendPolicy
312         * @param packet
313         */
314        private Event_MONITOR_WAIT(byte suspendPolicy, Packet packet) {
315            super(suspendPolicy, packet, JDWPConstants.EventKind.MONITOR_WAIT);
316            this.timeout = packet.getNextValueAsLong();
317        }
318
319        public long getTimeout(){
320            return timeout;
321        }
322    }
323
324    /**
325     * The class implements JDWP METHOD_EXIT_WITH_RETURN_VALUE event.
326     */
327    public static final class Event_MONITOR_WAITED extends EventThreadMonitor {
328
329        private boolean timed_out;
330
331        /**
332         * A constructor.
333         *
334         * @param suspendPolicy
335         * @param packet
336         */
337        private Event_MONITOR_WAITED(byte suspendPolicy, Packet packet) {
338            super(suspendPolicy, packet, JDWPConstants.EventKind.MONITOR_WAITED);
339            this.timed_out = packet.getNextValueAsBoolean();
340        }
341
342        public boolean getTimedout(){
343            return timed_out;
344        }
345    }
346
347    /**
348     * The class implements JDWP EXCEPTION event.
349     */
350    public static final class Event_EXCEPTION extends EventThreadLocation {
351
352        private TaggedObject exception;
353
354        private Location catchLocation;
355
356        /**
357         * A constructor.
358         *
359         * @param suspendPolicy
360         * @param packet
361         */
362        private Event_EXCEPTION(byte suspendPolicy, Packet packet) {
363            super(suspendPolicy, packet, JDWPConstants.EventKind.EXCEPTION);
364            exception = packet.getNextValueAsTaggedObject();
365            catchLocation = packet.getNextValueAsLocation();
366        }
367
368        /**
369         * @return Returns the location of the caught exception.
370         */
371        public Location getCatchLocation() {
372            return catchLocation;
373        }
374
375        /**
376         * @return Returns the exception.
377         */
378        public TaggedObject getException() {
379            return exception;
380        }
381    }
382
383    /**
384     * The class implements JDWP THREAD_START event.
385     */
386    public static final class Event_THREAD_START extends EventThread {
387
388        /**
389         * A constructor.
390         *
391         * @param suspendPolicy
392         * @param packet
393         */
394        private Event_THREAD_START(byte suspendPolicy, Packet packet) {
395            super(suspendPolicy, packet, JDWPConstants.EventKind.THREAD_START);
396        }
397    }
398
399    /**
400     * The class implements JDWP THREAD_DEATH event.
401     */
402    public static final class Event_THREAD_DEATH extends EventThread {
403
404        /**
405         * A constructor.
406         *
407         * @param suspendPolicy
408         * @param packet
409         */
410        private Event_THREAD_DEATH(byte suspendPolicy, Packet packet) {
411            super(suspendPolicy, packet, JDWPConstants.EventKind.THREAD_DEATH);
412        }
413    }
414
415    /**
416     * The class implements JDWP CLASS_PREPARE event.
417     */
418    public static final class Event_CLASS_PREPARE extends EventThread {
419
420        private byte refTypeTag;
421
422        private long typeID;
423
424        private String signature;
425
426        private int status;
427
428        /**
429         * A constructor.
430         *
431         * @param suspendPolicy
432         * @param packet
433         */
434        protected Event_CLASS_PREPARE(byte suspendPolicy, Packet packet) {
435            super(suspendPolicy, packet, JDWPConstants.EventKind.CLASS_PREPARE);
436            refTypeTag = packet.getNextValueAsByte();
437            typeID = packet.getNextValueAsReferenceTypeID();
438            signature = packet.getNextValueAsString();
439            status = packet.getNextValueAsInt();
440        }
441
442        /**
443         * @return Returns the refTypeTag.
444         */
445        public byte getRefTypeTag() {
446            return refTypeTag;
447        }
448
449        /**
450         * @return Returns the signature.
451         */
452        public String getSignature() {
453            return signature;
454        }
455
456        /**
457         * @return Returns the status.
458         */
459        public int getStatus() {
460            return status;
461        }
462
463        /**
464         * @return Returns the typeID.
465         */
466        public long getTypeID() {
467            return typeID;
468        }
469    }
470
471    /**
472     * The class implements JDWP CLASS_UNLOAD event.
473     */
474    public static final class Event_CLASS_UNLOAD extends ParsedEvent {
475
476        private String signature;
477
478        /**
479         * A constructor.
480         *
481         * @param suspendPolicy
482         * @param packet
483         */
484        private Event_CLASS_UNLOAD(byte suspendPolicy, Packet packet) {
485            super(suspendPolicy, packet, JDWPConstants.EventKind.CLASS_UNLOAD);
486            signature = packet.getNextValueAsString();
487        }
488
489        /**
490         * @return Returns the signature.
491         */
492        public String getSignature() {
493            return signature;
494        }
495    }
496
497    /**
498     * The class implements JDWP FIELD_ACCESS event.
499     */
500    public static final class Event_FIELD_ACCESS extends EventThreadLocation {
501
502        private byte refTypeTag;
503
504        private long typeID;
505
506        private long fieldID;
507
508        private TaggedObject object;
509
510        /**
511         * A constructor.
512         *
513         * @param suspendPolicy
514         * @param packet
515         */
516        private Event_FIELD_ACCESS(byte suspendPolicy, Packet packet) {
517            super(suspendPolicy, packet, JDWPConstants.EventKind.FIELD_ACCESS);
518            refTypeTag = packet.getNextValueAsByte();
519            typeID = packet.getNextValueAsReferenceTypeID();
520            fieldID = packet.getNextValueAsFieldID();
521            object = packet.getNextValueAsTaggedObject();
522        }
523
524        /**
525         * @return Returns the fieldID.
526         */
527        public long getFieldID() {
528            return fieldID;
529        }
530
531        /**
532         * @return Returns the object.
533         */
534        public TaggedObject getObject() {
535            return object;
536        }
537
538        /**
539         * @return Returns the refTypeTag.
540         */
541        public byte getRefTypeTag() {
542            return refTypeTag;
543        }
544
545        /**
546         * @return Returns the typeID.
547         */
548        public long getTypeID() {
549            return typeID;
550        }
551    }
552
553    /**
554     * The class implements JDWP FIELD_MODIFICATION event.
555     */
556    public static final class Event_FIELD_MODIFICATION extends
557            EventThreadLocation {
558        private byte refTypeTag;
559
560        private long typeID;
561
562        private long fieldID;
563
564        private TaggedObject object;
565
566        private Value valueToBe;
567
568        /**
569         * A constructor.
570         * @param suspendPolicy
571         * @param packet
572         */
573        private Event_FIELD_MODIFICATION(byte suspendPolicy, Packet packet) {
574            super(suspendPolicy, packet,
575                    JDWPConstants.EventKind.FIELD_MODIFICATION);
576            refTypeTag = packet.getNextValueAsByte();
577            typeID = packet.getNextValueAsReferenceTypeID();
578            fieldID = packet.getNextValueAsFieldID();
579            object = packet.getNextValueAsTaggedObject();
580            valueToBe = packet.getNextValueAsValue();
581        }
582
583        /**
584         * @return Returns the fieldID.
585         */
586        public long getFieldID() {
587            return fieldID;
588        }
589
590        /**
591         * @return Returns the object.
592         */
593        public TaggedObject getObject() {
594            return object;
595        }
596
597        /**
598         * @return Returns the refTypeTag.
599         */
600        public byte getRefTypeTag() {
601            return refTypeTag;
602        }
603
604        /**
605         * @return Returns the typeID.
606         */
607        public long getTypeID() {
608            return typeID;
609        }
610
611        /**
612         * @return Returns the valueToBe.
613         */
614        public Value getValueToBe() {
615            return valueToBe;
616        }
617    }
618
619    /**
620     * The class implements JDWP VM_DEATH event.
621     */
622    public static final class Event_VM_DEATH extends ParsedEvent {
623        /**
624         * A constructor.
625         * @param suspendPolicy
626         * @param packet
627         */
628        private Event_VM_DEATH(byte suspendPolicy, Packet packet) {
629            super(suspendPolicy, packet, JDWPConstants.EventKind.VM_DEATH);
630        }
631    }
632
633    /**
634     * Returns array of ParsedEvent extracted from given EventPacket.
635     *
636     * @param packet
637     *            EventPacket to parse events
638     * @return array of extracted ParsedEvents
639     */
640    public static ParsedEvent[] parseEventPacket(Packet packet) {
641
642        Packet packetCopy = new Packet(packet.toBytesArray());
643
644        // Suspend Policy field
645        byte suspendPolicy = packetCopy.getNextValueAsByte();
646
647        // Number of events
648        int eventCount = packetCopy.getNextValueAsInt();
649
650        ParsedEvent[] events = new ParsedEvent[eventCount];
651
652        // For all events in packet
653        for (int i = 0; i < eventCount; i++) {
654            byte eventKind = packetCopy.getNextValueAsByte();
655            switch (eventKind) {
656            case JDWPConstants.EventKind.VM_START: {
657                events[i] = new Event_VM_START(suspendPolicy, packetCopy);
658                break;
659            }
660            case JDWPConstants.EventKind.SINGLE_STEP: {
661                events[i] = new Event_SINGLE_STEP(suspendPolicy, packetCopy);
662                break;
663            }
664            case JDWPConstants.EventKind.BREAKPOINT: {
665                events[i] = new Event_BREAKPOINT(suspendPolicy, packetCopy);
666                break;
667            }
668            case JDWPConstants.EventKind.METHOD_ENTRY: {
669                events[i] = new Event_METHOD_ENTRY(suspendPolicy, packetCopy);
670                break;
671            }
672            case JDWPConstants.EventKind.METHOD_EXIT: {
673                events[i] = new Event_METHOD_EXIT(suspendPolicy, packetCopy);
674                break;
675            }
676            case JDWPConstants.EventKind.METHOD_EXIT_WITH_RETURN_VALUE: {
677                events[i] = new Event_METHOD_EXIT_WITH_RETURN_VALUE(suspendPolicy, packetCopy);
678                break;
679            }
680            case JDWPConstants.EventKind.MONITOR_CONTENDED_ENTER: {
681                events[i] = new Event_MONITOR_CONTENDED_ENTER(suspendPolicy, packetCopy);
682                break;
683            }
684            case JDWPConstants.EventKind.MONITOR_CONTENDED_ENTERED: {
685                events[i] = new Event_MONITOR_CONTENDED_ENTERED(suspendPolicy, packetCopy);
686                break;
687            }
688            case JDWPConstants.EventKind.MONITOR_WAIT: {
689                events[i] = new Event_MONITOR_WAIT(suspendPolicy, packetCopy);
690                break;
691            }
692            case JDWPConstants.EventKind.MONITOR_WAITED: {
693                events[i] = new Event_MONITOR_WAITED(suspendPolicy, packetCopy);
694                break;
695            }
696            case JDWPConstants.EventKind.EXCEPTION: {
697                events[i] = new Event_EXCEPTION(suspendPolicy, packetCopy);
698                break;
699            }
700            case JDWPConstants.EventKind.THREAD_START: {
701                events[i] = new Event_THREAD_START(suspendPolicy, packetCopy);
702                break;
703            }
704            case JDWPConstants.EventKind.THREAD_DEATH: {
705                events[i] = new Event_THREAD_DEATH(suspendPolicy, packetCopy);
706                break;
707            }
708            case JDWPConstants.EventKind.CLASS_PREPARE: {
709                events[i] = new Event_CLASS_PREPARE(suspendPolicy, packetCopy);
710                break;
711            }
712            case JDWPConstants.EventKind.CLASS_UNLOAD: {
713                events[i] = new Event_CLASS_UNLOAD(suspendPolicy, packetCopy);
714                break;
715            }
716            case JDWPConstants.EventKind.FIELD_ACCESS: {
717                events[i] = new Event_FIELD_ACCESS(suspendPolicy, packetCopy);
718                break;
719            }
720            case JDWPConstants.EventKind.FIELD_MODIFICATION: {
721                events[i] = new Event_FIELD_MODIFICATION(suspendPolicy,
722                        packetCopy);
723                break;
724            }
725            case JDWPConstants.EventKind.VM_DEATH: {
726                events[i] = new Event_VM_DEATH(suspendPolicy, packetCopy);
727                break;
728            }
729            default: {
730                throw new TestErrorException("Unexpected kind of event: "
731                        + eventKind);
732            }
733            }
734        }
735        return events;
736    }
737
738}
739