1 /*******************************************************************************
2 * Copyright (c) 2000, 2007 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
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package net.sourceforge.phpeclipse.xdebug.php.model;
14 import java.util.ArrayList;
15 //import java.util.Collection;
16 import java.util.HashMap;
17 import java.util.HashSet;
18 //import java.util.Iterator;
19 import java.util.List;
20 //import java.util.Map;
23 import org.eclipse.core.resources.IMarker;
24 import org.eclipse.core.runtime.CoreException;
25 //import org.eclipse.core.runtime.MultiStatus;
26 //import org.eclipse.core.runtime.Preferences;
27 //import org.eclipse.debug.core.DebugEvent;
28 import org.eclipse.debug.core.DebugPlugin;
29 //import org.eclipse.debug.core.IDebugEventSetListener;
30 import org.eclipse.debug.core.model.Breakpoint;
31 //import org.eclipse.debug.core.model.IDebugTarget;
32 import net.sourceforge.phpeclipse.xdebug.php.model.IXDebugBreakpoint;
34 //import org.eclipse.jdt.debug.core.IJavaDebugTarget;
35 import net.sourceforge.phpeclipse.xdebug.php.model.XDebugTarget;
37 //import org.eclipse.jdt.debug.core.IJavaThread;
38 //import net.sourceforge.phpeclipse.xdebug.php.model.XDebugThread;
40 //import org.eclipse.jdt.debug.core.IJavaObject;
41 //import org.eclipse.jdt.debug.core.IJavaType;
42 //import org.eclipse.jdt.debug.core.JDIDebugModel;
43 //import org.eclipse.jdt.internal.debug.core.IJDIEventListener;
44 //import net.sourceforge.phpeclipse.xdebug.core.XDebugCorePlugin;
45 //import org.eclipse.jdt.internal.debug.core.model.JDIDebugTarget;
46 /*import org.eclipse.jdt.internal.debug.core.model.JDIObjectValue;
47 import org.eclipse.jdt.internal.debug.core.model.JDIThread;
48 import org.eclipse.jdt.internal.debug.core.model.JDIType;*/
50 //import com.ibm.icu.text.MessageFormat;
51 //import com.sun.jdi.ObjectReference;
52 //import com.sun.jdi.ReferenceType;
53 /*import com.sun.jdi.ThreadReference;
54 import com.sun.jdi.VMDisconnectedException;
55 import com.sun.jdi.event.ClassPrepareEvent;
56 import com.sun.jdi.event.Event;
57 import com.sun.jdi.event.LocatableEvent;
58 import com.sun.jdi.request.ClassPrepareRequest;
59 import com.sun.jdi.request.EventRequest;
60 import com.sun.jdi.request.EventRequestManager;
62 public abstract class XDebugBreakpoint extends Breakpoint implements IXDebugBreakpoint/*,*/ /*IJDIEventListener,*/ /*IDebugEventSetListener*/ {
65 * Breakpoint attribute storing the expired value (value <code>"org.eclipse.jdt.debug.core.expired"</code>).
66 * This attribute is stored as a <code>boolean</code>. Once a hit count has
67 * been reached, a breakpoint is considered to be "expired".
69 protected static final String EXPIRED = "org.eclipse.jdt.debug.core.expired"; //$NON-NLS-1$
71 * Breakpoint attribute storing a breakpoint's hit count value
72 * (value <code>"org.eclipse.jdt.debug.core.hitCount"</code>). This attribute is stored as an
75 // protected static final String HIT_COUNT = "net.sourceforge.phpeclipse.xdebug.php.model.hitCount"; //$NON-NLS-1$
76 protected static final String HIT_COUNT = "net.sourceforge.phpeclipse.debug.hitCount"; //$NON-NLS-1$
79 * Breakpoint attribute storing a breakpoint's changeID. This is used for
80 * checking whether the breakpoint properties menu was finished with a
81 * OK-button. Which means a possible change of breakpoint condition or skip
82 * count. This is necessary because in method breakpointChanged in class
83 * PHPDebugTarget we need to know, whether the breakpoint has changed or not
84 * (breakpointChanged is called also when a PHP source file is modified and
87 protected static final String CHANGE_ID = "net.sourceforge.phpeclipse.debug.changeID"; //$NON-NLS-1$
91 * Breakpoint attribute storing a breakpoint's condition (value
92 * <code>"net.sourceforge.phpeclipse.debug.condition"</code>). This
93 * attribute is stored as an <code>string</code>.
95 protected static final String CONDITION = "net.sourceforge.phpeclipse.debug.condition"; //$NON-NLS-1$
98 * Breakpoint attribute storing whether a breakpoint's condition is enabled
100 * <code>"net.sourceforge.phpeclipse.debug.conditionEnabled"</code>).
101 * This attribute is stored as an <code>boolean</code>.
103 protected static final String CONDITION_ENABLED = "net.sourceforge.phpeclipse.debug.conditionEnabled"; //$NON-NLS-1$
106 * Breakpoint attribute storing the number of debug targets a
107 * breakpoint is installed in (value <code>"org.eclipse.jdt.debug.core.installCount"</code>).
108 * This attribute is a <code>int</code>.
110 protected static final String INSTALL_COUNT = "org.eclipse.jdt.debug.core.installCount"; //$NON-NLS-1$
113 * Breakpoint attribute storing the fully qualified name of the type
114 * this breakpoint is located in.
115 * (value <code>"org.eclipse.jdt.debug.core.typeName"</code>). This attribute is a <code>String</code>.
117 protected static final String TYPE_NAME = "org.eclipse.jdt.debug.core.typeName"; //$NON-NLS-1$
120 * Stores the collection of requests that this breakpoint has installed in
122 * key: a debug target
123 * value: the requests this breakpoint has installed in that target
125 protected HashMap fRequestsByTarget;
128 * The list of threads (ThreadReference objects) in which this breakpoint will suspend,
129 * associated with the target in which each thread exists (JDIDebugTarget).
130 * key: targets the debug targets (IJavaDebugTarget)
131 * value: thread the filtered thread (IJavaThread) in the given target
133 //protected Map fFilteredThreadsByTarget;
136 * Stores the type name that this breakpoint was last installed
137 * in. When a breakpoint is created, the TYPE_NAME attribute assigned to it
138 * is that of its top level enclosing type. When installed, the type
139 * may actually be an inner type. We need to keep track of the type
140 * type the breakpoint was installed in, in case we need to re-install
141 * the breakpoint for HCR (i.e. in case an inner type is HCR'd).
143 protected String fInstalledTypeName = null;
146 * List of targets in which this breakpoint is installed.
147 * Used to prevent firing of more than one install notification
148 * when a breakpoint's requests are re-created.
150 protected Set fInstalledTargets = null;
153 * List of active instance filters for this breakpoint
154 * (list of <code>IJavaObject</code>).
156 protected List fInstanceFilters = null;
159 * Empty instance filters array.
161 protected static final /*IJava*/Object[] fgEmptyInstanceFilters = new /*IJava*/Object[0];
164 * Property identifier for a breakpoint object on an event request
166 public static final String JAVA_BREAKPOINT_PROPERTY = "org.eclipse.jdt.debug.breakpoint"; //$NON-NLS-1$
169 * JavaBreakpoint attributes
171 protected static final String[] fgExpiredEnabledAttributes= new String[]{EXPIRED, ENABLED};
173 public XDebugBreakpoint() {
174 fRequestsByTarget = new HashMap(1);
175 //fFilteredThreadsByTarget= new HashMap(1);
179 * @see org.eclipse.debug.core.model.IBreakpoint#getModelIdentifier()
181 public String getModelIdentifier() {
182 return "asd"; //JDIDebugModel.getPluginIdentifier();
186 * @see org.eclipse.debug.core.model.Breakpoint#setMarker(org.eclipse.core.resources.IMarker)
188 public void setMarker(IMarker marker) throws CoreException {
189 super.setMarker(marker);
190 configureAtStartup();
194 * Add this breakpoint to the breakpoint manager,
195 * or sets it as unregistered.
197 protected void register(boolean register) throws CoreException {
198 DebugPlugin plugin = DebugPlugin.getDefault();
199 if (plugin != null && register) {
200 plugin.getBreakpointManager().addBreakpoint(this);
202 setRegistered(false);
207 * Add the given event request to the given debug target. If
208 * the request is the breakpoint request associated with this
209 * breakpoint, increment the install count.
211 /*protected void registerRequest(EventRequest request, XDebugTarget target) throws CoreException {
212 if (request == null) {
215 List reqs = getRequests(target);
216 if (reqs.isEmpty()) {
217 fRequestsByTarget.put(target, reqs);
220 target.addJDIEventListener(this, request);
221 // update the install attribute on the breakpoint
222 if (!(request instanceof ClassPrepareRequest)) {
223 incrementInstallCount();
225 fireInstalled(target);
230 * Returns a String corresponding to the reference type
231 * name to the top enclosing type in which this breakpoint
232 * is located or <code>null</code> if no reference type could be
235 /*protected String getEnclosingReferenceTypeName() throws CoreException {
236 String name= getTypeName();
237 int index = name.indexOf('$');
241 return name.substring(0, index);
245 * Returns the requests that this breakpoint has installed
246 * in the given target.
248 protected ArrayList getRequests(XDebugTarget target) {
249 ArrayList list= (ArrayList)fRequestsByTarget.get(target);
251 list= new ArrayList(2);
257 * Remove the given request from the given target. If the request
258 * is the breakpoint request associated with this breakpoint,
259 * decrement the install count.
261 /*protected void deregisterRequest(EventRequest request, XDebugTarget target) throws CoreException {
262 target.removeJDIEventListener(this, request);
263 // A request may be getting de-registered because the breakpoint has
264 // been deleted. It may be that this occurred because of a marker deletion.
265 // Don't try updating the marker (decrementing the install count) if
266 // it no longer exists.
267 if (!(request instanceof ClassPrepareRequest) && getMarker().exists()) {
268 decrementInstallCount();
273 * @see org.eclipse.jdt.internal.debug.core.IJDIEventListener#handleEvent(com.sun.jdi.event.Event, org.eclipse.jdt.internal.debug.core.model.JDIDebugTarget)
275 /*public boolean handleEvent(Event event, XDebugTarget target) {
276 if (event instanceof ClassPrepareEvent) {
277 return handleClassPrepareEvent((ClassPrepareEvent)event, target);
279 ThreadReference threadRef= ((LocatableEvent)event).thread();
280 XDebugThread thread= target.findThread(threadRef);
281 if (thread == null || thread.isIgnoringBreakpoints()) {
284 return handleBreakpointEvent(event, target, thread);
288 * @see org.eclipse.jdt.internal.debug.core.IJDIEventListener#wonSuspendVote(com.sun.jdi.event.Event, org.eclipse.jdt.internal.debug.core.model.JDIDebugTarget)
290 /*public void wonSuspendVote(Event event, XDebugTarget target) {
291 ThreadReference threadRef = null;
292 if (event instanceof ClassPrepareEvent) {
293 threadRef = ((ClassPrepareEvent)event).thread();
294 } else if (event instanceof LocatableEvent) {
295 threadRef = ((LocatableEvent)event).thread();
297 if (threadRef == null) {
300 XDebugThread thread= target.findThread(threadRef);
301 if (thread == null || thread.isIgnoringBreakpoints()) {
304 thread.wonSuspendVote(this);
308 * Handle the given class prepare event, which was generated by the
309 * class prepare event installed in the given target by this breakpoint.
311 * If the class which has been loaded is a class in which this breakpoint
312 * should install, create a breakpoint request for that class.
314 /*public boolean handleClassPrepareEvent(ClassPrepareEvent event, XDebugTarget target) {
316 if (!installableReferenceType(event.referenceType(), target)) {
317 // Don't install this breakpoint in an
318 // inappropriate type
321 createRequest(target, event.referenceType());
322 } catch (CoreException e) {
323 XDebugCorePlugin.log(e);
329 * @see IJDIEventListener#handleEvent(Event, JDIDebugTarget)
331 * Handle the given event, which was generated by the breakpoint request
332 * installed in the given target by this breakpoint.
334 /*public boolean handleBreakpointEvent(Event event, XDebugTarget target, XDebugThread thread) {
335 expireHitCount(event);
336 return !suspend(thread); // Resume if suspend fails
340 * Delegates to the given thread to suspend, and
341 * returns whether the thread suspended
342 * It is possible that the thread will not suspend
343 * as directed by a Java breakpoint listener.
345 * @see IJavaBreakpointListener#breakpointHit(IJavaThread, IJavaBreakpoint)
347 /*protected boolean suspend(XDebugThread thread) {
348 return thread.handleSuspendForBreakpoint(this, true);
352 * Returns whether the given reference type is appropriate for this
353 * breakpoint to be installed in the given target. Query registered
354 * breakpoint listeners.
356 /*protected boolean installableReferenceType(ReferenceType type, XDebugTarget target) throws CoreException {
357 String installableType= getTypeName();
358 String queriedType= type.name();
359 if (installableType == null || queriedType == null) {
362 int index= queriedType.indexOf('<');
364 queriedType= queriedType.substring(0, index);
366 if (installableType.equals(queriedType)) {
367 return queryInstallListeners(target, type);
369 index= queriedType.indexOf('$', 0);
373 if (installableType.regionMatches(0, queriedType, 0, index)) {
374 return queryInstallListeners(target, type);
380 * Called when a breakpoint event is encountered. Expires the
381 * hit count in the event's request and updates the marker.
382 * @param event the event whose request should have its hit count
383 * expired or <code>null</code> to only update the breakpoint marker.
385 /*protected void expireHitCount(Event event) {
386 Integer requestCount= null;
387 EventRequest request= null;
389 request= event.request();
390 requestCount= (Integer) request.getProperty(HIT_COUNT);
392 if (requestCount != null) {
393 if (request != null) {
394 request.putProperty(EXPIRED, Boolean.TRUE);
397 setAttributes(fgExpiredEnabledAttributes, new Object[]{Boolean.TRUE, Boolean.FALSE});
398 // make a note that we auto-disabled this breakpoint.
399 } catch (CoreException ce) {
400 XDebugCorePlugin.log(ce);
406 * Returns whether this breakpoint should be "skipped". Breakpoints
407 * are skipped if the breakpoint manager is disabled and the breakpoint
408 * is registered with the manager
410 * @return whether this breakpoint should be skipped
412 public boolean shouldSkipBreakpoint() throws CoreException {
413 DebugPlugin plugin = DebugPlugin.getDefault();
414 return plugin != null && isRegistered() && !plugin.getBreakpointManager().isEnabled();
418 * Attempts to create a breakpoint request for this breakpoint in the given
419 * reference type in the given target.
421 * @return Whether a request was created
423 /*protected boolean createRequest(XDebugTarget target, ReferenceType type) throws CoreException {
424 if (shouldSkipBreakpoint()) {
427 EventRequest[] requests= newRequests(target, type);
428 if (requests == null) {
431 fInstalledTypeName = type.name();
432 for (int i = 0; i < requests.length; i++) {
433 EventRequest request = requests[i];
434 registerRequest(request, target);
440 * Configure a breakpoint request with common properties:
442 * <li><code>JAVA_BREAKPOINT_PROPERTY</code></li>
443 * <li><code>HIT_COUNT</code></li>
444 * <li><code>EXPIRED</code></li>
446 * and sets the suspend policy of the request to suspend
449 /*protected void configureRequest(EventRequest request, XDebugTarget target) throws CoreException {
450 request.setSuspendPolicy(getJDISuspendPolicy());
451 request.putProperty(JAVA_BREAKPOINT_PROPERTY, this);
452 configureRequestThreadFilter(request, target);
453 configureRequestHitCount(request);
454 configureInstanceFilters(request, target);
455 // Important: only enable a request after it has been configured
456 updateEnabledState(request, target);
460 * Adds an instance filter to the given request. Since the implementation is
461 * request specific, subclasses must override.
464 * @param object instance filter
466 //protected abstract void addInstanceFilter(EventRequest request, ObjectReference object);
469 * Configure the thread filter property of the given request.
471 /*protected void configureRequestThreadFilter(EventRequest request, XDebugTarget target) {
472 IJavaThread thread= (IJavaThread)fFilteredThreadsByTarget.get(target);
473 if (thread == null || (!(thread instanceof JDIThread))) {
476 setRequestThreadFilter(request, ((JDIThread)thread).getUnderlyingThread());
480 * Configure the given request's hit count
482 /*protected void configureRequestHitCount(EventRequest request) throws CoreException {
483 int hitCount= getHitCount();
485 request.addCountFilter(hitCount);
486 request.putProperty(HIT_COUNT, new Integer(hitCount));
490 /*protected void configureInstanceFilters(EventRequest request, XDebugTarget target) {
491 if (fInstanceFilters != null && !fInstanceFilters.isEmpty()) {
492 Iterator iter = fInstanceFilters.iterator();
493 while (iter.hasNext()) {*/
494 /*IJava*//*Object object = (*//*IJava*//*Object)iter.next();
495 if (object.getDebugTarget().equals(target)) {
496 addInstanceFilter(request, ((JDIObjectValue)object).getUnderlyingObject());
503 * Creates, installs, and returns all event requests for this breakpoint
504 * in the given reference type and and target.
506 * @return the event requests created or <code>null</code> if creation failed
508 //protected abstract EventRequest[] newRequests(XDebugTarget target, ReferenceType type) throws CoreException;
511 * Add this breakpoint to the given target. After it has been
512 * added to the given target, this breakpoint will suspend
513 * execution of that target as appropriate.
515 /*public void addToTarget(XDebugTarget target) throws CoreException {
517 createRequests(target);
521 * Creates event requests for the given target
523 /*protected void createRequests(XDebugTarget target) throws CoreException {
524 if (target.isTerminated() || shouldSkipBreakpoint()) {
527 String referenceTypeName= getTypeName();
528 String enclosingTypeName= getEnclosingReferenceTypeName();
529 if (referenceTypeName == null || enclosingTypeName == null) {
532 // create request to listen to class loads
533 if (referenceTypeName.indexOf('$') == -1) {
534 registerRequest(target.createClassPrepareRequest(enclosingTypeName), target);
535 //register to ensure we hear about local and anonymous inner classes
536 registerRequest(target.createClassPrepareRequest(enclosingTypeName + "$*"), target); //$NON-NLS-1$
538 registerRequest(target.createClassPrepareRequest(referenceTypeName), target);
539 //register to ensure we hear about local and anonymous inner classes
540 registerRequest(target.createClassPrepareRequest(enclosingTypeName + "$*", referenceTypeName), target); //$NON-NLS-1$
543 // create breakpoint requests for each class currently loaded
544 List classes= target.jdiClassesByName(referenceTypeName);
545 if (classes.isEmpty() && enclosingTypeName.equals(referenceTypeName)) {
549 boolean success= false;
550 Iterator iter = classes.iterator();
551 while (iter.hasNext()) {
552 ReferenceType type= (ReferenceType) iter.next();
553 if (createRequest(target, type)) {
559 addToTargetForLocalType(target, enclosingTypeName);
564 * Local types (types defined in methods) are handled specially due to the
565 * different types that the local type is associated with as well as the
566 * performance problems of using ReferenceType#nestedTypes. From the Java
567 * model perspective a local type is defined within a method of a type.
568 * Therefore the type of a breakpoint placed in a local type is the type
569 * that encloses the method where the local type was defined.
570 * The local type is enclosed within the top level type according
572 * So if "normal" attempts to create a request when a breakpoint is
573 * being added to a target fail, we must be dealing with a local type and therefore resort
574 * to looking up all of the nested types of the top level enclosing type.
576 /*protected void addToTargetForLocalType(XDebugTarget target, String enclosingTypeName) throws CoreException {
577 List classes= target.jdiClassesByName(enclosingTypeName);
578 if (!classes.isEmpty()) {
579 Iterator iter = classes.iterator();
580 while (iter.hasNext()) {
581 ReferenceType type= (ReferenceType) iter.next();
582 Iterator nestedTypes= type.nestedTypes().iterator();
583 while (nestedTypes.hasNext()) {
584 ReferenceType nestedType= (ReferenceType) nestedTypes.next();
585 if (createRequest(target, nestedType)) {
594 * Returns the JDI suspend policy that corresponds to this
595 * breakpoint's suspend policy
597 * @return the JDI suspend policy that corresponds to this
598 * breakpoint's suspend policy
599 * @exception CoreException if unable to access this breakpoint's
600 * suspend policy setting
602 /*protected int getJDISuspendPolicy() throws CoreException {
603 int breakpointPolicy = getSuspendPolicy();
604 if (breakpointPolicy == IXDebugBreakpoint.SUSPEND_THREAD) {
605 return EventRequest.SUSPEND_EVENT_THREAD;
607 return EventRequest.SUSPEND_ALL;
611 * returns the default suspend policy based on the pref setting on the
612 * Java-Debug pref page
613 * @return the default suspend policy
616 /*protected int getDefaultSuspendPolicy() {
617 Preferences store = JDIDebugModel.getPreferences();
618 return store.getInt(JDIDebugPlugin.PREF_DEFAULT_BREAKPOINT_SUSPEND_POLICY);
623 * Returns whether the hitCount of this breakpoint is equal to the hitCount of
624 * the associated request.
626 /*protected boolean hasHitCountChanged(EventRequest request) throws CoreException {
627 int hitCount= getHitCount();
628 Integer requestCount= (Integer) request.getProperty(HIT_COUNT);
630 if (requestCount != null) {
631 oldCount = requestCount.intValue();
633 return hitCount != oldCount;
637 * Removes this breakpoint from the given target.
639 /*public void removeFromTarget(final XDebugTarget target) throws CoreException {
640 removeRequests(target);
641 Object removed = fFilteredThreadsByTarget.remove(target);
642 boolean changed = removed != null;
643 boolean markerExists = markerExists();
644 if (!markerExists || (markerExists && getInstallCount() == 0)) {
645 fInstalledTypeName = null;
648 // remove instance filters
649 if (fInstanceFilters != null && !fInstanceFilters.isEmpty()) {
650 for (int i = 0; i < fInstanceFilters.size(); i++) {
651 IJavaObject object = (IJavaObject)fInstanceFilters.get(i);
652 if (object.getDebugTarget().equals(target)) {
653 fInstanceFilters.remove(i);
659 // fire change notification if required
669 * Remove all requests that this breakpoint has installed in the given
672 /*protected void removeRequests(final XDebugTarget target) throws CoreException {
673 // removing was previously done is a workspace runnable, but that is
674 // not possible since it can be a resource callback (marker deletion) that
675 // causes a breakpoint to be removed
676 ArrayList requests= (ArrayList)getRequests(target).clone();
677 // Iterate over a copy of the requests since this list of requests
678 // can be changed in other threads which would cause an ConcurrentModificationException
679 Iterator iter = requests.iterator();
681 while (iter.hasNext()) {
682 req = (EventRequest)iter.next();
684 if (target.isAvailable() && !isExpired(req)) { // cannot delete an expired request
685 EventRequestManager manager = target.getEventRequestManager();
686 if (manager != null) {
687 manager.deleteEventRequest(req); // disable & remove
690 } catch (VMDisconnectedException e) {
691 if (target.isAvailable()) {
692 JDIDebugPlugin.log(e);
694 } catch (RuntimeException e) {
695 target.internalError(e);
697 deregisterRequest(req, target);
700 fRequestsByTarget.remove(target);
704 * Update the enabled state of the given request in the given target, which is associated
705 * with this breakpoint. Set the enabled state of the request
706 * to the enabled state of this breakpoint.
708 /*protected void updateEnabledState(EventRequest request, XDebugTarget target) throws CoreException {
709 internalUpdateEnabledState(request, isEnabled(), target);
713 * Set the enabled state of the given request to the given
714 * value, also taking into account instance filters.
716 /*protected void internalUpdateEnabledState(EventRequest request, boolean enabled, XDebugTarget target) {
717 if (request.isEnabled() != enabled) {
718 // change the enabled state
720 // if the request has expired, do not disable.
721 // BreakpointRequests that have expired cannot be deleted.
722 if (!isExpired(request)) {
723 request.setEnabled(enabled);
725 //} catch (VMDisconnectedException e) {
726 } catch (RuntimeException e) {
727 //target.internalError(e);
733 * Returns whether this breakpoint has expired.
735 public boolean isExpired() throws CoreException {
736 return ensureMarker().getAttribute(EXPIRED, false);
740 * Returns whether the given request is expired
742 /*protected boolean isExpired(EventRequest request) {
743 Boolean requestExpired= (Boolean) request.getProperty(EXPIRED);
744 if (requestExpired == null) {
747 return requestExpired.booleanValue();
751 * @see org.eclipse.jdt.debug.core.IJavaBreakpoint#isInstalled()
753 public boolean isInstalled() throws CoreException {
754 return ensureMarker().getAttribute(INSTALL_COUNT, 0) > 0;
758 * Increments the install count of this breakpoint
760 protected void incrementInstallCount() throws CoreException {
761 int count = getInstallCount();
762 setAttribute(INSTALL_COUNT, count + 1);
766 * Returns the <code>INSTALL_COUNT</code> attribute of this breakpoint
767 * or 0 if the attribute is not set.
769 public int getInstallCount() throws CoreException {
770 return ensureMarker().getAttribute(INSTALL_COUNT, 0);
774 * Decrements the install count of this breakpoint.
776 protected void decrementInstallCount() throws CoreException {
777 int count= getInstallCount();
779 setAttribute(INSTALL_COUNT, count - 1);
783 // if breakpoint was auto-disabled, re-enable it
784 setAttributes(fgExpiredEnabledAttributes,
785 new Object[]{Boolean.FALSE, Boolean.TRUE});
791 * Sets the type name in which to install this breakpoint.
793 protected void setTypeName(String typeName) throws CoreException {
794 setAttribute(TYPE_NAME, typeName);
798 * @see org.eclipse.jdt.debug.core.IJavaBreakpoint#getTypeName()
800 public String getTypeName() throws CoreException {
801 if (fInstalledTypeName == null) {
802 return ensureMarker().getAttribute(TYPE_NAME, null);
804 return fInstalledTypeName;
808 * Resets the install count attribute on this breakpoint's marker
809 * to "0". Resets the expired attribute on all breakpoint markers to <code>false</code>.
810 * Resets the enabled attribute on the breakpoint marker to <code>true</code>.
811 * If a workbench crashes, the attributes could have been persisted
812 * in an incorrect state.
814 private void configureAtStartup() throws CoreException {
815 List attributes= null;
818 attributes= new ArrayList(3);
819 values= new ArrayList(3);
820 attributes.add(INSTALL_COUNT);
821 values.add(new Integer(0));
824 if (attributes == null) {
825 attributes= new ArrayList(3);
826 values= new ArrayList(3);
828 // if breakpoint was auto-disabled, re-enable it
829 attributes.add(EXPIRED);
830 values.add(Boolean.FALSE);
831 attributes.add(ENABLED);
832 values.add(Boolean.TRUE);
834 if (attributes != null) {
835 String[] strAttributes= new String[attributes.size()];
836 setAttributes((String[])attributes.toArray(strAttributes), values.toArray());
841 * @see org.eclipse.jdt.debug.core.IJavaBreakpoint#getHitCount()
843 public int getHitCount() throws CoreException {
844 return ensureMarker().getAttribute(HIT_COUNT, -1);
848 * @see org.eclipse.jdt.debug.core.IJavaBreakpoint#setHitCount(int)
850 public void setHitCount(int count) throws CoreException {
851 if (getHitCount() != count) {
852 if (!isEnabled() && count > -1) {
853 setAttributes(new String []{ENABLED, HIT_COUNT, EXPIRED},
854 new Object[]{Boolean.TRUE, new Integer(count), Boolean.FALSE});
856 setAttributes(new String[]{HIT_COUNT, EXPIRED},
857 new Object[]{new Integer(count), Boolean.FALSE});
863 protected String getMarkerMessage(int hitCount, int suspendPolicy) {
864 StringBuffer buff= new StringBuffer();
866 buff.append(MessageFormat.format(JDIDebugBreakpointMessages.JavaBreakpoint___Hit_Count___0___1, new Object[]{Integer.toString(hitCount)}));
869 String suspendPolicyString;
870 if (suspendPolicy == IJavaBreakpoint.SUSPEND_THREAD) {
871 suspendPolicyString= JDIDebugBreakpointMessages.JavaBreakpoint__suspend_policy__thread__1;
873 suspendPolicyString= JDIDebugBreakpointMessages.JavaBreakpoint__suspend_policy__VM__2;
876 buff.append(suspendPolicyString);*/
877 return buff.toString();
881 * Sets whether this breakpoint's hit count has expired.
883 public void setExpired(boolean expired) throws CoreException {
884 setAttribute(EXPIRED, expired);
888 * @see org.eclipse.jdt.debug.core.IJavaBreakpoint#getSuspendPolicy()
890 /*public int getSuspendPolicy() throws CoreException {
891 return ensureMarker().getAttribute(SUSPEND_POLICY, IJavaBreakpoint.SUSPEND_THREAD);
895 * @see org.eclipse.jdt.debug.core.IJavaBreakpoint#setSuspendPolicy(int)
897 /*public void setSuspendPolicy(int suspendPolicy) throws CoreException {
898 if(getSuspendPolicy() != suspendPolicy) {
899 setAttribute(SUSPEND_POLICY, suspendPolicy);
905 * Notifies listeners this breakpoint is to be added to the
908 * @param target debug target
910 /*protected void fireAdding(XDebugTarget target) {
911 XDebugCorePlugin plugin = XDebugCorePlugin.getDefault();
913 plugin.fireBreakpointAdding(target, this);
917 * Notifies listeners this breakpoint has been removed from the
920 * @param target debug target
922 /*protected void fireRemoved(XDebugTarget target) {
923 XDebugCorePlugin plugin = XDebugCorePlugin.getDefault();
924 if (plugin != null) {
925 plugin.fireBreakpointRemoved(target, this);
926 setInstalledIn(target, false);
931 * Notifies listeners this breakpoint has been installed in the
934 * @param target debug target
936 /*protected void fireInstalled(XDebugTarget target) {
937 XDebugCorePlugin plugin = XDebugCorePlugin.getDefault();
938 if (plugin!= null && !isInstalledIn(target)) {
939 plugin.fireBreakpointInstalled(target, this);
940 setInstalledIn(target, true);
945 * Returns whether this breakpoint is installed in the given target.
948 * @return whether this breakpoint is installed in the given target
950 protected boolean isInstalledIn(XDebugTarget target) {
951 return fInstalledTargets != null && fInstalledTargets.contains(target);
955 * Sets this breakpoint as installed in the given target
958 * @param installed whether installed
960 protected void setInstalledIn(XDebugTarget target, boolean installed) {
962 if (fInstalledTargets == null) {
963 fInstalledTargets = new HashSet();
965 fInstalledTargets.add(target);
967 if (fInstalledTargets != null) {
968 fInstalledTargets.remove(target);
974 * @see org.eclipse.jdt.debug.core.IJavaBreakpoint#setThreadFilter(org.eclipse.jdt.debug.core.IJavaThread)
976 /*public void setThreadFilter(IJavaThread thread) throws CoreException {
977 if (!(thread.getDebugTarget() instanceof JDIDebugTarget) || !(thread instanceof JDIThread)) {
980 JDIDebugTarget target= (JDIDebugTarget)thread.getDebugTarget();
981 if (thread != fFilteredThreadsByTarget.put(target, thread) ) {
982 // recreate the breakpoint only if it is not the same thread
984 // Other breakpoints set attributes on the underlying
985 // marker and the marker changes are eventually
986 // propagated to the target. The target then asks the
987 // breakpoint to update its request. Since thread filters
988 // are transient properties, they are not set on
989 // the marker. Thus we must update the request
997 * @see org.eclipse.debug.core.IDebugEventSetListener#handleDebugEvents(org.eclipse.debug.core.DebugEvent[])
999 /*public void handleDebugEvents(DebugEvent[] events) {
1000 for (int i = 0; i < events.length; i++) {
1001 DebugEvent event = events[i];
1002 if (event.getKind() == DebugEvent.TERMINATE) {
1003 Object source= event.getSource();
1004 if (!(source instanceof JDIThread)) {
1008 cleanupForThreadTermination((JDIThread)source);
1009 } catch (VMDisconnectedException exception) {
1010 // Thread death often occurs at shutdown.
1011 // A VMDisconnectedException trying to
1012 // update the breakpoint request is
1020 * Removes cached information relevant to this thread which has
1023 * Remove thread filters for terminated threads
1025 * Subclasses may override but need to call super.
1027 /*protected void cleanupForThreadTermination(JDIThread thread) {
1028 JDIDebugTarget target= (JDIDebugTarget)thread.getDebugTarget();
1030 if (thread == getThreadFilter(target)) {
1031 removeThreadFilter(target);
1033 } catch (CoreException exception) {
1034 JDIDebugPlugin.log(exception);
1039 * EventRequest does not support thread filters, so they
1040 * can't be set generically here. However, each of the breakpoint
1041 * subclasses of EventRequest do support thread filters. So
1042 * subclasses can set thread filters on their specific
1045 //protected abstract void setRequestThreadFilter(EventRequest request, ThreadReference thread);
1048 * @see org.eclipse.jdt.debug.core.IJavaBreakpoint#getThreadFilter(org.eclipse.jdt.debug.core.IJavaDebugTarget)
1050 /*public IJavaThread getThreadFilter(IJavaDebugTarget target) {
1051 return (IJavaThread)fFilteredThreadsByTarget.get(target);
1055 * @see org.eclipse.jdt.debug.core.IJavaBreakpoint#getThreadFilters()
1057 /*public IJavaThread[] getThreadFilters() {
1058 IJavaThread[] threads= null;
1059 Collection values= fFilteredThreadsByTarget.values();
1060 threads= new IJavaThread[values.size()];
1061 values.toArray(threads);
1066 * @see org.eclipse.jdt.debug.core.IJavaBreakpoint#removeThreadFilter(org.eclipse.jdt.debug.core.IJavaDebugTarget)
1068 /*public void removeThreadFilter(XDebugTarget javaTarget) throws CoreException {
1069 if (!(javaTarget instanceof XDebugTarget)) {
1072 XDebugTarget target= (XDebugTarget)javaTarget;
1073 if (fFilteredThreadsByTarget.remove(target) != null) {
1080 * Returns whether this breakpoint should be installed in the given reference
1081 * type in the given target according to registered breakpoint listeners.
1083 * @param target debug target
1084 * @param type reference type or <code>null</code> if this breakpoint is
1085 * not installed in a specific type
1087 /*protected boolean queryInstallListeners(XDebugTarget target, ReferenceType type) {
1088 XDebugCorePlugin plugin = XDebugCorePlugin.getDefault();
1089 if (plugin != null) {
1090 IJavaType jt = null;
1092 jt = JDIType.createType(target, type);
1094 return plugin.fireInstalling(target, this, jt);
1100 * @see org.eclipse.jdt.debug.core.IJavaBreakpoint#addInstanceFilter(org.eclipse.jdt.debug.core.IJavaObject)
1102 public void addInstanceFilter(/*IJava*/Object object) throws CoreException {
1103 if (fInstanceFilters == null) {
1104 fInstanceFilters= new ArrayList();
1106 if (!fInstanceFilters.contains(object)) {
1107 fInstanceFilters.add(object);
1108 ///recreate((XDebugTarget)object.getDebugTarget());
1114 * Change notification when there are no marker changes. If the marker
1115 * does not exist, do not fire a change notification (the marker may not
1116 * exist if the associated project was closed).
1118 protected void fireChanged() {
1119 DebugPlugin plugin = DebugPlugin.getDefault();
1120 if (plugin != null && markerExists()) {
1121 plugin.getBreakpointManager().fireBreakpointChanged(this);
1126 * @see org.eclipse.jdt.debug.core.IJavaBreakpoint#getInstanceFilters()
1128 public /*IJava*/Object[] getInstanceFilters() {
1129 if (fInstanceFilters == null || fInstanceFilters.isEmpty()) {
1130 return fgEmptyInstanceFilters;
1132 return (/*IJava*/Object[])fInstanceFilters.toArray(new /*IJava*/Object[fInstanceFilters.size()]);
1136 * @see org.eclipse.jdt.debug.core.IJavaBreakpoint#removeInstanceFilter(org.eclipse.jdt.debug.core.IJavaObject)
1138 public void removeInstanceFilter(/*IJava*/Object object) throws CoreException {
1139 if (fInstanceFilters == null) {
1142 if (fInstanceFilters.remove(object)) {
1143 ///recreate((XDebugTarget)object.getDebugTarget());
1149 * An attribute of this breakpoint has changed - recreate event requests in
1152 /*protected void recreate() throws CoreException {
1153 DebugPlugin plugin = DebugPlugin.getDefault();
1154 if (plugin != null) {
1155 IDebugTarget[] targets = plugin.getLaunchManager().getDebugTargets();
1156 for (int i = 0; i < targets.length; i++) {
1157 IDebugTarget target = targets[i];
1158 MultiStatus multiStatus = new MultiStatus(XDebugCorePlugin.getUniqueIdentifier(), JDIDebugPlugin.ERROR, JDIDebugBreakpointMessages.JavaBreakpoint_Exception, null);
1159 IJavaDebugTarget jdiTarget = (IJavaDebugTarget) target.getAdapter(IJavaDebugTarget.class);
1160 if (jdiTarget instanceof JDIDebugTarget) {
1162 recreate((JDIDebugTarget) jdiTarget);
1163 } catch (CoreException e) {
1164 multiStatus.add(e.getStatus());
1167 if (!multiStatus.isOK()) {
1168 throw new CoreException(multiStatus);
1175 * Recreate this breakpoint in the given target, as long as the
1176 * target already contains this breakpoint.
1178 * @param target the target in which to re-create the breakpoint
1180 /*protected void recreate(XDebugTarget target) throws CoreException {
1181 if (target.isAvailable() && target.getBreakpoints().contains(this)) {
1182 removeRequests(target);
1183 createRequests(target);
1188 * @see org.eclipse.debug.core.model.Breakpoint#setEnabled(boolean)
1190 public void setEnabled(boolean enabled) throws CoreException {
1191 super.setEnabled(enabled);
1196 * @see org.eclipse.jdt.debug.core.IJavaBreakpoint#supportsInstanceFilters()
1198 public boolean supportsInstanceFilters() {
1202 * @see org.eclipse.jdt.debug.core.IJavaBreakpoint#supportsThreadFilters()
1204 /*public boolean supportsThreadFilters() {