OSDN Git Service

Imported GNU Classpath 0.90
[pf3gnuchains/gcc-fork.git] / libjava / classpath / gnu / classpath / jdwp / event / EventRequest.java
1 /* EventRequest.java -- an event request from the debugger
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.JdwpConstants;
43 import gnu.classpath.jdwp.event.filters.*;
44 import gnu.classpath.jdwp.exception.JdwpIllegalArgumentException;
45 import java.util.Collection;
46 import java.util.Iterator;
47 import java.util.LinkedList;
48
49 /**
50  * A class which represents a request by the debugger for an event
51  * in the VM. <code>EventRequest</code>s usually have event filters
52  * associated with them, which allow the debugger to specify conditions
53  * under which the notification should be sent (specific thread, specific
54  * class, ignore count, etc).
55  *
56  * @author Keith Seitz  (keiths@redhat.com)
57  */
58 public class EventRequest
59 {
60   /*
61    * Event types
62    */
63
64   /**
65    * Single step event
66    */
67   public static final byte EVENT_SINGLE_STEP =
68     JdwpConstants.EventKind.SINGLE_STEP;
69
70   /**
71    * Breakpoint event
72    */
73   public static final byte EVENT_BREAKPOINT =
74     JdwpConstants.EventKind.BREAKPOINT;
75
76   /**
77    * Frame pop event
78    */
79   public static final byte EVENT_FRAME_POP =
80     JdwpConstants.EventKind.FRAME_POP;
81
82   /**
83    * Exception event
84    */
85   public static final byte EVENT_EXCEPTION =
86     JdwpConstants.EventKind.EXCEPTION;
87
88   /**
89    * User-defined event
90    */
91   public static final byte EVENT_USER_DEFINED = 
92     JdwpConstants.EventKind.USER_DEFINED;
93
94   /**
95    * Thread start event
96    */
97   public static final byte EVENT_THREAD_START = 
98     JdwpConstants.EventKind.THREAD_START;
99
100   /**
101    * Thread end/death event
102    */
103   public static final byte EVENT_THREAD_END =
104     JdwpConstants.EventKind.THREAD_END;
105
106   /**
107    * Class prepare event
108    */
109   public static final byte EVENT_CLASS_PREPARE =
110     JdwpConstants.EventKind.CLASS_PREPARE;
111
112   /**
113    * Class unload event
114    */
115   public static final byte EVENT_CLASS_UNLOAD =
116     JdwpConstants.EventKind.CLASS_UNLOAD;
117
118   /**
119    * Class load event
120    */
121   public static final byte EVENT_CLASS_LOAD =
122     JdwpConstants.EventKind.CLASS_LOAD;
123
124   /**
125    * Field access event
126    */
127   public static final byte EVENT_FIELD_ACCESS =
128     JdwpConstants.EventKind.FIELD_ACCESS;
129
130   /**
131    * Field modify event
132    */
133   public static final byte EVENT_FIELD_MODIFY =
134     JdwpConstants.EventKind.FIELD_MODIFICATION;
135
136   /**
137    * Method entry event
138    */
139   public static final byte EVENT_METHOD_ENTRY =
140     JdwpConstants.EventKind.METHOD_ENTRY;
141
142   /**
143    * Method exit event
144    */
145   public static final byte EVENT_METHOD_EXIT = 
146     JdwpConstants.EventKind.METHOD_EXIT;
147
148   /**
149    * Virtual machine initialization/start
150    */
151   public static final byte EVENT_VM_INIT =
152     JdwpConstants.EventKind.VM_INIT;
153
154   /**
155    * Virutal machine death
156    */
157   public static final byte EVENT_VM_DEATH =
158     JdwpConstants.EventKind.VM_DEATH;
159
160
161   /*
162    * Suspend policies
163    */
164
165   /**
166    * Do not suspend any threads
167    */
168   public static final byte SUSPEND_NONE = 
169     JdwpConstants.SuspendPolicy.NONE;
170
171   /**
172    * Suspend the thread in which the event occurred
173    */
174   public static final byte SUSPEND_THREAD =
175     JdwpConstants.SuspendPolicy.EVENT_THREAD;
176
177   /**
178    * Suspend all threads
179    */
180   public static final byte SUSPEND_ALL =
181     JdwpConstants.SuspendPolicy.ALL;
182
183   // ID of last EventRequest
184   private static int _last_id = 0;
185   private static Object _idLock = new Object ();
186
187   // A list of filters
188   private LinkedList _filters;
189
190   // The ID of this request
191   private int _id;
192
193   // The suspend policy to enforce when this event occurs
194   private byte _suspendPolicy;
195
196   // Kind of event requested
197   private byte _kind;
198
199   /**
200    * Construct a new <code>EventRequest</code>
201    *
202    * @param kind           the kind of event requested
203    * @param suspendPolicy  how to suspend threads when event occurs
204    */
205   public EventRequest (byte kind, byte suspendPolicy)
206   {
207     _filters = new LinkedList ();
208     synchronized (_idLock)
209       {
210         _id = ++_last_id;
211       }
212     _kind = kind;
213     _suspendPolicy = suspendPolicy;
214   }
215
216   /**
217    * Construct a new <code>EventRequest</code> with the given ID
218    *
219    * @param id             the id of the request to create
220    * @param kind           the kind of event requested
221    * @param suspendPolicy  how to suspend threads when event occurs
222    */
223   public EventRequest (int id, byte kind, byte suspendPolicy)
224   {
225     _filters = new LinkedList ();
226     _kind = kind;
227     _suspendPolicy = suspendPolicy;
228   }
229
230   /**
231    * Creates a new event filter, adding it to this request
232    *
233    * @param  filter  the filter to add
234    * @throws JdwpIllegalArgumentException if an invalid or illegal filter
235    *         is added to the request
236    */
237   public void addFilter (IEventFilter filter)
238     throws JdwpIllegalArgumentException
239   {
240     // Check validity of filter for this request
241     boolean valid = true;
242
243     Class clazz = filter.getClass ();
244     if (clazz == ClassExcludeFilter.class)
245       {
246         if (_kind == EVENT_THREAD_START
247             || _kind == EVENT_THREAD_END)
248           valid = false;
249       }
250     else if (clazz == ClassMatchFilter.class)
251       {
252         if (_kind == EVENT_THREAD_START
253             || _kind == EVENT_THREAD_END)
254           valid = false;
255       }
256     else if (clazz == ClassOnlyFilter.class)
257       {
258         if (_kind == EVENT_CLASS_UNLOAD
259             || _kind == EVENT_THREAD_START
260             || _kind == EVENT_THREAD_END)
261           valid = false;
262       }
263     else if (clazz == ConditionalFilter.class)
264       {
265         // JDWP 1.4 does not say much about this
266       }
267     else if (clazz == CountFilter.class)
268       {
269         // may be used with any event
270       }
271     else if (clazz == ExceptionOnlyFilter.class)
272       {
273         if (_kind != EVENT_EXCEPTION)
274           valid = false;
275       }
276     else if (clazz == FieldOnlyFilter.class)
277       {
278         if (_kind != EVENT_FIELD_ACCESS
279             && _kind != EVENT_FIELD_MODIFY)
280           valid = false;
281       }
282     else if (clazz == InstanceOnlyFilter.class)
283       {
284         if (_kind == EVENT_CLASS_PREPARE
285             || _kind == EVENT_CLASS_UNLOAD
286             || _kind == EVENT_THREAD_START
287             || _kind == EVENT_THREAD_END)
288           valid = false;
289       }
290     else if (clazz == LocationOnlyFilter.class)
291       {
292         if (_kind != EVENT_BREAKPOINT
293             && _kind != EVENT_FIELD_ACCESS
294             && _kind != EVENT_FIELD_MODIFY
295             && _kind != EVENT_SINGLE_STEP
296             && _kind != EVENT_EXCEPTION)
297           valid = false;
298       }
299     else if (clazz == StepFilter.class)
300       {
301         if (_kind != EVENT_SINGLE_STEP)
302           valid = false;
303       }
304     else if (clazz == ThreadOnlyFilter.class)
305       {
306         if (_kind == EVENT_CLASS_UNLOAD)
307           valid = false;
308       }
309
310     if (!valid)
311       {
312         String msg = ("cannot use " + filter.getClass ().getName ()
313                       + " with class unload events");
314         throw new JdwpIllegalArgumentException (msg);
315       }
316
317     // Add filter to list
318     _filters.add (filter);
319   }
320
321   /**
322    * Returns the filters attached to this request
323    */
324   public Collection getFilters ()
325   {
326     return _filters;
327   }
328
329   /**
330    * Returns the suspend policy for this request
331    */
332   public byte getSuspendPolicy ()
333   {
334     return _suspendPolicy;
335   }
336
337   /**
338    * Returns the request id of this request
339    */
340   public int getId ()
341   {
342     return _id;
343   }
344
345   /**
346    * Sets the id of the request (used for auto-generated events)
347    */
348   public void setId (int id)
349   {
350     _id = id;
351   }
352
353   /**
354    * Returns the kind of event for this request
355    */
356   public byte getEventKind ()
357   {
358     return _kind;
359   }
360
361   /**
362    * Determines whether the given event matches this request
363    *
364    * @param  theEvent  the event to compare to
365    */
366   public boolean matches (Event theEvent)
367   {
368     boolean matches = true;
369
370     // Loop through filters; all must match
371     // Note that we must allow EVERY filter to evaluate. This way
372     // things like CountFilter will work.
373     Iterator iter = _filters.iterator ();
374     while (iter.hasNext ())
375       {
376         IEventFilter filter = (IEventFilter) iter.next ();
377         if (!filter.matches (theEvent))
378           matches = false;
379       }
380
381     return matches;
382   }
383 }