OSDN Git Service

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