Frames | No Frames |
1: /* EventManager.java -- event management and notification infrastructure 2: Copyright (C) 2005, 2006, 2007 Free Software Foundation 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: terms of your choice, provided that you also meet, for each linked 32: independent module, the terms and conditions of the license of that 33: module. An independent module is a module which is not derived from 34: or based on this library. If you modify this library, you may extend 35: this exception to your version of the library, but you are not 36: obligated to do so. If you do not wish to do so, delete this 37: exception statement from your version. */ 38: 39: 40: package gnu.classpath.jdwp.event; 41: 42: import gnu.classpath.jdwp.Jdwp; 43: import gnu.classpath.jdwp.VMVirtualMachine; 44: import gnu.classpath.jdwp.exception.InvalidEventTypeException; 45: import gnu.classpath.jdwp.exception.JdwpException; 46: 47: import java.util.ArrayList; 48: import java.util.Collection; 49: import java.util.Hashtable; 50: import java.util.Iterator; 51: 52: /** 53: * Manages event requests and filters event notifications. 54: * 55: * The purpose of this class is actually two-fold: 56: * 57: * 1) Maintain a list of event requests from the debugger 58: * 2) Filter event notifications from the VM 59: * 60: * If an event request arrives from the debugger, the back-end will 61: * call {@link #requestEvent}, which will first check for a valid event. 62: * If it is valid, <code>EventManager</code> will record the request 63: * internally and register the event with the virtual machine, which may 64: * choose to handle the request itself (as is likely the case with 65: * breakpoints and other execution-related events), or it may decide to 66: * allow the <code>EventManager</code> to handle notifications and all 67: * filtering (which is convenient for other events such as class (un)loading). 68: * 69: * @author Keith Seitz (keiths@redhat.com) 70: */ 71: public class EventManager 72: { 73: // Single instance 74: private static EventManager _instance = null; 75: 76: // maps event (EVENT_*) to lists of EventRequests 77: private Hashtable _requests = null; 78: 79: /** 80: * Returns an instance of the event manager 81: * 82: * @return the event manager 83: */ 84: public static EventManager getDefault() 85: { 86: if (_instance == null) 87: _instance = new EventManager(); 88: 89: return _instance; 90: } 91: 92: // Private constructs a new <code>EventManager</code> 93: private EventManager () 94: { 95: _requests = new Hashtable (); 96: 97: // Add lists for all the event types 98: _requests.put (new Byte (EventRequest.EVENT_SINGLE_STEP), 99: new Hashtable ()); 100: _requests.put (new Byte (EventRequest.EVENT_BREAKPOINT), 101: new Hashtable ()); 102: _requests.put (new Byte (EventRequest.EVENT_FRAME_POP), 103: new Hashtable ()); 104: _requests.put (new Byte (EventRequest.EVENT_EXCEPTION), 105: new Hashtable ()); 106: _requests.put (new Byte (EventRequest.EVENT_USER_DEFINED), 107: new Hashtable ()); 108: _requests.put (new Byte (EventRequest.EVENT_THREAD_START), 109: new Hashtable ()); 110: _requests.put (new Byte (EventRequest.EVENT_THREAD_END), 111: new Hashtable ()); 112: _requests.put (new Byte (EventRequest.EVENT_CLASS_PREPARE), 113: new Hashtable ()); 114: _requests.put (new Byte (EventRequest.EVENT_CLASS_UNLOAD), 115: new Hashtable ()); 116: _requests.put (new Byte (EventRequest.EVENT_CLASS_LOAD), 117: new Hashtable ()); 118: _requests.put (new Byte (EventRequest.EVENT_FIELD_ACCESS), 119: new Hashtable ()); 120: _requests.put (new Byte (EventRequest.EVENT_FIELD_MODIFY), 121: new Hashtable ()); 122: _requests.put (new Byte (EventRequest.EVENT_METHOD_ENTRY), 123: new Hashtable ()); 124: _requests.put (new Byte (EventRequest.EVENT_METHOD_EXIT), 125: new Hashtable ()); 126: _requests.put (new Byte (EventRequest.EVENT_VM_INIT), 127: new Hashtable ()); 128: _requests.put (new Byte (EventRequest.EVENT_VM_DEATH), 129: new Hashtable ()); 130: 131: // Add auto-generated event notifications 132: // only two: VM_INIT, VM_DEATH 133: try 134: { 135: byte sp = (Jdwp.suspendOnStartup() 136: ? EventRequest.SUSPEND_THREAD : EventRequest.SUSPEND_NONE); 137: requestEvent (new EventRequest (0, 138: EventRequest.EVENT_VM_INIT, sp)); 139: requestEvent (new EventRequest (0, 140: EventRequest.EVENT_VM_DEATH, 141: EventRequest.SUSPEND_NONE)); 142: } 143: catch (JdwpException e) 144: { 145: // This can't happen 146: } 147: } 148: 149: /** 150: * Returns all requests for the given event. This method will only 151: * be used if the <code>EventManager</code> is handling event filtering. 152: * 153: * @param event the event 154: * @return requests that are interested in this event 155: * or <code>null</code> if none (and event should not be sent) 156: * @throws IllegalArgumentException for invalid event kind 157: */ 158: public EventRequest[] getEventRequests(Event event) 159: { 160: ArrayList interestedEvents = new ArrayList(); 161: Hashtable requests; 162: Byte kind = new Byte(event.getEventKind()); 163: requests = (Hashtable) _requests.get(kind); 164: if (requests == null) 165: { 166: // Did not get a valid event type 167: throw new IllegalArgumentException("invalid event kind: " + kind); 168: } 169: 170: // Loop through the requests. Must look at ALL requests in order 171: // to evaluate all filters (think count filter). 172: Iterator rIter = requests.values().iterator(); 173: while (rIter.hasNext()) 174: { 175: EventRequest request = (EventRequest) rIter.next(); 176: if (request.matches(event)) 177: interestedEvents.add(request); 178: } 179: 180: EventRequest[] r = new EventRequest[interestedEvents.size()]; 181: interestedEvents.toArray(r); 182: return r; 183: } 184: 185: /** 186: * Requests monitoring of an event. 187: * 188: * The debugger registers for event notification through 189: * an event filter. If no event filter is specified for an event 190: * in the VM, it is assumed that the debugger is not interested in 191: * receiving notifications of this event. 192: * 193: * The virtual machine will be notified of the request. 194: * 195: * @param request the request to monitor 196: * @throws InvalidEventTypeException for invalid event kind 197: * @throws JdwpException for other errors involving request 198: */ 199: public void requestEvent (EventRequest request) 200: throws JdwpException 201: { 202: // Add request to request list 203: Hashtable requests; 204: Byte kind = new Byte (request.getEventKind ()); 205: requests = (Hashtable) _requests.get (kind); 206: if (requests == null) 207: { 208: // Did not get a valid event type 209: throw new InvalidEventTypeException (request.getEventKind ()); 210: } 211: 212: // Register the event with the VM 213: VMVirtualMachine.registerEvent (request); 214: requests.put (new Integer (request.getId ()), request); 215: } 216: 217: /** 218: * Deletes the given request from the management table 219: * 220: * @param kind the event kind 221: * @param id the ID of the request to delete 222: * @throws IllegalArgumentException for invalid event kind 223: * @throws JdwpException for other errors deleting request 224: */ 225: public void deleteRequest (byte kind, int id) 226: throws JdwpException 227: { 228: Hashtable requests; 229: requests = (Hashtable) _requests.get (new Byte (kind)); 230: if (requests == null) 231: { 232: // Did not get a valid event type 233: throw new IllegalArgumentException ("invalid event kind: " + kind); 234: } 235: 236: Integer iid = new Integer (id); 237: EventRequest request = (EventRequest) requests.get (iid); 238: if (request != null) 239: { 240: VMVirtualMachine.unregisterEvent (request); 241: requests.remove (iid); 242: } 243: } 244: 245: /** 246: * Clears all the requests for a given event 247: * 248: * @param kind the event kind 249: * @throws IllegalArgumentException for invalid event kind 250: * @throws JdwpException for error clearing events 251: */ 252: public void clearRequests (byte kind) 253: throws JdwpException 254: { 255: Hashtable requests = (Hashtable) _requests.get (new Byte (kind)); 256: if (requests == null) 257: { 258: // Did not get a valid event type 259: throw new IllegalArgumentException ("invalid event kind: " + kind); 260: } 261: 262: VMVirtualMachine.clearEvents (kind); 263: requests.clear (); 264: } 265: 266: /** 267: * Returns a given event request for an event 268: * 269: * @param kind the kind of event for the request 270: * @param id the integer request id to return 271: * @return the request for the given event kind with the given id 272: * (or <code>null</code> if not found) 273: * @throws IllegalArgumentException for invalid event kind 274: */ 275: public EventRequest getRequest (byte kind, int id) 276: { 277: Hashtable requests = (Hashtable) _requests.get (new Byte (kind)); 278: if (requests == null) 279: { 280: // Did not get a valid event type 281: throw new IllegalArgumentException ("invalid event kind: " + kind); 282: } 283: 284: return (EventRequest) requests.get (new Integer (id)); 285: } 286: 287: /** 288: * Returns all requests of the given event kind 289: * 290: * @param kind the event kind 291: * @returns a <code>Collection</code> of all the registered requests 292: * @throws IllegalArgumentException for invalid event kind 293: */ 294: public Collection getRequests (byte kind) 295: { 296: Hashtable requests = (Hashtable) _requests.get (new Byte (kind)); 297: if (requests == null) 298: { 299: // Did not get a valid event type 300: throw new IllegalArgumentException ("invalid event kind: " + kind); 301: } 302: 303: return requests.values (); 304: } 305: }