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