Source for gnu.classpath.jdwp.event.EventRequest

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