KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > debug > core > breakpoints > JavaWatchpoint


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.debug.core.breakpoints;
12
13  
14 import java.util.HashMap JavaDoc;
15 import java.util.Map JavaDoc;
16 import org.eclipse.core.resources.IResource;
17 import org.eclipse.core.resources.IWorkspaceRunnable;
18 import org.eclipse.core.runtime.CoreException;
19 import org.eclipse.core.runtime.IProgressMonitor;
20 import org.eclipse.core.runtime.IStatus;
21 import org.eclipse.core.runtime.Status;
22 import org.eclipse.debug.core.DebugException;
23 import org.eclipse.debug.core.DebugPlugin;
24 import org.eclipse.debug.core.model.IDebugTarget;
25 import org.eclipse.jdt.debug.core.IJavaWatchpoint;
26 import org.eclipse.jdt.internal.debug.core.model.JDIDebugTarget;
27 import com.sun.jdi.Field;
28 import com.sun.jdi.ObjectReference;
29 import com.sun.jdi.ReferenceType;
30 import com.sun.jdi.ThreadReference;
31 import com.sun.jdi.VMDisconnectedException;
32 import com.sun.jdi.event.AccessWatchpointEvent;
33 import com.sun.jdi.event.Event;
34 import com.sun.jdi.event.ModificationWatchpointEvent;
35 import com.sun.jdi.request.AccessWatchpointRequest;
36 import com.sun.jdi.request.EventRequest;
37 import com.sun.jdi.request.EventRequestManager;
38 import com.sun.jdi.request.ModificationWatchpointRequest;
39 import com.sun.jdi.request.WatchpointRequest;
40
41 public class JavaWatchpoint extends JavaLineBreakpoint implements IJavaWatchpoint {
42     
43     private static final String JavaDoc JAVA_WATCHPOINT= "org.eclipse.jdt.debug.javaWatchpointMarker"; //$NON-NLS-1$
44
/**
45      * Watchpoint attribute storing the access value (value <code>"org.eclipse.jdt.debug.core.access"</code>).
46      * This attribute is stored as a <code>boolean</code>, indicating whether a
47      * watchpoint is an access watchpoint.
48      */

49     protected static final String JavaDoc ACCESS= "org.eclipse.jdt.debug.core.access"; //$NON-NLS-1$
50
/**
51      * Watchpoint attribute storing the modification value (value <code>"org.eclipse.jdt.debug.core.modification"</code>).
52      * This attribute is stored as a <code>boolean</code>, indicating whether a
53      * watchpoint is a modification watchpoint.
54      */

55     protected static final String JavaDoc MODIFICATION= "org.eclipse.jdt.debug.core.modification"; //$NON-NLS-1$
56
/**
57      * Watchpoint attribute storing the auto_disabled value (value <code>"org.eclipse.jdt.debug.core.auto_disabled"</code>).
58      * This attribute is stored as a <code>boolean</code>, indicating whether a
59      * watchpoint has been auto-disabled (as opposed to being disabled explicitly by the user)
60      */

61     protected static final String JavaDoc AUTO_DISABLED="org.eclipse.jdt.debug.core.auto_disabled"; //$NON-NLS-1$
62

63     /**
64      * Breakpoint attribute storing the name of the field
65      * on which a breakpoint is set.
66      * (value <code>"org.eclipse.jdt.debug.core.fieldName"</code>). This attribute is a <code>String</code>.
67      */

68     protected static final String JavaDoc FIELD_NAME= "org.eclipse.jdt.debug.core.fieldName"; //$NON-NLS-1$
69
/**
70      * Flag indicating that this breakpoint last suspended execution
71      * due to a field access
72      */

73     protected static final Integer JavaDoc ACCESS_EVENT= new Integer JavaDoc(0);
74     /**
75      * Flag indicating that this breakpoint last suspended execution
76      * due to a field modification
77      */

78     protected static final Integer JavaDoc MODIFICATION_EVENT= new Integer JavaDoc(1);
79     /**
80      * Maps each debug target that is suspended for this breakpiont to reason that
81      * this breakpoint suspended it. Reasons include:
82      * <ol>
83      * <li>Field access (value <code>ACCESS_EVENT</code>)</li>
84      * <li>Field modification (value <code>MODIFICATION_EVENT</code>)</li>
85      * </ol>
86      */

87     private HashMap JavaDoc fLastEventTypes= new HashMap JavaDoc(10);
88     
89     public JavaWatchpoint() {
90     }
91
92     /**
93      * @see JDIDebugModel#createWatchpoint(IResource, String, String, int, int, int, int, boolean, Map)
94      */

95     public JavaWatchpoint(final IResource resource, final String JavaDoc typeName, final String JavaDoc fieldName, final int lineNumber, final int charStart, final int charEnd, final int hitCount, final boolean add, final Map JavaDoc attributes) throws DebugException {
96         IWorkspaceRunnable wr= new IWorkspaceRunnable() {
97             public void run(IProgressMonitor monitor) throws CoreException {
98                 setMarker(resource.createMarker(JAVA_WATCHPOINT));
99                 
100                 // add attributes
101
addLineBreakpointAttributes(attributes, getModelIdentifier(), true, lineNumber, charStart, charEnd);
102                 addTypeNameAndHitCount(attributes, typeName, hitCount);
103                 attributes.put(SUSPEND_POLICY, new Integer JavaDoc(getDefaultSuspendPolicy()));
104                 // configure the field handle
105
addFieldName(attributes, fieldName);
106                 // configure the access and modification flags to defaults
107
addDefaultAccessAndModification(attributes);
108                 
109                 // set attributes
110
ensureMarker().setAttributes(attributes);
111                 
112                 register(add);
113             }
114         };
115         run(getMarkerRule(resource), wr);
116     }
117     
118     /**
119      * @see JavaBreakpoint#createRequest(JDIDebugTarget, ReferenceType)
120      *
121      * Creates and installs an access and modification watchpoint request
122      * in the given reference type, configuring the requests as appropriate
123      * for this watchpoint. The requests are then enabled based on whether
124      * this watchpoint is an access watchpoint, modification watchpoint, or
125      * both. Finally, the requests are registered with the given target.
126      */

127     protected boolean createRequest(JDIDebugTarget target, ReferenceType type) throws CoreException {
128         if (shouldSkipBreakpoint()) {
129             return false;
130         }
131         Field field= null;
132         
133         field= type.fieldByName(getFieldName());
134         if (field == null) {
135             // error
136
return false;
137         }
138         AccessWatchpointRequest accessRequest= null;
139         ModificationWatchpointRequest modificationRequest= null;
140         if (target.supportsAccessWatchpoints()) {
141             accessRequest= createAccessWatchpoint(target, field);
142             registerRequest(accessRequest, target);
143         } else {
144             notSupported(JDIDebugBreakpointMessages.JavaWatchpoint_no_access_watchpoints);
145         }
146         if (target.supportsModificationWatchpoints()) {
147             modificationRequest= createModificationWatchpoint(target, field);
148             if (modificationRequest == null) {
149                 return false;
150             }
151             registerRequest(modificationRequest, target);
152             return true;
153         }
154         notSupported(JDIDebugBreakpointMessages.JavaWatchpoint_no_modification_watchpoints);
155         return false;
156     }
157     
158     /**
159      * @see JavaBreakpoint#setRequestThreadFilter(EventRequest)
160      */

161     protected void setRequestThreadFilter(EventRequest request, ThreadReference thread) {
162         ((WatchpointRequest)request).addThreadFilter(thread);
163     }
164     
165     /**
166      * Either access or modification watchpoints are not supported. Throw an appropriate exception.
167      *
168      * @param message the message that states that access or modification watchpoints
169      * are not supported
170      */

171     protected void notSupported(String JavaDoc message) throws DebugException {
172         throw new DebugException(new Status(IStatus.ERROR, DebugPlugin.getUniqueIdentifier(),
173             DebugException.NOT_SUPPORTED, message, null)); //
174
}
175     
176     /**
177      * Create an access watchpoint for the given breakpoint and associated field
178      */

179     protected AccessWatchpointRequest createAccessWatchpoint(JDIDebugTarget target, Field field) throws CoreException {
180         return (AccessWatchpointRequest) createWatchpoint(target, field, true);
181     }
182     
183     /**
184      * Create a modification watchpoint for the given breakpoint and associated field
185      */

186     protected ModificationWatchpointRequest createModificationWatchpoint(JDIDebugTarget target, Field field) throws CoreException {
187         return (ModificationWatchpointRequest) createWatchpoint(target, field, false);
188     }
189     
190     /**
191      * Create a watchpoint for the given breakpoint and associated field.
192      *
193      * @param target the target in which the request will be installed
194      * @param field the field on which the request will be set
195      * @param access <code>true</code> if an access watchpoint will be
196      * created. <code>false</code> if a modification watchpoint will
197      * be created.
198      *
199      * @return an WatchpointRequest (AccessWatchpointRequest if access is
200      * <code>true</code>; ModificationWatchpointRequest if access is <code>false</code>).
201      */

202     protected WatchpointRequest createWatchpoint(JDIDebugTarget target, Field field, boolean access) throws CoreException {
203         WatchpointRequest request= null;
204         EventRequestManager manager = target.getEventRequestManager();
205         if (manager == null) {
206             target.requestFailed(JDIDebugBreakpointMessages.JavaWatchpoint_Unable_to_create_breakpoint_request___VM_disconnected__1, null);
207         }
208         try {
209             if (access) {
210                 request= manager.createAccessWatchpointRequest(field);
211             } else {
212                 request= manager.createModificationWatchpointRequest(field);
213             }
214             configureRequest(request, target);
215         } catch (VMDisconnectedException e) {
216             if (!target.isAvailable()) {
217                 return null;
218             }
219             target.internalError(e);
220             return null;
221         } catch (RuntimeException JavaDoc e) {
222             target.internalError(e);
223             return null;
224         }
225         return request;
226     }
227
228     /**
229      * @see JavaBreakpoint#recreateRequest(EventRequest, JDIDebugTarget)
230      */

231     protected EventRequest recreateRequest(EventRequest request, JDIDebugTarget target) throws CoreException {
232         try {
233             Field field= ((WatchpointRequest) request).field();
234             if (request instanceof AccessWatchpointRequest) {
235                 request= createAccessWatchpoint(target, field);
236             } else if (request instanceof ModificationWatchpointRequest) {
237                 request= createModificationWatchpoint(target, field);
238             }
239         } catch (VMDisconnectedException e) {
240             if (!target.isAvailable()) {
241                 return request;
242             }
243             target.internalError(e);
244             return request;
245         } catch (RuntimeException JavaDoc e) {
246             target.internalError(e);
247         }
248         return request;
249     }
250
251     /**
252      * @see IBreakpoint#setEnabled(boolean)
253      *
254      * If the watchpoint is not watching access or modification,
255      * set the default values. If this isn't done, the resulting
256      * state (enabled with access and modification both disabled)
257      * is ambiguous.
258      */

259     public void setEnabled(boolean enabled) throws CoreException {
260         if (enabled) {
261             if (!(isAccess() || isModification())) {
262                 setDefaultAccessAndModification();
263             }
264         }
265         super.setEnabled(enabled);
266     }
267     
268     /**
269      * @see org.eclipse.debug.core.model.IWatchpoint#isAccess()
270      */

271     public boolean isAccess() throws CoreException {
272         return ensureMarker().getAttribute(ACCESS, false);
273     }
274     
275     /**
276      * Sets whether this breakpoint will suspend execution when its associated
277      * field is accessed. If true and this watchpoint is disabled, this watchpoint
278      * is automatically enabled. If both access and modification are false,
279      * this watchpoint is automatically disabled.
280      *
281      * @param access whether to suspend on field access
282      * @exception CoreException if unable to set the property
283      * on this breakpoint's underlying marker
284      * @see org.eclipse.debug.core.model.IWatchpoint#setAccess(boolean)
285      */

286     public void setAccess(boolean access) throws CoreException {
287         if (access == isAccess()) {
288             return;
289         }
290         setAttribute(ACCESS, access);
291         if (access && !isEnabled()) {
292             setEnabled(true);
293         } else if (!(access || isModification())) {
294             setEnabled(false);
295         }
296         recreate();
297     }
298     
299     /**
300      * @see org.eclipse.debug.core.model.IWatchpoint#isModification()
301      */

302     public boolean isModification() throws CoreException {
303         return ensureMarker().getAttribute(MODIFICATION, false);
304     }
305     
306     /**
307      * Sets whether this breakpoint will suspend execution when its associated
308      * field is modified. If true and this watchpoint is disabled, this watchpoint
309      * is automatically enabled. If both access and modification are false,
310      * this watchpoint is automatically disabled.
311      *
312      * @param modification whether to suspend on field modification
313      * @exception CoreException if unable to set the property on
314      * this breakpoint's underlying marker
315      * @see org.eclipse.debug.core.model.IWatchpoint#setModification(boolean)
316      */

317     public void setModification(boolean modification) throws CoreException {
318         if (modification == isModification()) {
319             return;
320         }
321         setAttribute(MODIFICATION, modification);
322         if (modification && !isEnabled()) {
323             setEnabled(true);
324         } else if (!(modification || isAccess())) {
325             setEnabled(false);
326         }
327         recreate();
328     }
329         
330     /**
331      * Sets the default access and modification attributes of the watchpoint.
332      * The default values are:
333      * <ul>
334      * <li>access = <code>false</code>
335      * <li>modification = <code>true</code>
336      * <ul>
337      */

338     protected void setDefaultAccessAndModification() throws CoreException {
339         Object JavaDoc[] values= new Object JavaDoc[]{Boolean.TRUE, Boolean.TRUE};
340         String JavaDoc[] attributes= new String JavaDoc[]{ACCESS, MODIFICATION};
341         setAttributes(attributes, values);
342     }
343
344
345     /**
346      * Adds the default access and modification attributes of
347      * the watchpoint to the given map
348      * <ul>
349      * <li>access = true
350      * <li>modification = true
351      * <li>auto disabled = false
352      * <ul>
353      */

354     protected void addDefaultAccessAndModification(Map JavaDoc attributes) {
355         attributes.put(ACCESS, Boolean.TRUE);
356         attributes.put(MODIFICATION, Boolean.TRUE);
357         attributes.put(AUTO_DISABLED, Boolean.FALSE);
358     }
359     
360     /**
361      * Adds the field name to the given attribute map
362      */

363     protected void addFieldName(Map JavaDoc attributes, String JavaDoc fieldName) {
364         attributes.put(FIELD_NAME, fieldName);
365     }
366
367     /**
368      * @see IJavaWatchpoint#getFieldName()
369      */

370     public String JavaDoc getFieldName() throws CoreException {
371         return ensureMarker().getAttribute(FIELD_NAME, null);
372     }
373     
374     /**
375      * Store the type of the event, then handle it as specified in
376      * the superclass. This is useful for correctly generating the
377      * thread text when asked (assumes thread text is requested after
378      * the event is passed to this breakpoint.
379      *
380      * Also, @see JavaBreakpoint#handleEvent(Event, JDIDebugTarget)
381      */

382     public boolean handleEvent(Event event, JDIDebugTarget target) {
383         if (event instanceof AccessWatchpointEvent) {
384             fLastEventTypes.put(target, ACCESS_EVENT);
385         } else if (event instanceof ModificationWatchpointEvent) {
386             fLastEventTypes.put(target, MODIFICATION_EVENT);
387         }
388         return super.handleEvent(event, target);
389     }
390     
391     
392     /**
393      * @see JavaBreakpoint#updateEnabledState(EventRequest, JDIDebugTarget)
394      */

395     protected void updateEnabledState(EventRequest request, JDIDebugTarget target) throws CoreException {
396         boolean enabled = isEnabled();
397         if (request instanceof AccessWatchpointRequest) {
398             if (isAccess()) {
399                 if (enabled != request.isEnabled()) {
400                     internalUpdateEnabledState(request, enabled, target);
401                 }
402             } else {
403                 if (request.isEnabled()) {
404                     internalUpdateEnabledState(request, false, target);
405                 }
406             }
407         }
408         if (request instanceof ModificationWatchpointRequest) {
409             if (isModification()) {
410                 if (enabled != request.isEnabled()) {
411                     internalUpdateEnabledState(request, enabled, target);
412                 }
413             } else {
414                 if (request.isEnabled()) {
415                     internalUpdateEnabledState(request, false, target);
416                 }
417             }
418         }
419     }
420     
421     /**
422      * @see IJavaWatchpoint#isAccessSuspend(IDebugTarget)
423      */

424     public boolean isAccessSuspend(IDebugTarget target) {
425         Integer JavaDoc lastEventType= (Integer JavaDoc) fLastEventTypes.get(target);
426         if (lastEventType == null) {
427             return false;
428         }
429         return lastEventType.equals(ACCESS_EVENT);
430     }
431     /**
432      * @see IJavaLineBreakpoint#supportsCondition()
433      */

434     public boolean supportsCondition() {
435         return false;
436     }
437
438     /**
439      * @see org.eclipse.jdt.internal.debug.core.breakpoints.JavaBreakpoint#removeFromTarget(JDIDebugTarget)
440      */

441     public void removeFromTarget(JDIDebugTarget target) throws CoreException {
442         fLastEventTypes.remove(target);
443         super.removeFromTarget(target);
444     }
445     
446     /**
447      * @see org.eclipse.jdt.internal.debug.core.breakpoints.JavaBreakpoint#addInstanceFilter(EventRequest, ObjectReference)
448      */

449     protected void addInstanceFilter(EventRequest request, ObjectReference object) {
450         if (request instanceof WatchpointRequest) {
451             ((WatchpointRequest)request).addInstanceFilter(object);
452         }
453     }
454
455     /* (non-Javadoc)
456      * @see org.eclipse.debug.core.model.IWatchpoint#supportsAccess()
457      */

458     public boolean supportsAccess() {
459         return true;
460     }
461
462     /* (non-Javadoc)
463      * @see org.eclipse.debug.core.model.IWatchpoint#supportsModification()
464      */

465     public boolean supportsModification() {
466         return true;
467     }
468
469     /* (non-Javadoc)
470      * @see org.eclipse.jdt.internal.debug.core.breakpoints.JavaBreakpoint#installableReferenceType(com.sun.jdi.ReferenceType, org.eclipse.jdt.internal.debug.core.model.JDIDebugTarget)
471      */

472     protected boolean installableReferenceType(ReferenceType type, JDIDebugTarget target) throws CoreException {
473         String JavaDoc installableType= getTypeName();
474         String JavaDoc queriedType= type.name();
475         if (installableType == null || queriedType == null) {
476             return false;
477         }
478         if (installableType.equals(queriedType)) {
479             return queryInstallListeners(target, type);
480         }
481         
482         return false;
483     }
484 }
485
Popular Tags