1 /* 2 * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.tools.jdi; 27 28 import com.sun.jdi.*; 29 import com.sun.jdi.event.*; 30 import com.sun.jdi.request.*; 31 32 import java.util.*; 33 enum EventDestination {UNKNOWN_EVENT, INTERNAL_EVENT, CLIENT_EVENT}; 34 35 /* 36 * An EventSet is normally created by the transport reader thread when 37 * it reads a JDWP Composite command. The constructor doesn't unpack 38 * the events contained in the Composite command and create EventImpls 39 * for them because that process might involve calling back into the back-end 40 * which should not be done by the transport reader thread. Instead, 41 * the raw bytes of the packet are read and stored in the EventSet. 42 * The EventSet is then added to each EventQueue. When an EventSet is 43 * removed from an EventQueue, the EventSetImpl.build() method is called. 44 * This method reads the packet bytes and creates the actual EventImpl objects. 45 * build() also filters out events for our internal handler and puts them in 46 * their own EventSet. This means that the EventImpls that are in the EventSet 47 * that is on the queues are all for client requests. 48 */ 49 public class EventSetImpl extends ArrayList<Event> implements EventSet { 50 private static final long serialVersionUID = -4857338819787924570L; 51 private VirtualMachineImpl vm; // we implement Mirror 52 private Packet pkt; 53 private byte suspendPolicy; 54 private EventSetImpl internalEventSet; 55 toString()56 public String toString() { 57 String string = "event set, policy:" + suspendPolicy + 58 ", count:" + this.size() + " = {"; 59 boolean first = true; 60 for (Event event : this) { 61 if (!first) { 62 string += ", "; 63 } 64 string += event.toString(); 65 first = false; 66 } 67 string += "}"; 68 return string; 69 } 70 71 abstract class EventImpl extends MirrorImpl implements Event { 72 73 private final byte eventCmd; 74 private final int requestID; 75 // This is set only for client requests, not internal requests. 76 private final EventRequest request; 77 78 /** 79 * Constructor for events. 80 */ EventImpl(JDWP.Event.Composite.Events.EventsCommon evt, int requestID)81 protected EventImpl(JDWP.Event.Composite.Events.EventsCommon evt, 82 int requestID) { 83 super(EventSetImpl.this.vm); 84 this.eventCmd = evt.eventKind(); 85 this.requestID = requestID; 86 EventRequestManagerImpl ermi = EventSetImpl.this. 87 vm.eventRequestManagerImpl(); 88 this.request = ermi.request(eventCmd, requestID); 89 } 90 91 /* 92 * Override superclass back to default equality 93 */ equals(Object obj)94 public boolean equals(Object obj) { 95 return this == obj; 96 } 97 hashCode()98 public int hashCode() { 99 return System.identityHashCode(this); 100 } 101 102 /** 103 * Constructor for VM disconnected events. 104 */ EventImpl(byte eventCmd)105 protected EventImpl(byte eventCmd) { 106 super(EventSetImpl.this.vm); 107 this.eventCmd = eventCmd; 108 this.requestID = 0; 109 this.request = null; 110 } 111 request()112 public EventRequest request() { 113 return request; 114 } 115 requestID()116 int requestID() { 117 return requestID; 118 } 119 destination()120 EventDestination destination() { 121 /* 122 * We need to decide if this event is for 123 * 1. an internal request 124 * 2. a client request that is no longer available, ie 125 * it has been deleted, or disabled and re-enabled 126 * which gives it a new ID. 127 * 3. a current client request that is disabled 128 * 4. a current enabled client request. 129 * 130 * We will filter this set into a set 131 * that contains only 1s for our internal queue 132 * and a set that contains only 4s for our client queue. 133 * If we get an EventSet that contains only 2 and 3 134 * then we have to resume it if it is not SUSPEND_NONE 135 * because no one else will. 136 */ 137 if (requestID == 0) { 138 /* An unsolicited event. These have traditionally 139 * been treated as client events. 140 */ 141 return EventDestination.CLIENT_EVENT; 142 } 143 144 // Is this an event for a current client request? 145 if (request == null) { 146 // Nope. Is it an event for an internal request? 147 EventRequestManagerImpl ermi = this.vm.getInternalEventRequestManager(); 148 if (ermi.request(eventCmd, requestID) != null) { 149 // Yep 150 return EventDestination.INTERNAL_EVENT; 151 } 152 return EventDestination.UNKNOWN_EVENT; 153 } 154 155 // We found a client request 156 if (request.isEnabled()) { 157 return EventDestination.CLIENT_EVENT; 158 } 159 return EventDestination.UNKNOWN_EVENT; 160 } 161 eventName()162 abstract String eventName(); 163 toString()164 public String toString() { 165 return eventName(); 166 } 167 168 } 169 170 abstract class ThreadedEventImpl extends EventImpl { 171 private ThreadReference thread; 172 ThreadedEventImpl(JDWP.Event.Composite.Events.EventsCommon evt, int requestID, ThreadReference thread)173 ThreadedEventImpl(JDWP.Event.Composite.Events.EventsCommon evt, 174 int requestID, ThreadReference thread) { 175 super(evt, requestID); 176 this.thread = thread; 177 } 178 thread()179 public ThreadReference thread() { 180 return thread; 181 } 182 toString()183 public String toString() { 184 return eventName() + " in thread " + thread.name(); 185 } 186 } 187 188 abstract class LocatableEventImpl extends ThreadedEventImpl 189 implements Locatable { 190 private Location location; 191 LocatableEventImpl(JDWP.Event.Composite.Events.EventsCommon evt, int requestID, ThreadReference thread, Location location)192 LocatableEventImpl(JDWP.Event.Composite.Events.EventsCommon evt, 193 int requestID, 194 ThreadReference thread, Location location) { 195 super(evt, requestID, thread); 196 this.location = location; 197 } 198 location()199 public Location location() { 200 return location; 201 } 202 203 /** 204 * For MethodEntry and MethodExit 205 */ method()206 public Method method() { 207 return location.method(); 208 } 209 toString()210 public String toString() { 211 return eventName() + "@" + 212 ((location() == null) ? " null" : location().toString()) + 213 " in thread " + thread().name(); 214 } 215 } 216 217 class BreakpointEventImpl extends LocatableEventImpl 218 implements BreakpointEvent { BreakpointEventImpl(JDWP.Event.Composite.Events.Breakpoint evt)219 BreakpointEventImpl(JDWP.Event.Composite.Events.Breakpoint evt) { 220 super(evt, evt.requestID, evt.thread, evt.location); 221 } 222 eventName()223 String eventName() { 224 return "BreakpointEvent"; 225 } 226 } 227 228 class StepEventImpl extends LocatableEventImpl implements StepEvent { StepEventImpl(JDWP.Event.Composite.Events.SingleStep evt)229 StepEventImpl(JDWP.Event.Composite.Events.SingleStep evt) { 230 super(evt, evt.requestID, evt.thread, evt.location); 231 } 232 eventName()233 String eventName() { 234 return "StepEvent"; 235 } 236 } 237 238 class MethodEntryEventImpl extends LocatableEventImpl 239 implements MethodEntryEvent { MethodEntryEventImpl(JDWP.Event.Composite.Events.MethodEntry evt)240 MethodEntryEventImpl(JDWP.Event.Composite.Events.MethodEntry evt) { 241 super(evt, evt.requestID, evt.thread, evt.location); 242 } 243 eventName()244 String eventName() { 245 return "MethodEntryEvent"; 246 } 247 } 248 249 class MethodExitEventImpl extends LocatableEventImpl 250 implements MethodExitEvent { 251 private Value returnVal = null; 252 MethodExitEventImpl(JDWP.Event.Composite.Events.MethodExit evt)253 MethodExitEventImpl(JDWP.Event.Composite.Events.MethodExit evt) { 254 super(evt, evt.requestID, evt.thread, evt.location); 255 } 256 MethodExitEventImpl(JDWP.Event.Composite.Events.MethodExitWithReturnValue evt)257 MethodExitEventImpl(JDWP.Event.Composite.Events.MethodExitWithReturnValue evt) { 258 super(evt, evt.requestID, evt.thread, evt.location); 259 returnVal = evt.value; 260 } 261 eventName()262 String eventName() { 263 return "MethodExitEvent"; 264 } 265 returnValue()266 public Value returnValue() { 267 if (!this.vm.canGetMethodReturnValues()) { 268 throw new UnsupportedOperationException( 269 "target does not support return values in MethodExit events"); 270 } 271 return returnVal; 272 } 273 274 } 275 276 class MonitorContendedEnterEventImpl extends LocatableEventImpl 277 implements MonitorContendedEnterEvent { 278 private ObjectReference monitor = null; 279 MonitorContendedEnterEventImpl(JDWP.Event.Composite.Events.MonitorContendedEnter evt)280 MonitorContendedEnterEventImpl(JDWP.Event.Composite.Events.MonitorContendedEnter evt) { 281 super(evt, evt.requestID, evt.thread, evt.location); 282 this.monitor = evt.object; 283 } 284 eventName()285 String eventName() { 286 return "MonitorContendedEnter"; 287 } 288 monitor()289 public ObjectReference monitor() { 290 return monitor; 291 }; 292 293 } 294 295 class MonitorContendedEnteredEventImpl extends LocatableEventImpl 296 implements MonitorContendedEnteredEvent { 297 private ObjectReference monitor = null; 298 MonitorContendedEnteredEventImpl(JDWP.Event.Composite.Events.MonitorContendedEntered evt)299 MonitorContendedEnteredEventImpl(JDWP.Event.Composite.Events.MonitorContendedEntered evt) { 300 super(evt, evt.requestID, evt.thread, evt.location); 301 this.monitor = evt.object; 302 } 303 eventName()304 String eventName() { 305 return "MonitorContendedEntered"; 306 } 307 monitor()308 public ObjectReference monitor() { 309 return monitor; 310 }; 311 312 } 313 314 class MonitorWaitEventImpl extends LocatableEventImpl 315 implements MonitorWaitEvent { 316 private ObjectReference monitor = null; 317 private long timeout; 318 MonitorWaitEventImpl(JDWP.Event.Composite.Events.MonitorWait evt)319 MonitorWaitEventImpl(JDWP.Event.Composite.Events.MonitorWait evt) { 320 super(evt, evt.requestID, evt.thread, evt.location); 321 this.monitor = evt.object; 322 this.timeout = evt.timeout; 323 } 324 eventName()325 String eventName() { 326 return "MonitorWait"; 327 } 328 monitor()329 public ObjectReference monitor() { 330 return monitor; 331 }; 332 timeout()333 public long timeout() { 334 return timeout; 335 } 336 } 337 338 class MonitorWaitedEventImpl extends LocatableEventImpl 339 implements MonitorWaitedEvent { 340 private ObjectReference monitor = null; 341 private boolean timed_out; 342 MonitorWaitedEventImpl(JDWP.Event.Composite.Events.MonitorWaited evt)343 MonitorWaitedEventImpl(JDWP.Event.Composite.Events.MonitorWaited evt) { 344 super(evt, evt.requestID, evt.thread, evt.location); 345 this.monitor = evt.object; 346 this.timed_out = evt.timed_out; 347 } 348 eventName()349 String eventName() { 350 return "MonitorWaited"; 351 } 352 monitor()353 public ObjectReference monitor() { 354 return monitor; 355 }; 356 timedout()357 public boolean timedout() { 358 return timed_out; 359 } 360 } 361 362 class ClassPrepareEventImpl extends ThreadedEventImpl 363 implements ClassPrepareEvent { 364 private ReferenceType referenceType; 365 ClassPrepareEventImpl(JDWP.Event.Composite.Events.ClassPrepare evt)366 ClassPrepareEventImpl(JDWP.Event.Composite.Events.ClassPrepare evt) { 367 super(evt, evt.requestID, evt.thread); 368 referenceType = this.vm.referenceType(evt.typeID, evt.refTypeTag, 369 evt.signature); 370 ((ReferenceTypeImpl)referenceType).setStatus(evt.status); 371 } 372 referenceType()373 public ReferenceType referenceType() { 374 return referenceType; 375 } 376 eventName()377 String eventName() { 378 return "ClassPrepareEvent"; 379 } 380 } 381 382 class ClassUnloadEventImpl extends EventImpl implements ClassUnloadEvent { 383 private String classSignature; 384 ClassUnloadEventImpl(JDWP.Event.Composite.Events.ClassUnload evt)385 ClassUnloadEventImpl(JDWP.Event.Composite.Events.ClassUnload evt) { 386 super(evt, evt.requestID); 387 this.classSignature = evt.signature; 388 } 389 className()390 public String className() { 391 return classSignature.substring(1, classSignature.length()-1) 392 .replace('/', '.'); 393 } 394 classSignature()395 public String classSignature() { 396 return classSignature; 397 } 398 eventName()399 String eventName() { 400 return "ClassUnloadEvent"; 401 } 402 } 403 404 class ExceptionEventImpl extends LocatableEventImpl 405 implements ExceptionEvent { 406 private ObjectReference exception; 407 private Location catchLocation; 408 ExceptionEventImpl(JDWP.Event.Composite.Events.Exception evt)409 ExceptionEventImpl(JDWP.Event.Composite.Events.Exception evt) { 410 super(evt, evt.requestID, evt.thread, evt.location); 411 this.exception = evt.exception; 412 this.catchLocation = evt.catchLocation; 413 } 414 exception()415 public ObjectReference exception() { 416 return exception; 417 } 418 catchLocation()419 public Location catchLocation() { 420 return catchLocation; 421 } 422 eventName()423 String eventName() { 424 return "ExceptionEvent"; 425 } 426 } 427 428 class ThreadDeathEventImpl extends ThreadedEventImpl 429 implements ThreadDeathEvent { ThreadDeathEventImpl(JDWP.Event.Composite.Events.ThreadDeath evt)430 ThreadDeathEventImpl(JDWP.Event.Composite.Events.ThreadDeath evt) { 431 super(evt, evt.requestID, evt.thread); 432 } 433 eventName()434 String eventName() { 435 return "ThreadDeathEvent"; 436 } 437 } 438 439 class ThreadStartEventImpl extends ThreadedEventImpl 440 implements ThreadStartEvent { ThreadStartEventImpl(JDWP.Event.Composite.Events.ThreadStart evt)441 ThreadStartEventImpl(JDWP.Event.Composite.Events.ThreadStart evt) { 442 super(evt, evt.requestID, evt.thread); 443 } 444 eventName()445 String eventName() { 446 return "ThreadStartEvent"; 447 } 448 } 449 450 class VMStartEventImpl extends ThreadedEventImpl 451 implements VMStartEvent { VMStartEventImpl(JDWP.Event.Composite.Events.VMStart evt)452 VMStartEventImpl(JDWP.Event.Composite.Events.VMStart evt) { 453 super(evt, evt.requestID, evt.thread); 454 } 455 eventName()456 String eventName() { 457 return "VMStartEvent"; 458 } 459 } 460 461 class VMDeathEventImpl extends EventImpl implements VMDeathEvent { 462 VMDeathEventImpl(JDWP.Event.Composite.Events.VMDeath evt)463 VMDeathEventImpl(JDWP.Event.Composite.Events.VMDeath evt) { 464 super(evt, evt.requestID); 465 } 466 eventName()467 String eventName() { 468 return "VMDeathEvent"; 469 } 470 } 471 472 class VMDisconnectEventImpl extends EventImpl 473 implements VMDisconnectEvent { 474 VMDisconnectEventImpl()475 VMDisconnectEventImpl() { 476 super((byte)JDWP.EventKind.VM_DISCONNECTED); 477 } 478 eventName()479 String eventName() { 480 return "VMDisconnectEvent"; 481 } 482 } 483 484 abstract class WatchpointEventImpl extends LocatableEventImpl 485 implements WatchpointEvent { 486 private final ReferenceTypeImpl refType; 487 private final long fieldID; 488 private final ObjectReference object; 489 private Field field = null; 490 WatchpointEventImpl(JDWP.Event.Composite.Events.EventsCommon evt, int requestID, ThreadReference thread, Location location, byte refTypeTag, long typeID, long fieldID, ObjectReference object)491 WatchpointEventImpl(JDWP.Event.Composite.Events.EventsCommon evt, 492 int requestID, 493 ThreadReference thread, Location location, 494 byte refTypeTag, long typeID, long fieldID, 495 ObjectReference object) { 496 super(evt, requestID, thread, location); 497 this.refType = this.vm.referenceType(typeID, refTypeTag); 498 this.fieldID = fieldID; 499 this.object = object; 500 } 501 field()502 public Field field() { 503 if (field == null) { 504 field = refType.getFieldMirror(fieldID); 505 } 506 return field; 507 } 508 object()509 public ObjectReference object() { 510 return object; 511 } 512 valueCurrent()513 public Value valueCurrent() { 514 if (object == null) { 515 return refType.getValue(field()); 516 } else { 517 return object.getValue(field()); 518 } 519 } 520 } 521 522 class AccessWatchpointEventImpl extends WatchpointEventImpl 523 implements AccessWatchpointEvent { 524 AccessWatchpointEventImpl(JDWP.Event.Composite.Events.FieldAccess evt)525 AccessWatchpointEventImpl(JDWP.Event.Composite.Events.FieldAccess evt) { 526 super(evt, evt.requestID, evt.thread, evt.location, 527 evt.refTypeTag, evt.typeID, evt.fieldID, evt.object); 528 } 529 eventName()530 String eventName() { 531 return "AccessWatchpoint"; 532 } 533 } 534 535 class ModificationWatchpointEventImpl extends WatchpointEventImpl 536 implements ModificationWatchpointEvent { 537 Value newValue; 538 ModificationWatchpointEventImpl( JDWP.Event.Composite.Events.FieldModification evt)539 ModificationWatchpointEventImpl( 540 JDWP.Event.Composite.Events.FieldModification evt) { 541 super(evt, evt.requestID, evt.thread, evt.location, 542 evt.refTypeTag, evt.typeID, evt.fieldID, evt.object); 543 this.newValue = evt.valueToBe; 544 } 545 valueToBe()546 public Value valueToBe() { 547 return newValue; 548 } 549 eventName()550 String eventName() { 551 return "ModificationWatchpoint"; 552 } 553 } 554 555 /** 556 * Events are constructed on the thread which reads all data from the 557 * transport. This means that the packet cannot be converted to real 558 * JDI objects as that may involve further communications with the 559 * back end which would deadlock. 560 * 561 * Hence the {@link #build()} method below called by EventQueue. 562 */ EventSetImpl(VirtualMachine aVm, Packet pkt)563 EventSetImpl(VirtualMachine aVm, Packet pkt) { 564 super(); 565 566 // From "MirrorImpl": 567 // Yes, its a bit of a hack. But by doing it this 568 // way, this is the only place we have to change 569 // typing to substitute a new impl. 570 vm = (VirtualMachineImpl)aVm; 571 572 this.pkt = pkt; 573 } 574 575 /** 576 * Constructor for special events like VM disconnected 577 */ EventSetImpl(VirtualMachine aVm, byte eventCmd)578 EventSetImpl(VirtualMachine aVm, byte eventCmd) { 579 this(aVm, null); 580 suspendPolicy = JDWP.SuspendPolicy.NONE; 581 switch (eventCmd) { 582 case JDWP.EventKind.VM_DISCONNECTED: 583 addEvent(new VMDisconnectEventImpl()); 584 break; 585 586 default: 587 throw new InternalException("Bad singleton event code"); 588 } 589 } 590 addEvent(EventImpl evt)591 private void addEvent(EventImpl evt) { 592 // Note that this class has a public add method that throws 593 // an exception so that clients can't modify the EventSet 594 super.add(evt); 595 } 596 597 /* 598 * Complete the construction of an EventSet. This is called from 599 * an event handler thread. It upacks the JDWP events inside 600 * the packet and creates EventImpls for them. The EventSet is already 601 * on EventQueues when this is called, so it has to be synch. 602 */ build()603 synchronized void build() { 604 if (pkt == null) { 605 return; 606 } 607 PacketStream ps = new PacketStream(vm, pkt); 608 JDWP.Event.Composite compEvt = new JDWP.Event.Composite(vm, ps); 609 suspendPolicy = compEvt.suspendPolicy; 610 if ((vm.traceFlags & VirtualMachine.TRACE_EVENTS) != 0) { 611 switch(suspendPolicy) { 612 case JDWP.SuspendPolicy.ALL: 613 vm.printTrace("EventSet: SUSPEND_ALL"); 614 break; 615 616 case JDWP.SuspendPolicy.EVENT_THREAD: 617 vm.printTrace("EventSet: SUSPEND_EVENT_THREAD"); 618 break; 619 620 case JDWP.SuspendPolicy.NONE: 621 vm.printTrace("EventSet: SUSPEND_NONE"); 622 break; 623 } 624 } 625 626 ThreadReference fix6485605 = null; 627 for (int i = 0; i < compEvt.events.length; i++) { 628 EventImpl evt = createEvent(compEvt.events[i]); 629 if ((vm.traceFlags & VirtualMachine.TRACE_EVENTS) != 0) { 630 try { 631 vm.printTrace("Event: " + evt); 632 } catch (VMDisconnectedException ee) { 633 // ignore - see bug 6502716 634 } 635 } 636 637 switch (evt.destination()) { 638 case UNKNOWN_EVENT: 639 // Ignore disabled, deleted, unknown events, but 640 // save the thread if there is one since we might 641 // have to resume it. Note that events for different 642 // threads can't be in the same event set. 643 if (evt instanceof ThreadedEventImpl && 644 suspendPolicy == JDWP.SuspendPolicy.EVENT_THREAD) { 645 fix6485605 = ((ThreadedEventImpl)evt).thread(); 646 } 647 continue; 648 case CLIENT_EVENT: 649 addEvent(evt); 650 break; 651 case INTERNAL_EVENT: 652 if (internalEventSet == null) { 653 internalEventSet = new EventSetImpl(this.vm, null); 654 } 655 internalEventSet.addEvent(evt); 656 break; 657 default: 658 throw new InternalException("Invalid event destination"); 659 } 660 } 661 pkt = null; // No longer needed - free it up 662 663 // Avoid hangs described in 6296125, 6293795 664 if (super.size() == 0) { 665 // This set has no client events. If we don't do 666 // needed resumes, no one else is going to. 667 if (suspendPolicy == JDWP.SuspendPolicy.ALL) { 668 vm.resume(); 669 } else if (suspendPolicy == JDWP.SuspendPolicy.EVENT_THREAD) { 670 // See bug 6485605. 671 if (fix6485605 != null) { 672 fix6485605.resume(); 673 } else { 674 // apparently, there is nothing to resume. 675 } 676 } 677 suspendPolicy = JDWP.SuspendPolicy.NONE; 678 679 } 680 681 } 682 683 /** 684 * Filter out internal events 685 */ userFilter()686 EventSet userFilter() { 687 return this; 688 } 689 690 /** 691 * Filter out user events. 692 */ internalFilter()693 EventSet internalFilter() { 694 return this.internalEventSet; 695 } 696 createEvent(JDWP.Event.Composite.Events evt)697 EventImpl createEvent(JDWP.Event.Composite.Events evt) { 698 JDWP.Event.Composite.Events.EventsCommon comm = evt.aEventsCommon; 699 switch (evt.eventKind) { 700 case JDWP.EventKind.THREAD_START: 701 return new ThreadStartEventImpl( 702 (JDWP.Event.Composite.Events.ThreadStart)comm); 703 704 case JDWP.EventKind.THREAD_END: 705 return new ThreadDeathEventImpl( 706 (JDWP.Event.Composite.Events.ThreadDeath)comm); 707 708 case JDWP.EventKind.EXCEPTION: 709 return new ExceptionEventImpl( 710 (JDWP.Event.Composite.Events.Exception)comm); 711 712 case JDWP.EventKind.BREAKPOINT: 713 return new BreakpointEventImpl( 714 (JDWP.Event.Composite.Events.Breakpoint)comm); 715 716 case JDWP.EventKind.METHOD_ENTRY: 717 return new MethodEntryEventImpl( 718 (JDWP.Event.Composite.Events.MethodEntry)comm); 719 720 case JDWP.EventKind.METHOD_EXIT: 721 return new MethodExitEventImpl( 722 (JDWP.Event.Composite.Events.MethodExit)comm); 723 724 case JDWP.EventKind.METHOD_EXIT_WITH_RETURN_VALUE: 725 return new MethodExitEventImpl( 726 (JDWP.Event.Composite.Events.MethodExitWithReturnValue)comm); 727 728 case JDWP.EventKind.FIELD_ACCESS: 729 return new AccessWatchpointEventImpl( 730 (JDWP.Event.Composite.Events.FieldAccess)comm); 731 732 case JDWP.EventKind.FIELD_MODIFICATION: 733 return new ModificationWatchpointEventImpl( 734 (JDWP.Event.Composite.Events.FieldModification)comm); 735 736 case JDWP.EventKind.SINGLE_STEP: 737 return new StepEventImpl( 738 (JDWP.Event.Composite.Events.SingleStep)comm); 739 740 case JDWP.EventKind.CLASS_PREPARE: 741 return new ClassPrepareEventImpl( 742 (JDWP.Event.Composite.Events.ClassPrepare)comm); 743 744 case JDWP.EventKind.CLASS_UNLOAD: 745 return new ClassUnloadEventImpl( 746 (JDWP.Event.Composite.Events.ClassUnload)comm); 747 748 case JDWP.EventKind.MONITOR_CONTENDED_ENTER: 749 return new MonitorContendedEnterEventImpl( 750 (JDWP.Event.Composite.Events.MonitorContendedEnter)comm); 751 752 case JDWP.EventKind.MONITOR_CONTENDED_ENTERED: 753 return new MonitorContendedEnteredEventImpl( 754 (JDWP.Event.Composite.Events.MonitorContendedEntered)comm); 755 756 case JDWP.EventKind.MONITOR_WAIT: 757 return new MonitorWaitEventImpl( 758 (JDWP.Event.Composite.Events.MonitorWait)comm); 759 760 case JDWP.EventKind.MONITOR_WAITED: 761 return new MonitorWaitedEventImpl( 762 (JDWP.Event.Composite.Events.MonitorWaited)comm); 763 764 case JDWP.EventKind.VM_START: 765 return new VMStartEventImpl( 766 (JDWP.Event.Composite.Events.VMStart)comm); 767 768 case JDWP.EventKind.VM_DEATH: 769 return new VMDeathEventImpl( 770 (JDWP.Event.Composite.Events.VMDeath)comm); 771 772 default: 773 // Ignore unknown event types 774 System.err.println("Ignoring event cmd " + 775 evt.eventKind + " from the VM"); 776 return null; 777 } 778 } 779 virtualMachine()780 public VirtualMachine virtualMachine() { 781 return vm; 782 } 783 suspendPolicy()784 public int suspendPolicy() { 785 return EventRequestManagerImpl.JDWPtoJDISuspendPolicy(suspendPolicy); 786 } 787 eventThread()788 private ThreadReference eventThread() { 789 for (Event event : this) { 790 if (event instanceof ThreadedEventImpl) { 791 return ((ThreadedEventImpl)event).thread(); 792 } 793 } 794 return null; 795 } 796 resume()797 public void resume() { 798 switch (suspendPolicy()) { 799 case EventRequest.SUSPEND_ALL: 800 vm.resume(); 801 break; 802 case EventRequest.SUSPEND_EVENT_THREAD: 803 ThreadReference thread = eventThread(); 804 if (thread == null) { 805 throw new InternalException("Inconsistent suspend policy"); 806 } 807 thread.resume(); 808 break; 809 case EventRequest.SUSPEND_NONE: 810 // Do nothing 811 break; 812 default: 813 throw new InternalException("Invalid suspend policy"); 814 } 815 } 816 iterator()817 public Iterator<Event> iterator() { 818 return new Itr(); 819 } 820 eventIterator()821 public EventIterator eventIterator() { 822 return new Itr(); 823 } 824 825 public class Itr implements EventIterator { 826 /** 827 * Index of element to be returned by subsequent call to next. 828 */ 829 int cursor = 0; 830 hasNext()831 public boolean hasNext() { 832 return cursor != size(); 833 } 834 next()835 public Event next() { 836 try { 837 Event nxt = get(cursor); 838 ++cursor; 839 return nxt; 840 } catch(IndexOutOfBoundsException e) { 841 throw new NoSuchElementException(); 842 } 843 } 844 nextEvent()845 public Event nextEvent() { 846 return next(); 847 } 848 remove()849 public void remove() { 850 throw new UnsupportedOperationException(); 851 } 852 } 853 854 @Override spliterator()855 public Spliterator<Event> spliterator() { 856 return Spliterators.spliterator(this, Spliterator.DISTINCT); 857 } 858 859 /* below make this unmodifiable */ 860 add(Event o)861 public boolean add(Event o){ 862 throw new UnsupportedOperationException(); 863 } remove(Object o)864 public boolean remove(Object o) { 865 throw new UnsupportedOperationException(); 866 } addAll(Collection<? extends Event> coll)867 public boolean addAll(Collection<? extends Event> coll) { 868 throw new UnsupportedOperationException(); 869 } removeAll(Collection<?> coll)870 public boolean removeAll(Collection<?> coll) { 871 throw new UnsupportedOperationException(); 872 } retainAll(Collection<?> coll)873 public boolean retainAll(Collection<?> coll) { 874 throw new UnsupportedOperationException(); 875 } clear()876 public void clear() { 877 throw new UnsupportedOperationException(); 878 } 879 } 880