1 /*
   2  * Copyright (c) 1998, 2020, 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             // trim leading "L" and trailing ";"
 429             String name = classSignature.substring(1, classSignature.length() - 1);
 430             int index = name.indexOf(".");  // check if it is a hidden class
 431             if (index < 0) {
 432                 return name.replace('/', '.');
 433             }  else {
 434                 // map the type descriptor from: "L" + N + "." + <suffix> + ";"
 435                 // to class name: N.replace('/', '.') + "/" + <suffix>
 436                 return name.substring(0, index).replace('/', '.')
 437                         + "/" + name.substring(index + 1);
 438             }
 439         }
 440 
 441         public String classSignature() {
 442             return classSignature;
 443         }
 444 
 445         String eventName() {
 446             return "ClassUnloadEvent";
 447         }
 448     }
 449 
 450     class ExceptionEventImpl extends LocatableEventImpl
 451                                              implements ExceptionEvent {
 452         private ObjectReference exception;
 453         private Location catchLocation;
 454 
 455         ExceptionEventImpl(JDWP.Event.Composite.Events.Exception evt) {
 456             super(evt, evt.requestID, evt.thread, evt.location);
 457             this.exception = evt.exception;
 458             this.catchLocation = evt.catchLocation;
 459         }
 460 
 461         public ObjectReference exception() {
 462             return exception;
 463         }
 464 
 465         public Location catchLocation() {
 466             return catchLocation;
 467         }
 468 
 469         String eventName() {
 470             return "ExceptionEvent";
 471         }
 472     }
 473 
 474     class ThreadDeathEventImpl extends ThreadedEventImpl
 475                                         implements ThreadDeathEvent {
 476         ThreadDeathEventImpl(JDWP.Event.Composite.Events.ThreadDeath evt) {
 477             super(evt, evt.requestID, evt.thread);
 478         }
 479 
 480         String eventName() {
 481             return "ThreadDeathEvent";
 482         }
 483     }
 484 
 485     class ThreadStartEventImpl extends ThreadedEventImpl
 486                                         implements ThreadStartEvent {
 487         ThreadStartEventImpl(JDWP.Event.Composite.Events.ThreadStart evt) {
 488             super(evt, evt.requestID, evt.thread);
 489         }
 490 
 491         String eventName() {
 492             return "ThreadStartEvent";
 493         }
 494     }
 495 
 496     class VMStartEventImpl extends ThreadedEventImpl
 497                                         implements VMStartEvent {
 498         VMStartEventImpl(JDWP.Event.Composite.Events.VMStart evt) {
 499             super(evt, evt.requestID, evt.thread);
 500         }
 501 
 502         String eventName() {
 503             return "VMStartEvent";
 504         }
 505     }
 506 
 507     class VMDeathEventImpl extends EventImpl implements VMDeathEvent {
 508 
 509         VMDeathEventImpl(JDWP.Event.Composite.Events.VMDeath evt) {
 510             super(evt, evt.requestID);
 511         }
 512 
 513         String eventName() {
 514             return "VMDeathEvent";
 515         }
 516     }
 517 
 518     class VMDisconnectEventImpl extends EventImpl
 519                                          implements VMDisconnectEvent {
 520 
 521         VMDisconnectEventImpl() {
 522             super((byte)JDWP.EventKind.VM_DISCONNECTED);
 523         }
 524 
 525         String eventName() {
 526             return "VMDisconnectEvent";
 527         }
 528     }
 529 
 530     abstract class WatchpointEventImpl extends LocatableEventImpl
 531                                             implements WatchpointEvent {
 532         private final ReferenceTypeImpl refType;
 533         private final long fieldID;
 534         private final ObjectReference object;
 535         private Field field = null;
 536 
 537         WatchpointEventImpl(JDWP.Event.Composite.Events.EventsCommon evt,
 538                             int requestID,
 539                             ThreadReference thread, Location location,
 540                             byte refTypeTag, long typeID, long fieldID,
 541                             ObjectReference object) {
 542             super(evt, requestID, thread, location);
 543             this.refType = this.vm.referenceType(typeID, refTypeTag);
 544             this.fieldID = fieldID;
 545             this.object = object;
 546         }
 547 
 548         public Field field() {
 549             if (field == null) {
 550                 field = refType.getFieldMirror(fieldID);
 551             }
 552             return field;
 553         }
 554 
 555         public ObjectReference object() {
 556             return object;
 557         }
 558 
 559         public Value valueCurrent() {
 560             if (object == null) {
 561                 return refType.getValue(field());
 562             } else {
 563                 return object.getValue(field());
 564             }
 565         }
 566     }
 567 
 568     class AccessWatchpointEventImpl extends WatchpointEventImpl
 569                                             implements AccessWatchpointEvent {
 570 
 571         AccessWatchpointEventImpl(JDWP.Event.Composite.Events.FieldAccess evt) {
 572             super(evt, evt.requestID, evt.thread, evt.location,
 573                   evt.refTypeTag, evt.typeID, evt.fieldID, evt.object);
 574         }
 575 
 576         String eventName() {
 577             return "AccessWatchpoint";
 578         }
 579     }
 580 
 581     class ModificationWatchpointEventImpl extends WatchpointEventImpl
 582                            implements ModificationWatchpointEvent {
 583         Value newValue;
 584 
 585         ModificationWatchpointEventImpl(
 586                         JDWP.Event.Composite.Events.FieldModification evt) {
 587             super(evt, evt.requestID, evt.thread, evt.location,
 588                   evt.refTypeTag, evt.typeID, evt.fieldID, evt.object);
 589             this.newValue = evt.valueToBe;
 590         }
 591 
 592         public Value valueToBe() {
 593             return newValue;
 594         }
 595 
 596         String eventName() {
 597             return "ModificationWatchpoint";
 598         }
 599     }
 600 
 601     /**
 602      * Events are constructed on the thread which reads all data from the
 603      * transport. This means that the packet cannot be converted to real
 604      * JDI objects as that may involve further communications with the
 605      * back end which would deadlock.
 606      *
 607      * Hence the {@link #build()} method below called by EventQueue.
 608      */
 609     EventSetImpl(VirtualMachine aVm, Packet pkt) {
 610         super();
 611 
 612         // From "MirrorImpl":
 613         // Yes, its a bit of a hack. But by doing it this
 614         // way, this is the only place we have to change
 615         // typing to substitute a new impl.
 616         vm = (VirtualMachineImpl)aVm;
 617 
 618         this.pkt = pkt;
 619     }
 620 
 621     /**
 622      * Constructor for special events like VM disconnected
 623      */
 624     EventSetImpl(VirtualMachine aVm, byte eventCmd) {
 625         this(aVm, null);
 626         suspendPolicy = JDWP.SuspendPolicy.NONE;
 627         switch (eventCmd) {
 628             case JDWP.EventKind.VM_DISCONNECTED:
 629                 addEvent(new VMDisconnectEventImpl());
 630                 break;
 631 
 632             default:
 633                 throw new InternalException("Bad singleton event code");
 634         }
 635     }
 636 
 637     private void addEvent(EventImpl evt) {
 638         // Note that this class has a public add method that throws
 639         // an exception so that clients can't modify the EventSet
 640         super.add(evt);
 641     }
 642 
 643     /*
 644      * Complete the construction of an EventSet.  This is called from
 645      * an event handler thread.  It upacks the JDWP events inside
 646      * the packet and creates EventImpls for them.  The EventSet is already
 647      * on EventQueues when this is called, so it has to be synch.
 648      */
 649     synchronized void build() {
 650         if (pkt == null) {
 651             return;
 652         }
 653         PacketStream ps = new PacketStream(vm, pkt);
 654         JDWP.Event.Composite compEvt = new JDWP.Event.Composite(vm, ps);
 655         suspendPolicy = compEvt.suspendPolicy;
 656         if ((vm.traceFlags & VirtualMachine.TRACE_EVENTS) != 0) {
 657             switch(suspendPolicy) {
 658                 case JDWP.SuspendPolicy.ALL:
 659                     vm.printTrace("EventSet: SUSPEND_ALL");
 660                     break;
 661 
 662                 case JDWP.SuspendPolicy.EVENT_THREAD:
 663                     vm.printTrace("EventSet: SUSPEND_EVENT_THREAD");
 664                     break;
 665 
 666                 case JDWP.SuspendPolicy.NONE:
 667                     vm.printTrace("EventSet: SUSPEND_NONE");
 668                     break;
 669             }
 670         }
 671 
 672         ThreadReference fix6485605 = null;
 673         for (int i = 0; i < compEvt.events.length; i++) {
 674             EventImpl evt = createEvent(compEvt.events[i]);
 675             if ((vm.traceFlags & VirtualMachine.TRACE_EVENTS) != 0) {
 676                 try {
 677                     vm.printTrace("Event: " + evt);
 678                 } catch (VMDisconnectedException ee) {
 679                     // ignore - see bug 6502716
 680                 }
 681             }
 682 
 683             switch (evt.destination()) {
 684                 case UNKNOWN_EVENT:
 685                     // Ignore disabled, deleted, unknown events, but
 686                     // save the thread if there is one since we might
 687                     // have to resume it.  Note that events for different
 688                     // threads can't be in the same event set.
 689                     if (evt instanceof ThreadedEventImpl &&
 690                         suspendPolicy == JDWP.SuspendPolicy.EVENT_THREAD) {
 691                         fix6485605 = ((ThreadedEventImpl)evt).thread();
 692                     }
 693                     continue;
 694                 case CLIENT_EVENT:
 695                     addEvent(evt);
 696                     break;
 697                 case INTERNAL_EVENT:
 698                     if (internalEventSet == null) {
 699                         internalEventSet = new EventSetImpl(this.vm, null);
 700                     }
 701                     internalEventSet.addEvent(evt);
 702                     break;
 703                 default:
 704                     throw new InternalException("Invalid event destination");
 705             }
 706         }
 707         pkt = null; // No longer needed - free it up
 708 
 709         // Avoid hangs described in 6296125, 6293795
 710         if (super.size() == 0) {
 711             // This set has no client events.  If we don't do
 712             // needed resumes, no one else is going to.
 713             if (suspendPolicy == JDWP.SuspendPolicy.ALL) {
 714                 vm.resume();
 715             } else if (suspendPolicy == JDWP.SuspendPolicy.EVENT_THREAD) {
 716                 // See bug 6485605.
 717                 if (fix6485605 != null) {
 718                     fix6485605.resume();
 719                 } else {
 720                     // apparently, there is nothing to resume.
 721                 }
 722             }
 723             suspendPolicy = JDWP.SuspendPolicy.NONE;
 724 
 725         }
 726 
 727     }
 728 
 729     /**
 730      * Filter out internal events
 731      */
 732     EventSet userFilter() {
 733         return this;
 734     }
 735 
 736     /**
 737      * Filter out user events.
 738      */
 739     EventSet internalFilter() {
 740         return this.internalEventSet;
 741     }
 742 
 743     EventImpl createEvent(JDWP.Event.Composite.Events evt) {
 744         JDWP.Event.Composite.Events.EventsCommon comm = evt.aEventsCommon;
 745         switch (evt.eventKind) {
 746             case JDWP.EventKind.THREAD_START:
 747                 return new ThreadStartEventImpl(
 748                       (JDWP.Event.Composite.Events.ThreadStart)comm);
 749 
 750             case JDWP.EventKind.THREAD_END:
 751                 return new ThreadDeathEventImpl(
 752                       (JDWP.Event.Composite.Events.ThreadDeath)comm);
 753 
 754             case JDWP.EventKind.EXCEPTION:
 755                 return new ExceptionEventImpl(
 756                       (JDWP.Event.Composite.Events.Exception)comm);
 757 
 758             case JDWP.EventKind.BREAKPOINT:
 759                 return new BreakpointEventImpl(
 760                       (JDWP.Event.Composite.Events.Breakpoint)comm);
 761 
 762             case JDWP.EventKind.METHOD_ENTRY:
 763                 return new MethodEntryEventImpl(
 764                       (JDWP.Event.Composite.Events.MethodEntry)comm);
 765 
 766             case JDWP.EventKind.METHOD_EXIT:
 767                 return new MethodExitEventImpl(
 768                       (JDWP.Event.Composite.Events.MethodExit)comm);
 769 
 770             case JDWP.EventKind.METHOD_EXIT_WITH_RETURN_VALUE:
 771                 return new MethodExitEventImpl(
 772                       (JDWP.Event.Composite.Events.MethodExitWithReturnValue)comm);
 773 
 774             case JDWP.EventKind.FIELD_ACCESS:
 775                 return new AccessWatchpointEventImpl(
 776                       (JDWP.Event.Composite.Events.FieldAccess)comm);
 777 
 778             case JDWP.EventKind.FIELD_MODIFICATION:
 779                 return new ModificationWatchpointEventImpl(
 780                       (JDWP.Event.Composite.Events.FieldModification)comm);
 781 
 782             case JDWP.EventKind.SINGLE_STEP:
 783                 return new StepEventImpl(
 784                       (JDWP.Event.Composite.Events.SingleStep)comm);
 785 
 786             case JDWP.EventKind.CLASS_PREPARE:
 787                 return new ClassPrepareEventImpl(
 788                       (JDWP.Event.Composite.Events.ClassPrepare)comm);
 789 
 790             case JDWP.EventKind.CLASS_UNLOAD:
 791                 return new ClassUnloadEventImpl(
 792                       (JDWP.Event.Composite.Events.ClassUnload)comm);
 793 
 794             case JDWP.EventKind.MONITOR_CONTENDED_ENTER:
 795                 return new MonitorContendedEnterEventImpl(
 796                       (JDWP.Event.Composite.Events.MonitorContendedEnter)comm);
 797 
 798             case JDWP.EventKind.MONITOR_CONTENDED_ENTERED:
 799                 return new MonitorContendedEnteredEventImpl(
 800                       (JDWP.Event.Composite.Events.MonitorContendedEntered)comm);
 801 
 802             case JDWP.EventKind.MONITOR_WAIT:
 803                 return new MonitorWaitEventImpl(
 804                       (JDWP.Event.Composite.Events.MonitorWait)comm);
 805 
 806             case JDWP.EventKind.MONITOR_WAITED:
 807                 return new MonitorWaitedEventImpl(
 808                       (JDWP.Event.Composite.Events.MonitorWaited)comm);
 809 
 810             case JDWP.EventKind.VM_START:
 811                 return new VMStartEventImpl(
 812                       (JDWP.Event.Composite.Events.VMStart)comm);
 813 
 814             case JDWP.EventKind.VM_DEATH:
 815                 return new VMDeathEventImpl(
 816                       (JDWP.Event.Composite.Events.VMDeath)comm);
 817 
 818             default:
 819                 // Ignore unknown event types
 820                 System.err.println("Ignoring event cmd " +
 821                                    evt.eventKind + " from the VM");
 822                 return null;
 823         }
 824     }
 825 
 826     public VirtualMachine virtualMachine() {
 827         return vm;
 828     }
 829 
 830     public int suspendPolicy() {
 831         return EventRequestManagerImpl.JDWPtoJDISuspendPolicy(suspendPolicy);
 832     }
 833 
 834     private ThreadReference eventThread() {
 835         for (Event event : this) {
 836             if (event instanceof ThreadedEventImpl) {
 837                 return ((ThreadedEventImpl)event).thread();
 838             }
 839         }
 840         return null;
 841     }
 842 
 843     public void resume() {
 844         switch (suspendPolicy()) {
 845             case EventRequest.SUSPEND_ALL:
 846                 vm.resume();
 847                 break;
 848             case EventRequest.SUSPEND_EVENT_THREAD:
 849                 ThreadReference thread = eventThread();
 850                 if (thread == null) {
 851                     throw new InternalException("Inconsistent suspend policy");
 852                 }
 853                 thread.resume();
 854                 break;
 855             case EventRequest.SUSPEND_NONE:
 856                 // Do nothing
 857                 break;
 858             default:
 859                 throw new InternalException("Invalid suspend policy");
 860         }
 861     }
 862 
 863     public Iterator<Event> iterator() {
 864         return new Itr();
 865     }
 866 
 867     public EventIterator eventIterator() {
 868         return new Itr();
 869     }
 870 
 871     public class Itr implements EventIterator {
 872         /**
 873          * Index of element to be returned by subsequent call to next.
 874          */
 875         int cursor = 0;
 876 
 877         public boolean hasNext() {
 878             return cursor != size();
 879         }
 880 
 881         public Event next() {
 882             try {
 883                 Event nxt = get(cursor);
 884                 ++cursor;
 885                 return nxt;
 886             } catch(IndexOutOfBoundsException e) {
 887                 throw new NoSuchElementException();
 888             }
 889         }
 890 
 891         public Event nextEvent() {
 892             return next();
 893         }
 894 
 895         public void remove() {
 896             throw new UnsupportedOperationException();
 897         }
 898     }
 899 
 900     @Override
 901     public Spliterator<Event> spliterator() {
 902         return Spliterators.spliterator(this, Spliterator.DISTINCT);
 903     }
 904 
 905     /* below make this unmodifiable */
 906 
 907     public boolean add(Event o){
 908         throw new UnsupportedOperationException();
 909     }
 910     public boolean remove(Object o) {
 911         throw new UnsupportedOperationException();
 912     }
 913     public boolean addAll(Collection<? extends Event> coll) {
 914         throw new UnsupportedOperationException();
 915     }
 916     public boolean removeAll(Collection<?> coll) {
 917         throw new UnsupportedOperationException();
 918     }
 919     public boolean retainAll(Collection<?> coll) {
 920         throw new UnsupportedOperationException();
 921     }
 922     public void clear() {
 923         throw new UnsupportedOperationException();
 924     }
 925 }