Source for gnu.classpath.jdwp.event.EventRequest

   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: }