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