Frames | No Frames |
1: /* EventManager.java -- event management and notification infrastructure 2: Copyright (C) 2005 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.VMVirtualMachine; 43: import gnu.classpath.jdwp.exception.InvalidEventTypeException; 44: 45: import java.util.Collection; 46: import java.util.Hashtable; 47: import java.util.Iterator; 48: 49: /** 50: * Manages event requests and filters event notifications. 51: * 52: * The purpose of this class is actually two-fold: 53: * 54: * 1) Maintain a list of event requests from the debugger 55: * 2) Filter event notifications from the VM 56: * 57: * If an event request arrives from the debugger, the back-end will 58: * call {@link #reqestEvent}, which will first check for a valid event. 59: * If it is valid, <code>EventManager</code> will record the request 60: * internally and register the event with the virtual machine, which may 61: * choose to handle the request itself (as is likely the case with 62: * breakpoints and other execution-related events), or it may decide to 63: * allow the <code>EventManager</code> to handle notifications and all 64: * filtering (which is convenient for other events such as class (un)loading). 65: * 66: * @author Keith Seitz (keiths@redhat.com) 67: */ 68: public class EventManager 69: { 70: // Single instance 71: private static EventManager _instance = new EventManager (); 72: 73: // maps event (EVENT_*) to lists of EventRequests 74: private Hashtable _requests = null; 75: 76: /** 77: * Returns an instance of the event manager 78: * 79: * @return the event manager 80: */ 81: public static EventManager getDefault () 82: { 83: return _instance; 84: } 85: 86: // Private constructs a new <code>EventManager</code> 87: private EventManager () 88: { 89: _requests = new Hashtable (); 90: 91: // Add lists for all the event types 92: _requests.put (new Byte (EventRequest.EVENT_SINGLE_STEP), 93: new Hashtable ()); 94: _requests.put (new Byte (EventRequest.EVENT_BREAKPOINT), 95: new Hashtable ()); 96: _requests.put (new Byte (EventRequest.EVENT_FRAME_POP), 97: new Hashtable ()); 98: _requests.put (new Byte (EventRequest.EVENT_EXCEPTION), 99: new Hashtable ()); 100: _requests.put (new Byte (EventRequest.EVENT_USER_DEFINED), 101: new Hashtable ()); 102: _requests.put (new Byte (EventRequest.EVENT_THREAD_START), 103: new Hashtable ()); 104: _requests.put (new Byte (EventRequest.EVENT_THREAD_END), 105: new Hashtable ()); 106: _requests.put (new Byte (EventRequest.EVENT_CLASS_PREPARE), 107: new Hashtable ()); 108: _requests.put (new Byte (EventRequest.EVENT_CLASS_UNLOAD), 109: new Hashtable ()); 110: _requests.put (new Byte (EventRequest.EVENT_CLASS_LOAD), 111: new Hashtable ()); 112: _requests.put (new Byte (EventRequest.EVENT_FIELD_ACCESS), 113: new Hashtable ()); 114: _requests.put (new Byte (EventRequest.EVENT_FIELD_MODIFY), 115: new Hashtable ()); 116: _requests.put (new Byte (EventRequest.EVENT_METHOD_ENTRY), 117: new Hashtable ()); 118: _requests.put (new Byte (EventRequest.EVENT_METHOD_EXIT), 119: new Hashtable ()); 120: _requests.put (new Byte (EventRequest.EVENT_VM_INIT), 121: new Hashtable ()); 122: _requests.put (new Byte (EventRequest.EVENT_VM_DEATH), 123: new Hashtable ()); 124: 125: // Add auto-generated event notifications 126: // only two: VM_INIT, VM_DEATH 127: try 128: { 129: requestEvent (new EventRequest (0, 130: EventRequest.EVENT_VM_INIT, 131: EventRequest.SUSPEND_NONE)); 132: requestEvent (new EventRequest (0, 133: EventRequest.EVENT_VM_DEATH, 134: EventRequest.SUSPEND_NONE)); 135: } 136: catch (InvalidEventTypeException e) 137: { 138: // This can't happen 139: } 140: } 141: 142: /** 143: * Returns a request for the given event. This method will only 144: * be used if the <code>EventManager</code> is handling event filtering. 145: * 146: * @param event the event 147: * @return request that was interested in this event 148: * or <code>null</code> if none (and event should not be sent) 149: * @throws IllegalArgumentException for invalid event kind 150: */ 151: public EventRequest getEventRequest (Event event) 152: { 153: EventRequest interestedRequest = null; 154: Hashtable requests; 155: Byte kind = new Byte (event.getEventKind ()); 156: requests = (Hashtable) _requests.get (kind); 157: if (requests == null) 158: { 159: // Did not get a valid event type 160: throw new IllegalArgumentException ("invalid event kind: " + kind); 161: } 162: boolean match = false; 163: 164: // Loop through the requests. Must look at ALL requests in order 165: // to evaluate all filters (think count filter). 166: // TODO: What if multiple matches? Spec isn't so clear on this. 167: Iterator rIter = requests.values().iterator (); 168: while (rIter.hasNext ()) 169: { 170: EventRequest request = (EventRequest) rIter.next (); 171: if (request.matches (event)) 172: interestedRequest = request; 173: } 174: 175: return interestedRequest; 176: } 177: 178: /** 179: * Requests monitoring of an event. 180: * 181: * The debugger registers for event notification through 182: * an event filter. If no event filter is specified for an event 183: * in the VM, it is assumed that the debugger is not interested in 184: * receiving notifications of this event. 185: * 186: * The virtual machine will be notified of the request. 187: * 188: * @param request the request to monitor 189: * @throws InvalidEventTypeException for invalid event kind 190: */ 191: public void requestEvent (EventRequest request) 192: throws InvalidEventTypeException 193: { 194: // Add request to request list 195: Hashtable requests; 196: Byte kind = new Byte (request.getEventKind ()); 197: requests = (Hashtable) _requests.get (kind); 198: if (requests == null) 199: { 200: // Did not get a valid event type 201: throw new InvalidEventTypeException (request.getEventKind ()); 202: } 203: 204: // Register the event with the VM 205: VMVirtualMachine.registerEvent (request); 206: requests.put (new Integer (request.getId ()), request); 207: } 208: 209: /** 210: * Deletes the given request from the management table 211: * 212: * @param kind the event kind 213: * @param id the ID of the request to delete 214: * @throws IllegalArgumentException for invalid event kind 215: */ 216: public void deleteRequest (byte kind, int id) 217: { 218: Hashtable requests; 219: requests = (Hashtable) _requests.get (new Byte (kind)); 220: if (requests == null) 221: { 222: // Did not get a valid event type 223: throw new IllegalArgumentException ("invalid event kind: " + kind); 224: } 225: 226: Integer iid = new Integer (id); 227: EventRequest request = (EventRequest) requests.get (iid); 228: if (request != null) 229: { 230: VMVirtualMachine.unregisterEvent (request); 231: requests.remove (iid); 232: } 233: } 234: 235: /** 236: * Clears all the requests for a given event 237: * 238: * @param kind the event kind 239: * @throws IllegalArgumentException for invalid event kind 240: */ 241: public void clearRequests (byte kind) 242: { 243: Hashtable requests = (Hashtable) _requests.get (new Byte (kind)); 244: if (requests == null) 245: { 246: // Did not get a valid event type 247: throw new IllegalArgumentException ("invalid event kind: " + kind); 248: } 249: 250: VMVirtualMachine.clearEvents (kind); 251: requests.clear (); 252: } 253: 254: /** 255: * Returns a given event request for an event 256: * 257: * @param kind the kind of event for the request 258: * @param id the integer request id to return 259: * @return the request for the given event kind with the given id 260: * (or <code>null</code> if not found) 261: * @throws IllegalArgumentException for invalid event kind 262: */ 263: public EventRequest getRequest (byte kind, int id) 264: { 265: Hashtable requests = (Hashtable) _requests.get (new Byte (kind)); 266: if (requests == null) 267: { 268: // Did not get a valid event type 269: throw new IllegalArgumentException ("invalid event kind: " + kind); 270: } 271: 272: return (EventRequest) requests.get (new Integer (id)); 273: } 274: 275: /** 276: * Returns all requests of the given event kind 277: * 278: * @param kind the event kind 279: * @returns a <code>Collection</code> of all the registered requests 280: * @throws IllegalArgumentException for invalid event kind 281: */ 282: public Collection getRequests (byte kind) 283: { 284: Hashtable requests = (Hashtable) _requests.get (new Byte (kind)); 285: if (requests == null) 286: { 287: // Did not get a valid event type 288: throw new IllegalArgumentException ("invalid event kind: " + kind); 289: } 290: 291: return requests.values (); 292: } 293: }