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;
public class BreakpointManager implements IBreakpointManager, IResourceChangeListener {
private final static int ADDED = 0;
private final static int REMOVED = 1;
private final static int CHANGED = 2;
private Vector<IBreakpoint> fBreakpoints;
private HashMap<String, ArrayList<BreakpointImportParticipantDelegate>> fImportParticipants;
private IBreakpointImportParticipant fDefaultParticipant;
private final Set<IMarker> fPostChangMarkersChanged = new HashSet<>();
private final Set<IMarker> fPostBuildMarkersAdded = new HashSet<>();
private final List<IBreakpoint> fSuppressChange = new ArrayList<>();
private final HashMap<String, IConfigurationElement> fBreakpointExtensions;
private final HashMap<IMarker, IBreakpoint> fMarkersToBreakpoints;
private final ListenerList<IBreakpointListener> fBreakpointListeners = new ListenerList<>();
private ListenerList<IBreakpointsListener> fBreakpointsListeners= new ListenerList<>();
private static BreakpointManagerVisitor fgVisitor;
private final ListenerList<IBreakpointManagerListener> fBreakpointManagerListeners = new ListenerList<>();
private final Set<IBreakpoint> fTriggerPointBreakpointList = new LinkedHashSet<>();
private final Set<IBreakpoint> fTriggerPointDisabledList = new LinkedHashSet<>();
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);
}
}
}
}
class DefaultImportParticipant implements IBreakpointImportParticipant {
@Override
public boolean matches(Map<String, Object> attributes, IBreakpoint breakpoint) throws CoreException {
IMarker marker = breakpoint.getMarker();
String type = (String) attributes.get("type");
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 {}
}
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;
}
}
public BreakpointManager() {
fMarkersToBreakpoints = new HashMap<>(10);
fBreakpointExtensions = new HashMap<>(15);
}
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);
}
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)) {
String modelId = marker.getAttribute(IBreakpoint.ID, null);
if (modelId == null) {
delete.add(marker);
} else if (!marker.getAttribute(IBreakpoint.PERSISTED, true)) {
delete.add(marker);
} else {
persisted.add(marker);
}
}
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()]);
}
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();
}
}
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));
} 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));
} else {
fBreakpointExtensions.put(markerType, element);
}
}
}
private IWorkspace getWorkspace() {
return ResourcesPlugin.getWorkspace();
}
@Override
public IBreakpoint getBreakpoint(IMarker marker) {
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;
}
public void ensureInitialized() {
getBreakpoints0();
}
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()]);
}
}
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));
}
}
@Override
public boolean isRegistered(IBreakpoint breakpoint) {
return getBreakpoints0().contains(breakpoint);
}
@Override
public void removeBreakpoint(IBreakpoint breakpoint, boolean delete) throws CoreException {
removeBreakpoints(new IBreakpoint[]{breakpoint}, delete);
}
@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 {
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);
}
}
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));
}
return breakpoint;
} catch (CoreException e) {
throw new DebugException(e.getStatus());
}
}
@Override
public void addBreakpoint(IBreakpoint breakpoint) throws CoreException {
addBreakpoints(new IBreakpoint[]{breakpoint});
}
@Override
public void addBreakpoints(IBreakpoint[] breakpoints) throws CoreException {
addBreakpoints(breakpoints, true);
}
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()) {
added.add(breakpoint);
getBreakpoints0().add(breakpoint);
fMarkersToBreakpoints.put(breakpoint.getMarker(), breakpoint);
} else {
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);
}
}
};
fSuppressChange.addAll(update);
getWorkspace().run(r, null, 0, null);
fSuppressChange.removeAll(update);
if (notify) {
fireUpdate(update, null, ADDED);
}
}
}
protected boolean isChangeSuppressed(IBreakpoint breakpoint) {
return fSuppressChange.contains(breakpoint);
}
@Override
public void fireBreakpointChanged(IBreakpoint breakpoint) {
if (getBreakpoints0().contains(breakpoint)) {
List<IBreakpoint> changed = new ArrayList<>();
changed.add(breakpoint);
fireUpdate(changed, null, CHANGED);
}
}
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());
}
}
@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);
}
}
}
class BreakpointManagerVisitor implements IResourceDeltaVisitor {
private List<IMarker> fMoved = new ArrayList<>();
private List<IBreakpoint> fRemoved = new ArrayList<>();
private List<IBreakpoint> fAdded = new ArrayList<>();
private List<IBreakpoint> fChanged = new ArrayList<>();
private List<IMarkerDelta> fChangedDeltas = new ArrayList<>();
protected void reset() {
fMoved.clear();
fRemoved.clear();
fAdded.clear();
fChanged.clear();
fChangedDeltas.clear();
}
public void update() {
if (!fMoved.isEmpty()) {
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();
}
@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;
}
protected void handleAddBreakpoint(IResourceDelta rDelta, IMarker marker, IMarkerDelta mDelta) {
if (0 != (rDelta.getFlags() & IResourceDelta.MOVED_FROM)) {
if (getBreakpoint(marker) == null) {
fMoved.add(marker);
}
} else {
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 {
IBreakpoint breakpoint = findMatchingBreakpoint(marker);
if (breakpoint != null) {
removeBreakpoint(breakpoint, true);
}
fAdded.add(createBreakpoint(marker));
} catch (CoreException e) {
DebugPlugin.log(e);
}
}
fPostBuildMarkersAdded.add(marker);
}
}
}
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) {
}
return null;
}
protected void handleRemoveBreakpoint(IMarker marker) {
synchronized (fPostChangMarkersChanged) {
fPostChangMarkersChanged.remove(marker);
fPostBuildMarkersAdded.remove(marker);
}
IBreakpoint breakpoint= getBreakpoint(marker);
if (breakpoint != null) {
fRemoved.add(breakpoint);
}
}
protected void handleChangeBreakpoint(IMarker marker, IMarkerDelta delta) {
IBreakpoint breakpoint= getBreakpoint(marker);
if (breakpoint != null && isRegistered(breakpoint) && !isChangeSuppressed(breakpoint)) {
fChanged.add(breakpoint);
fChangedDeltas.add(delta);
}
}
private void handleProjectResourceOpenStateChange(final IResource project) {
if (!project.isAccessible()) {
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);
}
}
}
@Override
public void addBreakpointListener(IBreakpointListener listener) {
fBreakpointListeners.add(listener);
}
@Override
public void removeBreakpointListener(IBreakpointListener listener) {
fBreakpointListeners.remove(listener);
}
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);
}
getBreakpointNotifier().notify(bpArray, deltaArray, update);
getBreakpointsNotifier().notify(bpArray, deltaArray, update);
}
protected void setBreakpoints(Vector<IBreakpoint> breakpoints) {
fBreakpoints = breakpoints;
}
@Override
public boolean hasBreakpoints() {
return !getBreakpoints0().isEmpty();
}
@Override
public void addBreakpointListener(IBreakpointsListener listener) {
fBreakpointsListeners.add(listener);
}
@Override
public void removeBreakpointListener(IBreakpointsListener listener) {
fBreakpointsListeners.remove(listener);
}
private BreakpointNotifier getBreakpointNotifier() {
return new BreakpointNotifier();
}
class BreakpointNotifier implements ISafeRunnable {
private IBreakpointListener fListener;
private int fType;
private IMarkerDelta fDelta;
private IBreakpoint fBreakpoint;
@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);
DebugPlugin.log(status);
}
@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;
}
}
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();
}
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);
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;
}
}
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);
}
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);
DebugPlugin.log(status);
}
@Override
public void run() throws Exception {
fListener.breakpointManagerEnablementChanged(fManagerEnabled);
}
public void notify(boolean enabled) {
fManagerEnabled= enabled;
for (IBreakpointManagerListener iBreakpointManagerListener : fBreakpointManagerListeners) {
fListener = iBreakpointManagerListener;
SafeRunner.run(this);
}
fListener = null;
}
}
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);
DebugPlugin.log(status);
}
@Override
public void run() throws Exception {
fListener.breakpointManagerTriggerPointChanged(fManagerTriggerPoint);
}
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");
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);
}
}
@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;
}
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) {
}
}
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) {
}
}
synchronized (fTriggerPointDisabledList) {
fTriggerPointDisabledList.clear();
if (!enable) {
fTriggerPointDisabledList.addAll(toDisable);
}
}
}
@Override
public void refreshTriggerpointDisplay() {
touchAllBreakpoints();
}
private void touchAllBreakpoints() {
IWorkspaceRunnable runnable = new IWorkspaceRunnable() {
@Override
public void run(IProgressMonitor monitor) throws CoreException {
for (IBreakpoint breakpoint : getBreakpoints()) {
try {
breakpoint.getMarker().setAttribute(IBreakpoint.ENABLED, breakpoint.isEnabled());
} catch (CoreException e) {
}
}
}
};
try {
ResourcesPlugin.getWorkspace().run(runnable, null, IWorkspace.AVOID_UPDATE, null);
} catch (CoreException e) {
DebugPlugin.log(e);
}
}
}