Copyright (c) 2000, 2018 IBM Corporation and others. This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0 which accompanies this distribution, and is available at https://www.eclipse.org/legal/epl-2.0/ SPDX-License-Identifier: EPL-2.0 Contributors: IBM Corporation - initial API and implementation
/******************************************************************************* * Copyright (c) 2000, 2018 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at * https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/
package org.eclipse.debug.internal.core; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.Vector; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IMarkerDelta; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceChangeEvent; import org.eclipse.core.resources.IResourceChangeListener; import org.eclipse.core.resources.IResourceDelta; import org.eclipse.core.resources.IResourceDeltaVisitor; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.IWorkspaceRunnable; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IExtensionPoint; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.ISafeRunnable; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.ListenerList; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.SafeRunner; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.IBreakpointListener; import org.eclipse.debug.core.IBreakpointManager; import org.eclipse.debug.core.IBreakpointManagerListener; import org.eclipse.debug.core.IBreakpointsListener; import org.eclipse.debug.core.model.IBreakpoint; import org.eclipse.debug.core.model.IBreakpointImportParticipant; import org.eclipse.debug.core.model.ITriggerPoint; import com.ibm.icu.text.MessageFormat;
The breakpoint manager manages all registered breakpoints for the Debug plug-in. It is instantiated by the Debug plug-in at startup.

Note: This manager is created while the Debug plug-in is started, but it will not automatically be initialized. Client code that expects markers and breakpoints to be initialized must call ensureInitialized().

See Also:
/** * The breakpoint manager manages all registered breakpoints for the Debug plug-in. It is * instantiated by the Debug plug-in at startup. * <p> * <strong>Note:</strong> This manager is created while the Debug plug-in is started, but it * will not automatically be initialized. Client code that expects markers and breakpoints to be * initialized must call {@link #ensureInitialized()}. * </p> * * @see IBreakpointManager */
public class BreakpointManager implements IBreakpointManager, IResourceChangeListener {
Constants for breakpoint add/remove/change updates
/** * Constants for breakpoint add/remove/change updates */
private final static int ADDED = 0; private final static int REMOVED = 1; private final static int CHANGED = 2;
A collection of breakpoints registered with this manager.
/** * A collection of breakpoints registered with this manager. */
private Vector<IBreakpoint> fBreakpoints;
Map of breakpoint import participants. Map has the form:
Map(String - marker_id, List of IBreakpointImportParticipant)
/** * Map of breakpoint import participants. * Map has the form: * <pre>Map(String - marker_id, List of {@link IBreakpointImportParticipant})</pre> */
private HashMap<String, ArrayList<BreakpointImportParticipantDelegate>> fImportParticipants;
A system default import participant that performs legacy comparison support when no participants are provided for a given type.
Since:3.5
/** * A system default import participant that performs legacy comparison support * when no participants are provided for a given type. * * @since 3.5 */
private IBreakpointImportParticipant fDefaultParticipant;
A collection of breakpoint markers that have received a POST_CHANGE notification that they have changed before a POST_BUILD notification of add. This allows us to tell if a marker has been created & changed since the breakpoint has been registered (see bug 138473).
/** * A collection of breakpoint markers that have received a POST_CHANGE notification * that they have changed before a POST_BUILD notification of add. This allows us * to tell if a marker has been created & changed since the breakpoint has been * registered (see bug 138473). */
private final Set<IMarker> fPostChangMarkersChanged = new HashSet<>();
A collection of breakpoint markers that have received a POST_BUILD notification of being added.
/** * A collection of breakpoint markers that have received a POST_BUILD notification * of being added. */
private final Set<IMarker> fPostBuildMarkersAdded = new HashSet<>();
Collection of breakpoints being added currently. Used to suppress change notification of "REGISTERED" attribute when being added.
/** * Collection of breakpoints being added currently. Used to * suppress change notification of "REGISTERED" attribute when * being added. */
private final List<IBreakpoint> fSuppressChange = new ArrayList<>();
A table of breakpoint extension points, keyed by marker type key: a marker type value: the breakpoint extension which corresponds to that marker type
/** * A table of breakpoint extension points, keyed by * marker type * key: a marker type * value: the breakpoint extension which corresponds to that marker type */
private final HashMap<String, IConfigurationElement> fBreakpointExtensions;
Collection of markers that associates markers to breakpoints key: a marker value: the breakpoint which contains that marker
/** * Collection of markers that associates markers to breakpoints * key: a marker * value: the breakpoint which contains that marker */
private final HashMap<IMarker, IBreakpoint> fMarkersToBreakpoints;
Collection of breakpoint listeners.
/** * Collection of breakpoint listeners. */
private final ListenerList<IBreakpointListener> fBreakpointListeners = new ListenerList<>();
Collection of (plural) breakpoint listeners.
/** * Collection of (plural) breakpoint listeners. */
private ListenerList<IBreakpointsListener> fBreakpointsListeners= new ListenerList<>();
Singleton resource delta visitor which handles marker additions, changes, and removals.
/** * Singleton resource delta visitor which handles marker * additions, changes, and removals. */
private static BreakpointManagerVisitor fgVisitor;
Collection of breakpoint manager listeners which are notified when this manager's state changes.
/** * Collection of breakpoint manager listeners which are * notified when this manager's state changes. */
private final ListenerList<IBreakpointManagerListener> fBreakpointManagerListeners = new ListenerList<>();
Breakpoint which acts a the triggering point in a workspace.
/** * Breakpoint which acts a the triggering point in a workspace. */
private final Set<IBreakpoint> fTriggerPointBreakpointList = new LinkedHashSet<>();
Trigger points disabled by system after the first trigger point is enabled in a workspace.
/** * Trigger points disabled by system after the first trigger point is * enabled in a workspace. */
private final Set<IBreakpoint> fTriggerPointDisabledList = new LinkedHashSet<>();
Listens to POST_CHANGE notifications of breakpoint markers to detect when a breakpoint is added & changed before the POST_BUILD add notification is sent.
/** * Listens to POST_CHANGE notifications of breakpoint markers to detect when * a breakpoint is added & changed before the POST_BUILD add notification is * sent. */
class PostChangeListener implements IResourceChangeListener { private PostChangeVisitor fVisitor = new PostChangeVisitor(); @Override public void resourceChanged(IResourceChangeEvent event) { IResourceDelta delta= event.getDelta(); if (delta != null) { try { delta.accept(fVisitor); } catch (CoreException ce) { DebugPlugin.log(ce); } } } }
Default implementation of a breakpoint import participant
Since:3.5
/** * Default implementation of a breakpoint import participant * * @since 3.5 */
class DefaultImportParticipant implements IBreakpointImportParticipant { @Override public boolean matches(Map<String, Object> attributes, IBreakpoint breakpoint) throws CoreException { //perform legacy comparison IMarker marker = breakpoint.getMarker(); String type = (String) attributes.get("type"); //$NON-NLS-1$ Integer line = (Integer) attributes.get(IMarker.LINE_NUMBER); Object localline = marker.getAttribute(IMarker.LINE_NUMBER); String localtype = marker.getType(); if (type.equals(localtype)) { if(line != null && line.equals(localline)) { return true; } else if(line == null) { return true; } } return false; } @Override public void verify(IBreakpoint breakpoint) throws CoreException {} }
The listener
/** * The listener */
private PostChangeListener fPostChangeListener = new PostChangeListener(); class PostChangeVisitor implements IResourceDeltaVisitor { @Override public boolean visit(IResourceDelta delta) throws CoreException { if (delta == null) { return false; } for (IMarkerDelta markerDelta : delta.getMarkerDeltas()) { if (markerDelta.isSubtypeOf(IBreakpoint.BREAKPOINT_MARKER)) { switch (markerDelta.getKind()) { case IResourceDelta.ADDED : break; case IResourceDelta.REMOVED : break; case IResourceDelta.CHANGED : IMarker marker = markerDelta.getMarker(); synchronized (fPostChangMarkersChanged) { if (!fPostBuildMarkersAdded.contains(marker)) { fPostChangMarkersChanged.add(marker); } } break; default: break; } } } return true; } }
Constructs a new breakpoint manager.
/** * Constructs a new breakpoint manager. */
public BreakpointManager() { fMarkersToBreakpoints = new HashMap<>(10); fBreakpointExtensions = new HashMap<>(15); }
Loads all the breakpoints on the given resource.
Params:
  • resource – the resource which contains the breakpoints
  • notify – whether to notify of the breakpoint additions
Throws:
/** * Loads all the breakpoints on the given resource. * * @param resource the resource which contains the breakpoints * @param notify whether to notify of the breakpoint additions * @throws CoreException if a problem is encountered */
private void loadBreakpoints(IResource resource, boolean notify) throws CoreException { initBreakpointExtensions(); List<IBreakpoint> added = new ArrayList<>(); for (IMarker marker : getPersistedMarkers(resource)) { try { IBreakpoint breakpoint = createBreakpoint(marker); synchronized (fPostChangMarkersChanged) { fPostBuildMarkersAdded.add(marker); } if (breakpoint.isRegistered()) { added.add(breakpoint); } if (breakpoint instanceof ITriggerPoint && ((ITriggerPoint) breakpoint).isTriggerPoint()) { addTriggerPoint(breakpoint); } } catch (DebugException e) { DebugPlugin.log(e); } } addBreakpoints(added.toArray(new IBreakpoint[added.size()]), notify); }
Returns the persisted markers associated with the given resource. Delete any invalid breakpoint markers. This is done at startup rather than shutdown, since the changes made at shutdown are not persisted as the workspace state has already been saved. See bug 7683. Since the TRANSIENT marker attribute/feature has been added, we no longer have to manually delete non-persisted markers - the platform does this for us (at shutdown, transient markers are not saved). However, the code is still present to delete non-persisted markers from old workspaces.
Params:
  • resource – the IResource to get markers for
Throws:
Returns:the complete listing of persisted markers for the given IResource
/** * Returns the persisted markers associated with the given resource. * * Delete any invalid breakpoint markers. This is done at startup rather * than shutdown, since the changes made at shutdown are not persisted as * the workspace state has already been saved. See bug 7683. * * Since the <code>TRANSIENT</code> marker attribute/feature has been added, * we no longer have to manually delete non-persisted markers - the platform * does this for us (at shutdown, transient markers are not saved). However, * the code is still present to delete non-persisted markers from old * workspaces. * @param resource the {@link IResource} to get markers for * @return the complete listing of persisted markers for the given {@link IResource} * @throws CoreException if a problem is encountered */
protected IMarker[] getPersistedMarkers(IResource resource) throws CoreException { final List<IMarker> delete = new ArrayList<>(); List<IMarker> persisted = new ArrayList<>(); for (IMarker marker : resource.findMarkers(IBreakpoint.BREAKPOINT_MARKER, true, IResource.DEPTH_INFINITE)) { // ensure the marker has a valid model identifier attribute // and delete the breakpoint if not String modelId = marker.getAttribute(IBreakpoint.ID, null); if (modelId == null) { // marker with old/invalid format - delete delete.add(marker); } else if (!marker.getAttribute(IBreakpoint.PERSISTED, true)) { // the breakpoint is marked as not to be persisted, // schedule for deletion delete.add(marker); } else { persisted.add(marker); } } // delete any markers that are not to be restored if (!delete.isEmpty()) { final IMarker[] delMarkers = delete.toArray(new IMarker[delete.size()]); IWorkspaceRunnable wr = new IWorkspaceRunnable() { @Override public void run(IProgressMonitor pm) throws CoreException { for (IMarker marker : delMarkers) { marker.delete(); } } }; new BreakpointManagerJob(wr).schedule(); } return persisted.toArray(new IMarker[persisted.size()]); }
Removes this manager as a resource change listener and removes all breakpoint listeners.
/** * Removes this manager as a resource change listener * and removes all breakpoint listeners. */
public void shutdown() { getWorkspace().removeResourceChangeListener(this); getWorkspace().removeResourceChangeListener(fPostChangeListener); fBreakpointListeners.clear(); fBreakpointsListeners.clear(); fBreakpointManagerListeners.clear(); if(fImportParticipants != null) { fImportParticipants.clear(); fImportParticipants = null; fDefaultParticipant = null; } if(fBreakpoints != null) { fBreakpoints.clear(); fBreakpoints = null; } if(fMarkersToBreakpoints != null) { fMarkersToBreakpoints.clear(); } }
Find the defined breakpoint extensions and cache them for use in recreating breakpoints from markers.
/** * Find the defined breakpoint extensions and cache them for use in recreating * breakpoints from markers. */
private void initBreakpointExtensions() { IExtensionPoint ep = Platform.getExtensionRegistry().getExtensionPoint(DebugPlugin.getUniqueIdentifier(), DebugPlugin.EXTENSION_POINT_BREAKPOINTS); for (IConfigurationElement element : ep.getConfigurationElements()) { String markerType = element.getAttribute(IConfigurationElementConstants.MARKER_TYPE); String className = element.getAttribute(IConfigurationElementConstants.CLASS); if (markerType == null) { DebugPlugin.log(new Status(IStatus.ERROR, DebugPlugin.getUniqueIdentifier(), DebugPlugin.INTERNAL_ERROR, "Breakpoint extension " + element.getDeclaringExtension().getUniqueIdentifier() + " missing required attribute: markerType", null)); //$NON-NLS-1$ //$NON-NLS-2$ } else if (className == null){ DebugPlugin.log(new Status(IStatus.ERROR, DebugPlugin.getUniqueIdentifier(), DebugPlugin.INTERNAL_ERROR, "Breakpoint extension " + element.getDeclaringExtension().getUniqueIdentifier() + " missing required attribute: class", null)); //$NON-NLS-1$ //$NON-NLS-2$ } else { fBreakpointExtensions.put(markerType, element); } } }
Convenience method to get the workspace
Returns:the default IWorkspace
/** * Convenience method to get the workspace * @return the default {@link IWorkspace} */
private IWorkspace getWorkspace() { return ResourcesPlugin.getWorkspace(); }
See Also:
  • getBreakpoint.getBreakpoint(IMarker)
/** * @see IBreakpointManager#getBreakpoint(IMarker) */
@Override public IBreakpoint getBreakpoint(IMarker marker) { // ensure that breakpoints are initialized getBreakpoints0(); return fMarkersToBreakpoints.get(marker); } @Override public IBreakpoint[] getBreakpoints() { IBreakpoint[] temp = new IBreakpoint[0]; Vector<IBreakpoint> breakpoints = getBreakpoints0(); synchronized (breakpoints) { temp = new IBreakpoint[breakpoints.size()]; breakpoints.copyInto(temp); } return temp; }
Ensures that this manager is initialized.

This manager is created while the Debug plug-in is started, but it will not automatically be initialized. Client code that expects markers and breakpoints to be initialized must call this method.

Since:3.8
/** * Ensures that this manager is initialized. * <p> * This manager is created while the Debug plug-in is started, but it will not automatically * be initialized. Client code that expects markers and breakpoints to be initialized must call * this method. * </p> * * @since 3.8 */
public void ensureInitialized() { getBreakpoints0(); }
The BreakpointManager waits to load the breakpoints of the workspace until a request is made to retrieve the breakpoints.
Returns:the underlying Vector of breakpoints
/** * The BreakpointManager waits to load the breakpoints * of the workspace until a request is made to retrieve the * breakpoints. * @return the underlying {@link Vector} of breakpoints */
private synchronized Vector<IBreakpoint> getBreakpoints0() { if (fBreakpoints == null) { initializeBreakpoints(); } return fBreakpoints; } @Override public IBreakpoint[] getBreakpoints(String modelIdentifier) { Vector<IBreakpoint> allBreakpoints = getBreakpoints0(); synchronized (allBreakpoints) { ArrayList<IBreakpoint> temp = new ArrayList<>(allBreakpoints.size()); for (IBreakpoint breakpoint : allBreakpoints) { String id= breakpoint.getModelIdentifier(); if (id != null && id.equals(modelIdentifier)) { temp.add(breakpoint); } } return temp.toArray(new IBreakpoint[temp.size()]); } }
Loads the list of breakpoints from the breakpoint markers in the workspace. Start listening to resource deltas.
/** * Loads the list of breakpoints from the breakpoint markers in the * workspace. Start listening to resource deltas. */
private void initializeBreakpoints() { setBreakpoints(new Vector<>(10)); try { loadBreakpoints(getWorkspace().getRoot(), false); getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.POST_BUILD); getWorkspace().addResourceChangeListener(fPostChangeListener, IResourceChangeEvent.POST_CHANGE); } catch (CoreException ce) { DebugPlugin.log(ce); setBreakpoints(new Vector<>(0)); } }
See Also:
  • isRegistered.isRegistered(IBreakpoint)
/** * @see IBreakpointManager#isRegistered(IBreakpoint) */
@Override public boolean isRegistered(IBreakpoint breakpoint) { return getBreakpoints0().contains(breakpoint); }
See Also:
  • removeBreakpoint.removeBreakpoint(IBreakpoint, boolean)
/** * @see IBreakpointManager#removeBreakpoint(IBreakpoint, boolean) */
@Override public void removeBreakpoint(IBreakpoint breakpoint, boolean delete) throws CoreException { removeBreakpoints(new IBreakpoint[]{breakpoint}, delete); }
See Also:
  • removeBreakpoints.removeBreakpoints(IBreakpoint[], boolean)
/** * @see IBreakpointManager#removeBreakpoints(IBreakpoint[], boolean) */
@Override public void removeBreakpoints(IBreakpoint[] breakpoints, final boolean delete) throws CoreException { final List<IBreakpoint> remove = new ArrayList<>(breakpoints.length); List<IBreakpoint> bps = getBreakpoints0(); for (IBreakpoint breakpoint : breakpoints) { if (bps.contains(breakpoint)) { remove.add(breakpoint); } } if (!remove.isEmpty()) { for (IBreakpoint breakpoint : remove) { bps.remove(breakpoint); fMarkersToBreakpoints.remove(breakpoint.getMarker()); } fireUpdate(remove, null, REMOVED); refreshTriggerpointDisplay(); IWorkspaceRunnable r = new IWorkspaceRunnable() { @Override public void run(IProgressMonitor montitor) throws CoreException { for (IBreakpoint breakpoint : remove) { if (delete) { breakpoint.delete(); } else { // if the breakpoint is being removed from the manager // because the project is closing, the breakpoint should // remain as registered, otherwise, the breakpoint should // be marked as unregistered IMarker marker = breakpoint.getMarker(); if (marker.exists()) { IProject project = breakpoint.getMarker().getResource().getProject(); if (project == null || project.isOpen()) { breakpoint.setRegistered(false); } } } } } }; getWorkspace().run(r, null, 0, null); } }
Create a breakpoint for the given marker. The created breakpoint is of the type specified in the breakpoint extension associated with the given marker type.
Params:
  • marker – marker to create a breakpoint for
Throws:
  • DebugException – if breakpoint creation fails. Reasons for failure include:
    1. The breakpoint manager cannot determine what kind of breakpoint to instantiate for the given marker type
    2. A lower level exception occurred while accessing the given marker
Returns:a breakpoint on this marker
/** * Create a breakpoint for the given marker. The created breakpoint * is of the type specified in the breakpoint extension associated * with the given marker type. * * @param marker marker to create a breakpoint for * @return a breakpoint on this marker * @exception DebugException if breakpoint creation fails. Reasons for * failure include: * <ol> * <li>The breakpoint manager cannot determine what kind of breakpoint * to instantiate for the given marker type</li> * <li>A lower level exception occurred while accessing the given marker</li> * </ol> */
public IBreakpoint createBreakpoint(IMarker marker) throws DebugException { IBreakpoint breakpoint= fMarkersToBreakpoints.get(marker); if (breakpoint != null) { return breakpoint; } try { IConfigurationElement config = fBreakpointExtensions.get(marker.getType()); if (config == null) { throw new DebugException(new Status(IStatus.ERROR, DebugPlugin.getUniqueIdentifier(), DebugException.CONFIGURATION_INVALID, MessageFormat.format(DebugCoreMessages.BreakpointManager_Missing_breakpoint_definition, new Object[] { marker.getType() }), null)); } Object object = config.createExecutableExtension(IConfigurationElementConstants.CLASS); if (object instanceof IBreakpoint) { breakpoint = (IBreakpoint)object; breakpoint.setMarker(marker); } else { DebugPlugin.log(new Status(IStatus.ERROR, DebugPlugin.getUniqueIdentifier(), DebugPlugin.INTERNAL_ERROR, "Breakpoint extension " + config.getDeclaringExtension().getUniqueIdentifier() + " missing required attribute: class", null)); //$NON-NLS-1$ //$NON-NLS-2$ } return breakpoint; } catch (CoreException e) { throw new DebugException(e.getStatus()); } }
See Also:
  • addBreakpoint.addBreakpoint(IBreakpoint)
/** * @see IBreakpointManager#addBreakpoint(IBreakpoint) */
@Override public void addBreakpoint(IBreakpoint breakpoint) throws CoreException { addBreakpoints(new IBreakpoint[]{breakpoint}); }
See Also:
  • addBreakpoints.addBreakpoints(IBreakpoint[])
/** * @see IBreakpointManager#addBreakpoints(IBreakpoint[]) */
@Override public void addBreakpoints(IBreakpoint[] breakpoints) throws CoreException { addBreakpoints(breakpoints, true); }
Registers the given breakpoints and notifies listeners if specified.
Params:
  • breakpoints – the breakpoints to register
  • notify – whether to notify listeners of the add
Throws:
/** * Registers the given breakpoints and notifies listeners if specified. * * @param breakpoints the breakpoints to register * @param notify whether to notify listeners of the add * @throws CoreException if a problem is encountered */
private void addBreakpoints(IBreakpoint[] breakpoints, boolean notify) throws CoreException { List<IBreakpoint> added = new ArrayList<>(breakpoints.length); final List<IBreakpoint> update = new ArrayList<>(); for (IBreakpoint breakpoint : breakpoints) { if (!getBreakpoints0().contains(breakpoint)) { verifyBreakpoint(breakpoint); if (breakpoint.isRegistered()) { // If notify == false, the breakpoints are just being added at startup added.add(breakpoint); getBreakpoints0().add(breakpoint); fMarkersToBreakpoints.put(breakpoint.getMarker(), breakpoint); } else { // need to update the 'registered' and/or 'group' attributes update.add(breakpoint); } } } if (notify) { fireUpdate(added, null, ADDED); } if (!update.isEmpty()) { IWorkspaceRunnable r = new IWorkspaceRunnable() { @Override public void run(IProgressMonitor monitor) throws CoreException { List<IBreakpoint> bps = getBreakpoints0(); for (IBreakpoint breakpoint : update) { bps.add(breakpoint); breakpoint.setRegistered(true); fMarkersToBreakpoints.put(breakpoint.getMarker(), breakpoint); } } }; // Need to suppress change notification, since this is really // an add notification fSuppressChange.addAll(update); getWorkspace().run(r, null, 0, null); fSuppressChange.removeAll(update); if (notify) { fireUpdate(update, null, ADDED); } } }
Returns whether change notification is to be suppressed for the given breakpoint. Used when adding breakpoints and changing the "REGISTERED" attribute.
Params:
  • breakpoint – the breakpoint
Returns:boolean whether change notification is suppressed
/** * Returns whether change notification is to be suppressed for the given breakpoint. * Used when adding breakpoints and changing the "REGISTERED" attribute. * * @param breakpoint the breakpoint * @return boolean whether change notification is suppressed */
protected boolean isChangeSuppressed(IBreakpoint breakpoint) { return fSuppressChange.contains(breakpoint); }
See Also:
  • fireBreakpointChanged.fireBreakpointChanged(IBreakpoint)
/** * @see IBreakpointManager#fireBreakpointChanged(IBreakpoint) */
@Override public void fireBreakpointChanged(IBreakpoint breakpoint) { if (getBreakpoints0().contains(breakpoint)) { List<IBreakpoint> changed = new ArrayList<>(); changed.add(breakpoint); fireUpdate(changed, null, CHANGED); } }
Verifies that the breakpoint marker has the minimal required attributes, and throws a debug exception if not.
Params:
Throws:
/** * Verifies that the breakpoint marker has the minimal required attributes, * and throws a debug exception if not. * @param breakpoint the {@link IBreakpoint} to verify * @throws DebugException if a problem is encountered */
private void verifyBreakpoint(IBreakpoint breakpoint) throws DebugException { try { String id= breakpoint.getModelIdentifier(); if (id == null) { throw new DebugException(new Status(IStatus.ERROR, DebugPlugin.getUniqueIdentifier(), DebugException.CONFIGURATION_INVALID, DebugCoreMessages.BreakpointManager_Missing_model_identifier, null)); } } catch (CoreException e) { throw new DebugException(e.getStatus()); } }
A resource has changed. Traverses the delta for breakpoint changes.
Params:
  • event – resource change event
/** * A resource has changed. Traverses the delta for breakpoint changes. * * @param event resource change event */
@Override public void resourceChanged(IResourceChangeEvent event) { IResourceDelta delta= event.getDelta(); if (delta != null) { try { if (fgVisitor == null) { fgVisitor= new BreakpointManagerVisitor(); } delta.accept(fgVisitor); fgVisitor.update(); } catch (CoreException ce) { DebugPlugin.log(ce); } } }
Visitor for handling resource deltas
/** * Visitor for handling resource deltas */
class BreakpointManagerVisitor implements IResourceDeltaVisitor {
Moved markers
/** * Moved markers */
private List<IMarker> fMoved = new ArrayList<>();
Removed breakpoints
/** * Removed breakpoints */
private List<IBreakpoint> fRemoved = new ArrayList<>();
Added breakpoints.
Since:3.7
/** * Added breakpoints. * @since 3.7 */
private List<IBreakpoint> fAdded = new ArrayList<>();
Changed breakpoints and associated marker deltas
/** * Changed breakpoints and associated marker deltas */
private List<IBreakpoint> fChanged = new ArrayList<>(); private List<IMarkerDelta> fChangedDeltas = new ArrayList<>();
Resets the visitor for a delta traversal - empties collections of removed/changed breakpoints.
/** * Resets the visitor for a delta traversal - empties * collections of removed/changed breakpoints. */
protected void reset() { fMoved.clear(); fRemoved.clear(); fAdded.clear(); fChanged.clear(); fChangedDeltas.clear(); }
Performs updates on accumulated changes, and fires change notification after a traversal. Accumulated updates are reset.
/** * Performs updates on accumulated changes, and fires change notification after * a traversal. Accumulated updates are reset. */
public void update() { if (!fMoved.isEmpty()) { // delete moved markers IWorkspaceRunnable wRunnable= new IWorkspaceRunnable() { @Override public void run(IProgressMonitor monitor) throws CoreException { for (IMarker marker : fMoved) { marker.delete(); } } }; try { getWorkspace().run(wRunnable, null, 0, null); } catch (CoreException e) { } } if (!fRemoved.isEmpty()) { try { removeBreakpoints(fRemoved.toArray(new IBreakpoint[fRemoved.size()]), false); } catch (CoreException e) { DebugPlugin.log(e); } } if (!fAdded.isEmpty()) { try { IWorkspaceRunnable runnable= new IWorkspaceRunnable() { @Override public void run(IProgressMonitor monitor) throws CoreException { for (IBreakpoint breakpoint : fAdded) { breakpoint.getMarker().setAttribute(DebugPlugin.ATTR_BREAKPOINT_IS_DELETED, false); breakpoint.setRegistered(true); } } }; getWorkspace().run(runnable, null, 0, null); addBreakpoints(fAdded.toArray(new IBreakpoint[fAdded.size()]), false); } catch (CoreException e) { DebugPlugin.log(e); } } if (!fChanged.isEmpty()) { fireUpdate(fChanged, fChangedDeltas, CHANGED); } reset(); }
See Also:
  • visit.visit(IResourceDelta)
/** * @see IResourceDeltaVisitor#visit(IResourceDelta) */
@Override public boolean visit(IResourceDelta delta) { if (delta == null) { return false; } if (0 != (delta.getFlags() & IResourceDelta.OPEN) && 0 == (delta.getFlags() & IResourceDelta.MOVED_FROM)) { handleProjectResourceOpenStateChange(delta.getResource()); return false; } for (IMarkerDelta markerDelta : delta.getMarkerDeltas()) { if (markerDelta.isSubtypeOf(IBreakpoint.BREAKPOINT_MARKER)) { switch (markerDelta.getKind()) { case IResourceDelta.ADDED : handleAddBreakpoint(delta, markerDelta.getMarker(), markerDelta); break; case IResourceDelta.REMOVED : handleRemoveBreakpoint(markerDelta.getMarker()); break; case IResourceDelta.CHANGED : handleChangeBreakpoint(markerDelta.getMarker(), markerDelta); break; default: break; } } } return true; }
Wrapper for handling adds
Params:
/** * Wrapper for handling adds * @param rDelta the {@link IResourceDelta} * @param marker the new {@link IMarker} * @param mDelta the accompanying {@link IMarkerDelta} */
protected void handleAddBreakpoint(IResourceDelta rDelta, IMarker marker, IMarkerDelta mDelta) { if (0 != (rDelta.getFlags() & IResourceDelta.MOVED_FROM)) { // This breakpoint has actually been moved - already removed // from the Breakpoint manager during the remove callback. // Schedule the marker associated with the new resource for deletion. if (getBreakpoint(marker) == null) { fMoved.add(marker); } } else { // check if the an add & change have be combined into one add notification synchronized (fPostChangMarkersChanged) { if (fPostChangMarkersChanged.contains(marker)) { handleChangeBreakpoint(marker, mDelta); fPostChangMarkersChanged.remove(marker); } else if (marker.getAttribute(DebugPlugin.ATTR_BREAKPOINT_IS_DELETED, false) && getBreakpoint(marker) == null) { try { /* * There may be breakpoints with matching resource * and same line number */ IBreakpoint breakpoint = findMatchingBreakpoint(marker); if (breakpoint != null) { removeBreakpoint(breakpoint, true); } fAdded.add(createBreakpoint(marker)); } catch (CoreException e) { DebugPlugin.log(e); } } fPostBuildMarkersAdded.add(marker); } } }
To find a breakpoint with matching marker resources and line number.
Params:
  • marker – the IMarker for which existing breakpoint is retrieved
Returns:matching breakpoint if exists else return null
/** * To find a breakpoint with matching marker resources and line number. * * @param marker the {@link IMarker} for which existing breakpoint is * retrieved * @return matching breakpoint if exists else return <code>null</code> */
private IBreakpoint findMatchingBreakpoint(IMarker marker) { try { Integer line = (Integer) marker.getAttribute(IMarker.LINE_NUMBER); for (IBreakpoint breakpoint : getBreakpoints0()) { IMarker bpMarker = breakpoint.getMarker(); if (bpMarker != null && marker.getResource().equals(bpMarker.getResource()) && bpMarker.getAttribute(IMarker.LINE_NUMBER, -1) == (line == null ? -1 : line.intValue())) { return breakpoint; } } } catch (CoreException e) { // ignore } return null; }
Wrapper for handling removes
Params:
/** * Wrapper for handling removes * @param marker the {@link IMarker} */
protected void handleRemoveBreakpoint(IMarker marker) { synchronized (fPostChangMarkersChanged) { fPostChangMarkersChanged.remove(marker); fPostBuildMarkersAdded.remove(marker); } IBreakpoint breakpoint= getBreakpoint(marker); if (breakpoint != null) { fRemoved.add(breakpoint); } }
Wrapper for handling changes
Params:
/** * Wrapper for handling changes * @param marker the {@link IMarker} that was changed * @param delta the {@link IMarkerDelta} */
protected void handleChangeBreakpoint(IMarker marker, IMarkerDelta delta) { IBreakpoint breakpoint= getBreakpoint(marker); if (breakpoint != null && isRegistered(breakpoint) && !isChangeSuppressed(breakpoint)) { fChanged.add(breakpoint); fChangedDeltas.add(delta); } }
A project has been opened or closed. Updates the breakpoints for that project
Params:
  • project – the IProject that was changed
/** * A project has been opened or closed. Updates the breakpoints for * that project * @param project the {@link IProject} that was changed */
private void handleProjectResourceOpenStateChange(final IResource project) { if (!project.isAccessible()) { //closed for (@SuppressWarnings("unchecked") IBreakpoint breakpoint : (Vector<IBreakpoint>) getBreakpoints0().clone()) { IResource markerResource= breakpoint.getMarker().getResource(); if (project.getFullPath().isPrefixOf(markerResource.getFullPath())) { fRemoved.add(breakpoint); } } return; } try { loadBreakpoints(project, true); } catch (CoreException e) { DebugPlugin.log(e); } } }
See Also:
  • addBreakpointListener.addBreakpointListener(IBreakpointListener)
/** * @see IBreakpointManager#addBreakpointListener(IBreakpointListener) */
@Override public void addBreakpointListener(IBreakpointListener listener) { fBreakpointListeners.add(listener); }
See Also:
  • removeBreakpointListener.removeBreakpointListener(IBreakpointListener)
/** * @see IBreakpointManager#removeBreakpointListener(IBreakpointListener) */
@Override public void removeBreakpointListener(IBreakpointListener listener) { fBreakpointListeners.remove(listener); }
Notifies listeners of the adds/removes/changes
Params:
  • breakpoints – associated breakpoints
  • deltas – or null
  • update – type of change
/** * Notifies listeners of the adds/removes/changes * * @param breakpoints associated breakpoints * @param deltas or <code>null</code> * @param update type of change */
private void fireUpdate(List<IBreakpoint> breakpoints, List<IMarkerDelta> deltas, int update) { if (breakpoints.isEmpty()) { return; } IBreakpoint[] bpArray = breakpoints.toArray(new IBreakpoint[breakpoints.size()]); IMarkerDelta[] deltaArray = new IMarkerDelta[bpArray.length]; if (deltas != null) { deltaArray = deltas.toArray(deltaArray); } // single listeners getBreakpointNotifier().notify(bpArray, deltaArray, update); // plural listeners getBreakpointsNotifier().notify(bpArray, deltaArray, update); } protected void setBreakpoints(Vector<IBreakpoint> breakpoints) { fBreakpoints = breakpoints; }
See Also:
  • hasBreakpoints.hasBreakpoints()
/** * @see IBreakpointManager#hasBreakpoints() */
@Override public boolean hasBreakpoints() { return !getBreakpoints0().isEmpty(); }
See Also:
  • addBreakpointListener.addBreakpointListener(IBreakpointsListener)
/** * @see org.eclipse.debug.core.IBreakpointManager#addBreakpointListener(org.eclipse.debug.core.IBreakpointsListener) */
@Override public void addBreakpointListener(IBreakpointsListener listener) { fBreakpointsListeners.add(listener); }
See Also:
  • removeBreakpointListener.removeBreakpointListener(IBreakpointsListener)
/** * @see org.eclipse.debug.core.IBreakpointManager#removeBreakpointListener(org.eclipse.debug.core.IBreakpointsListener) */
@Override public void removeBreakpointListener(IBreakpointsListener listener) { fBreakpointsListeners.remove(listener); } private BreakpointNotifier getBreakpointNotifier() { return new BreakpointNotifier(); }
Notifies breakpoint listener (single breakpoint) in a safe runnable to handle exceptions.
/** * Notifies breakpoint listener (single breakpoint) in a safe runnable to * handle exceptions. */
class BreakpointNotifier implements ISafeRunnable { private IBreakpointListener fListener; private int fType; private IMarkerDelta fDelta; private IBreakpoint fBreakpoint;
See Also:
  • handleException.handleException(Throwable)
/** * @see org.eclipse.core.runtime.ISafeRunnable#handleException(java.lang.Throwable) */
@Override public void handleException(Throwable exception) { IStatus status = new Status(IStatus.ERROR, DebugPlugin.getUniqueIdentifier(), DebugPlugin.INTERNAL_ERROR, "An exception occurred during breakpoint change notification.", exception); //$NON-NLS-1$ DebugPlugin.log(status); }
See Also:
  • run.run()
/** * @see org.eclipse.core.runtime.ISafeRunnable#run() */
@Override public void run() throws Exception { switch (fType) { case ADDED: fListener.breakpointAdded(fBreakpoint); break; case REMOVED: fListener.breakpointRemoved(fBreakpoint, fDelta); break; case CHANGED: fListener.breakpointChanged(fBreakpoint, fDelta); break; default: break; } }
Notifies the listeners of the add/change/remove
Params:
  • breakpoints – the breakpoints that changed
  • deltas – the deltas associated with the change
  • update – the type of change
/** * Notifies the listeners of the add/change/remove * * @param breakpoints the breakpoints that changed * @param deltas the deltas associated with the change * @param update the type of change */
public void notify(IBreakpoint[] breakpoints, IMarkerDelta[] deltas, int update) { fType = update; for (IBreakpointListener iBreakpointListener : fBreakpointListeners) { fListener = iBreakpointListener; for (int j = 0; j < breakpoints.length; j++) { fBreakpoint = breakpoints[j]; fDelta = deltas[j]; SafeRunner.run(this); } } fListener = null; fDelta = null; fBreakpoint = null; } } private BreakpointsNotifier getBreakpointsNotifier() { return new BreakpointsNotifier(); }
Notifies breakpoint listener (multiple breakpoints) in a safe runnable to handle exceptions.
/** * Notifies breakpoint listener (multiple breakpoints) in a safe runnable to * handle exceptions. */
class BreakpointsNotifier implements ISafeRunnable { private IBreakpointsListener fListener; private int fType; private IMarkerDelta[] fDeltas; private IBreakpoint[] fNotifierBreakpoints; @Override public void handleException(Throwable exception) { IStatus status = new Status(IStatus.ERROR, DebugPlugin.getUniqueIdentifier(), DebugPlugin.INTERNAL_ERROR, "An exception occurred during breakpoint change notification.", exception); //$NON-NLS-1$ DebugPlugin.log(status); } @Override public void run() throws Exception { switch (fType) { case ADDED: fListener.breakpointsAdded(fNotifierBreakpoints); break; case REMOVED: fListener.breakpointsRemoved(fNotifierBreakpoints, fDeltas); break; case CHANGED: fListener.breakpointsChanged(fNotifierBreakpoints, fDeltas); break; default: break; } }
Notifies the listeners of the adds/changes/removes
Params:
  • breakpoints – the breakpoints that changed
  • deltas – the deltas associated with the changed breakpoints
  • update – the type of change
/** * Notifies the listeners of the adds/changes/removes * * @param breakpoints the breakpoints that changed * @param deltas the deltas associated with the changed breakpoints * @param update the type of change */
public void notify(IBreakpoint[] breakpoints, IMarkerDelta[] deltas, int update) { fType = update; fNotifierBreakpoints = breakpoints; fDeltas = deltas; for (IBreakpointsListener iBreakpointsListener : fBreakpointsListeners) { fListener = iBreakpointsListener; SafeRunner.run(this); } fDeltas = null; fNotifierBreakpoints = null; fListener = null; } } @Override public boolean isEnabled() { return Platform.getPreferencesService().getBoolean(DebugPlugin.getUniqueIdentifier(), IInternalDebugCoreConstants.PREF_BREAKPOINT_MANAGER_ENABLED_STATE, true, null); } @Override public void setEnabled(final boolean enabled) { if (isEnabled() != enabled) { Preferences.setBoolean(DebugPlugin.getUniqueIdentifier(), IInternalDebugCoreConstants.PREF_BREAKPOINT_MANAGER_ENABLED_STATE, enabled, null); touchAllBreakpoints(); new BreakpointManagerNotifier().notify(enabled); } } @Override public void addBreakpointManagerListener(IBreakpointManagerListener listener) { fBreakpointManagerListeners.add(listener); } @Override public void removeBreakpointManagerListener(IBreakpointManagerListener listener) { fBreakpointManagerListeners.remove(listener); }
Notifies breakpoint manager listeners in a safe runnable to handle exceptions.
/** * Notifies breakpoint manager listeners in a safe runnable to * handle exceptions. */
class BreakpointManagerNotifier implements ISafeRunnable { private IBreakpointManagerListener fListener; private boolean fManagerEnabled; @Override public void handleException(Throwable exception) { IStatus status = new Status(IStatus.ERROR, DebugPlugin.getUniqueIdentifier(), DebugPlugin.INTERNAL_ERROR, "An exception occurred during breakpoint change notification.", exception); //$NON-NLS-1$ DebugPlugin.log(status); } @Override public void run() throws Exception { fListener.breakpointManagerEnablementChanged(fManagerEnabled); }
Notifies the listeners of the enabled state change
Params:
  • enabled – whether the manager is enabled
/** * Notifies the listeners of the enabled state change * * @param enabled whether the manager is enabled */
public void notify(boolean enabled) { fManagerEnabled= enabled; for (IBreakpointManagerListener iBreakpointManagerListener : fBreakpointManagerListeners) { fListener = iBreakpointManagerListener; SafeRunner.run(this); } fListener = null; } }
Notifies breakpoint manager listeners in a safe runnable to handle exceptions.
/** * Notifies breakpoint manager listeners in a safe runnable to handle * exceptions. */
class BreakpointManagerTriggerPointNotifier implements ISafeRunnable { private IBreakpointManagerListener fListener; private IBreakpoint fManagerTriggerPoint; @Override public void handleException(Throwable exception) { IStatus status = new Status(IStatus.ERROR, DebugPlugin.getUniqueIdentifier(), DebugPlugin.INTERNAL_ERROR, "An exception occurred during breakpoint change notification.", exception); //$NON-NLS-1$ DebugPlugin.log(status); } @Override public void run() throws Exception { fListener.breakpointManagerTriggerPointChanged(fManagerTriggerPoint); }
Notifies the listeners of the enabled state change
Params:
  • triggerBreakpoint – new breakpoint as trigger point
/** * Notifies the listeners of the enabled state change * * @param triggerBreakpoint new breakpoint as trigger point */
public void notify(IBreakpoint triggerBreakpoint) { fManagerTriggerPoint = triggerBreakpoint; for (IBreakpointManagerListener iBreakpointManagerListener : fBreakpointManagerListeners) { fListener = iBreakpointManagerListener; SafeRunner.run(this); } fListener = null; } } class BreakpointManagerJob extends Job { private final IWorkspaceRunnable fRunnable; public BreakpointManagerJob (IWorkspaceRunnable wRunnable) { super("breakpoint manager job"); //$NON-NLS-1$ fRunnable= wRunnable; setSystem(true); } @Override protected IStatus run(IProgressMonitor monitor) { try { getWorkspace().run(fRunnable, null, 0, null); } catch (CoreException ce) { DebugPlugin.log(ce); } return new Status(IStatus.OK, DebugPlugin.getUniqueIdentifier(), IStatus.OK, "", null); //$NON-NLS-1$ } } @Override public String getTypeName(IBreakpoint breakpoint) { String typeName= null; IMarker marker = breakpoint.getMarker(); if (marker != null) { try { IConfigurationElement element = fBreakpointExtensions.get(marker.getType()); if (element != null) { typeName= element.getAttribute(IConfigurationElementConstants.NAME); } } catch (CoreException e) {} } return typeName; } @Override public IBreakpointImportParticipant[] getImportParticipants(String markertype) throws CoreException { initializeImportParticipants(); ArrayList<BreakpointImportParticipantDelegate> list = fImportParticipants.get(markertype); if(list == null) { return new IBreakpointImportParticipant[] {fDefaultParticipant}; } IBreakpointImportParticipant[] participants = new IBreakpointImportParticipant[list.size()]; BreakpointImportParticipantDelegate delegate = null; for(int i = 0; i < list.size(); i++) { delegate = list.get(i); participants[i] = delegate.getDelegate(); } if(participants.length == 0) { return new IBreakpointImportParticipant[] {fDefaultParticipant}; } return participants; }
Initializes the cache of breakpoint import participants. Does no work if the cache has already been initialized
/** * Initializes the cache of breakpoint import participants. Does no work if the cache * has already been initialized */
private synchronized void initializeImportParticipants() { if(fImportParticipants == null) { fImportParticipants = new HashMap<>(); fDefaultParticipant = new DefaultImportParticipant(); IExtensionPoint ep = Platform.getExtensionRegistry().getExtensionPoint(DebugPlugin.getUniqueIdentifier(), DebugPlugin.EXTENSION_POINT_BREAKPOINT_IMPORT_PARTICIPANTS); String type = null; ArrayList<BreakpointImportParticipantDelegate> list = null; for (IConfigurationElement element : ep.getConfigurationElements()) { type = element.getAttribute(IConfigurationElementConstants.TYPE); if(type != null) { list = fImportParticipants.get(type); if(list == null) { list = new ArrayList<>(); fImportParticipants.put(type, list); } list.add(new BreakpointImportParticipantDelegate(element)); } } } } @Override public IBreakpoint[] getTriggerPoints() { return fTriggerPointBreakpointList.toArray(new IBreakpoint[0]); } @Override public void addTriggerPoint(IBreakpoint triggerPoint) throws CoreException { if (triggerPoint == null) { return; } fTriggerPointBreakpointList.add(triggerPoint); new BreakpointManagerTriggerPointNotifier().notify(triggerPoint); } @Override public void removeTriggerPoint(IBreakpoint breakpoint) throws CoreException { if (breakpoint != null) { fTriggerPointBreakpointList.remove(breakpoint); } } @Override public void removeAllTriggerPoints() throws CoreException { IBreakpoint[] triggerPointBreakpointList = getTriggerPoints(); for (IBreakpoint iBreakpoint : triggerPointBreakpointList) { if (iBreakpoint instanceof ITriggerPoint) { ((ITriggerPoint) iBreakpoint).setTriggerPoint(false); } } refreshTriggerpointDisplay(); } @Override public boolean hasActiveTriggerPoints() { if (fTriggerPointBreakpointList.isEmpty()) { return false; } for (IBreakpoint iBreakpoint : fTriggerPointBreakpointList) { try { if (iBreakpoint.isEnabled()) { return true; } } catch (CoreException e) { // ignore } } return false; } @Override public void enableTriggerPoints(IBreakpoint[] triggerPoints, boolean enable) { IBreakpoint[] triggerPointArray = triggerPoints; if (triggerPoints == null) { if (enable) { synchronized (fTriggerPointDisabledList) { triggerPointArray = fTriggerPointDisabledList.toArray(new IBreakpoint[0]); } } else { triggerPointArray = getTriggerPoints(); } } List<IBreakpoint> toDisable = new ArrayList<>(); for (IBreakpoint iBreakpoint : triggerPointArray) { try { IMarker m = iBreakpoint.getMarker(); if (m != null && m.exists()) { if (!enable && iBreakpoint.isEnabled()) { toDisable.add(iBreakpoint); } iBreakpoint.setEnabled(enable); } } catch (CoreException e) { // ignore } } synchronized (fTriggerPointDisabledList) { fTriggerPointDisabledList.clear(); if (!enable) { fTriggerPointDisabledList.addAll(toDisable); } } } @Override public void refreshTriggerpointDisplay() { touchAllBreakpoints(); } /* * Touch and refresh display of all breakpoints */ private void touchAllBreakpoints() { IWorkspaceRunnable runnable = new IWorkspaceRunnable() { @Override public void run(IProgressMonitor monitor) throws CoreException { for (IBreakpoint breakpoint : getBreakpoints()) { // Touch the marker (but don't actually change anything) so // that the icon in // the editor ruler will be updated (editors listen to // marker changes). try { breakpoint.getMarker().setAttribute(IBreakpoint.ENABLED, breakpoint.isEnabled()); } catch (CoreException e) { // don't care if marker was already deleted } } } }; try { ResourcesPlugin.getWorkspace().run(runnable, null, IWorkspace.AVOID_UPDATE, null); } catch (CoreException e) { DebugPlugin.log(e); } } }